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!

War es hilfreich?

Lösung

Einige Fragen, die hier nicht berücksichtigt wurden:

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

  3. die Meta-Daten wie IOMetadata des IOImage gesetzt. Diese Metadaten werden durch JPEGImageWriter verwendet. Der richtige Schreibaufruf dann ist

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top