X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=tim%2Fprune%2Fjpeg%2Fdrew%2FExifTiffHandler.java;fp=tim%2Fprune%2Fjpeg%2Fdrew%2FExifTiffHandler.java;h=a98e720328939c27dcc13666938333200247b602;hp=0000000000000000000000000000000000000000;hb=92dad5df664287acb51728e9ea599f150765d34a;hpb=81843c3d8d0771bf00d0f26034a13aa515465c78 diff --git a/tim/prune/jpeg/drew/ExifTiffHandler.java b/tim/prune/jpeg/drew/ExifTiffHandler.java new file mode 100644 index 0000000..a98e720 --- /dev/null +++ b/tim/prune/jpeg/drew/ExifTiffHandler.java @@ -0,0 +1,171 @@ +/* + * Copyright 2002-2015 Drew Noakes + * + * More information about this project is available at: + * + * https://drewnoakes.com/code/exif/ + * https://github.com/drewnoakes/metadata-extractor + */ +package tim.prune.jpeg.drew; + +import tim.prune.jpeg.JpegData; + +/** + * Implementation of TiffHandler used for handling TIFF tags according to the Exif standard. + * + * @author Drew Noakes https://drewnoakes.com + */ +public class ExifTiffHandler +{ + private JpegData _jpegData = null; + private long _thumbnailOffset = -1L, _thumbnailLength = -1L; + + /** This tag is a pointer to the Exif SubIFD. */ + final int DIR_EXIF_SUB_IFD_OFFSET = 0x8769; + /** This tag is a pointer to the Exif GPS IFD. */ + final int DIR_GPS_INFO_OFFSET = 0x8825; + + private static final int TAG_GPS_LATITUDE_REF = 0x0001; + private static final int TAG_GPS_LATITUDE = 0x0002; + private static final int TAG_GPS_LONGITUDE_REF = 0x0003; + private static final int TAG_GPS_LONGITUDE = 0x0004; + private static final int TAG_GPS_ALTITUDE = 0x0006; + private static final int TAG_GPS_BEARING = 0x0011; + + private static final int TAG_ORIENTATION = 0x0112; + private static final int TAG_THUMBNAIL_OFFSET = 0x0201; + private static final int TAG_THUMBNAIL_LENGTH = 0x0202; + + private static final int TAG_SUB_ORITIME = 0x9003; + private static final int TAG_SUB_DIGITIME = 0x9004; + + + /** + * Constructor + * @param jpegData data object to populate with received results + */ + public ExifTiffHandler(JpegData jpegData) + { + _jpegData = jpegData; + _thumbnailOffset = _thumbnailLength = -1L; + } + + public boolean isTagIfdPointer(int tagType) + { + if (tagType == DIR_EXIF_SUB_IFD_OFFSET) { + return true; + } else if (tagType == DIR_GPS_INFO_OFFSET) { + return true; + } + + return false; + } + + public void completed(final ByteArrayReader reader, final int tiffHeaderOffset) + { + // after the extraction process, if we have the correct tags, we may be able to store thumbnail information + if (_thumbnailOffset >= 0L && _thumbnailLength > 0L) + { + try { + byte[] thumbData = reader.getBytes(tiffHeaderOffset + (int) _thumbnailOffset, (int) _thumbnailLength); + if (thumbData != null) + { + byte[] thumbCopy = new byte[thumbData.length]; + System.arraycopy(thumbData, 0, thumbCopy, 0, thumbData.length); + _jpegData.setThumbnailImage(thumbCopy); + } + } catch (ExifException ex) {} + } + } + + public void setRationalArray(int tagId, Rational[] array) + { + switch (tagId) + { + case TAG_GPS_LATITUDE: + _jpegData.setLatitude(new double[] {array[0].doubleValue(), array[1].doubleValue(), + array[2].convertToPositiveValue()}); + break; + case TAG_GPS_LONGITUDE: + _jpegData.setLongitude(new double[] {array[0].doubleValue(), array[1].doubleValue(), + array[2].convertToPositiveValue()}); + break; + } + } + + public void setRational(int tagId, Rational rational) + { + switch (tagId) + { + case TAG_GPS_ALTITUDE: + _jpegData.setAltitude(rational.intValue()); + return; + case TAG_GPS_BEARING: + _jpegData.setBearing(rational.doubleValue()); + return; + } + // maybe it was an integer passed as a rational? + if (rational.getDenominator() == 1L) { + setIntegerValue(tagId, rational.intValue()); + } + } + + public void setString(int tagId, String string) + { + switch (tagId) + { + case TAG_SUB_ORITIME: + _jpegData.setOriginalTimestamp(string); + break; + case TAG_SUB_DIGITIME: + _jpegData.setDigitizedTimestamp(string); + break; + case TAG_GPS_LATITUDE_REF: + _jpegData.setLatitudeRef(string); + break; + case TAG_GPS_LONGITUDE_REF: + _jpegData.setLongitudeRef(string); + break; + } + } + + public void setIntegerValue(int tagId, int intVal) + { + switch (tagId) + { + case TAG_ORIENTATION: + _jpegData.setOrientationCode(intVal); + break; + case TAG_THUMBNAIL_OFFSET: + _thumbnailOffset = intVal; + break; + case TAG_THUMBNAIL_LENGTH: + _thumbnailLength = intVal; + break; + } + } + + + /** + * Decide, based on the directory id and the tag id, if we want to parse and process it + * @param inDirectoryId + * @param childTagId + * @return true if the tag should be parsed + */ + public boolean isInterestingTag(int inDirectoryId, int childTagId) + { + switch (inDirectoryId) + { + case DIR_GPS_INFO_OFFSET: + return true; + case DIR_EXIF_SUB_IFD_OFFSET: + return childTagId == TAG_SUB_ORITIME + || childTagId == TAG_SUB_DIGITIME; + case 0: + return childTagId == TAG_THUMBNAIL_OFFSET + || childTagId == TAG_THUMBNAIL_LENGTH + || childTagId == TAG_ORIENTATION; + } + return false; + } +}