Re: How Do You Specify DPI in .png Image File
On Aug 9, 7:12 pm, markspace <nos...@nowhere.com> wrote:
Steve Yates wrote:
contains this information I will see if I can browse the metadata of
this file in Java and determine where this value is stored.
That's what I would do, just dump all the metadata and see what's in
there. Note that some devices or applications assume a default value i=
f
none is present, so if you don't see anything likely in your dump, you
might have to edit the DPI value to something else to make PSP actually
store a value.
This is what I came up with. It seems that there must be a more
direct way to get at some of these objects, but this does give me what
I was looking for. I am seeing an unwanted change in the metadata
though that concerns me.
static private void writePngFile(RenderedImage image, String
filename, int dotsPerInch) {
String dotsPerMeter = String.valueOf((int) (dotsPerInch / 0.0254));
// retrieve list of ImageWriters for png images (most likely only
one but who knows)
Iterator<ImageWriter> imageWriters =
ImageIO.getImageWritersByFormatName("png");
// loop through available ImageWriters until one succeeds
while (imageWriters.hasNext()) {
ImageWriter iw = imageWriters.next();
// get default metadata for png files
ImageWriteParam iwp = iw.getDefaultWriteParam();
IIOMetadata metadata = iw.getDefaultImageMetadata(new
ImageTypeSpecifier(image), iwp);
// get png specific metatdata tree
String pngFormatName = metadata.getNativeMetadataFormatName();
IIOMetadataNode pngNode =
(IIOMetadataNode) metadata.getAsTree(pngFormatName);
// find pHYs node, or create it if it doesn't exist
IIOMetadataNode physNode = null;
NodeList childNodes = pngNode.getElementsByTagName("pHYs");
if (childNodes.getLength() == 0) {
physNode = new IIOMetadataNode("pHYs");
pngNode.appendChild(physNode);
} else if (childNodes.getLength() == 1) {
physNode = (IIOMetadataNode) childNodes.item(0);
} else {
throw new IllegalStateException("Don't know what to do with
multiple pHYs nodes");
}
physNode.setAttribute("pixelsPerUnitXAxis", dotsPerMeter);
physNode.setAttribute("pixelsPerUnitYAxis", dotsPerMeter);
physNode.setAttribute("unitSpecifier", "meter");
try {
metadata.setFromTree(pngFormatName, pngNode);
IIOImage iioImage = new IIOImage(image, null, metadata);
File file = new File(filename);
ImageOutputStream ios = ImageIO.createImageOutputStream(file);
iw.setOutput(ios);
iw.write(iioImage);
ios.flush();
ios.close();
} catch (Exception e) {
e.printStackTrace();
continue;
}
break;
}
}
I copied a dump of the image metadata tree after the first line in the
try block blow. The pHYs block in the javax_imageio_png_1.0 is what
my code added, and the HorizontalPixelSize and VerticalPixelSize nodes
in the javax_imageio_1.0/Dimension block were added as a side effect.
That is fine, but the bitDepth in javax_imageio_png_1.0/IHDR changed
from 8 to 3, and the BitsPerSample in javax_imageio_1.0/Data changed
from "8 8 8" to "3 3 3". From the documentation I have seen, 3 is not
a valid value for bitDepth, so this concerns me. Everything else is
unchanged from the dump of the defaults retrieved from the writer.
When I read the file with an ImageReader and dump the metadata I see 8
for the bitDepth though, and when I open the document in Paint Shop
Pro it shows me the resolution is 300 dots per inch as I wanted. It
still shows the color depth as 24 bits/16 million colors, which is a
good sign, because I would expect only 256 colors with 3 bits. So
while I don't understand why the values are changing in the metadata
tree, they are somehow getting changed back before the image file is
actually written. So I guess this solution will work.
javax_imageio_png_1.0:|null|
IHDR:|null|
Attributes
width:|0|
height:|0|
bitDepth:|3|
colorType:|RGB|
compressionMethod:|deflate|
filterMethod:|adaptive|
interlaceMethod:|none|
pHYs:|null|
Attributes
pixelsPerUnitXAxis:|11811|
pixelsPerUnitYAxis:|11811|
unitSpecifier:|meter|
javax_imageio_1.0:|null|
Chroma:|null|
ColorSpaceType:|null|
Attributes
name:|RGB|
NumChannels:|null|
Attributes
value:|3|
BlackIsZero:|null|
Attributes
value:|true|
Compression:|null|
CompressionTypeName:|null|
Attributes
value:|deflate|
Lossless:|null|
Attributes
value:|true|
NumProgressiveScans:|null|
Attributes
value:|1|
Data:|null|
PlanarConfiguration:|null|
Attributes
value:|PixelInterleaved|
SampleFormat:|null|
Attributes
value:|UnsignedIntegral|
BitsPerSample:|null|
Attributes
value:|3 3 3|
Dimension:|null|
PixelAspectRatio:|null|
Attributes
value:|1.0|
ImageOrientation:|null|
Attributes
value:|Normal|
HorizontalPixelSize:|null|
Attributes
value:|0.08466683|
VerticalPixelSize:|null|
Attributes
value:|0.08466683|
Transparency:|null|
Alpha:|null|
Attributes
value:|none|