Escribir metadatos dpi en una imagen jpeg en Java
-
04-07-2019 - |
Pregunta
Estoy tratando de establecer programáticamente los metadatos de ppp de una imagen jpeg en Java. La fuente de la imagen es un escáner, así que obtengo la resolución horizontal / vertical de TWAIN, junto con los datos en bruto de la imagen. Me gustaría guardar esta información para obtener mejores resultados de impresión.
Aquí está el código que tengo hasta ahora. Guarda la imagen en bruto (byteArray) en un archivo JPEG, pero ignora la información de X / Ydensity que especifico a través de IIOMetadata. ¿Algún consejo de lo que estoy haciendo mal?
Cualquier otra solución (biblioteca de terceros, etc.) también sería bienvenida.
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.ImageOutputStream
import org.w3c.dom.Element;
import com.sun.imageio.plugins.jpeg.JPEGImageWriter;
public boolean saveJpeg(int[] byteArray, int width, int height, int dpi, String file)
{
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
WritableRaster wr = bufferedImage.getRaster();
wr.setPixels(0, 0, width, height, byteArray);
try
{
// Image writer
JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix("jpeg").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(new File(file));
imageWriter.setOutput(ios);
// Compression
JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
jpegParams.setCompressionQuality(0.85f);
// Metadata (dpi)
IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage), jpegParams);
Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0");
Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0);
jfif.setAttribute("Xdensity", Integer.toString(dpi));
jfif.setAttribute("Ydensity", Integer.toString(dpi));
jfif.setAttribute("resUnits", "1"); // density is dots per inch
// Write and clean up
imageWriter.write(data, new IIOImage(bufferedImage, null, null), jpegParams);
ios.close();
imageWriter.dispose();
}
catch (Exception e)
{
return false;
}
return true;
}
¡Gracias!
Solución
Algunos problemas que no se consideraron aquí:
-
El árbol no está directamente asignado a IOMetaData. Para aplicar los datos del árbol, agregue la siguiente llamada después de configurar las densidades y los parámetros ráster:
data.setFromTree("javax_imageio_jpeg_image_1.0", tree);
-
no use los metadatos como primer parámetro en la llamada de escritura. Consulte
JPEGImageWriter # write (IIOMetaData, IIOImage, ImageWriteParam)
. Si streamMetaData no es NULL, se generará una advertencia (WARNING_STREAM_METADATA_IGNORED). -
establece los metadatos como
IOMetadata
deIOImage
. Estos metadatos son utilizados por JPEGImageWriter. La llamada de escritura correcta esimageWriter.write(null, new IIOImage(F_scaledImg, null, data), jpegParams);
Otros consejos
Parece que esto podría ser un error.
Encontré esta publicación de algunas búsquedas en Google
Aparentemente, hay muchos más que apuntan a un error también.
La publicación anterior habla sobre el uso de JMagick como una solución de terceros.