2008-11-26 21 views
23

Tengo una aplicación que deseo exportar imágenes de alta resolución (¿o mejor, densidad de píxeles alta?) Para imprimir; por ejemplo, quiero imágenes que impriman a 250 puntos por pulgada (PPP), en lugar de las predeterminadas, que Entiendo que es 72 DPI.¿Cómo establecer la información de DPI en una imagen?

Estoy usando una Imagen Buffered con un objeto Graphics2D para dibujar la imagen, luego ImageIO.write() para guardar la imagen.

¿Alguna idea de cómo puedo configurar el DPI?

Respuesta

24

La respuesta de Kurt mostró el camino, aun así me llevó bastante tiempo ejecutarla, así que aquí está el código que establece DPI al guardar un archivo PNG. Hay mucho que hacer para conseguir los escritores apropiados y tal ...

private BufferedImage gridImage; 
... 

private void saveGridImage(File output) throws IOException { 
    output.delete(); 

    final String formatName = "png"; 

    for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName(formatName); iw.hasNext();) { 
     ImageWriter writer = iw.next(); 
     ImageWriteParam writeParam = writer.getDefaultWriteParam(); 
     ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB); 
     IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam); 
     if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) { 
      continue; 
     } 

     setDPI(metadata); 

     final ImageOutputStream stream = ImageIO.createImageOutputStream(output); 
     try { 
      writer.setOutput(stream); 
      writer.write(metadata, new IIOImage(gridImage, null, metadata), writeParam); 
     } finally { 
      stream.close(); 
     } 
     break; 
    } 
} 

private void setDPI(IIOMetadata metadata) throws IIOInvalidTreeException { 

    // for PMG, it's dots per millimeter 
    double dotsPerMilli = 1.0 * DPI/10/INCH_2_CM; 

    IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize"); 
    horiz.setAttribute("value", Double.toString(dotsPerMilli)); 

    IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize"); 
    vert.setAttribute("value", Double.toString(dotsPerMilli)); 

    IIOMetadataNode dim = new IIOMetadataNode("Dimension"); 
    dim.appendChild(horiz); 
    dim.appendChild(vert); 

    IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0"); 
    root.appendChild(dim); 

    metadata.mergeTree("javax_imageio_1.0", root); 
} 
+0

¿por qué se llama imagen de cuadrícula? algo diferente de una imagen regular? – Zeveso

+0

@Zeveso Acabo de copiar/pegar este código de una aplicación en funcionamiento que estaba guardando una imagen de una grilla, de ahí el nombre de la Imagen Buffered y el método. El código funciona para cada Imagen Buffered. –

+1

@PeterKofler estoy usando el código anterior sin ningún cambio. el código anterior crea el archivo PNG como se esperaba (utilizando los ppp dados), pero cuando utilizo el código anterior para el archivo JPEG falla, ¿necesito establecer algún parámetro para JPEG o este código funciona solo para PNG? – Mihir

0

estoy usando el código para el archivo tiff en mi proyecto y funciona bien ..

import java.awt.image.BufferedImage; 
import java.awt.image.RenderedImage; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
import java.util.ArrayList; 
import java.util.List; 
import javax.imageio.ImageIO; 
import javax.media.jai.NullOpImage; 
import javax.media.jai.OpImage; 
import javax.media.jai.PlanarImage; 
import com.sun.media.jai.codec.FileSeekableStream; 
import com.sun.media.jai.codec.ImageCodec; 
import com.sun.media.jai.codec.ImageDecoder; 
import com.sun.media.jai.codec.ImageEncoder; 
import com.sun.media.jai.codec.SeekableStream; 
import com.sun.media.jai.codec.TIFFEncodeParam; 
import com.sun.media.jai.codec.TIFFField; 
class SetDDPI 
{ 
static void tiff_Maker(List<BufferedImage> output, String result) throws IOException 
{ 
    TIFFEncodeParam params = new TIFFEncodeParam(); 
    OutputStream out = new FileOutputStream(result); 
    List<BufferedImage> imageList = new ArrayList<BufferedImage>(); 
    for (int i = 1; i < output.size(); i++) 
    { 
     imageList.add(output.get(i)); 
    } 
    params.setWriteTiled(true); 
    params.setCompression(TIFFEncodeParam.COMPRESSION_GROUP4); 
    params.setExtraImages(imageList.iterator()); 
    TIFFField[] extras = new TIFFField[2]; 
    extras[0] = new TIFFField(282, TIFFField.TIFF_RATIONAL, 1, (Object) new long[][] { { (long) 300, (long) 1 }, 
      { (long) 0, (long) 0 } }); 
    extras[1] = new TIFFField(283, TIFFField.TIFF_RATIONAL, 1, (Object) new long[][] { { (long) 300, (long) 1 }, 
      { (long) 0, (long) 0 } }); 
    params.setExtraFields(extras); 
    ImageEncoder encoder = ImageCodec.createImageEncoder("tiff", out, params); 
    encoder.encode(output.get(0)); 
    out.close(); 
} 
static List<BufferedImage> tiff_Extractor(File tiff) throws IOException 
{ 
    List<BufferedImage> images = new ArrayList<BufferedImage>(); 
    SeekableStream ss = new FileSeekableStream(tiff); 
    ImageDecoder decoder = ImageCodec.createImageDecoder("tiff", ss, null); 
    int numPages = decoder.getNumPages(); 
    for (int j = 0; j < numPages; j++) 
    { 
     PlanarImage op = new NullOpImage(decoder.decodeAsRenderedImage(j), null, null, OpImage.OP_IO_BOUND); 
     images.add(op.getAsBufferedImage()); 

    } 
    return images; 
} 
} 

esto es establecer 300 DPI de la imagen de Tiff. puedes cambiarlo de acuerdo a tu necesidad

extras[0] = new TIFFField(282, TIFFField.TIFF_RATIONAL, 1, (Object) new  
long[][] { { (long) 300, (long) 1 },{ (long) 0, (long) 0 } }); 

extras[1] = new TIFFField(283, TIFFField.TIFF_RATIONAL, 1, (Object) new  
long[][] { { (long) 300, (long) 1 },{ (long) 0, (long) 0 } }); 
0

Seting hasta TIFF DPI

Si desea establecer dpi para TIFF, tratar de hacerlo mediante los siguientes pasos:

private static IIOMetadata createMetadata(ImageWriter writer, ImageWriteParam writerParams, int resolution) throws 
                              IIOInvalidTreeException 
{ 
    // Get default metadata from writer 
    ImageTypeSpecifier type = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY); 
    IIOMetadata meta = writer.getDefaultImageMetadata(type, writerParams); 

    // Convert default metadata to TIFF metadata 
    TIFFDirectory dir = TIFFDirectory.createFromMetadata(meta); 

    // Get {X,Y} resolution tags 
    BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance(); 
    TIFFTag tagXRes = base.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION); 
    TIFFTag tagYRes = base.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION); 

    // Create {X,Y} resolution fields 
    TIFFField fieldXRes = new TIFFField(tagXRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } }); 
    TIFFField fieldYRes = new TIFFField(tagYRes, TIFFTag.TIFF_RATIONAL, 1, new long[][] { { resolution, 1 } }); 

    // Add {X,Y} resolution fields to TIFFDirectory 
    dir.addTIFFField(fieldXRes); 
    dir.addTIFFField(fieldYRes); 

    // Return TIFF metadata so it can be picked up by the IIOImage 
    return dir.getAsMetadata(); 
} 

Además, de forma similar se puede configuración de cualquier etiqueta TIFF .

Ver más en el source

Cuestiones relacionadas