2008-10-24 34 views
14

Estoy tratando de establecer programáticamente los metadatos de dpi de una imagen jpeg en Java. La fuente de la imagen es un escáner, por lo que obtengo la resolución horizontal/vertical de TWAIN, junto con los datos brutos de la imagen. Me gustaría guardar esta información para obtener mejores resultados de impresión.Escribir metadatos de dpi en una imagen jpeg en Java

Aquí está el código que tengo hasta ahora. Guarda la imagen sin procesar (byteArray) en un archivo JPEG, pero ignora la información X/Ydensity que especifico a través de IIOMetadata. ¿Algún consejo sobre 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!

Respuesta

13

Algunas cuestiones que no fueron considerados aquí:

  1. El árbol no se asignan directamente a la IOMetaData. Para aplicar los datos de árbol, añadir siguiente llamada después de ajustar las densidades y parámetros de trama:

    data.setFromTree("javax_imageio_jpeg_image_1.0", tree); 
    
  2. no utilizan los metadatos como primer parámetro de la llamada de escritura. Ver JPEGImageWriter#write(IIOMetaData, IIOImage, ImageWriteParam). Si streamMetaData no es NULL, se generará una advertencia (WARNING_STREAM_METADATA_IGNORED).

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

    imageWriter.write(null, new IIOImage(F_scaledImg, null, data), jpegParams); 
    
+2

Cuando se establece F_scaledImg? ¿Es lo mismo que imagen almacenada? Lo siento si esta es una pregunta tonta ... –

+2

Sí, en realidad es una imagen amortiguada. Christoph debe haber copiado el fragmento y se olvidó de editarlo. – dasp

1

Me parece que esto podría ser un error.

me encontré con este post from a few google searches

Al parecer hay mucho más que apuntan a un error así.

En la publicación anterior se habla sobre el uso de JMagick como un trabajo de terceros.

Cuestiones relacionadas