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!

¿Fue útil?

Solución

Algunos problemas que no se consideraron aquí:

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

  3. establece los metadatos como IOMetadata de IOImage . Estos metadatos son utilizados por JPEGImageWriter. La llamada de escritura correcta es

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top