Как установить DPI информацию в изображении?

У меня есть приложение, в которое я хочу экспортировать изображения с высоким разрешением (или, скорее, с высокой плотностью пикселей?) Для печати - например, я хочу, чтобы изображения печатались со скоростью 250 точек на дюйм (DPI) вместо значения по умолчанию, которое, как я понимаю, быть 72 DPI.

Я использую BufferedImage с объектом Graphics2D, чтобы нарисовать изображение, затем ImageIO.write(), чтобы сохранить изображение.

Любая идея, как я могу установить DPI?

5 ответов

Решение

Ответ Курта показал путь, но мне потребовалось немало времени, чтобы запустить его, так что вот код, который устанавливает DPI при сохранении PNG. Существует много сделать, чтобы найти подходящих авторов и тому подобное...

 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);
 }

Настройка TIFF DPI

Если вы хотите установить dpi для TIFF, попробуйте сделать это следующим образом:

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);

    // Add unit field to TIFFDirectory (change to RESOLUTION_UNIT_CENTIMETER if necessary)
    dir.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH));

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

Кроме того, аналогичным образом вы можете настроить любой тег TIFF.

Читайте больше в источнике

Я использую этот код для файла TIFF в моем проекте, и он работает хорошо..

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;
}
}

это должно установить 300 DPI изображения Tiff. Вы можете изменить его в соответствии с вашими потребностями.

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 } });

Первая ссылка Google:

http://www.tracemodeler.com/articles/aging-bugs-and-setting-dpi-with-java-image-io/

И, похоже, в нем есть нужная вам информация.

Я нашел эту ветку в каталоге сообщества Oracle:

https://community.oracle.com/thread/1265028?tstart=0

Итак, похоже, что это не так просто, как image.setDPI(200, 400),

Другие вопросы по тегам