You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@commons.apache.org by Scott Neville <sc...@bluestar-software.co.uk> on 2019/03/20 17:21:32 UTC

[imaging] Writing X/YResolution

Hi, 

I am having a problem with writing EXIF Meta Data onto an existing JPEG image using commons imaging. I am trying to set the XResolution and the YResolution on the image. In this instance I have a photograph of a flat surface taken at exactly 90 degrees with a calibrated rule in it. The user has the option of specifying the length of the rule (clicking on two parts of the image) and entering the phyiscal length. I want to then add the XResolution and YResolution so that it can be used later to support printing the image at the same physical size (apprciate this might not be 100% accurate). The process originally started using scans taken via scanner where the X/YResolution would already be on the image and useable for turning the data back into physical space. 

I am using the following code: 

private static TiffImageMetadata _readImageMetaData(byte[] pImage) 
{ 
try 
{ 
IImageMetadata tMD = Imaging.getMetadata(pImage); 

if (tMD instanceof JpegImageMetadata) 
{ 
JpegImageMetadata tJMD = (JpegImageMetadata)tMD; 
return tJMD.getExif(); 
} 
else if (tMD instanceof TiffImageMetadata) 
{ 
return (TiffImageMetadata)tMD; 
} 
} 
catch (ImageReadException | IOException tEx) 
{ 
System.out.println(tEx.getMessage()); 
} 

return null; 
} 


private static org.apache.commons.imaging.formats.tiff.write.TiffOutputSet _getExifMetadata(TiffImageMetadata oMD, String pUserID, double pPPI, int pWidth, int pLength) 
{ 
try 
{ 
//the first version of this would copy the data out of the existing TiffImageMetaData rather than creating a new TiffOutputSet 
org.apache.commons.imaging.formats.tiff.write.TiffOutputSet tOutputSet = new org.apache.commons.imaging.formats.tiff.write.TiffOutputSet(); 
org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory tOutputDirectory = tOutputSet.getOrCreateRootDirectory(); 

tOutputDirectory.removeField(282); //XResoloution 
tOutputDirectory.removeField(283); //YResoloution 
tOutputDirectory.removeField(296); //ResoloutionUnit 
tOutputDirectory.removeField(256); //ImageWidth 
tOutputDirectory.removeField(257); //ImageLength 

tOutputDirectory.add(org.apache.commons.imaging.formats.tiff.write.TiffOutputField.TIFF_TAG_XRESOLUTION, new org.apache.commons.imaging.common.RationalNumber((int)pPPI, 1)); 
tOutputDirectory.add(org.apache.commons.imaging.formats.tiff.write.TiffOutputField.TIFF_TAG_YRESOLUTION, new org.apache.commons.imaging.common.RationalNumber((int)pPPI, 1)); 
tOutputDirectory.add(org.apache.commons.imaging.formats.tiff.write.TiffOutputField.TIFF_TAG_RESOLUTION_UNIT, (short)2); 

tOutputDirectory.add(org.apache.commons.imaging.formats.tiff.write.TiffOutputField.EXIF_TAG_IMAGE_WIDTH, pWidth); 
tOutputDirectory.add(org.apache.commons.imaging.formats.tiff.write.TiffOutputField.EXIF_TAG_IMAGE_HEIGHT, pLength); 
tOutputDirectory.add(org.apache.commons.imaging.formats.tiff.write.TiffOutputField.TIFF_TAG_ARTIST, pUserID); 

return tOutputSet; 
} 
catch (ImageWriteException tEx) 
{ 
System.out.println(tEx.getMessage()); 
return null; 
} 
} 



TiffImageMetadata tMetaData = _readImageMetaData(pInstruction.mGetBytes); //passing in a byte array[] 
BufferedImage tImage = ImageIO.read(new ByteArrayInputStream(pInstruction.mGetBytes)); 

//there is potentially some cropping done here depending on settings in pInstruction, left out for space 

org.apache.commons.imaging.formats.tiff.write.TiffOutputSet tOutputSet = _getExifMetadata(tMetaData, pUserID, pInstruction.mImagePPI, tImage.getWidth(), tImage.getHeight()); 

ByteArrayOutputStream tBAOS = new ByteArrayOutputStream(); 

//here we use ImageIO to write out the image into tBAOS (this will be the one we have potentially cropped) 

org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter tRW = new org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter(); 
byte[] tData = tBAOS.toByteArray(); 
tBAOS = new ByteArrayOutputStream(); 
tRW.updateExifMetadataLossless(tData, tBAOS, tOutputSet); 





Once this has run the image held in bytes in tBAOS will be an image with the EXIF correctly set for the artist, but the XResolution and YResolution will be both set to 96 DPI reegardless of any settings I put in the PPI (I hard coded a large value and a small one, and they always come out at 96). 

Am I doing something wrong or does commons imaging not support setting this data? 

Thanks 

Scott 



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DISCLAIMER: This email message and any attachments is for the sole
use of the intended recipient(s) and may contain confidential and
privileged information.  Any unauthorised review, use, disclosure
or distribution is prohibited. If you are not the intended recipient,
please contact the sender by reply email and destroy all copies of
the original message.

The views expressed in this message may not necessarily reflect the
views of Bluestar Software Ltd.

Bluestar Software Ltd, Registered in England
Company Registration No. 03537860, VAT No. 709 2751 29
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~