Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing DPI and Paper Size information in a JPEG with Java

I have the following code:

ImageIO.write(originalImage, OUTPUT_TYPE, resultOutput);

This is an invocation of the following javax.imageio.ImageIO method:

public static boolean write(RenderedImage im,
                            String formatName,
                            File output)
                     throws IOException

This turns an original BMP image into a JGP output. Is it possible to also store DPI and Paper Size information in the JPEG to aid in printing operations?

like image 330
Paul Reiners Avatar asked Dec 23 '11 17:12

Paul Reiners


2 Answers

I found this post for setting DPI on PNG Files. It pointed out that you should use 'metadata.mergeTree' to properly save your metadata.

With that in mind, here is some working groovy code that takes a BMP file and creates a JPG file at arbitrary DPI:

import java.awt.image.BufferedImage
import java.io.File
import java.util.Hashtable
import java.util.Map
import javax.imageio.*
import javax.imageio.stream.*
import javax.imageio.metadata.*
import javax.imageio.plugins.jpeg.*
import org.w3c.dom.*

File sourceFile = new File("sample.bmp")
File destinationFile = new File("sample.jpg")

dpi = 100

BufferedImage sourceImage = ImageIO.read(sourceFile)
ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next();
ImageOutputStream ios = ImageIO.createImageOutputStream(destinationFile);
imageWriter.setOutput(ios);
def jpegParams = imageWriter.getDefaultWriteParam();

IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(sourceImage), 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                 
data.mergeTree("javax_imageio_jpeg_image_1.0",tree)

// Write and clean up
imageWriter.write(data, new IIOImage(sourceImage, null, data), jpegParams);
ios.close();
imageWriter.dispose();

Worked fine for me in that OSX's Preview app and Gimp both reported that the resulting image was 100 DPI. As to Paper Size...I imagine this is directly determined by DPI? I couldn't find any JPEG property that would set that particular value.

like image 132
dsummersl Avatar answered Sep 18 '22 17:09

dsummersl


You may consider using Commons Sanselan, instead of ImageIO for this task.

See http://commons.apache.org/sanselan/whysanselan.html for more info.

like image 20
Guillaume Serre Avatar answered Sep 22 '22 17:09

Guillaume Serre