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