Schreiben dpi Metadaten zu einem JPEG-Bild in Java
-
04-07-2019 - |
Frage
Ich versuche, die dpi-Metadaten eines JPEG-Bildes in Java programmatisch festgelegt. Die Quelle des Bildes ist ein Scanner, so dass ich die horizontale / vertikale Auflösung von TWAIN, zusammen mit der Bild Rohdaten. Ich möchte diese Informationen für eine bessere Druckergebnisse speichern.
Hier ist der Code, den ich bis jetzt haben. Es speichert das Rohbild (byteArray) in eine JPEG-Datei, aber es ignoriert die X / Ydensity Informationen, die ich über IIOMetadata angeben. Jede Beratung, was ich falsch mache?
Jede andere Lösung (Drittanbieter-Bibliothek, etc.) wäre zu begrüßen.
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;
}
Danke!
Lösung
Einige Fragen, die hier nicht berücksichtigt wurden:
-
Der Baum nicht direkt auf den IOMetaData abgebildet wird. So wenden Sie Daten von Baum, fügen Sie folgenden Aufruf nach den Dichten und Raster Parameter einstellen:
data.setFromTree("javax_imageio_jpeg_image_1.0", tree);
-
nicht die Meta-Daten als erste Parameter in dem Schreibaufruf verwenden. Siehe
JPEGImageWriter#write(IIOMetaData, IIOImage, ImageWriteParam)
. Wenn StreamMetadata nicht NULL ist, wird eine Warnung (WARNING_STREAM_METADATA_IGNORED) erzeugt werden. -
die Meta-Daten wie
IOMetadata
desIOImage
gesetzt. Diese Metadaten werden durch JPEGImageWriter verwendet. Der richtige Schreibaufruf dann istimageWriter.write(null, new IIOImage(F_scaledImg, null, data), jpegParams);
Andere Tipps
Ich scheint dies ein Fehler sein könnte.
Ich fand diesen Beitrag von ein paar Google-Suchen
Anscheinend gibt es viel mehr, dass Punkt zu einem auch Fehler.
Der Beitrag oben spricht über JMagick als Dritte Arbeit um verwenden.