Introduction
In the previous post, I showed available tags in ExifTagConstants, TiffTagConstants, GpsTagConstants classes.
In this post, I will show you code snippet for extracting metada from jpeg using the tags.
In order to run example code, you should download commons-imaging.jar from here. Somehow the official homepage of Commons Imaging doesn't provide commons-imaging.jar!!
Code
package com.dulesoftware.image; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; import org.apache.commons.imaging.ImageReadException; import org.apache.commons.imaging.Imaging; import org.apache.commons.imaging.common.IImageMetadata; import org.apache.commons.imaging.common.IImageMetadata.IImageMetadataItem; import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata; import org.apache.commons.imaging.formats.tiff.TiffField; import org.apache.commons.imaging.formats.tiff.TiffImageMetadata; import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants; import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants; import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo; import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants; public class PrintExifMetadata { public static void main(String[] args) throws Exception { printMetaData(new File("c:/temp/metadata_eample.jpg")); } public static void printMetaData(final File file) throws ImageReadException, IOException, IllegalArgumentException, IllegalAccessException { // get all metadata stored in EXIF format (ie. from JPEG or TIFF). IImageMetadata metadata = Imaging.getMetadata(file); if (!(metadata instanceof JpegImageMetadata)) { throw new RuntimeException("Only support " + JpegImageMetadata.class.getSimpleName()); } JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata; // JPEG EXIF metadata List<Field> exifTagfields = getTagInfoDefinedInClass(ExifTagConstants.class); System.out.println("=== " + ExifTagConstants.class.getSimpleName() + " ==="); printTagInfos(exifTagfields, jpegMetadata); // Tiff metadata List<Field> tiffTagfields = getTagInfoDefinedInClass(TiffTagConstants.class); System.out.println("=== " + TiffTagConstants.class.getSimpleName() + " ==="); printTagInfos(tiffTagfields, jpegMetadata); // Gps metadata List<Field> gpsTagfields = getTagInfoDefinedInClass(GpsTagConstants.class); System.out.println("=== " + GpsTagConstants.class.getSimpleName() + " ==="); printTagInfos(gpsTagfields, jpegMetadata); // simple interface to EXIF jpegMetadata TiffImageMetadata exifMetadata = jpegMetadata.getExif(); if (null != exifMetadata) { System.out.println("=== ExifMetadata ==="); jpegMetadata.getExif().getAllFields().stream().forEach(System.out::println); System.out.println(); } // All IImageMetadataItem List<IImageMetadataItem> items = jpegMetadata.getItems(); printIImageMetadataItems(items); } private static void printTagInfos(List<Field> tagfields, JpegImageMetadata jpegMetadata) throws IllegalAccessException, IllegalArgumentException, ImageReadException { for (Field field : tagfields) { printTagValue(jpegMetadata, (TagInfo) field.get(null)); } System.out.println(); } private static void printIImageMetadataItems(List<IImageMetadataItem> items) { System.out.println("=== " + IImageMetadataItem.class.getSimpleName() + " in " + JpegImageMetadata.class.getSimpleName() + " ==="); for (IImageMetadataItem item : items) { System.out.println(item); } System.out.println(); } private static void printTagValue(JpegImageMetadata jpegMetadata, TagInfo tagInfo) throws ImageReadException { try { // --------------------------------- // KEY PART: Extract EXIF by TagInfo // if you use findEXIFValueWithExactMatch, // the method throws NullPointerException when the provided tag does not present in the metadata // --------------------------------- TiffField field = jpegMetadata.findEXIFValue(tagInfo); if (field != null) { // get actual stored value in metadata Object value = field.getValue(); System.out.println(tagInfo.name + ": " + toString(value)); } } catch (NullPointerException e) { } } private static List<Field> getTagInfoDefinedInClass(Class<?> clazz) { Field[] declaredFields = clazz.getDeclaredFields(); return Arrays.stream(declaredFields) .filter(field -> TagInfo.class.isAssignableFrom(field.getType()) && Modifier.isStatic(field.getModifiers()) ) .collect(Collectors.toList()); } public static String toString(Object value) { if (value instanceof int[]) { return Arrays.toString((int[]) value); } else if (value instanceof boolean[]) { return Arrays.toString((boolean[]) value); } else if (value instanceof byte[]) { return Arrays.toString((byte[]) value); } else if (value instanceof char[]) { return Arrays.toString((char[]) value); } else if (value instanceof long[]) { return Arrays.toString((long[]) value); } else if (value instanceof short[]) { return Arrays.toString((short[]) value); } else if (value instanceof double[]) { return Arrays.toString((double[]) value); } else if (value instanceof float[]) { return Arrays.toString((float[]) value); } else if (value.getClass().isArray()) { return Arrays.toString((Object[]) value); } else { return value.toString(); } } }
Example Result
I will show you the example execution result of the above code.The test image is below.
The code outputs following result from the test image.
=== ExifTagConstants === Software: Picasa JpgFromRawStart: 4488 OtherImageStart: 4488 JpgFromRawLength: 6780 OtherImageLength: 6780 ExifOffset: 2172 ExifVersion: [48, 50, 50, 48] ExifImageWidth: 1440 ExifImageLength: 1440 ImageUniqueID: 199e785efd74401dff564baa559c2f25 === TiffTagConstants === Compression: 6 ImageDescription: MetaData Example XResolution: 72 YResolution: 72 ResolutionUnit: 2 Software: Picasa === GpsTagConstants === === ExifMetadata === 270 (0x10e: ImageDescription): 'MetaData Example' (17 ASCII) 305 (0x131: Software): 'Picasa' (7 ASCII) 34665 (0x8769: ExifOffset): 2172 (1 Long) 40091 (0x9c9b: XPTitle): 'MetaData Example' (34 Byte) 40092 (0x9c9c: XPComment): 'Test Comments' (28 Byte) 59932 (0xea1c: Padding): 28, -22, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0... (2060) (2060 Undefined) 36864 (0x9000: ExifVersion): 48, 50, 50, 48 (4 Undefined) 40962 (0xa002: ExifImageWidth): 1440 (1 Long) 40963 (0xa003: ExifImageLength): 1440 (1 Long) 42016 (0xa420: ImageUniqueID): '199e785efd74401dff564baa559c2f25' (33 ASCII) 59932 (0xea1c: Padding): 28, -22, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0... (2060) (2060 Undefined) 259 (0x103: Compression): 6 (1 Short) 282 (0x11a: XResolution): 72 (1 Rational) 283 (0x11b: YResolution): 72 (1 Rational) 296 (0x128: ResolutionUnit): 2 (1 Short) 513 (0x201: JpgFromRawStart): 4488 (1 Long) 514 (0x202: JpgFromRawLength): 6780 (1 Long) === IImageMetadataItem in JpegImageMetadata === ImageDescription: 'MetaData Example' Software: 'Picasa' ExifOffset: 2172 XPTitle: 'MetaData Example' XPComment: 'Test Comments' Padding: 28, -22, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0... (2060) ExifVersion: 48, 50, 50, 48 ExifImageWidth: 1440 ExifImageLength: 1440 ImageUniqueID: '199e785efd74401dff564baa559c2f25' Padding: 28, -22, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0... (2060) Compression: 6 XResolution: 72 YResolution: 72 ResolutionUnit: 2 JpgFromRawStart: 4488 JpgFromRawLength: 6780 Caption/Abstract: MetaData Example
コメント