-2

I am creating a java program which I need to increase input JPEG image's PPI/DPI and save it as JPEG.

Anyone can give me some hits on if this is workable?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Szewing
  • 27
  • 1
  • 3
  • ppi/dpi is just a conversion factor. it doesn't change how many pixels there are in an image... a 200x200 jpeg is 200x200, whether it's 1 dpi or (infinity)dpi. – Marc B Oct 11 '16 at 19:30
  • You can't get a quart into a pint pot, and you can't get a quart out of a pint pot either. You can increase the size and use interpolation but nothing will accurately recreate the missing pixels. – user207421 Oct 12 '16 at 07:48

1 Answers1

6

You can do it like in this answer, except you have to use "jpeg" as the format name and you need to implement the setDPI method to work with JPEG-specific metadata.

public static final String DENSITY_UNITS_NO_UNITS = "00";
public static final String DENSITY_UNITS_PIXELS_PER_INCH = "01";
public static final String DENSITY_UNITS_PIXELS_PER_CM = "02";

private BufferedImage gridImage;

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

    final String formatName = "jpeg";

    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 static void setDPI(IIOMetadata metadata) throws IIOInvalidTreeException {
    String metadataFormat = "javax_imageio_jpeg_image_1.0";
    IIOMetadataNode root = new IIOMetadataNode(metadataFormat);
    IIOMetadataNode jpegVariety = new IIOMetadataNode("JPEGvariety");
    IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");

    IIOMetadataNode app0JFIF = new IIOMetadataNode("app0JFIF");
    app0JFIF.setAttribute("majorVersion", "1");
    app0JFIF.setAttribute("minorVersion", "2");
    app0JFIF.setAttribute("thumbWidth", "0");
    app0JFIF.setAttribute("thumbHeight", "0");
    app0JFIF.setAttribute("resUnits", DENSITY_UNITS_PIXELS_PER_INCH);
    app0JFIF.setAttribute("Xdensity", String.valueOf(300));
    app0JFIF.setAttribute("Ydensity", String.valueOf(300));

    root.appendChild(jpegVariety);
    root.appendChild(markerSequence);
    jpegVariety.appendChild(app0JFIF);

    metadata.mergeTree(metadataFormat, root);
}

This code sets the PPI to 300x300 but you may want to make this variable.

Community
  • 1
  • 1
Thomas
  • 17,016
  • 4
  • 46
  • 70