Écrire des métadonnées dpi sur une image jpeg en Java
-
04-07-2019 - |
Question
J'essaie de définir par programme les métadonnées dpi d'une image jpeg en Java. La source de l'image étant un scanner, j'obtiens la résolution horizontale / verticale de TWAIN, ainsi que les données brutes de l'image. J'aimerais sauvegarder cette information pour de meilleurs résultats d'impression.
Voici le code que j'ai jusqu'à présent. Il enregistre l'image brute (byteArray) dans un fichier JPEG, mais ignore les informations X / Ydensity que je spécifie via IIOMetadata. Un conseil que je fais mal?
Toute autre solution (bibliothèque tierce, etc.) serait également la bienvenue.
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;
}
Merci!
La solution
Certaines questions non prises en compte ici:
-
L'arbre n'est pas directement mappé sur IOMetaData. Pour appliquer les données de l’arbre, ajoutez l’appel suivant après avoir défini les densités et les paramètres de raster:
data.setFromTree("javax_imageio_jpeg_image_1.0", tree);
-
n'utilisez pas les métadonnées en tant que premier paramètre de l'appel en écriture. Voir
JPEGImageWriter # write (IIOMetaData, IIOImage, ImageWriteParam)
. Si streamMetaData n'est pas NULL, un avertissement (WARNING_STREAM_METADATA_IGNORED) sera généré. -
définissez les métadonnées en tant que
IOMetadata ??code> de
IOImage
. Ces métadonnées sont utilisées par JPEGImageWriter. Le bon appel en écriture est alorsimageWriter.write(null, new IIOImage(F_scaledImg, null, data), jpegParams);
Autres conseils
Je pense que cela pourrait être un bug.
J'ai trouvé ce post à partir de quelques recherches sur Google
Apparemment, il y en a beaucoup plus qui indiquent un bogue.
Le message ci-dessus parle de l'utilisation de JMagick en tant que tiers.