| 1 | /*
|
|---|
| 2 | * ExifDirectory.java
|
|---|
| 3 | *
|
|---|
| 4 | * This is public domain software - that is, you can do whatever you want
|
|---|
| 5 | * with it, and include it software that is licensed under the GNU or the
|
|---|
| 6 | * BSD license, or whatever other licence you choose, including proprietary
|
|---|
| 7 | * closed source licenses. I do ask that you leave this header in tact.
|
|---|
| 8 | *
|
|---|
| 9 | * If you make modifications to this code that you think would benefit the
|
|---|
| 10 | * wider community, please send me a copy and I'll post it on my site.
|
|---|
| 11 | *
|
|---|
| 12 | * If you make use of this code, I'd appreciate hearing about it.
|
|---|
| 13 | * drew@drewnoakes.com
|
|---|
| 14 | * Latest version of this software kept at
|
|---|
| 15 | * http://drewnoakes.com/
|
|---|
| 16 | *
|
|---|
| 17 | * Created by dnoakes on 25-Nov-2002 20:41:00 using IntelliJ IDEA.
|
|---|
| 18 | */
|
|---|
| 19 | package com.drew.metadata.exif;
|
|---|
| 20 |
|
|---|
| 21 | import com.drew.metadata.Directory;
|
|---|
| 22 | import com.drew.metadata.MetadataException;
|
|---|
| 23 |
|
|---|
| 24 | import java.io.FileOutputStream;
|
|---|
| 25 | import java.io.IOException;
|
|---|
| 26 | import java.util.HashMap;
|
|---|
| 27 |
|
|---|
| 28 | /**
|
|---|
| 29 | *
|
|---|
| 30 | */
|
|---|
| 31 | public class ExifDirectory extends Directory
|
|---|
| 32 | {
|
|---|
| 33 | // TODO do these tags belong in the exif directory?
|
|---|
| 34 | public static final int TAG_SUB_IFDS = 0x014A;
|
|---|
| 35 | public static final int TAG_GPS_INFO = 0x8825;
|
|---|
| 36 |
|
|---|
| 37 | /**
|
|---|
| 38 | * The actual aperture value of lens when the image was taken. Unit is APEX.
|
|---|
| 39 | * To convert this value to ordinary F-number (F-stop), calculate this value's
|
|---|
| 40 | * power of root 2 (=1.4142). For example, if the ApertureValue is '5',
|
|---|
| 41 | * F-number is 1.4142^5 = F5.6.
|
|---|
| 42 | */
|
|---|
| 43 | public static final int TAG_APERTURE = 0x9202;
|
|---|
| 44 | /**
|
|---|
| 45 | * When image format is no compression, this value shows the number of bits
|
|---|
| 46 | * per component for each pixel. Usually this value is '8,8,8'.
|
|---|
| 47 | */
|
|---|
| 48 | public static final int TAG_BITS_PER_SAMPLE = 0x0102;
|
|---|
| 49 | /**
|
|---|
| 50 | * Shows compression method for Thumbnail.
|
|---|
| 51 | * 1 = Uncompressed
|
|---|
| 52 | * 2 = CCITT 1D
|
|---|
| 53 | * 3 = T4/Group 3 Fax
|
|---|
| 54 | * 4 = T6/Group 4 Fax
|
|---|
| 55 | * 5 = LZW
|
|---|
| 56 | * 6 = JPEG (old-style)
|
|---|
| 57 | * 7 = JPEG
|
|---|
| 58 | * 8 = Adobe Deflate
|
|---|
| 59 | * 9 = JBIG B&W
|
|---|
| 60 | * 10 = JBIG Color
|
|---|
| 61 | * 32766 = Next
|
|---|
| 62 | * 32771 = CCIRLEW
|
|---|
| 63 | * 32773 = PackBits
|
|---|
| 64 | * 32809 = Thunderscan
|
|---|
| 65 | * 32895 = IT8CTPAD
|
|---|
| 66 | * 32896 = IT8LW
|
|---|
| 67 | * 32897 = IT8MP
|
|---|
| 68 | * 32898 = IT8BL
|
|---|
| 69 | * 32908 = PixarFilm
|
|---|
| 70 | * 32909 = PixarLog
|
|---|
| 71 | * 32946 = Deflate
|
|---|
| 72 | * 32947 = DCS
|
|---|
| 73 | * 34661 = JBIG
|
|---|
| 74 | * 34676 = SGILog
|
|---|
| 75 | * 34677 = SGILog24
|
|---|
| 76 | * 34712 = JPEG 2000
|
|---|
| 77 | * 34713 = Nikon NEF Compressed
|
|---|
| 78 | */
|
|---|
| 79 | public static final int TAG_COMPRESSION = 0x0103;
|
|---|
| 80 | public static final int COMPRESSION_NONE = 1;
|
|---|
| 81 | public static final int COMPRESSION_JPEG = 6;
|
|---|
| 82 |
|
|---|
| 83 | /**
|
|---|
| 84 | * Shows the color space of the image data components.
|
|---|
| 85 | * 0 = WhiteIsZero
|
|---|
| 86 | * 1 = BlackIsZero
|
|---|
| 87 | * 2 = RGB
|
|---|
| 88 | * 3 = RGB Palette
|
|---|
| 89 | * 4 = Transparency Mask
|
|---|
| 90 | * 5 = CMYK
|
|---|
| 91 | * 6 = YCbCr
|
|---|
| 92 | * 8 = CIELab
|
|---|
| 93 | * 9 = ICCLab
|
|---|
| 94 | * 10 = ITULab
|
|---|
| 95 | * 32803 = Color Filter Array
|
|---|
| 96 | * 32844 = Pixar LogL
|
|---|
| 97 | * 32845 = Pixar LogLuv
|
|---|
| 98 | * 34892 = Linear Raw
|
|---|
| 99 | */
|
|---|
| 100 | public static final int TAG_PHOTOMETRIC_INTERPRETATION = 0x0106;
|
|---|
| 101 | /**
|
|---|
| 102 | * 1 = No dithering or halftoning
|
|---|
| 103 | * 2 = Ordered dither or halftone
|
|---|
| 104 | * 3 = Randomized dither
|
|---|
| 105 | */
|
|---|
| 106 | public static final int TAG_THRESHOLDING = 0x0107;
|
|---|
| 107 | public static final int PHOTOMETRIC_INTERPRETATION_MONOCHROME = 1;
|
|---|
| 108 | public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2;
|
|---|
| 109 | public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6;
|
|---|
| 110 |
|
|---|
| 111 | /** The position in the file of raster data. */
|
|---|
| 112 | public static final int TAG_STRIP_OFFSETS = 0x0111;
|
|---|
| 113 | /** Each pixel is composed of this many samples. */
|
|---|
| 114 | public static final int TAG_SAMPLES_PER_PIXEL = 0x0115;
|
|---|
| 115 | /** The raster is codified by a single block of data holding this many rows. */
|
|---|
| 116 | public static final int TAG_ROWS_PER_STRIP = 0x116;
|
|---|
| 117 | /** The size of the raster data in bytes. */
|
|---|
| 118 | public static final int TAG_STRIP_BYTE_COUNTS = 0x0117;
|
|---|
| 119 | public static final int TAG_MIN_SAMPLE_VALUE = 0x0118;
|
|---|
| 120 | public static final int TAG_MAX_SAMPLE_VALUE = 0x0119;
|
|---|
| 121 | /**
|
|---|
| 122 | * When image format is no compression YCbCr, this value shows byte aligns of
|
|---|
| 123 | * YCbCr data. If value is '1', Y/Cb/Cr value is chunky format, contiguous for
|
|---|
| 124 | * each subsampling pixel. If value is '2', Y/Cb/Cr value is separated and
|
|---|
| 125 | * stored to Y plane/Cb plane/Cr plane format.
|
|---|
| 126 | */
|
|---|
| 127 | public static final int TAG_PLANAR_CONFIGURATION = 0x011C;
|
|---|
| 128 | public static final int TAG_YCBCR_SUBSAMPLING = 0x0212;
|
|---|
| 129 | public static final int TAG_IMAGE_DESCRIPTION = 0x010E;
|
|---|
| 130 | public static final int TAG_SOFTWARE = 0x0131;
|
|---|
| 131 | public static final int TAG_DATETIME = 0x0132;
|
|---|
| 132 | public static final int TAG_WHITE_POINT = 0x013E;
|
|---|
| 133 | public static final int TAG_PRIMARY_CHROMATICITIES = 0x013F;
|
|---|
| 134 | public static final int TAG_YCBCR_COEFFICIENTS = 0x0211;
|
|---|
| 135 | public static final int TAG_REFERENCE_BLACK_WHITE = 0x0214;
|
|---|
| 136 | public static final int TAG_COPYRIGHT = 0x8298;
|
|---|
| 137 |
|
|---|
| 138 | /**
|
|---|
| 139 | * The new subfile type tag.
|
|---|
| 140 | * 0 = Full-resolution Image
|
|---|
| 141 | * 1 = Reduced-resolution image
|
|---|
| 142 | * 2 = Single page of multi-page image
|
|---|
| 143 | * 3 = Single page of multi-page reduced-resolution image
|
|---|
| 144 | * 4 = Transparency mask
|
|---|
| 145 | * 5 = Transparency mask of reduced-resolution image
|
|---|
| 146 | * 6 = Transparency mask of multi-page image
|
|---|
| 147 | * 7 = Transparency mask of reduced-resolution multi-page image
|
|---|
| 148 | */
|
|---|
| 149 | public static final int TAG_NEW_SUBFILE_TYPE = 0x00FE;
|
|---|
| 150 | /**
|
|---|
| 151 | * The old subfile type tag.
|
|---|
| 152 | * 1 = Full-resolution image (Main image)
|
|---|
| 153 | * 2 = Reduced-resolution image (Thumbnail)
|
|---|
| 154 | * 3 = Single page of multi-page image
|
|---|
| 155 | */
|
|---|
| 156 | public static final int TAG_SUBFILE_TYPE = 0x00FF;
|
|---|
| 157 | public static final int TAG_TRANSFER_FUNCTION = 0x012D;
|
|---|
| 158 | public static final int TAG_ARTIST = 0x013B;
|
|---|
| 159 | public static final int TAG_PREDICTOR = 0x013D;
|
|---|
| 160 | public static final int TAG_TILE_WIDTH = 0x0142;
|
|---|
| 161 | public static final int TAG_TILE_LENGTH = 0x0143;
|
|---|
| 162 | public static final int TAG_TILE_OFFSETS = 0x0144;
|
|---|
| 163 | public static final int TAG_TILE_BYTE_COUNTS = 0x0145;
|
|---|
| 164 | public static final int TAG_JPEG_TABLES = 0x015B;
|
|---|
| 165 | public static final int TAG_CFA_REPEAT_PATTERN_DIM = 0x828D;
|
|---|
| 166 | /** There are two definitions for CFA pattern, I don't know the difference... */
|
|---|
| 167 | public static final int TAG_CFA_PATTERN_2 = 0x828E;
|
|---|
| 168 | public static final int TAG_BATTERY_LEVEL = 0x828F;
|
|---|
| 169 | public static final int TAG_IPTC_NAA = 0x83BB;
|
|---|
| 170 | public static final int TAG_INTER_COLOR_PROFILE = 0x8773;
|
|---|
| 171 | public static final int TAG_SPECTRAL_SENSITIVITY = 0x8824;
|
|---|
| 172 | public static final int TAG_OECF = 0x8828;
|
|---|
| 173 | public static final int TAG_INTERLACE = 0x8829;
|
|---|
| 174 | public static final int TAG_TIME_ZONE_OFFSET = 0x882A;
|
|---|
| 175 | public static final int TAG_SELF_TIMER_MODE = 0x882B;
|
|---|
| 176 | public static final int TAG_FLASH_ENERGY = 0x920B;
|
|---|
| 177 | public static final int TAG_SPATIAL_FREQ_RESPONSE = 0x920C;
|
|---|
| 178 | public static final int TAG_NOISE = 0x920D;
|
|---|
| 179 | public static final int TAG_IMAGE_NUMBER = 0x9211;
|
|---|
| 180 | public static final int TAG_SECURITY_CLASSIFICATION = 0x9212;
|
|---|
| 181 | public static final int TAG_IMAGE_HISTORY = 0x9213;
|
|---|
| 182 | public static final int TAG_SUBJECT_LOCATION = 0x9214;
|
|---|
| 183 | /** There are two definitions for exposure index, I don't know the difference... */
|
|---|
| 184 | public static final int TAG_EXPOSURE_INDEX_2 = 0x9215;
|
|---|
| 185 | public static final int TAG_TIFF_EP_STANDARD_ID = 0x9216;
|
|---|
| 186 | public static final int TAG_FLASH_ENERGY_2 = 0xA20B;
|
|---|
| 187 | public static final int TAG_SPATIAL_FREQ_RESPONSE_2 = 0xA20C;
|
|---|
| 188 | public static final int TAG_SUBJECT_LOCATION_2 = 0xA214;
|
|---|
| 189 | public static final int TAG_MAKE = 0x010F;
|
|---|
| 190 | public static final int TAG_MODEL = 0x0110;
|
|---|
| 191 | public static final int TAG_ORIENTATION = 0x0112;
|
|---|
| 192 | public static final int TAG_X_RESOLUTION = 0x011A;
|
|---|
| 193 | public static final int TAG_Y_RESOLUTION = 0x011B;
|
|---|
| 194 | public static final int TAG_PAGE_NAME = 0x011D;
|
|---|
| 195 | public static final int TAG_RESOLUTION_UNIT = 0x0128;
|
|---|
| 196 | public static final int TAG_THUMBNAIL_OFFSET = 0x0201;
|
|---|
| 197 | public static final int TAG_THUMBNAIL_LENGTH = 0x0202;
|
|---|
| 198 | public static final int TAG_YCBCR_POSITIONING = 0x0213;
|
|---|
| 199 | /**
|
|---|
| 200 | * Exposure time (reciprocal of shutter speed). Unit is second.
|
|---|
| 201 | */
|
|---|
| 202 | public static final int TAG_EXPOSURE_TIME = 0x829A;
|
|---|
| 203 | /**
|
|---|
| 204 | * The actual F-number(F-stop) of lens when the image was taken.
|
|---|
| 205 | */
|
|---|
| 206 | public static final int TAG_FNUMBER = 0x829D;
|
|---|
| 207 | /**
|
|---|
| 208 | * Exposure program that the camera used when image was taken. '1' means
|
|---|
| 209 | * manual control, '2' program normal, '3' aperture priority, '4' shutter
|
|---|
| 210 | * priority, '5' program creative (slow program), '6' program action
|
|---|
| 211 | * (high-speed program), '7' portrait mode, '8' landscape mode.
|
|---|
| 212 | */
|
|---|
| 213 | public static final int TAG_EXPOSURE_PROGRAM = 0x8822;
|
|---|
| 214 | public static final int TAG_ISO_EQUIVALENT = 0x8827;
|
|---|
| 215 | public static final int TAG_EXIF_VERSION = 0x9000;
|
|---|
| 216 | public static final int TAG_DATETIME_ORIGINAL = 0x9003;
|
|---|
| 217 | public static final int TAG_DATETIME_DIGITIZED = 0x9004;
|
|---|
| 218 | public static final int TAG_COMPONENTS_CONFIGURATION = 0x9101;
|
|---|
| 219 | /**
|
|---|
| 220 | * Average (rough estimate) compression level in JPEG bits per pixel.
|
|---|
| 221 | * */
|
|---|
| 222 | public static final int TAG_COMPRESSION_LEVEL = 0x9102;
|
|---|
| 223 | /**
|
|---|
| 224 | * Shutter speed by APEX value. To convert this value to ordinary 'Shutter Speed';
|
|---|
| 225 | * calculate this value's power of 2, then reciprocal. For example, if the
|
|---|
| 226 | * ShutterSpeedValue is '4', shutter speed is 1/(24)=1/16 second.
|
|---|
| 227 | */
|
|---|
| 228 | public static final int TAG_SHUTTER_SPEED = 0x9201;
|
|---|
| 229 | public static final int TAG_BRIGHTNESS_VALUE = 0x9203;
|
|---|
| 230 | public static final int TAG_EXPOSURE_BIAS = 0x9204;
|
|---|
| 231 | /**
|
|---|
| 232 | * Maximum aperture value of lens. You can convert to F-number by calculating
|
|---|
| 233 | * power of root 2 (same process of ApertureValue:0x9202).
|
|---|
| 234 | * The actual aperture value of lens when the image was taken. To convert this
|
|---|
| 235 | * value to ordinary f-number(f-stop), calculate the value's power of root 2
|
|---|
| 236 | * (=1.4142). For example, if the ApertureValue is '5', f-number is 1.41425^5 = F5.6.
|
|---|
| 237 | */
|
|---|
| 238 | public static final int TAG_MAX_APERTURE = 0x9205;
|
|---|
| 239 | /**
|
|---|
| 240 | * Indicates the distance the autofocus camera is focused to. Tends to be less accurate as distance increases.
|
|---|
| 241 | */
|
|---|
| 242 | public static final int TAG_SUBJECT_DISTANCE = 0x9206;
|
|---|
| 243 | /**
|
|---|
| 244 | * Exposure metering method. '0' means unknown, '1' average, '2' center
|
|---|
| 245 | * weighted average, '3' spot, '4' multi-spot, '5' multi-segment, '6' partial,
|
|---|
| 246 | * '255' other.
|
|---|
| 247 | */
|
|---|
| 248 | public static final int TAG_METERING_MODE = 0x9207;
|
|---|
| 249 |
|
|---|
| 250 | public static final int TAG_LIGHT_SOURCE = 0x9208;
|
|---|
| 251 | /**
|
|---|
| 252 | * White balance (aka light source). '0' means unknown, '1' daylight,
|
|---|
| 253 | * '2' fluorescent, '3' tungsten, '10' flash, '17' standard light A,
|
|---|
| 254 | * '18' standard light B, '19' standard light C, '20' D55, '21' D65,
|
|---|
| 255 | * '22' D75, '255' other.
|
|---|
| 256 | */
|
|---|
| 257 | public static final int TAG_WHITE_BALANCE = 0x9208;
|
|---|
| 258 | /**
|
|---|
| 259 | * 0x0 = 0000000 = No Flash
|
|---|
| 260 | * 0x1 = 0000001 = Fired
|
|---|
| 261 | * 0x5 = 0000101 = Fired, Return not detected
|
|---|
| 262 | * 0x7 = 0000111 = Fired, Return detected
|
|---|
| 263 | * 0x9 = 0001001 = On
|
|---|
| 264 | * 0xd = 0001101 = On, Return not detected
|
|---|
| 265 | * 0xf = 0001111 = On, Return detected
|
|---|
| 266 | * 0x10 = 0010000 = Off
|
|---|
| 267 | * 0x18 = 0011000 = Auto, Did not fire
|
|---|
| 268 | * 0x19 = 0011001 = Auto, Fired
|
|---|
| 269 | * 0x1d = 0011101 = Auto, Fired, Return not detected
|
|---|
| 270 | * 0x1f = 0011111 = Auto, Fired, Return detected
|
|---|
| 271 | * 0x20 = 0100000 = No flash function
|
|---|
| 272 | * 0x41 = 1000001 = Fired, Red-eye reduction
|
|---|
| 273 | * 0x45 = 1000101 = Fired, Red-eye reduction, Return not detected
|
|---|
| 274 | * 0x47 = 1000111 = Fired, Red-eye reduction, Return detected
|
|---|
| 275 | * 0x49 = 1001001 = On, Red-eye reduction
|
|---|
| 276 | * 0x4d = 1001101 = On, Red-eye reduction, Return not detected
|
|---|
| 277 | * 0x4f = 1001111 = On, Red-eye reduction, Return detected
|
|---|
| 278 | * 0x59 = 1011001 = Auto, Fired, Red-eye reduction
|
|---|
| 279 | * 0x5d = 1011101 = Auto, Fired, Red-eye reduction, Return not detected
|
|---|
| 280 | * 0x5f = 1011111 = Auto, Fired, Red-eye reduction, Return detected
|
|---|
| 281 | * 6543210 (positions)
|
|---|
| 282 | *
|
|---|
| 283 | * This is a bitmask.
|
|---|
| 284 | * 0 = flash fired
|
|---|
| 285 | * 1 = return detected
|
|---|
| 286 | * 2 = return able to be detected
|
|---|
| 287 | * 3 = unknown
|
|---|
| 288 | * 4 = auto used
|
|---|
| 289 | * 5 = unknown
|
|---|
| 290 | * 6 = red eye reduction used
|
|---|
| 291 | */
|
|---|
| 292 | public static final int TAG_FLASH = 0x9209;
|
|---|
| 293 | /**
|
|---|
| 294 | * Focal length of lens used to take image. Unit is millimeter.
|
|---|
| 295 | * Nice digital cameras actually save the focal length as a function of how far they are zoomed in.
|
|---|
| 296 | */
|
|---|
| 297 | public static final int TAG_FOCAL_LENGTH = 0x920A;
|
|---|
| 298 | public static final int TAG_USER_COMMENT = 0x9286;
|
|---|
| 299 | public static final int TAG_SUBSECOND_TIME = 0x9290;
|
|---|
| 300 | public static final int TAG_SUBSECOND_TIME_ORIGINAL = 0x9291;
|
|---|
| 301 | public static final int TAG_SUBSECOND_TIME_DIGITIZED = 0x9292;
|
|---|
| 302 | public static final int TAG_FLASHPIX_VERSION = 0xA000;
|
|---|
| 303 | /**
|
|---|
| 304 | * Defines Color Space. DCF image must use sRGB color space so value is
|
|---|
| 305 | * always '1'. If the picture uses the other color space, value is
|
|---|
| 306 | * '65535':Uncalibrated.
|
|---|
| 307 | */
|
|---|
| 308 | public static final int TAG_COLOR_SPACE = 0xA001;
|
|---|
| 309 | public static final int TAG_EXIF_IMAGE_WIDTH = 0xA002;
|
|---|
| 310 | public static final int TAG_EXIF_IMAGE_HEIGHT = 0xA003;
|
|---|
| 311 | public static final int TAG_RELATED_SOUND_FILE = 0xA004;
|
|---|
| 312 | public static final int TAG_FOCAL_PLANE_X_RES = 0xA20E;
|
|---|
| 313 | public static final int TAG_FOCAL_PLANE_Y_RES = 0xA20F;
|
|---|
| 314 | /**
|
|---|
| 315 | * Unit of FocalPlaneXResoluton/FocalPlaneYResolution. '1' means no-unit,
|
|---|
| 316 | * '2' inch, '3' centimeter.
|
|---|
| 317 | *
|
|---|
| 318 | * Note: Some of Fujifilm's digicam(e.g.FX2700,FX2900,Finepix4700Z/40i etc)
|
|---|
| 319 | * uses value '3' so it must be 'centimeter', but it seems that they use a
|
|---|
| 320 | * '8.3mm?'(1/3in.?) to their ResolutionUnit. Fuji's BUG? Finepix4900Z has
|
|---|
| 321 | * been changed to use value '2' but it doesn't match to actual value also.
|
|---|
| 322 | */
|
|---|
| 323 | public static final int TAG_FOCAL_PLANE_UNIT = 0xA210;
|
|---|
| 324 | public static final int TAG_EXPOSURE_INDEX = 0xA215;
|
|---|
| 325 | public static final int TAG_SENSING_METHOD = 0xA217;
|
|---|
| 326 | public static final int TAG_FILE_SOURCE = 0xA300;
|
|---|
| 327 | public static final int TAG_SCENE_TYPE = 0xA301;
|
|---|
| 328 | public static final int TAG_CFA_PATTERN = 0xA302;
|
|---|
| 329 |
|
|---|
| 330 | // these tags new with Exif 2.2 (?) [A401 - A4
|
|---|
| 331 | /**
|
|---|
| 332 | * This tag indicates the use of special processing on image data, such as rendering
|
|---|
| 333 | * geared to output. When special processing is performed, the reader is expected to
|
|---|
| 334 | * disable or minimize any further processing.
|
|---|
| 335 | * Tag = 41985 (A401.H)
|
|---|
| 336 | * Type = SHORT
|
|---|
| 337 | * Count = 1
|
|---|
| 338 | * Default = 0
|
|---|
| 339 | * 0 = Normal process
|
|---|
| 340 | * 1 = Custom process
|
|---|
| 341 | * Other = reserved
|
|---|
| 342 | */
|
|---|
| 343 | public static final int TAG_CUSTOM_RENDERED = 0xA401;
|
|---|
| 344 |
|
|---|
| 345 | /**
|
|---|
| 346 | * This tag indicates the exposure mode set when the image was shot. In auto-bracketing
|
|---|
| 347 | * mode, the camera shoots a series of frames of the same scene at different exposure settings.
|
|---|
| 348 | * Tag = 41986 (A402.H)
|
|---|
| 349 | * Type = SHORT
|
|---|
| 350 | * Count = 1
|
|---|
| 351 | * Default = none
|
|---|
| 352 | * 0 = Auto exposure
|
|---|
| 353 | * 1 = Manual exposure
|
|---|
| 354 | * 2 = Auto bracket
|
|---|
| 355 | * Other = reserved
|
|---|
| 356 | */
|
|---|
| 357 | public static final int TAG_EXPOSURE_MODE = 0xA402;
|
|---|
| 358 |
|
|---|
| 359 | /**
|
|---|
| 360 | * This tag indicates the white balance mode set when the image was shot.
|
|---|
| 361 | * Tag = 41987 (A403.H)
|
|---|
| 362 | * Type = SHORT
|
|---|
| 363 | * Count = 1
|
|---|
| 364 | * Default = none
|
|---|
| 365 | * 0 = Auto white balance
|
|---|
| 366 | * 1 = Manual white balance
|
|---|
| 367 | * Other = reserved
|
|---|
| 368 | */
|
|---|
| 369 | public static final int TAG_WHITE_BALANCE_MODE = 0xA403;
|
|---|
| 370 |
|
|---|
| 371 | /**
|
|---|
| 372 | * This tag indicates the digital zoom ratio when the image was shot. If the
|
|---|
| 373 | * numerator of the recorded value is 0, this indicates that digital zoom was
|
|---|
| 374 | * not used.
|
|---|
| 375 | * Tag = 41988 (A404.H)
|
|---|
| 376 | * Type = RATIONAL
|
|---|
| 377 | * Count = 1
|
|---|
| 378 | * Default = none
|
|---|
| 379 | */
|
|---|
| 380 | public static final int TAG_DIGITAL_ZOOM_RATIO = 0xA404;
|
|---|
| 381 |
|
|---|
| 382 | /**
|
|---|
| 383 | * This tag indicates the equivalent focal length assuming a 35mm film camera,
|
|---|
| 384 | * in mm. A value of 0 means the focal length is unknown. Note that this tag
|
|---|
| 385 | * differs from the FocalLength tag.
|
|---|
| 386 | * Tag = 41989 (A405.H)
|
|---|
| 387 | * Type = SHORT
|
|---|
| 388 | * Count = 1
|
|---|
| 389 | * Default = none
|
|---|
| 390 | */
|
|---|
| 391 | public static final int TAG_35MM_FILM_EQUIV_FOCAL_LENGTH = 0xA405;
|
|---|
| 392 |
|
|---|
| 393 | /**
|
|---|
| 394 | * This tag indicates the type of scene that was shot. It can also be used to
|
|---|
| 395 | * record the mode in which the image was shot. Note that this differs from
|
|---|
| 396 | * the scene type (SceneType) tag.
|
|---|
| 397 | * Tag = 41990 (A406.H)
|
|---|
| 398 | * Type = SHORT
|
|---|
| 399 | * Count = 1
|
|---|
| 400 | * Default = 0
|
|---|
| 401 | * 0 = Standard
|
|---|
| 402 | * 1 = Landscape
|
|---|
| 403 | * 2 = Portrait
|
|---|
| 404 | * 3 = Night scene
|
|---|
| 405 | * Other = reserved
|
|---|
| 406 | */
|
|---|
| 407 | public static final int TAG_SCENE_CAPTURE_TYPE = 0xA406;
|
|---|
| 408 |
|
|---|
| 409 | /**
|
|---|
| 410 | * This tag indicates the degree of overall image gain adjustment.
|
|---|
| 411 | * Tag = 41991 (A407.H)
|
|---|
| 412 | * Type = SHORT
|
|---|
| 413 | * Count = 1
|
|---|
| 414 | * Default = none
|
|---|
| 415 | * 0 = None
|
|---|
| 416 | * 1 = Low gain up
|
|---|
| 417 | * 2 = High gain up
|
|---|
| 418 | * 3 = Low gain down
|
|---|
| 419 | * 4 = High gain down
|
|---|
| 420 | * Other = reserved
|
|---|
| 421 | */
|
|---|
| 422 | public static final int TAG_GAIN_CONTROL = 0xA407;
|
|---|
| 423 |
|
|---|
| 424 | /**
|
|---|
| 425 | * This tag indicates the direction of contrast processing applied by the camera
|
|---|
| 426 | * when the image was shot.
|
|---|
| 427 | * Tag = 41992 (A408.H)
|
|---|
| 428 | * Type = SHORT
|
|---|
| 429 | * Count = 1
|
|---|
| 430 | * Default = 0
|
|---|
| 431 | * 0 = Normal
|
|---|
| 432 | * 1 = Soft
|
|---|
| 433 | * 2 = Hard
|
|---|
| 434 | * Other = reserved
|
|---|
| 435 | */
|
|---|
| 436 | public static final int TAG_CONTRAST = 0xA408;
|
|---|
| 437 |
|
|---|
| 438 | /**
|
|---|
| 439 | * This tag indicates the direction of saturation processing applied by the camera
|
|---|
| 440 | * when the image was shot.
|
|---|
| 441 | * Tag = 41993 (A409.H)
|
|---|
| 442 | * Type = SHORT
|
|---|
| 443 | * Count = 1
|
|---|
| 444 | * Default = 0
|
|---|
| 445 | * 0 = Normal
|
|---|
| 446 | * 1 = Low saturation
|
|---|
| 447 | * 2 = High saturation
|
|---|
| 448 | * Other = reserved
|
|---|
| 449 | */
|
|---|
| 450 | public static final int TAG_SATURATION = 0xA409;
|
|---|
| 451 |
|
|---|
| 452 | /**
|
|---|
| 453 | * This tag indicates the direction of sharpness processing applied by the camera
|
|---|
| 454 | * when the image was shot.
|
|---|
| 455 | * Tag = 41994 (A40A.H)
|
|---|
| 456 | * Type = SHORT
|
|---|
| 457 | * Count = 1
|
|---|
| 458 | * Default = 0
|
|---|
| 459 | * 0 = Normal
|
|---|
| 460 | * 1 = Soft
|
|---|
| 461 | * 2 = Hard
|
|---|
| 462 | * Other = reserved
|
|---|
| 463 | */
|
|---|
| 464 | public static final int TAG_SHARPNESS = 0xA40A;
|
|---|
| 465 |
|
|---|
| 466 | // TODO support this tag (I haven't seen a camera's actual implementation of this yet)
|
|---|
| 467 |
|
|---|
| 468 | /**
|
|---|
| 469 | * This tag indicates information on the picture-taking conditions of a particular
|
|---|
| 470 | * camera model. The tag is used only to indicate the picture-taking conditions in
|
|---|
| 471 | * the reader.
|
|---|
| 472 | * Tag = 41995 (A40B.H)
|
|---|
| 473 | * Type = UNDEFINED
|
|---|
| 474 | * Count = Any
|
|---|
| 475 | * Default = none
|
|---|
| 476 | *
|
|---|
| 477 | * The information is recorded in the format shown below. The data is recorded
|
|---|
| 478 | * in Unicode using SHORT type for the number of display rows and columns and
|
|---|
| 479 | * UNDEFINED type for the camera settings. The Unicode (UCS-2) string including
|
|---|
| 480 | * Signature is NULL terminated. The specifics of the Unicode string are as given
|
|---|
| 481 | * in ISO/IEC 10464-1.
|
|---|
| 482 | *
|
|---|
| 483 | * Length Type Meaning
|
|---|
| 484 | * ------+-----------+------------------
|
|---|
| 485 | * 2 SHORT Display columns
|
|---|
| 486 | * 2 SHORT Display rows
|
|---|
| 487 | * Any UNDEFINED Camera setting-1
|
|---|
| 488 | * Any UNDEFINED Camera setting-2
|
|---|
| 489 | * : : :
|
|---|
| 490 | * Any UNDEFINED Camera setting-n
|
|---|
| 491 | */
|
|---|
| 492 | public static final int TAG_DEVICE_SETTING_DESCRIPTION = 0xA40B;
|
|---|
| 493 |
|
|---|
| 494 | /**
|
|---|
| 495 | * This tag indicates the distance to the subject.
|
|---|
| 496 | * Tag = 41996 (A40C.H)
|
|---|
| 497 | * Type = SHORT
|
|---|
| 498 | * Count = 1
|
|---|
| 499 | * Default = none
|
|---|
| 500 | * 0 = unknown
|
|---|
| 501 | * 1 = Macro
|
|---|
| 502 | * 2 = Close view
|
|---|
| 503 | * 3 = Distant view
|
|---|
| 504 | * Other = reserved
|
|---|
| 505 | */
|
|---|
| 506 | public static final int TAG_SUBJECT_DISTANCE_RANGE = 0xA40C;
|
|---|
| 507 |
|
|---|
| 508 | /**
|
|---|
| 509 | * The image title, as used by Windows XP.
|
|---|
| 510 | */
|
|---|
| 511 | public static final int TAG_WIN_TITLE = 0x9C9B;
|
|---|
| 512 |
|
|---|
| 513 | /**
|
|---|
| 514 | * The image comment, as used by Windows XP.
|
|---|
| 515 | */
|
|---|
| 516 | public static final int TAG_WIN_COMMENT = 0x9C9C;
|
|---|
| 517 |
|
|---|
| 518 | /**
|
|---|
| 519 | * The image author, as used by Windows XP (called Artist in the Windows shell).
|
|---|
| 520 | */
|
|---|
| 521 | public static final int TAG_WIN_AUTHOR = 0x9C9D;
|
|---|
| 522 |
|
|---|
| 523 | /**
|
|---|
| 524 | * The image keywords, as used by Windows XP.
|
|---|
| 525 | */
|
|---|
| 526 | public static final int TAG_WIN_KEYWORDS = 0x9C9E;
|
|---|
| 527 |
|
|---|
| 528 | /**
|
|---|
| 529 | * The image subject, as used by Windows XP.
|
|---|
| 530 | */
|
|---|
| 531 | public static final int TAG_WIN_SUBJECT = 0x9C9F;
|
|---|
| 532 |
|
|---|
| 533 | /**
|
|---|
| 534 | * This tag indicates an identifier assigned uniquely to each image. It is
|
|---|
| 535 | * recorded as an ASCII string equivalent to hexadecimal notation and 128-bit
|
|---|
| 536 | * fixed length.
|
|---|
| 537 | * Tag = 42016 (A420.H)
|
|---|
| 538 | * Type = ASCII
|
|---|
| 539 | * Count = 33
|
|---|
| 540 | * Default = none
|
|---|
| 541 | */
|
|---|
| 542 | public static final int TAG_IMAGE_UNIQUE_ID = 0xA420;
|
|---|
| 543 |
|
|---|
| 544 | public static final int TAG_THUMBNAIL_IMAGE_WIDTH = 0x0100;
|
|---|
| 545 | public static final int TAG_THUMBNAIL_IMAGE_HEIGHT = 0x0101;
|
|---|
| 546 | public static final int TAG_THUMBNAIL_DATA = 0xF001;
|
|---|
| 547 |
|
|---|
| 548 | /**
|
|---|
| 549 | * 1 = Normal
|
|---|
| 550 | * 2 = Reversed
|
|---|
| 551 | */
|
|---|
| 552 | public static final int TAG_FILL_ORDER = 0x010A;
|
|---|
| 553 | public static final int TAG_DOCUMENT_NAME = 0x010D;
|
|---|
| 554 |
|
|---|
| 555 | protected static final HashMap tagNameMap = new HashMap();
|
|---|
| 556 |
|
|---|
| 557 | static
|
|---|
| 558 | {
|
|---|
| 559 | tagNameMap.put(new Integer(TAG_FILL_ORDER), "Fill Order");
|
|---|
| 560 | tagNameMap.put(new Integer(TAG_DOCUMENT_NAME), "Document Name");
|
|---|
| 561 | tagNameMap.put(new Integer(0x1000), "Related Image File Format");
|
|---|
| 562 | tagNameMap.put(new Integer(0x1001), "Related Image Width");
|
|---|
| 563 | tagNameMap.put(new Integer(0x1002), "Related Image Length");
|
|---|
| 564 | tagNameMap.put(new Integer(0x0156), "Transfer Range");
|
|---|
| 565 | tagNameMap.put(new Integer(0x0200), "JPEG Proc");
|
|---|
| 566 | tagNameMap.put(new Integer(0x8769), "Exif Offset");
|
|---|
| 567 | tagNameMap.put(new Integer(TAG_COMPRESSION_LEVEL), "Compressed Bits Per Pixel");
|
|---|
| 568 | tagNameMap.put(new Integer(0x927C), "Maker Note");
|
|---|
| 569 | tagNameMap.put(new Integer(0xA005), "Interoperability Offset");
|
|---|
| 570 |
|
|---|
| 571 | tagNameMap.put(new Integer(TAG_NEW_SUBFILE_TYPE), "New Subfile Type");
|
|---|
| 572 | tagNameMap.put(new Integer(TAG_SUBFILE_TYPE), "Subfile Type");
|
|---|
| 573 | tagNameMap.put(new Integer(TAG_THUMBNAIL_IMAGE_WIDTH), "Thumbnail Image Width");
|
|---|
| 574 | tagNameMap.put(new Integer(TAG_THUMBNAIL_IMAGE_HEIGHT), "Thumbnail Image Height");
|
|---|
| 575 | tagNameMap.put(new Integer(TAG_BITS_PER_SAMPLE), "Bits Per Sample");
|
|---|
| 576 | tagNameMap.put(new Integer(TAG_COMPRESSION), "Compression");
|
|---|
| 577 | tagNameMap.put(new Integer(TAG_PHOTOMETRIC_INTERPRETATION), "Photometric Interpretation");
|
|---|
| 578 | tagNameMap.put(new Integer(TAG_THRESHOLDING), "Thresholding");
|
|---|
| 579 | tagNameMap.put(new Integer(TAG_IMAGE_DESCRIPTION), "Image Description");
|
|---|
| 580 | tagNameMap.put(new Integer(TAG_MAKE), "Make");
|
|---|
| 581 | tagNameMap.put(new Integer(TAG_MODEL), "Model");
|
|---|
| 582 | tagNameMap.put(new Integer(TAG_STRIP_OFFSETS), "Strip Offsets");
|
|---|
| 583 | tagNameMap.put(new Integer(TAG_ORIENTATION), "Orientation");
|
|---|
| 584 | tagNameMap.put(new Integer(TAG_SAMPLES_PER_PIXEL), "Samples Per Pixel");
|
|---|
| 585 | tagNameMap.put(new Integer(TAG_ROWS_PER_STRIP), "Rows Per Strip");
|
|---|
| 586 | tagNameMap.put(new Integer(TAG_STRIP_BYTE_COUNTS), "Strip Byte Counts");
|
|---|
| 587 | tagNameMap.put(new Integer(TAG_X_RESOLUTION), "X Resolution");
|
|---|
| 588 | tagNameMap.put(new Integer(TAG_Y_RESOLUTION), "Y Resolution");
|
|---|
| 589 | tagNameMap.put(new Integer(TAG_PAGE_NAME), "Page Name");
|
|---|
| 590 | tagNameMap.put(new Integer(TAG_PLANAR_CONFIGURATION), "Planar Configuration");
|
|---|
| 591 | tagNameMap.put(new Integer(TAG_RESOLUTION_UNIT), "Resolution Unit");
|
|---|
| 592 | tagNameMap.put(new Integer(TAG_TRANSFER_FUNCTION), "Transfer Function");
|
|---|
| 593 | tagNameMap.put(new Integer(TAG_SOFTWARE), "Software");
|
|---|
| 594 | tagNameMap.put(new Integer(TAG_DATETIME), "Date/Time");
|
|---|
| 595 | tagNameMap.put(new Integer(TAG_ARTIST), "Artist");
|
|---|
| 596 | tagNameMap.put(new Integer(TAG_PREDICTOR), "Predictor");
|
|---|
| 597 | tagNameMap.put(new Integer(TAG_WHITE_POINT), "White Point");
|
|---|
| 598 | tagNameMap.put(new Integer(TAG_PRIMARY_CHROMATICITIES), "Primary Chromaticities");
|
|---|
| 599 | tagNameMap.put(new Integer(TAG_TILE_WIDTH), "Tile Width");
|
|---|
| 600 | tagNameMap.put(new Integer(TAG_TILE_LENGTH), "Tile Length");
|
|---|
| 601 | tagNameMap.put(new Integer(TAG_TILE_OFFSETS), "Tile Offsets");
|
|---|
| 602 | tagNameMap.put(new Integer(TAG_TILE_BYTE_COUNTS), "Tile Byte Counts");
|
|---|
| 603 | tagNameMap.put(new Integer(TAG_SUB_IFDS), "Sub IFDs");
|
|---|
| 604 | tagNameMap.put(new Integer(TAG_JPEG_TABLES), "JPEG Tables");
|
|---|
| 605 | tagNameMap.put(new Integer(TAG_THUMBNAIL_OFFSET), "Thumbnail Offset");
|
|---|
| 606 | tagNameMap.put(new Integer(TAG_THUMBNAIL_LENGTH), "Thumbnail Length");
|
|---|
| 607 | tagNameMap.put(new Integer(TAG_THUMBNAIL_DATA), "Thumbnail Data");
|
|---|
| 608 | tagNameMap.put(new Integer(TAG_YCBCR_COEFFICIENTS), "YCbCr Coefficients");
|
|---|
| 609 | tagNameMap.put(new Integer(TAG_YCBCR_SUBSAMPLING), "YCbCr Sub-Sampling");
|
|---|
| 610 | tagNameMap.put(new Integer(TAG_YCBCR_POSITIONING), "YCbCr Positioning");
|
|---|
| 611 | tagNameMap.put(new Integer(TAG_REFERENCE_BLACK_WHITE), "Reference Black/White");
|
|---|
| 612 | tagNameMap.put(new Integer(TAG_CFA_REPEAT_PATTERN_DIM), "CFA Repeat Pattern Dim");
|
|---|
| 613 | tagNameMap.put(new Integer(TAG_CFA_PATTERN_2), "CFA Pattern");
|
|---|
| 614 | tagNameMap.put(new Integer(TAG_BATTERY_LEVEL), "Battery Level");
|
|---|
| 615 | tagNameMap.put(new Integer(TAG_COPYRIGHT), "Copyright");
|
|---|
| 616 | tagNameMap.put(new Integer(TAG_EXPOSURE_TIME), "Exposure Time");
|
|---|
| 617 | tagNameMap.put(new Integer(TAG_FNUMBER), "F-Number");
|
|---|
| 618 | tagNameMap.put(new Integer(TAG_IPTC_NAA), "IPTC/NAA");
|
|---|
| 619 | tagNameMap.put(new Integer(TAG_INTER_COLOR_PROFILE), "Inter Color Profile");
|
|---|
| 620 | tagNameMap.put(new Integer(TAG_EXPOSURE_PROGRAM), "Exposure Program");
|
|---|
| 621 | tagNameMap.put(new Integer(TAG_SPECTRAL_SENSITIVITY), "Spectral Sensitivity");
|
|---|
| 622 | tagNameMap.put(new Integer(TAG_GPS_INFO), "GPS Info");
|
|---|
| 623 | tagNameMap.put(new Integer(TAG_ISO_EQUIVALENT), "ISO Speed Ratings");
|
|---|
| 624 | tagNameMap.put(new Integer(TAG_OECF), "OECF");
|
|---|
| 625 | tagNameMap.put(new Integer(TAG_INTERLACE), "Interlace");
|
|---|
| 626 | tagNameMap.put(new Integer(TAG_TIME_ZONE_OFFSET), "Time Zone Offset");
|
|---|
| 627 | tagNameMap.put(new Integer(TAG_SELF_TIMER_MODE), "Self Timer Mode");
|
|---|
| 628 | tagNameMap.put(new Integer(TAG_EXIF_VERSION), "Exif Version");
|
|---|
| 629 | tagNameMap.put(new Integer(TAG_DATETIME_ORIGINAL), "Date/Time Original");
|
|---|
| 630 | tagNameMap.put(new Integer(TAG_DATETIME_DIGITIZED), "Date/Time Digitized");
|
|---|
| 631 | tagNameMap.put(new Integer(TAG_COMPONENTS_CONFIGURATION), "Components Configuration");
|
|---|
| 632 | tagNameMap.put(new Integer(TAG_SHUTTER_SPEED), "Shutter Speed Value");
|
|---|
| 633 | tagNameMap.put(new Integer(TAG_APERTURE), "Aperture Value");
|
|---|
| 634 | tagNameMap.put(new Integer(TAG_BRIGHTNESS_VALUE), "Brightness Value");
|
|---|
| 635 | tagNameMap.put(new Integer(TAG_EXPOSURE_BIAS), "Exposure Bias Value");
|
|---|
| 636 | tagNameMap.put(new Integer(TAG_MAX_APERTURE), "Max Aperture Value");
|
|---|
| 637 | tagNameMap.put(new Integer(TAG_SUBJECT_DISTANCE), "Subject Distance");
|
|---|
| 638 | tagNameMap.put(new Integer(TAG_METERING_MODE), "Metering Mode");
|
|---|
| 639 | tagNameMap.put(new Integer(TAG_WHITE_BALANCE), "Light Source");
|
|---|
| 640 | tagNameMap.put(new Integer(TAG_FLASH), "Flash");
|
|---|
| 641 | tagNameMap.put(new Integer(TAG_FOCAL_LENGTH), "Focal Length");
|
|---|
| 642 | tagNameMap.put(new Integer(TAG_FLASH_ENERGY), "Flash Energy");
|
|---|
| 643 | tagNameMap.put(new Integer(TAG_SPATIAL_FREQ_RESPONSE), "Spatial Frequency Response");
|
|---|
| 644 | tagNameMap.put(new Integer(TAG_NOISE), "Noise");
|
|---|
| 645 | tagNameMap.put(new Integer(TAG_IMAGE_NUMBER), "Image Number");
|
|---|
| 646 | tagNameMap.put(new Integer(TAG_SECURITY_CLASSIFICATION), "Security Classification");
|
|---|
| 647 | tagNameMap.put(new Integer(TAG_IMAGE_HISTORY), "Image History");
|
|---|
| 648 | tagNameMap.put(new Integer(TAG_SUBJECT_LOCATION), "Subject Location");
|
|---|
| 649 | tagNameMap.put(new Integer(TAG_EXPOSURE_INDEX), "Exposure Index");
|
|---|
| 650 | tagNameMap.put(new Integer(TAG_TIFF_EP_STANDARD_ID), "TIFF/EP Standard ID");
|
|---|
| 651 | tagNameMap.put(new Integer(TAG_USER_COMMENT), "User Comment");
|
|---|
| 652 | tagNameMap.put(new Integer(TAG_SUBSECOND_TIME), "Sub-Sec Time");
|
|---|
| 653 | tagNameMap.put(new Integer(TAG_SUBSECOND_TIME_ORIGINAL), "Sub-Sec Time Original");
|
|---|
| 654 | tagNameMap.put(new Integer(TAG_SUBSECOND_TIME_DIGITIZED), "Sub-Sec Time Digitized");
|
|---|
| 655 | tagNameMap.put(new Integer(TAG_FLASHPIX_VERSION), "FlashPix Version");
|
|---|
| 656 | tagNameMap.put(new Integer(TAG_COLOR_SPACE), "Color Space");
|
|---|
| 657 | tagNameMap.put(new Integer(TAG_EXIF_IMAGE_WIDTH), "Exif Image Width");
|
|---|
| 658 | tagNameMap.put(new Integer(TAG_EXIF_IMAGE_HEIGHT), "Exif Image Height");
|
|---|
| 659 | tagNameMap.put(new Integer(TAG_RELATED_SOUND_FILE), "Related Sound File");
|
|---|
| 660 | // 0x920B in TIFF/EP
|
|---|
| 661 | tagNameMap.put(new Integer(TAG_FLASH_ENERGY_2), "Flash Energy");
|
|---|
| 662 | // 0x920C in TIFF/EP
|
|---|
| 663 | tagNameMap.put(new Integer(TAG_SPATIAL_FREQ_RESPONSE_2), "Spatial Frequency Response");
|
|---|
| 664 | // 0x920E in TIFF/EP
|
|---|
| 665 | tagNameMap.put(new Integer(TAG_FOCAL_PLANE_X_RES), "Focal Plane X Resolution");
|
|---|
| 666 | // 0x920F in TIFF/EP
|
|---|
| 667 | tagNameMap.put(new Integer(TAG_FOCAL_PLANE_Y_RES), "Focal Plane Y Resolution");
|
|---|
| 668 | // 0x9210 in TIFF/EP
|
|---|
| 669 | tagNameMap.put(new Integer(TAG_FOCAL_PLANE_UNIT), "Focal Plane Resolution Unit");
|
|---|
| 670 | // 0x9214 in TIFF/EP
|
|---|
| 671 | tagNameMap.put(new Integer(TAG_SUBJECT_LOCATION_2), "Subject Location");
|
|---|
| 672 | // 0x9215 in TIFF/EP
|
|---|
| 673 | tagNameMap.put(new Integer(TAG_EXPOSURE_INDEX_2), "Exposure Index");
|
|---|
| 674 | // 0x9217 in TIFF/EP
|
|---|
| 675 | tagNameMap.put(new Integer(TAG_SENSING_METHOD), "Sensing Method");
|
|---|
| 676 | tagNameMap.put(new Integer(TAG_FILE_SOURCE), "File Source");
|
|---|
| 677 | tagNameMap.put(new Integer(TAG_SCENE_TYPE), "Scene Type");
|
|---|
| 678 | tagNameMap.put(new Integer(TAG_CFA_PATTERN), "CFA Pattern");
|
|---|
| 679 |
|
|---|
| 680 | tagNameMap.put(new Integer(TAG_CUSTOM_RENDERED), "Custom Rendered");
|
|---|
| 681 | tagNameMap.put(new Integer(TAG_EXPOSURE_MODE), "Exposure Mode");
|
|---|
| 682 | tagNameMap.put(new Integer(TAG_WHITE_BALANCE_MODE), "White Balance");
|
|---|
| 683 | tagNameMap.put(new Integer(TAG_DIGITAL_ZOOM_RATIO), "Digital Zoom Ratio");
|
|---|
| 684 | tagNameMap.put(new Integer(TAG_35MM_FILM_EQUIV_FOCAL_LENGTH), "Focal Length 35");
|
|---|
| 685 | tagNameMap.put(new Integer(TAG_SCENE_CAPTURE_TYPE), "Scene Capture Type");
|
|---|
| 686 | tagNameMap.put(new Integer(TAG_GAIN_CONTROL), "Gain Control");
|
|---|
| 687 | tagNameMap.put(new Integer(TAG_CONTRAST), "Contrast");
|
|---|
| 688 | tagNameMap.put(new Integer(TAG_SATURATION), "Saturation");
|
|---|
| 689 | tagNameMap.put(new Integer(TAG_SHARPNESS), "Sharpness");
|
|---|
| 690 | tagNameMap.put(new Integer(TAG_DEVICE_SETTING_DESCRIPTION), "Device Setting Description");
|
|---|
| 691 | tagNameMap.put(new Integer(TAG_SUBJECT_DISTANCE_RANGE), "Subject Distance Range");
|
|---|
| 692 |
|
|---|
| 693 | tagNameMap.put(new Integer(TAG_WIN_AUTHOR), "Windows XP Author");
|
|---|
| 694 | tagNameMap.put(new Integer(TAG_WIN_COMMENT), "Windows XP Comment");
|
|---|
| 695 | tagNameMap.put(new Integer(TAG_WIN_KEYWORDS), "Windows XP Keywords");
|
|---|
| 696 | tagNameMap.put(new Integer(TAG_WIN_SUBJECT), "Windows XP Subject");
|
|---|
| 697 | tagNameMap.put(new Integer(TAG_WIN_TITLE), "Windows XP Title");
|
|---|
| 698 |
|
|---|
| 699 | tagNameMap.put(new Integer(TAG_MIN_SAMPLE_VALUE), "Minimum sample value");
|
|---|
| 700 | tagNameMap.put(new Integer(TAG_MAX_SAMPLE_VALUE), "Maximum sample value");
|
|---|
| 701 | }
|
|---|
| 702 |
|
|---|
| 703 | public ExifDirectory()
|
|---|
| 704 | {
|
|---|
| 705 | this.setDescriptor(new ExifDescriptor(this));
|
|---|
| 706 | }
|
|---|
| 707 |
|
|---|
| 708 | public String getName()
|
|---|
| 709 | {
|
|---|
| 710 | return "Exif";
|
|---|
| 711 | }
|
|---|
| 712 |
|
|---|
| 713 | protected HashMap getTagNameMap()
|
|---|
| 714 | {
|
|---|
| 715 | return tagNameMap;
|
|---|
| 716 | }
|
|---|
| 717 |
|
|---|
| 718 | public byte[] getThumbnailData() throws MetadataException
|
|---|
| 719 | {
|
|---|
| 720 | if (!containsThumbnail())
|
|---|
| 721 | return null;
|
|---|
| 722 |
|
|---|
| 723 | return this.getByteArray(ExifDirectory.TAG_THUMBNAIL_DATA);
|
|---|
| 724 | }
|
|---|
| 725 |
|
|---|
| 726 | public void writeThumbnail(String filename) throws MetadataException, IOException
|
|---|
| 727 | {
|
|---|
| 728 | byte[] data = getThumbnailData();
|
|---|
| 729 |
|
|---|
| 730 | if (data==null)
|
|---|
| 731 | throw new MetadataException("No thumbnail data exists.");
|
|---|
| 732 |
|
|---|
| 733 | FileOutputStream stream = null;
|
|---|
| 734 | try {
|
|---|
| 735 | stream = new FileOutputStream(filename);
|
|---|
| 736 | stream.write(data);
|
|---|
| 737 | } finally {
|
|---|
| 738 | if (stream!=null)
|
|---|
| 739 | stream.close();
|
|---|
| 740 | }
|
|---|
| 741 | }
|
|---|
| 742 |
|
|---|
| 743 | /*
|
|---|
| 744 | // This thumbnail extraction code is not complete, and is included to assist anyone who feels like looking into
|
|---|
| 745 | // it. Please share any progress with the original author, and hence the community. Thanks.
|
|---|
| 746 |
|
|---|
| 747 | /**
|
|---|
| 748 | *
|
|---|
| 749 | * @return
|
|---|
| 750 | * @throws MetadataException
|
|---|
| 751 | * /
|
|---|
| 752 | public Image getThumbnailImage() throws MetadataException
|
|---|
| 753 | {
|
|---|
| 754 | if (!containsThumbnail())
|
|---|
| 755 | return null;
|
|---|
| 756 |
|
|---|
| 757 | int compression = 0;
|
|---|
| 758 | try {
|
|---|
| 759 | compression = this.getInt(ExifDirectory.TAG_COMPRESSION);
|
|---|
| 760 | } catch (Throwable e) {
|
|---|
| 761 | this.addError("Unable to determine thumbnail type " + e.getMessage());
|
|---|
| 762 | }
|
|---|
| 763 |
|
|---|
| 764 | final byte[] thumbnailBytes = getThumbnailData();
|
|---|
| 765 |
|
|---|
| 766 | if (compression == ExifDirectory.COMPRESSION_JPEG)
|
|---|
| 767 | {
|
|---|
| 768 | // JPEG Thumbnail
|
|---|
| 769 | // operate directly on thumbnailBytes
|
|---|
| 770 | // try {
|
|---|
| 771 | // int offset = this.getInt(ExifDirectory.TAG_THUMBNAIL_OFFSET);
|
|---|
| 772 | // int length = this.getInt(ExifDirectory.TAG_THUMBNAIL_LENGTH);
|
|---|
| 773 | // byte[] result = new byte[length];
|
|---|
| 774 | // for (int i = 0; i<result.length; i++) {
|
|---|
| 775 | // result[i] = _data[tiffHeaderOffset + offset + i];
|
|---|
| 776 | // }
|
|---|
| 777 | // this.setByteArray(ExifDirectory.TAG_THUMBNAIL_DATA, result);
|
|---|
| 778 | // } catch (Throwable e) {
|
|---|
| 779 | // this.addError("Unable to extract thumbnail: " + e.getMessage());
|
|---|
| 780 | // }
|
|---|
| 781 | // TODO decode the JPEG bytes as an image
|
|---|
| 782 | return null; //new Image();
|
|---|
| 783 | }
|
|---|
| 784 | else if (compression == ExifDirectory.COMPRESSION_NONE)
|
|---|
| 785 | {
|
|---|
| 786 | // uncompressed thumbnail (raw RGB data)
|
|---|
| 787 | if (!this.containsTag(ExifDirectory.TAG_PHOTOMETRIC_INTERPRETATION))
|
|---|
| 788 | return null;
|
|---|
| 789 |
|
|---|
| 790 | try
|
|---|
| 791 | {
|
|---|
| 792 | // If the image is RGB format, then convert it to a bitmap
|
|---|
| 793 | final int photometricInterpretation = this.getInt(ExifDirectory.TAG_PHOTOMETRIC_INTERPRETATION);
|
|---|
| 794 | if (photometricInterpretation == ExifDirectory.PHOTOMETRIC_INTERPRETATION_RGB)
|
|---|
| 795 | {
|
|---|
| 796 | // RGB
|
|---|
| 797 | Image image = createImageFromRawRgb(thumbnailBytes);
|
|---|
| 798 | return image;
|
|---|
| 799 | }
|
|---|
| 800 | else if (photometricInterpretation == ExifDirectory.PHOTOMETRIC_INTERPRETATION_YCBCR)
|
|---|
| 801 | {
|
|---|
| 802 | // YCbCr
|
|---|
| 803 | Image image = createImageFromRawYCbCr(thumbnailBytes);
|
|---|
| 804 | return image;
|
|---|
| 805 | }
|
|---|
| 806 | else if (photometricInterpretation == ExifDirectory.PHOTOMETRIC_INTERPRETATION_MONOCHROME)
|
|---|
| 807 | {
|
|---|
| 808 | // Monochrome
|
|---|
| 809 | // TODO
|
|---|
| 810 | return null;
|
|---|
| 811 | }
|
|---|
| 812 | } catch (Throwable e) {
|
|---|
| 813 | this.addError("Unable to extract thumbnail: " + e.getMessage());
|
|---|
| 814 | }
|
|---|
| 815 | }
|
|---|
| 816 | return null;
|
|---|
| 817 | }
|
|---|
| 818 |
|
|---|
| 819 | /**
|
|---|
| 820 | * Handle the YCbCr thumbnail encoding used by Ricoh RDC4200/4300, Fuji DS-7/300 and DX-5/7/9 cameras.
|
|---|
| 821 | *
|
|---|
| 822 | * At DX-5/7/9, YCbCrSubsampling(0x0212) has values of '2,1', PlanarConfiguration(0x011c) has a value '1'. So the
|
|---|
| 823 | * data align of this image is below.
|
|---|
| 824 | *
|
|---|
| 825 | * Y(0,0),Y(1,0),Cb(0,0),Cr(0,0), Y(2,0),Y(3,0),Cb(2,0),Cr(3.0), Y(4,0),Y(5,0),Cb(4,0),Cr(4,0). . . .
|
|---|
| 826 | *
|
|---|
| 827 | * The numerics in parenthesis are pixel coordinates. DX series' YCbCrCoefficients(0x0211) has values '0.299/0.587/0.114',
|
|---|
| 828 | * ReferenceBlackWhite(0x0214) has values '0,255,128,255,128,255'. Therefore to convert from Y/Cb/Cr to RGB is;
|
|---|
| 829 | *
|
|---|
| 830 | * B(0,0)=(Cb-128)*(2-0.114*2)+Y(0,0)
|
|---|
| 831 | * R(0,0)=(Cr-128)*(2-0.299*2)+Y(0,0)
|
|---|
| 832 | * G(0,0)=(Y(0,0)-0.114*B(0,0)-0.299*R(0,0))/0.587
|
|---|
| 833 | *
|
|---|
| 834 | * Horizontal subsampling is a value '2', so you can calculate B(1,0)/R(1,0)/G(1,0) by using the Y(1,0) and Cr(0,0)/Cb(0,0).
|
|---|
| 835 | * Repeat this conversion by value of ImageWidth(0x0100) and ImageLength(0x0101).
|
|---|
| 836 | *
|
|---|
| 837 | * @param thumbnailBytes
|
|---|
| 838 | * @return
|
|---|
| 839 | * @throws com.drew.metadata.MetadataException
|
|---|
| 840 | * /
|
|---|
| 841 | private Image createImageFromRawYCbCr(byte[] thumbnailBytes) throws MetadataException
|
|---|
| 842 | {
|
|---|
| 843 | /*
|
|---|
| 844 | Y = 0.257R + 0.504G + 0.098B + 16
|
|---|
| 845 | Cb = -0.148R - 0.291G + 0.439B + 128
|
|---|
| 846 | Cr = 0.439R - 0.368G - 0.071B + 128
|
|---|
| 847 |
|
|---|
| 848 | G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128)
|
|---|
| 849 | R = 1.164(Y-16) + 1.596(Cr-128)
|
|---|
| 850 | B = 1.164(Y-16) + 2.018(Cb-128)
|
|---|
| 851 |
|
|---|
| 852 | R, G and B range from 0 to 255.
|
|---|
| 853 | Y ranges from 16 to 235.
|
|---|
| 854 | Cb and Cr range from 16 to 240.
|
|---|
| 855 |
|
|---|
| 856 | http://www.faqs.org/faqs/graphics/colorspace-faq/
|
|---|
| 857 | * /
|
|---|
| 858 |
|
|---|
| 859 | int length = thumbnailBytes.length; // this.getInt(ExifDirectory.TAG_STRIP_BYTE_COUNTS);
|
|---|
| 860 | final int imageWidth = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);
|
|---|
| 861 | final int imageHeight = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);
|
|---|
| 862 | // final int headerLength = 54;
|
|---|
| 863 | // byte[] result = new byte[length + headerLength];
|
|---|
| 864 | // // Add a windows BMP header described:
|
|---|
| 865 | // // http://www.onicos.com/staff/iz/formats/bmp.html
|
|---|
| 866 | // result[0] = 'B';
|
|---|
| 867 | // result[1] = 'M'; // File Type identifier
|
|---|
| 868 | // result[3] = (byte)(result.length / 256);
|
|---|
| 869 | // result[2] = (byte)result.length;
|
|---|
| 870 | // result[10] = (byte)headerLength;
|
|---|
| 871 | // result[14] = 40; // MS Windows BMP header
|
|---|
| 872 | // result[18] = (byte)imageWidth;
|
|---|
| 873 | // result[22] = (byte)imageHeight;
|
|---|
| 874 | // result[26] = 1; // 1 Plane
|
|---|
| 875 | // result[28] = 24; // Colour depth
|
|---|
| 876 | // result[34] = (byte)length;
|
|---|
| 877 | // result[35] = (byte)(length / 256);
|
|---|
| 878 |
|
|---|
| 879 | final BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
|
|---|
| 880 |
|
|---|
| 881 | // order is YCbCr and image is upside down, bitmaps are BGR
|
|---|
| 882 | //// for (int i = headerLength, dataOffset = length; i<result.length; i += 3, dataOffset -= 3)
|
|---|
| 883 | // {
|
|---|
| 884 | // final int y = thumbnailBytes[dataOffset - 2] & 0xFF;
|
|---|
| 885 | // final int cb = thumbnailBytes[dataOffset - 1] & 0xFF;
|
|---|
| 886 | // final int cr = thumbnailBytes[dataOffset] & 0xFF;
|
|---|
| 887 | // if (y<16 || y>235 || cb<16 || cb>240 || cr<16 || cr>240)
|
|---|
| 888 | // "".toString();
|
|---|
| 889 | //
|
|---|
| 890 | // int g = (int)(1.164*(y-16) - 0.391*(cb-128) - 0.813*(cr-128));
|
|---|
| 891 | // int r = (int)(1.164*(y-16) + 1.596*(cr-128));
|
|---|
| 892 | // int b = (int)(1.164*(y-16) + 2.018*(cb-128));
|
|---|
| 893 | //
|
|---|
| 894 | //// result[i] = (byte)b;
|
|---|
| 895 | //// result[i + 1] = (byte)g;
|
|---|
| 896 | //// result[i + 2] = (byte)r;
|
|---|
| 897 | //
|
|---|
| 898 | // // TODO compose the image here
|
|---|
| 899 | // image.setRGB(1, 2, 3);
|
|---|
| 900 | // }
|
|---|
| 901 |
|
|---|
| 902 | return image;
|
|---|
| 903 | }
|
|---|
| 904 |
|
|---|
| 905 | /**
|
|---|
| 906 | * Creates a thumbnail image in (Windows) BMP format from raw RGB data.
|
|---|
| 907 | * @param thumbnailBytes
|
|---|
| 908 | * @return
|
|---|
| 909 | * @throws com.drew.metadata.MetadataException
|
|---|
| 910 | * /
|
|---|
| 911 | private Image createImageFromRawRgb(byte[] thumbnailBytes) throws MetadataException
|
|---|
| 912 | {
|
|---|
| 913 | final int length = thumbnailBytes.length; // this.getInt(ExifDirectory.TAG_STRIP_BYTE_COUNTS);
|
|---|
| 914 | final int imageWidth = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_WIDTH);
|
|---|
| 915 | final int imageHeight = this.getInt(ExifDirectory.TAG_THUMBNAIL_IMAGE_HEIGHT);
|
|---|
| 916 | // final int headerlength = 54;
|
|---|
| 917 | // final byte[] result = new byte[length + headerlength];
|
|---|
| 918 | // // Add a windows BMP header described:
|
|---|
| 919 | // // http://www.onicos.com/staff/iz/formats/bmp.html
|
|---|
| 920 | // result[0] = 'B';
|
|---|
| 921 | // result[1] = 'M'; // File Type identifier
|
|---|
| 922 | // result[3] = (byte)(result.length / 256);
|
|---|
| 923 | // result[2] = (byte)result.length;
|
|---|
| 924 | // result[10] = (byte)headerlength;
|
|---|
| 925 | // result[14] = 40; // MS Windows BMP header
|
|---|
| 926 | // result[18] = (byte)imageWidth;
|
|---|
| 927 | // result[22] = (byte)imageHeight;
|
|---|
| 928 | // result[26] = 1; // 1 Plane
|
|---|
| 929 | // result[28] = 24; // Colour depth
|
|---|
| 930 | // result[34] = (byte)length;
|
|---|
| 931 | // result[35] = (byte)(length / 256);
|
|---|
| 932 |
|
|---|
| 933 | final BufferedImage image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB);
|
|---|
| 934 |
|
|---|
| 935 | // order is RGB and image is upside down, bitmaps are BGR
|
|---|
| 936 | // for (int i = headerlength, dataOffset = length; i<result.length; i += 3, dataOffset -= 3)
|
|---|
| 937 | // {
|
|---|
| 938 | // byte b = thumbnailBytes[dataOffset - 2];
|
|---|
| 939 | // byte g = thumbnailBytes[dataOffset - 1];
|
|---|
| 940 | // byte r = thumbnailBytes[dataOffset];
|
|---|
| 941 | //
|
|---|
| 942 | // // TODO compose the image here
|
|---|
| 943 | // image.setRGB(1, 2, 3);
|
|---|
| 944 | // }
|
|---|
| 945 |
|
|---|
| 946 | return image;
|
|---|
| 947 | }
|
|---|
| 948 | */
|
|---|
| 949 |
|
|---|
| 950 | public boolean containsThumbnail()
|
|---|
| 951 | {
|
|---|
| 952 | return containsTag(ExifDirectory.TAG_THUMBNAIL_DATA);
|
|---|
| 953 | }
|
|---|
| 954 | }
|
|---|