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!

Était-ce utile?

La solution

Certaines questions non prises en compte ici:

  1. 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);
    
  2. 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é.

  3. définissez les métadonnées en tant que IOMetadata de IOImage . Ces métadonnées sont utilisées par JPEGImageWriter. Le bon appel en écriture est alors

    imageWriter.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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top