Lately for a project of mine I had to alter the EXIF metadata of a JPEG file using Java. After googleing and improvising, I finally wrote a code sample that demonstrates how to change several metadata of a JPEG file, using the Sanselan library from Apache; you can download the jar file and source here. The code below changes Camera Model, Camera Maker and X Resolution, which are included in the Root IFD0 of a JPEG image as well as Digital Zoom Ratio and Image Width, stored in the EXIF Sub IFD.
Notice: You will be able to view the changes from the image properties of your operating system, except from the Image Width. Use this code to view the raw image metadata.
References:
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.apache.sanselan.ImageReadException; import org.apache.sanselan.ImageWriteException; import org.apache.sanselan.Sanselan; import org.apache.sanselan.common.IImageMetadata; import org.apache.sanselan.formats.jpeg.JpegImageMetadata; import org.apache.sanselan.formats.jpeg.exifRewrite.ExifRewriter; import org.apache.sanselan.formats.tiff.TiffImageMetadata; import org.apache.sanselan.formats.tiff.constants.ExifTagConstants; import org.apache.sanselan.formats.tiff.constants.TiffConstants; import org.apache.sanselan.formats.tiff.constants.TiffFieldTypeConstants; import org.apache.sanselan.formats.tiff.write.TiffOutputDirectory; import org.apache.sanselan.formats.tiff.write.TiffOutputField; import org.apache.sanselan.formats.tiff.write.TiffOutputSet; public class TestWriteExif { /** * @param args */ public static void main(String[] args) { File file = new File("test.jpg"); //Change filename here File dst = new File("OutputImage.jpg"); changeMetadata(file, dst); System.out.println("DONE"); } public static void changeMetadata(File file, File output) { IImageMetadata metadata = null; JpegImageMetadata jpegMetadata = null; TiffImageMetadata exif = null; OutputStream os = null; TiffOutputSet outputSet = new TiffOutputSet(); // establish metadata try { metadata = Sanselan.getMetadata(file); } catch (ImageReadException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // establish jpegMedatadata if (metadata != null) { jpegMetadata = (JpegImageMetadata) metadata; } // establish exif if (jpegMetadata != null) { exif = jpegMetadata.getExif(); } // establish outputSet if (exif != null) { try { outputSet = exif.getOutputSet(); } catch (ImageWriteException e) { e.printStackTrace(); } } if (outputSet != null) { //CAMERA MODEL CHANGE //check if field already EXISTS - if so remove TiffOutputField cameraModelPre = outputSet.findField(TiffConstants.EXIF_TAG_MODEL); if (cameraModelPre != null) { outputSet.removeField(TiffConstants.EXIF_TAG_MODEL); } //add field try { String model = "Canon IXUS 115HS"; TiffOutputField cameraModel = new TiffOutputField( ExifTagConstants.EXIF_TAG_MODEL, TiffFieldTypeConstants.FIELD_TYPE_ASCII, model.length(), model.getBytes()); TiffOutputDirectory exifDirectory = outputSet.getOrCreateRootDirectory(); //Since camera model is included in the Root directory //we use the appropriate function exifDirectory.add(cameraModel); } catch (ImageWriteException e) { e.printStackTrace(); } //CAMERA MAKER CHANGE TiffOutputField cameraMakerPre = outputSet.findField(TiffConstants.EXIF_TAG_MAKE); if (cameraMakerPre != null) { outputSet.removeField(TiffConstants.EXIF_TAG_MAKE); } // add field try { String model = "HP"; TiffOutputField cameraMaker = new TiffOutputField( ExifTagConstants.EXIF_TAG_MAKE, TiffFieldTypeConstants.FIELD_TYPE_ASCII, model.length(), model.getBytes()); TiffOutputDirectory exifDirectory = outputSet.getOrCreateRootDirectory(); //Since camera model is included in the Root directory //we use the appropriate function exifDirectory.add(cameraMaker); } catch (ImageWriteException e) { e.printStackTrace(); } // XRESOLUTION CHANGE - Using different method TiffOutputField xresPre = outputSet.findField(TiffConstants.EXIF_TAG_XRESOLUTION); if (xresPre != null) { outputSet.removeField(TiffConstants.EXIF_TAG_XRESOLUTION); } // add field try { TiffOutputField xres = TiffOutputField.create( ExifTagConstants.EXIF_TAG_XRESOLUTION, outputSet.byteOrder, new Double(74)); TiffOutputDirectory exifDirectory = outputSet.getOrCreateRootDirectory(); //Since camera XRes is included in the Root directory //we use the appropriate function exifDirectory.add(xres); } catch (ImageWriteException e) { e.printStackTrace(); } // DIGITAL ZOOM RATIO - Stored in EXIF directory TiffOutputField zoomPre = outputSet.findField(TiffConstants.EXIF_TAG_DIGITAL_ZOOM_RATIO); if (zoomPre != null) { outputSet.removeField(TiffConstants.EXIF_TAG_DIGITAL_ZOOM_RATIO); } // add field try { TiffOutputField zoom = TiffOutputField.create( TiffConstants.EXIF_TAG_DIGITAL_ZOOM_RATIO, outputSet.byteOrder, new Double(61146.071)); TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory(); //Since camera XRes is included in the Root directory //we use the appropriate function exifDirectory.add(zoom); } catch (ImageWriteException e) { e.printStackTrace(); } //EXIF IMAGE WIDTH - Stored in EXIF directory TiffOutputField imageWid = outputSet.findField(TiffConstants.EXIF_TAG_EXIF_IMAGE_WIDTH); if (imageWid != null) { outputSet.removeField(TiffConstants.EXIF_TAG_EXIF_IMAGE_WIDTH); } // add field try { TiffOutputField xres = TiffOutputField.create( TiffConstants.EXIF_TAG_EXIF_IMAGE_WIDTH, outputSet.byteOrder, new Integer(2590)); TiffOutputDirectory exifDirectory = outputSet.getOrCreateExifDirectory(); //Since camera XRes is included in the Root directory //we use the appropriate function exifDirectory.add(xres); } catch (ImageWriteException e) { e.printStackTrace(); } } // create stream using temp file for dst try { os = new FileOutputStream(output); os = new BufferedOutputStream(os); } catch (IOException e) { e.printStackTrace(); } // write/update EXIF metadata to output stream try { new ExifRewriter().updateExifMetadataLossless(file, os, outputSet); } catch (ImageReadException e) { e.printStackTrace(); } catch (ImageWriteException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (os != null) { try { os.close(); } catch (IOException e) { } } } } }
No comments:
Post a Comment