Changeset 6127 in josm for trunk/src/com/drew/metadata/exif
- Timestamp:
- 2013-08-09T18:05:11+02:00 (11 years ago)
- Location:
- trunk/src/com/drew/metadata/exif
- Files:
-
- 12 added
- 5 deleted
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/com/drew/metadata/exif/CanonMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:12:05 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 19 import com.drew. metadata.Directory;20 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 21 25 import com.drew.metadata.TagDescriptor; 22 26 23 27 /** 28 * Provides human-readable string representations of tag values stored in a <code>CanonMakernoteDirectory</code>. 24 29 * 30 * @author Drew Noakes http://drewnoakes.com 25 31 */ 26 public class CanonMakernoteDescriptor extends TagDescriptor 32 public class CanonMakernoteDescriptor extends TagDescriptor<CanonMakernoteDirectory> 27 33 { 28 public CanonMakernoteDescriptor(Directory directory) 34 public CanonMakernoteDescriptor(@NotNull CanonMakernoteDirectory directory) 29 35 { 30 36 super(directory); 31 37 } 32 38 33 public String getDescription(int tagType) throws MetadataException 39 @Nullable 40 public String getDescription(int tagType) 34 41 { 35 42 switch (tagType) { 36 case CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_ACTIVITY: 43 case CanonMakernoteDirectory.TAG_CANON_SERIAL_NUMBER: 44 return getSerialNumberDescription(); 45 case CanonMakernoteDirectory.CameraSettings.TAG_FLASH_ACTIVITY: 37 46 return getFlashActivityDescription(); 38 case CanonMakernoteDirectory. TAG_CANON_STATE1_FOCUS_TYPE:47 case CanonMakernoteDirectory.CameraSettings.TAG_FOCUS_TYPE: 39 48 return getFocusTypeDescription(); 40 case CanonMakernoteDirectory. TAG_CANON_STATE1_DIGITAL_ZOOM:49 case CanonMakernoteDirectory.CameraSettings.TAG_DIGITAL_ZOOM: 41 50 return getDigitalZoomDescription(); 42 case CanonMakernoteDirectory. TAG_CANON_STATE1_QUALITY:51 case CanonMakernoteDirectory.CameraSettings.TAG_QUALITY: 43 52 return getQualityDescription(); 44 case CanonMakernoteDirectory. TAG_CANON_STATE1_MACRO_MODE:53 case CanonMakernoteDirectory.CameraSettings.TAG_MACRO_MODE: 45 54 return getMacroModeDescription(); 46 case CanonMakernoteDirectory. TAG_CANON_STATE1_SELF_TIMER_DELAY:55 case CanonMakernoteDirectory.CameraSettings.TAG_SELF_TIMER_DELAY: 47 56 return getSelfTimerDelayDescription(); 48 case CanonMakernoteDirectory. TAG_CANON_STATE1_FLASH_MODE:57 case CanonMakernoteDirectory.CameraSettings.TAG_FLASH_MODE: 49 58 return getFlashModeDescription(); 50 case CanonMakernoteDirectory. TAG_CANON_STATE1_CONTINUOUS_DRIVE_MODE:59 case CanonMakernoteDirectory.CameraSettings.TAG_CONTINUOUS_DRIVE_MODE: 51 60 return getContinuousDriveModeDescription(); 52 case CanonMakernoteDirectory. TAG_CANON_STATE1_FOCUS_MODE_1:61 case CanonMakernoteDirectory.CameraSettings.TAG_FOCUS_MODE_1: 53 62 return getFocusMode1Description(); 54 case CanonMakernoteDirectory. TAG_CANON_STATE1_IMAGE_SIZE:63 case CanonMakernoteDirectory.CameraSettings.TAG_IMAGE_SIZE: 55 64 return getImageSizeDescription(); 56 case CanonMakernoteDirectory. TAG_CANON_STATE1_EASY_SHOOTING_MODE:65 case CanonMakernoteDirectory.CameraSettings.TAG_EASY_SHOOTING_MODE: 57 66 return getEasyShootingModeDescription(); 58 case CanonMakernoteDirectory. TAG_CANON_STATE1_CONTRAST:67 case CanonMakernoteDirectory.CameraSettings.TAG_CONTRAST: 59 68 return getContrastDescription(); 60 case CanonMakernoteDirectory. TAG_CANON_STATE1_SATURATION:69 case CanonMakernoteDirectory.CameraSettings.TAG_SATURATION: 61 70 return getSaturationDescription(); 62 case CanonMakernoteDirectory. TAG_CANON_STATE1_SHARPNESS:71 case CanonMakernoteDirectory.CameraSettings.TAG_SHARPNESS: 63 72 return getSharpnessDescription(); 64 case CanonMakernoteDirectory. TAG_CANON_STATE1_ISO:73 case CanonMakernoteDirectory.CameraSettings.TAG_ISO: 65 74 return getIsoDescription(); 66 case CanonMakernoteDirectory. TAG_CANON_STATE1_METERING_MODE:75 case CanonMakernoteDirectory.CameraSettings.TAG_METERING_MODE: 67 76 return getMeteringModeDescription(); 68 case CanonMakernoteDirectory. TAG_CANON_STATE1_AF_POINT_SELECTED:77 case CanonMakernoteDirectory.CameraSettings.TAG_AF_POINT_SELECTED: 69 78 return getAfPointSelectedDescription(); 70 case CanonMakernoteDirectory. TAG_CANON_STATE1_EXPOSURE_MODE:79 case CanonMakernoteDirectory.CameraSettings.TAG_EXPOSURE_MODE: 71 80 return getExposureModeDescription(); 72 case CanonMakernoteDirectory. TAG_CANON_STATE1_LONG_FOCAL_LENGTH:81 case CanonMakernoteDirectory.CameraSettings.TAG_LONG_FOCAL_LENGTH: 73 82 return getLongFocalLengthDescription(); 74 case CanonMakernoteDirectory. TAG_CANON_STATE1_SHORT_FOCAL_LENGTH:83 case CanonMakernoteDirectory.CameraSettings.TAG_SHORT_FOCAL_LENGTH: 75 84 return getShortFocalLengthDescription(); 76 case CanonMakernoteDirectory. TAG_CANON_STATE1_FOCAL_UNITS_PER_MM:85 case CanonMakernoteDirectory.CameraSettings.TAG_FOCAL_UNITS_PER_MM: 77 86 return getFocalUnitsPerMillimetreDescription(); 78 case CanonMakernoteDirectory. TAG_CANON_STATE1_FLASH_DETAILS:87 case CanonMakernoteDirectory.CameraSettings.TAG_FLASH_DETAILS: 79 88 return getFlashDetailsDescription(); 80 case CanonMakernoteDirectory. TAG_CANON_STATE1_FOCUS_MODE_2:89 case CanonMakernoteDirectory.CameraSettings.TAG_FOCUS_MODE_2: 81 90 return getFocusMode2Description(); 82 case CanonMakernoteDirectory. TAG_CANON_STATE2_WHITE_BALANCE:91 case CanonMakernoteDirectory.FocalLength.TAG_WHITE_BALANCE: 83 92 return getWhiteBalanceDescription(); 84 case CanonMakernoteDirectory. TAG_CANON_STATE2_AF_POINT_USED:93 case CanonMakernoteDirectory.FocalLength.TAG_AF_POINT_USED: 85 94 return getAfPointUsedDescription(); 86 case CanonMakernoteDirectory. TAG_CANON_STATE2_FLASH_BIAS:95 case CanonMakernoteDirectory.FocalLength.TAG_FLASH_BIAS: 87 96 return getFlashBiasDescription(); 88 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION: 89 return getLongExposureNoiseReductionDescription(); 90 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS: 91 return getShutterAutoExposureLockButtonDescription(); 92 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP: 93 return getMirrorLockupDescription(); 94 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL: 95 return getTvAndAvExposureLevelDescription(); 96 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT: 97 return getAutoFocusAssistLightDescription(); 98 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE: 99 return getShutterSpeedInAvModeDescription(); 100 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_BRACKETTING: 101 return getAutoExposureBrackettingSequenceAndAutoCancellationDescription(); 102 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC: 103 return getShutterCurtainSyncDescription(); 104 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_STOP: 105 return getLensAutoFocusStopButtonDescription(); 106 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION: 107 return getFillFlashReductionDescription(); 108 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN: 109 return getMenuButtonReturnPositionDescription(); 110 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION: 111 return getSetButtonFunctionWhenShootingDescription(); 112 case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING: 113 return getSensorCleaningDescription(); 114 default: 115 return _directory.getString(tagType); 116 } 117 } 118 119 public String getLongExposureNoiseReductionDescription() throws MetadataException 120 { 121 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION)) return null; 122 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION); 97 98 // It turns out that these values are dependent upon the camera model and therefore the below code was 99 // incorrect for some Canon models. This needs to be revisited. 100 101 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION: 102 // return getLongExposureNoiseReductionDescription(); 103 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS: 104 // return getShutterAutoExposureLockButtonDescription(); 105 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP: 106 // return getMirrorLockupDescription(); 107 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL: 108 // return getTvAndAvExposureLevelDescription(); 109 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT: 110 // return getAutoFocusAssistLightDescription(); 111 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE: 112 // return getShutterSpeedInAvModeDescription(); 113 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_BRACKETTING: 114 // return getAutoExposureBrackettingSequenceAndAutoCancellationDescription(); 115 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC: 116 // return getShutterCurtainSyncDescription(); 117 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_STOP: 118 // return getLensAutoFocusStopButtonDescription(); 119 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION: 120 // return getFillFlashReductionDescription(); 121 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN: 122 // return getMenuButtonReturnPositionDescription(); 123 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION: 124 // return getSetButtonFunctionWhenShootingDescription(); 125 // case CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING: 126 // return getSensorCleaningDescription(); 127 default: 128 return super.getDescription(tagType); 129 } 130 } 131 132 @Nullable 133 public String getSerialNumberDescription() 134 { 135 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_SERIAL_NUMBER); 136 if (value==null) 137 return null; 138 return String.format("%04X%05d", (value >> 8) & 0xFF, value & 0xFF); 139 } 140 141 /* 142 @Nullable 143 public String getLongExposureNoiseReductionDescription() 144 { 145 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION); 146 if (value==null) 147 return null; 123 148 switch (value) { 124 149 case 0: return "Off"; … … 127 152 } 128 153 } 129 public String getShutterAutoExposureLockButtonDescription() throws MetadataException 130 { 131 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS)) return null; 132 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS); 154 155 @Nullable 156 public String getShutterAutoExposureLockButtonDescription() 157 { 158 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS); 159 if (value==null) 160 return null; 133 161 switch (value) { 134 162 case 0: return "AF/AE lock"; … … 139 167 } 140 168 } 141 public String getMirrorLockupDescription() throws MetadataException 142 { 143 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP)) return null; 144 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP); 169 170 @Nullable 171 public String getMirrorLockupDescription() 172 { 173 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP); 174 if (value==null) 175 return null; 145 176 switch (value) { 146 177 case 0: return "Disabled"; … … 149 180 } 150 181 } 151 public String getTvAndAvExposureLevelDescription() throws MetadataException 152 { 153 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL)) return null; 154 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL); 182 183 @Nullable 184 public String getTvAndAvExposureLevelDescription() 185 { 186 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL); 187 if (value==null) 188 return null; 155 189 switch (value) { 156 190 case 0: return "1/2 stop"; … … 159 193 } 160 194 } 161 public String getAutoFocusAssistLightDescription() throws MetadataException 162 { 163 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT)) return null; 164 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT); 195 196 @Nullable 197 public String getAutoFocusAssistLightDescription() 198 { 199 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT); 200 if (value==null) 201 return null; 165 202 switch (value) { 166 203 case 0: return "On (Auto)"; … … 169 206 } 170 207 } 171 public String getShutterSpeedInAvModeDescription() throws MetadataException 172 { 173 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE)) return null; 174 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE); 208 209 @Nullable 210 public String getShutterSpeedInAvModeDescription() 211 { 212 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE); 213 if (value==null) 214 return null; 175 215 switch (value) { 176 216 case 0: return "Automatic"; … … 179 219 } 180 220 } 181 public String getAutoExposureBrackettingSequenceAndAutoCancellationDescription() throws MetadataException 182 { 183 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_BRACKETTING)) return null; 184 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_BRACKETTING); 221 222 @Nullable 223 public String getAutoExposureBrackettingSequenceAndAutoCancellationDescription() 224 { 225 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_BRACKETTING); 226 if (value==null) 227 return null; 185 228 switch (value) { 186 229 case 0: return "0,-,+ / Enabled"; … … 191 234 } 192 235 } 193 public String getShutterCurtainSyncDescription() throws MetadataException 194 { 195 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC)) return null; 196 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC); 236 237 @Nullable 238 public String getShutterCurtainSyncDescription() 239 { 240 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC); 241 if (value==null) 242 return null; 197 243 switch (value) { 198 244 case 0: return "1st Curtain Sync"; … … 201 247 } 202 248 } 203 public String getLensAutoFocusStopButtonDescription() throws MetadataException 204 { 205 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_STOP)) return null; 206 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_STOP); 249 250 @Nullable 251 public String getLensAutoFocusStopButtonDescription() 252 { 253 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_AF_STOP); 254 if (value==null) 255 return null; 207 256 switch (value) { 208 257 case 0: return "AF stop"; … … 212 261 } 213 262 } 214 public String getFillFlashReductionDescription() throws MetadataException 215 { 216 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION)) return null; 217 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION); 263 264 @Nullable 265 public String getFillFlashReductionDescription() 266 { 267 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION); 268 if (value==null) 269 return null; 218 270 switch (value) { 219 271 case 0: return "Enabled"; … … 222 274 } 223 275 } 224 public String getMenuButtonReturnPositionDescription() throws MetadataException 225 { 226 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN)) return null; 227 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN); 276 277 @Nullable 278 public String getMenuButtonReturnPositionDescription() 279 { 280 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN); 281 if (value==null) 282 return null; 228 283 switch (value) { 229 284 case 0: return "Top"; … … 233 288 } 234 289 } 235 public String getSetButtonFunctionWhenShootingDescription() throws MetadataException 236 { 237 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION)) return null; 238 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION); 290 291 @Nullable 292 public String getSetButtonFunctionWhenShootingDescription() 293 { 294 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION); 295 if (value==null) 296 return null; 239 297 switch (value) { 240 298 case 0: return "Not Assigned"; … … 245 303 } 246 304 } 247 public String getSensorCleaningDescription() throws MetadataException 248 { 249 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING)) return null; 250 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING); 305 306 @Nullable 307 public String getSensorCleaningDescription() 308 { 309 Integer value = _directory.getInteger(CanonMakernoteDirectory.TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING); 310 if (value==null) 311 return null; 251 312 switch (value) { 252 313 case 0: return "Disabled"; … … 255 316 } 256 317 } 257 258 public String getFlashBiasDescription() throws MetadataException 259 { 260 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE2_FLASH_BIAS)) return null; 261 262 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE2_FLASH_BIAS); 318 */ 319 320 @Nullable 321 public String getFlashBiasDescription() 322 { 323 Integer value = _directory.getInteger(CanonMakernoteDirectory.FocalLength.TAG_FLASH_BIAS); 324 325 if (value==null) 326 return null; 263 327 264 328 boolean isNegative = false; … … 278 342 } 279 343 280 public String getAfPointUsedDescription() throws MetadataException 281 { 282 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE2_AF_POINT_USED)) return null; 283 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE2_AF_POINT_USED); 344 @Nullable 345 public String getAfPointUsedDescription() 346 { 347 Integer value = _directory.getInteger(CanonMakernoteDirectory.FocalLength.TAG_AF_POINT_USED); 348 if (value==null) 349 return null; 284 350 if ((value & 0x7) == 0) { 285 351 return "Right"; … … 293 359 } 294 360 295 public String getWhiteBalanceDescription() throws MetadataException 296 { 297 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE2_WHITE_BALANCE)) return null; 298 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE2_WHITE_BALANCE); 361 @Nullable 362 public String getWhiteBalanceDescription() 363 { 364 Integer value = _directory.getInteger(CanonMakernoteDirectory.FocalLength.TAG_WHITE_BALANCE); 365 if (value==null) 366 return null; 299 367 switch (value) { 300 368 case 0: … … 307 375 return "Tungsten"; 308 376 case 4: 309 return "Flo urescent";377 return "Florescent"; 310 378 case 5: 311 379 return "Flash"; … … 317 385 } 318 386 319 public String getFocusMode2Description() throws MetadataException 320 { 321 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCUS_MODE_2)) return null; 322 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCUS_MODE_2); 387 @Nullable 388 public String getFocusMode2Description() 389 { 390 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FOCUS_MODE_2); 391 if (value==null) 392 return null; 323 393 switch (value) { 324 394 case 0: … … 331 401 } 332 402 333 public String getFlashDetailsDescription() throws MetadataException 334 { 335 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_DETAILS)) return null; 336 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_DETAILS); 337 if (((value << 14) & 1) > 0) { 403 @Nullable 404 public String getFlashDetailsDescription() 405 { 406 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FLASH_DETAILS); 407 if (value==null) 408 return null; 409 if (((value >> 14) & 1) > 0) { 338 410 return "External E-TTL"; 339 411 } 340 if (((value <<13) & 1) > 0) {412 if (((value >> 13) & 1) > 0) { 341 413 return "Internal flash"; 342 414 } 343 if (((value <<11) & 1) > 0) {415 if (((value >> 11) & 1) > 0) { 344 416 return "FP sync used"; 345 417 } 346 if (((value <<4) & 1) > 0) {418 if (((value >> 4) & 1) > 0) { 347 419 return "FP sync enabled"; 348 420 } … … 350 422 } 351 423 352 public String getFocalUnitsPerMillimetreDescription() throws MetadataException 353 { 354 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCAL_UNITS_PER_MM)) return ""; 355 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCAL_UNITS_PER_MM); 424 @Nullable 425 public String getFocalUnitsPerMillimetreDescription() 426 { 427 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FOCAL_UNITS_PER_MM); 428 if (value==null) 429 return null; 356 430 if (value != 0) { 357 431 return Integer.toString(value); … … 361 435 } 362 436 363 public String getShortFocalLengthDescription() throws MetadataException 364 { 365 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_SHORT_FOCAL_LENGTH)) return null; 366 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_SHORT_FOCAL_LENGTH); 437 @Nullable 438 public String getShortFocalLengthDescription() 439 { 440 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_SHORT_FOCAL_LENGTH); 441 if (value==null) 442 return null; 367 443 String units = getFocalUnitsPerMillimetreDescription(); 368 444 return Integer.toString(value) + " " + units; 369 445 } 370 446 371 public String getLongFocalLengthDescription() throws MetadataException 372 { 373 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_LONG_FOCAL_LENGTH)) return null; 374 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_LONG_FOCAL_LENGTH); 447 @Nullable 448 public String getLongFocalLengthDescription() 449 { 450 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_LONG_FOCAL_LENGTH); 451 if (value==null) 452 return null; 375 453 String units = getFocalUnitsPerMillimetreDescription(); 376 454 return Integer.toString(value) + " " + units; 377 455 } 378 456 379 public String getExposureModeDescription() throws MetadataException 380 { 381 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_EXPOSURE_MODE)) return null; 382 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_EXPOSURE_MODE); 457 @Nullable 458 public String getExposureModeDescription() 459 { 460 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_EXPOSURE_MODE); 461 if (value==null) 462 return null; 383 463 switch (value) { 384 464 case 0: … … 399 479 } 400 480 401 public String getAfPointSelectedDescription() throws MetadataException 402 { 403 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_AF_POINT_SELECTED)) return null; 404 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_AF_POINT_SELECTED); 481 @Nullable 482 public String getAfPointSelectedDescription() 483 { 484 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_AF_POINT_SELECTED); 485 if (value==null) 486 return null; 405 487 switch (value) { 406 488 case 0x3000: … … 419 501 } 420 502 421 public String getMeteringModeDescription() throws MetadataException 422 { 423 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_METERING_MODE)) return null; 424 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_METERING_MODE); 503 @Nullable 504 public String getMeteringModeDescription() 505 { 506 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_METERING_MODE); 507 if (value==null) 508 return null; 425 509 switch (value) { 426 510 case 3: … … 435 519 } 436 520 437 public String getIsoDescription() throws MetadataException 438 { 439 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_ISO)) return null; 440 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_ISO); 521 @Nullable 522 public String getIsoDescription() 523 { 524 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_ISO); 525 if (value==null) 526 return null; 527 528 // Canon PowerShot S3 is special 529 int canonMask = 0x4000; 530 if ((value & canonMask) > 0) 531 return "" + (value & ~canonMask); 532 441 533 switch (value) { 442 534 case 0: … … 457 549 } 458 550 459 public String getSharpnessDescription() throws MetadataException 460 { 461 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_SHARPNESS)) return null; 462 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_SHARPNESS); 551 @Nullable 552 public String getSharpnessDescription() 553 { 554 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_SHARPNESS); 555 if (value==null) 556 return null; 463 557 switch (value) { 464 558 case 0xFFFF: … … 473 567 } 474 568 475 public String getSaturationDescription() throws MetadataException 476 { 477 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_SATURATION)) return null; 478 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_SATURATION); 569 @Nullable 570 public String getSaturationDescription() 571 { 572 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_SATURATION); 573 if (value==null) 574 return null; 479 575 switch (value) { 480 576 case 0xFFFF: … … 489 585 } 490 586 491 public String getContrastDescription() throws MetadataException 492 { 493 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_CONTRAST)) return null; 494 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_CONTRAST); 587 @Nullable 588 public String getContrastDescription() 589 { 590 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_CONTRAST); 591 if (value==null) 592 return null; 495 593 switch (value) { 496 594 case 0xFFFF: … … 505 603 } 506 604 507 public String getEasyShootingModeDescription() throws MetadataException 508 { 509 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_EASY_SHOOTING_MODE)) return null; 510 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_EASY_SHOOTING_MODE); 605 @Nullable 606 public String getEasyShootingModeDescription() 607 { 608 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_EASY_SHOOTING_MODE); 609 if (value==null) 610 return null; 511 611 switch (value) { 512 612 case 0: … … 539 639 } 540 640 541 public String getImageSizeDescription() throws MetadataException 542 { 543 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_IMAGE_SIZE)) return null; 544 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_IMAGE_SIZE); 641 @Nullable 642 public String getImageSizeDescription() 643 { 644 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_IMAGE_SIZE); 645 if (value==null) 646 return null; 545 647 switch (value) { 546 648 case 0: … … 555 657 } 556 658 557 public String getFocusMode1Description() throws MetadataException 558 { 559 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCUS_MODE_1)) return null; 560 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCUS_MODE_1); 659 @Nullable 660 public String getFocusMode1Description() 661 { 662 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FOCUS_MODE_1); 663 if (value==null) 664 return null; 561 665 switch (value) { 562 666 case 0: … … 580 684 } 581 685 582 public String getContinuousDriveModeDescription() throws MetadataException583 {584 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_CONTINUOUS_DRIVE_MODE)) return null;585 intvalue = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_CONTINUOUS_DRIVE_MODE);586 switch(value) {587 case 0:588 if (_directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_SELF_TIMER_DELAY) == 0) {589 return "Single shot";590 } else {591 return "Single shot with self-timer";592 }686 @Nullable 687 public String getContinuousDriveModeDescription() 688 { 689 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_CONTINUOUS_DRIVE_MODE); 690 if (value==null) 691 return null; 692 switch (value) { 693 case 0: 694 final Integer delay = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_SELF_TIMER_DELAY); 695 if (delay!=null) 696 return delay == 0 ? "Single shot" : "Single shot with self-timer"; 593 697 case 1: 594 698 return "Continuous"; 595 default: 596 return "Unknown (" + value + ")"; 597 } 598 } 599 600 public String getFlashModeDescription() throws MetadataException 601 { 602 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_MODE)) return null; 603 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_MODE); 699 } 700 return "Unknown (" + value + ")"; 701 } 702 703 @Nullable 704 public String getFlashModeDescription() 705 { 706 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FLASH_MODE); 707 if (value==null) 708 return null; 604 709 switch (value) { 605 710 case 0: … … 619 724 case 16: 620 725 // note: this value not set on Canon D30 621 return "Extenal flash"; 622 default: 623 return "Unknown (" + value + ")"; 624 } 625 } 626 627 public String getSelfTimerDelayDescription() throws MetadataException 628 { 629 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_SELF_TIMER_DELAY)) return null; 630 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_SELF_TIMER_DELAY); 726 return "External flash"; 727 default: 728 return "Unknown (" + value + ")"; 729 } 730 } 731 732 @Nullable 733 public String getSelfTimerDelayDescription() 734 { 735 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_SELF_TIMER_DELAY); 736 if (value==null) 737 return null; 631 738 if (value == 0) { 632 739 return "Self timer not used"; … … 637 744 } 638 745 639 public String getMacroModeDescription() throws MetadataException 640 { 641 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_MACRO_MODE)) return null; 642 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_MACRO_MODE); 746 @Nullable 747 public String getMacroModeDescription() 748 { 749 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_MACRO_MODE); 750 if (value==null) 751 return null; 643 752 switch (value) { 644 753 case 1: … … 651 760 } 652 761 653 public String getQualityDescription() throws MetadataException 654 { 655 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_QUALITY)) return null; 656 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_QUALITY); 762 @Nullable 763 public String getQualityDescription() 764 { 765 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_QUALITY); 766 if (value==null) 767 return null; 657 768 switch (value) { 658 769 case 2: … … 667 778 } 668 779 669 public String getDigitalZoomDescription() throws MetadataException 670 { 671 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_DIGITAL_ZOOM)) return null; 672 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_DIGITAL_ZOOM); 780 @Nullable 781 public String getDigitalZoomDescription() 782 { 783 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_DIGITAL_ZOOM); 784 if (value==null) 785 return null; 673 786 switch (value) { 674 787 case 0: … … 683 796 } 684 797 685 public String getFocusTypeDescription() throws MetadataException 686 { 687 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCUS_TYPE)) return null; 688 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FOCUS_TYPE); 798 @Nullable 799 public String getFocusTypeDescription() 800 { 801 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FOCUS_TYPE); 802 if (value==null) 803 return null; 689 804 switch (value) { 690 805 case 0: … … 701 816 } 702 817 703 public String getFlashActivityDescription() throws MetadataException 704 { 705 if (!_directory.containsTag(CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_ACTIVITY)) return null; 706 int value = _directory.getInt(CanonMakernoteDirectory.TAG_CANON_STATE1_FLASH_ACTIVITY); 818 @Nullable 819 public String getFlashActivityDescription() 820 { 821 Integer value = _directory.getInteger(CanonMakernoteDirectory.CameraSettings.TAG_FLASH_ACTIVITY); 822 if (value==null) 823 return null; 707 824 switch (value) { 708 825 case 0: -
trunk/src/com/drew/metadata/exif/CanonMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 27 32 * 28 33 * Many tag definitions explained here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/canon_mn.html 34 * 35 * @author Drew Noakes http://drewnoakes.com 29 36 */ 30 37 public class CanonMakernoteDirectory extends Directory 31 38 { 32 // CANON cameras have some funny bespoke fields that need further processing... 33 public static final int TAG_CANON_CAMERA_STATE_1 = 0x0001; 34 public static final int TAG_CANON_CAMERA_STATE_2 = 0x0004; 35 36 public static final int TAG_CANON_IMAGE_TYPE = 0x0006; 37 public static final int TAG_CANON_FIRMWARE_VERSION = 0x0007; 38 public static final int TAG_CANON_IMAGE_NUMBER = 0x0008; 39 public static final int TAG_CANON_OWNER_NAME = 0x0009; 40 /** 41 * To display serial number as on camera use: printf( "%04X%05d", highbyte, lowbyte ) 42 * TODO handle this in CanonMakernoteDescriptor 43 */ 44 public static final int TAG_CANON_SERIAL_NUMBER = 0x000C; 45 public static final int TAG_CANON_UNKNOWN_1 = 0x000D; 46 public static final int TAG_CANON_CUSTOM_FUNCTIONS = 0x000F; 47 48 // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment 49 /** 50 * 1 = Macro 51 * 2 = Normal 52 */ 53 public static final int TAG_CANON_STATE1_MACRO_MODE = 0xC101; 54 public static final int TAG_CANON_STATE1_SELF_TIMER_DELAY = 0xC102; 55 /** 56 * 2 = Normal 57 * 3 = Fine 58 * 5 = Superfine 59 */ 60 public static final int TAG_CANON_STATE1_QUALITY = 0xC103; 61 /** 62 * 0 = Flash Not Fired 63 * 1 = Auto 64 * 2 = On 65 * 3 = Red Eye Reduction 66 * 4 = Slow Synchro 67 * 5 = Auto + Red Eye Reduction 68 * 6 = On + Red Eye Reduction 69 * 16 = External Flash 70 */ 71 public static final int TAG_CANON_STATE1_FLASH_MODE = 0xC104; 72 /** 73 * 0 = Single Frame or Timer Mode 74 * 1 = Continuous 75 */ 76 public static final int TAG_CANON_STATE1_CONTINUOUS_DRIVE_MODE = 0xC105; 77 public static final int TAG_CANON_STATE1_UNKNOWN_2 = 0xC106; 78 /** 79 * 0 = One-Shot 80 * 1 = AI Servo 81 * 2 = AI Focus 82 * 3 = Manual Focus 83 * 4 = Single 84 * 5 = Continuous 85 * 6 = Manual Focus 86 */ 87 public static final int TAG_CANON_STATE1_FOCUS_MODE_1 = 0xC107; 88 public static final int TAG_CANON_STATE1_UNKNOWN_3 = 0xC108; 89 public static final int TAG_CANON_STATE1_UNKNOWN_4 = 0xC109; 90 /** 91 * 0 = Large 92 * 1 = Medium 93 * 2 = Small 94 */ 95 public static final int TAG_CANON_STATE1_IMAGE_SIZE = 0xC10A; 96 /** 97 * 0 = Full Auto 98 * 1 = Manual 99 * 2 = Landscape 100 * 3 = Fast Shutter 101 * 4 = Slow Shutter 102 * 5 = Night 103 * 6 = Black & White 104 * 7 = Sepia 105 * 8 = Portrait 106 * 9 = Sports 107 * 10 = Macro / Close-Up 108 * 11 = Pan Focus 109 */ 110 public static final int TAG_CANON_STATE1_EASY_SHOOTING_MODE = 0xC10B; 111 /** 112 * 0 = No Digital Zoom 113 * 1 = 2x 114 * 2 = 4x 115 */ 116 public static final int TAG_CANON_STATE1_DIGITAL_ZOOM = 0xC10C; 117 /** 118 * 0 = Normal 119 * 1 = High 120 * 65535 = Low 121 */ 122 public static final int TAG_CANON_STATE1_CONTRAST = 0xC10D; 123 /** 124 * 0 = Normal 125 * 1 = High 126 * 65535 = Low 127 */ 128 public static final int TAG_CANON_STATE1_SATURATION = 0xC10E; 129 /** 130 * 0 = Normal 131 * 1 = High 132 * 65535 = Low 133 */ 134 public static final int TAG_CANON_STATE1_SHARPNESS = 0xC10F; 135 /** 136 * 0 = Check ISOSpeedRatings EXIF tag for ISO Speed 137 * 15 = Auto ISO 138 * 16 = ISO 50 139 * 17 = ISO 100 140 * 18 = ISO 200 141 * 19 = ISO 400 142 */ 143 public static final int TAG_CANON_STATE1_ISO = 0xC110; 144 /** 145 * 3 = Evaluative 146 * 4 = Partial 147 * 5 = Centre Weighted 148 */ 149 public static final int TAG_CANON_STATE1_METERING_MODE = 0xC111; 150 /** 151 * 0 = Manual 152 * 1 = Auto 153 * 3 = Close-up (Macro) 154 * 8 = Locked (Pan Mode) 155 */ 156 public static final int TAG_CANON_STATE1_FOCUS_TYPE = 0xC112; 157 /** 158 * 12288 = None (Manual Focus) 159 * 12289 = Auto Selected 160 * 12290 = Right 161 * 12291 = Centre 162 * 12292 = Left 163 */ 164 public static final int TAG_CANON_STATE1_AF_POINT_SELECTED = 0xC113; 165 /** 166 * 0 = Easy Shooting (See Easy Shooting Mode) 167 * 1 = Program 168 * 2 = Tv-Priority 169 * 3 = Av-Priority 170 * 4 = Manual 171 * 5 = A-DEP 172 */ 173 public static final int TAG_CANON_STATE1_EXPOSURE_MODE = 0xC114; 174 public static final int TAG_CANON_STATE1_UNKNOWN_7 = 0xC115; 175 public static final int TAG_CANON_STATE1_UNKNOWN_8 = 0xC116; 176 public static final int TAG_CANON_STATE1_LONG_FOCAL_LENGTH = 0xC117; 177 public static final int TAG_CANON_STATE1_SHORT_FOCAL_LENGTH = 0xC118; 178 public static final int TAG_CANON_STATE1_FOCAL_UNITS_PER_MM = 0xC119; 179 public static final int TAG_CANON_STATE1_UNKNOWN_9 = 0xC11A; 180 public static final int TAG_CANON_STATE1_UNKNOWN_10 = 0xC11B; 181 /** 182 * 0 = Flash Did Not Fire 183 * 1 = Flash Fired 184 */ 185 public static final int TAG_CANON_STATE1_FLASH_ACTIVITY = 0xC11C; 186 public static final int TAG_CANON_STATE1_FLASH_DETAILS = 0xC11D; 187 public static final int TAG_CANON_STATE1_UNKNOWN_12 = 0xC11E; 188 public static final int TAG_CANON_STATE1_UNKNOWN_13 = 0xC11F; 189 /** 190 * 0 = Focus Mode: Single 191 * 1 = Focus Mode: Continuous 192 */ 193 public static final int TAG_CANON_STATE1_FOCUS_MODE_2 = 0xC120; 194 195 /** 196 * 0 = Auto 197 * 1 = Sunny 198 * 2 = Cloudy 199 * 3 = Tungsten 200 * 4 = Flourescent 201 * 5 = Flash 202 * 6 = Custom 203 */ 204 public static final int TAG_CANON_STATE2_WHITE_BALANCE = 0xC207; 205 public static final int TAG_CANON_STATE2_SEQUENCE_NUMBER = 0xC209; 206 public static final int TAG_CANON_STATE2_AF_POINT_USED = 0xC20E; 207 /** 208 * The value of this tag may be translated into a flash bias value, in EV. 209 * 210 * 0xffc0 = -2 EV 211 * 0xffcc = -1.67 EV 212 * 0xffd0 = -1.5 EV 213 * 0xffd4 = -1.33 EV 214 * 0xffe0 = -1 EV 215 * 0xffec = -0.67 EV 216 * 0xfff0 = -0.5 EV 217 * 0xfff4 = -0.33 EV 218 * 0x0000 = 0 EV 219 * 0x000c = 0.33 EV 220 * 0x0010 = 0.5 EV 221 * 0x0014 = 0.67 EV 222 * 0x0020 = 1 EV 223 * 0x002c = 1.33 EV 224 * 0x0030 = 1.5 EV 225 * 0x0034 = 1.67 EV 226 * 0x0040 = 2 EV 227 */ 228 public static final int TAG_CANON_STATE2_FLASH_BIAS = 0xC20F; 229 public static final int TAG_CANON_STATE2_AUTO_EXPOSURE_BRACKETING = 0xC210; 230 public static final int TAG_CANON_STATE2_AEB_BRACKET_VALUE = 0xC211; 231 public static final int TAG_CANON_STATE2_SUBJECT_DISTANCE = 0xC213; 232 233 /** 234 * Long Exposure Noise Reduction 235 * 0 = Off 236 * 1 = On 237 */ 238 public static final int TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION = 0xC301; 239 240 /** 241 * Shutter/Auto Exposure-lock buttons 242 * 0 = AF/AE lock 243 * 1 = AE lock/AF 244 * 2 = AF/AF lock 245 * 3 = AE+release/AE+AF 246 */ 247 public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS = 0xC302; 248 249 /** 250 * Mirror lockup 251 * 0 = Disable 252 * 1 = Enable 253 */ 254 public static final int TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP = 0xC303; 255 256 /** 257 * Tv/Av and exposure level 258 * 0 = 1/2 stop 259 * 1 = 1/3 stop 260 */ 261 public static final int TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL = 0xC304; 262 263 /** 264 * AF-assist light 265 * 0 = On (Auto) 266 * 1 = Off 267 */ 268 public static final int TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT = 0xC305; 269 270 /** 271 * Shutter speed in Av mode 272 * 0 = Automatic 273 * 1 = 1/200 (fixed) 274 */ 275 public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE = 0xC306; 276 277 /** 278 * Auto-Exposure Bracketting sequence/auto cancellation 279 * 0 = 0,-,+ / Enabled 280 * 1 = 0,-,+ / Disabled 281 * 2 = -,0,+ / Enabled 282 * 3 = -,0,+ / Disabled 283 */ 284 public static final int TAG_CANON_CUSTOM_FUNCTION_BRACKETTING = 0xC307; 285 286 /** 287 * Shutter Curtain Sync 288 * 0 = 1st Curtain Sync 289 * 1 = 2nd Curtain Sync 290 */ 291 public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC = 0xC308; 292 293 /** 294 * Lens Auto-Focus stop button Function Switch 295 * 0 = AF stop 296 * 1 = Operate AF 297 * 2 = Lock AE and start timer 298 */ 299 public static final int TAG_CANON_CUSTOM_FUNCTION_AF_STOP = 0xC309; 300 301 /** 302 * Auto reduction of fill flash 303 * 0 = Enable 304 * 1 = Disable 305 */ 306 public static final int TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION = 0xC30A; 307 308 /** 309 * Menu button return position 310 * 0 = Top 311 * 1 = Previous (volatile) 312 * 2 = Previous 313 */ 314 public static final int TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN = 0xC30B; 315 316 /** 317 * SET button function when shooting 318 * 0 = Not Assigned 319 * 1 = Change Quality 320 * 2 = Change ISO Speed 321 * 3 = Select Parameters 322 */ 323 public static final int TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION = 0xC30C; 324 325 /** 326 * Sensor cleaning 327 * 0 = Disable 328 * 1 = Enable 329 */ 330 public static final int TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING = 0xC30D; 39 // These TAG_*_ARRAY Exif tags map to arrays of int16 values which are split out into separate 'fake' tags. 40 // When an attempt is made to set one of these on the directory, it is split and the corresponding offset added to the tagType. 41 // So the resulting tag is the offset + the index into the array. 42 43 private static final int TAG_CAMERA_SETTINGS_ARRAY = 0x0001; 44 private static final int TAG_FOCAL_LENGTH_ARRAY = 0x0002; 45 private static final int TAG_SHOT_INFO_ARRAY = 0x0004; 46 private static final int TAG_PANORAMA_ARRAY = 0x0005; 47 48 public static final int TAG_CANON_IMAGE_TYPE = 0x0006; 49 public static final int TAG_CANON_FIRMWARE_VERSION = 0x0007; 50 public static final int TAG_CANON_IMAGE_NUMBER = 0x0008; 51 public static final int TAG_CANON_OWNER_NAME = 0x0009; 52 public static final int TAG_CANON_SERIAL_NUMBER = 0x000C; 53 public static final int TAG_CAMERA_INFO_ARRAY = 0x000D; // depends upon model, so leave for now 54 public static final int TAG_CANON_FILE_LENGTH = 0x000E; 55 public static final int TAG_CANON_CUSTOM_FUNCTIONS_ARRAY = 0x000F; // depends upon model, so leave for now 56 public static final int TAG_MODEL_ID = 0x0010; 57 public static final int TAG_MOVIE_INFO_ARRAY = 0x0011; // not currently decoded as not sure we see it in still images 58 private static final int TAG_AF_INFO_ARRAY = 0x0012; // not currently decoded 59 public static final int TAG_THUMBNAIL_IMAGE_VALID_AREA = 0x0013; 60 public static final int TAG_SERIAL_NUMBER_FORMAT = 0x0015; 61 public static final int TAG_SUPER_MACRO = 0x001A; 62 public static final int TAG_DATE_STAMP_MODE = 0x001C; 63 public static final int TAG_MY_COLORS = 0x001D; 64 public static final int TAG_FIRMWARE_REVISION = 0x001E; 65 public static final int TAG_CATEGORIES = 0x0023; 66 public static final int TAG_FACE_DETECT_ARRAY_1 = 0x0024; 67 public static final int TAG_FACE_DETECT_ARRAY_2 = 0x0025; 68 public static final int TAG_AF_INFO_ARRAY_2 = 0x0026; 69 public static final int TAG_IMAGE_UNIQUE_ID = 0x0028; 70 public static final int TAG_RAW_DATA_OFFSET = 0x0081; 71 public static final int TAG_ORIGINAL_DECISION_DATA_OFFSET = 0x0083; 72 public static final int TAG_CUSTOM_FUNCTIONS_1D_ARRAY = 0x0090; // not currently decoded 73 public static final int TAG_PERSONAL_FUNCTIONS_ARRAY = 0x0091; // not currently decoded 74 public static final int TAG_PERSONAL_FUNCTION_VALUES_ARRAY = 0x0092; // not currently decoded 75 public static final int TAG_FILE_INFO_ARRAY = 0x0093; // not currently decoded 76 public static final int TAG_AF_POINTS_IN_FOCUS_1D = 0x0094; 77 public static final int TAG_LENS_MODEL = 0x0095; 78 public static final int TAG_SERIAL_INFO_ARRAY = 0x0096; // not currently decoded 79 public static final int TAG_DUST_REMOVAL_DATA = 0x0097; 80 public static final int TAG_CROP_INFO = 0x0098; // not currently decoded 81 public static final int TAG_CUSTOM_FUNCTIONS_ARRAY_2 = 0x0099; // not currently decoded 82 public static final int TAG_ASPECT_INFO_ARRAY = 0x009A; // not currently decoded 83 public static final int TAG_PROCESSING_INFO_ARRAY = 0x00A0; // not currently decoded 84 public static final int TAG_TONE_CURVE_TABLE = 0x00A1; 85 public static final int TAG_SHARPNESS_TABLE = 0x00A2; 86 public static final int TAG_SHARPNESS_FREQ_TABLE = 0x00A3; 87 public static final int TAG_WHITE_BALANCE_TABLE = 0x00A4; 88 public static final int TAG_COLOR_BALANCE_ARRAY = 0x00A9; // not currently decoded 89 public static final int TAG_MEASURED_COLOR_ARRAY = 0x00AA; // not currently decoded 90 public static final int TAG_COLOR_TEMPERATURE = 0x00AE; 91 public static final int TAG_CANON_FLAGS_ARRAY = 0x00B0; // not currently decoded 92 public static final int TAG_MODIFIED_INFO_ARRAY = 0x00B1; // not currently decoded 93 public static final int TAG_TONE_CURVE_MATCHING = 0x00B2; 94 public static final int TAG_WHITE_BALANCE_MATCHING = 0x00B3; 95 public static final int TAG_COLOR_SPACE = 0x00B4; 96 public static final int TAG_PREVIEW_IMAGE_INFO_ARRAY = 0x00B6; // not currently decoded 97 public static final int TAG_VRD_OFFSET = 0x00D0; 98 public static final int TAG_SENSOR_INFO_ARRAY = 0x00E0; // not currently decoded 99 public static final int TAG_COLOR_DATA_ARRAY_2 = 0x4001; // depends upon camera model, not currently decoded 100 public static final int TAG_COLOR_INFO_ARRAY_2 = 0x4003; // not currently decoded 101 public static final int TAG_CUSTOM_PICTURE_STYLE_FILE_NAME = 0x4010; 102 public static final int TAG_COLOR_INFO_ARRAY = 0x4013; // not currently decoded 103 public static final int TAG_VIGNETTING_CORRECTION_ARRAY_1 = 0x4015; // not currently decoded 104 public static final int TAG_VIGNETTING_CORRECTION_ARRAY_2 = 0x4016; // not currently decoded 105 public static final int TAG_LIGHTING_OPTIMIZER_ARRAY = 0x4018; // not currently decoded 106 public static final int TAG_LENS_INFO_ARRAY = 0x4019; // not currently decoded 107 public static final int TAG_AMBIANCE_INFO_ARRAY = 0x4020; // not currently decoded 108 public static final int TAG_FILTER_INFO_ARRAY = 0x4024; // not currently decoded 109 110 public final static class CameraSettings 111 { 112 // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment 113 private static final int OFFSET = 0xC100; 114 115 /** 116 * 1 = Macro 117 * 2 = Normal 118 */ 119 public static final int TAG_MACRO_MODE = OFFSET + 0x01; 120 public static final int TAG_SELF_TIMER_DELAY = OFFSET + 0x02; 121 /** 122 * 2 = Normal 123 * 3 = Fine 124 * 5 = Superfine 125 */ 126 public static final int TAG_QUALITY = OFFSET + 0x03; 127 /** 128 * 0 = Flash Not Fired 129 * 1 = Auto 130 * 2 = On 131 * 3 = Red Eye Reduction 132 * 4 = Slow Synchro 133 * 5 = Auto + Red Eye Reduction 134 * 6 = On + Red Eye Reduction 135 * 16 = External Flash 136 */ 137 public static final int TAG_FLASH_MODE = OFFSET + 0x04; 138 /** 139 * 0 = Single Frame or Timer Mode 140 * 1 = Continuous 141 */ 142 public static final int TAG_CONTINUOUS_DRIVE_MODE = OFFSET + 0x05; 143 public static final int TAG_UNKNOWN_2 = OFFSET + 0x06; 144 /** 145 * 0 = One-Shot 146 * 1 = AI Servo 147 * 2 = AI Focus 148 * 3 = Manual Focus 149 * 4 = Single 150 * 5 = Continuous 151 * 6 = Manual Focus 152 */ 153 public static final int TAG_FOCUS_MODE_1 = OFFSET + 0x07; 154 public static final int TAG_UNKNOWN_3 = OFFSET + 0x08; 155 public static final int TAG_UNKNOWN_4 = OFFSET + 0x09; 156 /** 157 * 0 = Large 158 * 1 = Medium 159 * 2 = Small 160 */ 161 public static final int TAG_IMAGE_SIZE = OFFSET + 0x0A; 162 /** 163 * 0 = Full Auto 164 * 1 = Manual 165 * 2 = Landscape 166 * 3 = Fast Shutter 167 * 4 = Slow Shutter 168 * 5 = Night 169 * 6 = Black & White 170 * 7 = Sepia 171 * 8 = Portrait 172 * 9 = Sports 173 * 10 = Macro / Close-Up 174 * 11 = Pan Focus 175 */ 176 public static final int TAG_EASY_SHOOTING_MODE = OFFSET + 0x0B; 177 /** 178 * 0 = No Digital Zoom 179 * 1 = 2x 180 * 2 = 4x 181 */ 182 public static final int TAG_DIGITAL_ZOOM = OFFSET + 0x0C; 183 /** 184 * 0 = Normal 185 * 1 = High 186 * 65535 = Low 187 */ 188 public static final int TAG_CONTRAST = OFFSET + 0x0D; 189 /** 190 * 0 = Normal 191 * 1 = High 192 * 65535 = Low 193 */ 194 public static final int TAG_SATURATION = OFFSET + 0x0E; 195 /** 196 * 0 = Normal 197 * 1 = High 198 * 65535 = Low 199 */ 200 public static final int TAG_SHARPNESS = OFFSET + 0x0F; 201 /** 202 * 0 = Check ISOSpeedRatings EXIF tag for ISO Speed 203 * 15 = Auto ISO 204 * 16 = ISO 50 205 * 17 = ISO 100 206 * 18 = ISO 200 207 * 19 = ISO 400 208 */ 209 public static final int TAG_ISO = OFFSET + 0x10; 210 /** 211 * 3 = Evaluative 212 * 4 = Partial 213 * 5 = Centre Weighted 214 */ 215 public static final int TAG_METERING_MODE = OFFSET + 0x11; 216 /** 217 * 0 = Manual 218 * 1 = Auto 219 * 3 = Close-up (Macro) 220 * 8 = Locked (Pan Mode) 221 */ 222 public static final int TAG_FOCUS_TYPE = OFFSET + 0x12; 223 /** 224 * 12288 = None (Manual Focus) 225 * 12289 = Auto Selected 226 * 12290 = Right 227 * 12291 = Centre 228 * 12292 = Left 229 */ 230 public static final int TAG_AF_POINT_SELECTED = OFFSET + 0x13; 231 /** 232 * 0 = Easy Shooting (See Easy Shooting Mode) 233 * 1 = Program 234 * 2 = Tv-Priority 235 * 3 = Av-Priority 236 * 4 = Manual 237 * 5 = A-DEP 238 */ 239 public static final int TAG_EXPOSURE_MODE = OFFSET + 0x14; 240 public static final int TAG_UNKNOWN_7 = OFFSET + 0x15; 241 public static final int TAG_UNKNOWN_8 = OFFSET + 0x16; 242 public static final int TAG_LONG_FOCAL_LENGTH = OFFSET + 0x17; 243 public static final int TAG_SHORT_FOCAL_LENGTH = OFFSET + 0x18; 244 public static final int TAG_FOCAL_UNITS_PER_MM = OFFSET + 0x19; 245 public static final int TAG_UNKNOWN_9 = OFFSET + 0x1A; 246 public static final int TAG_UNKNOWN_10 = OFFSET + 0x1B; 247 /** 248 * 0 = Flash Did Not Fire 249 * 1 = Flash Fired 250 */ 251 public static final int TAG_FLASH_ACTIVITY = OFFSET + 0x1C; 252 public static final int TAG_FLASH_DETAILS = OFFSET + 0x1D; 253 public static final int TAG_UNKNOWN_12 = OFFSET + 0x1E; 254 public static final int TAG_UNKNOWN_13 = OFFSET + 0x1F; 255 /** 256 * 0 = Focus Mode: Single 257 * 1 = Focus Mode: Continuous 258 */ 259 public static final int TAG_FOCUS_MODE_2 = OFFSET + 0x20; 260 } 261 262 public final static class FocalLength 263 { 264 // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment 265 266 private static final int OFFSET = 0xC200; 267 268 /** 269 * 0 = Auto 270 * 1 = Sunny 271 * 2 = Cloudy 272 * 3 = Tungsten 273 * 4 = Florescent 274 * 5 = Flash 275 * 6 = Custom 276 */ 277 public static final int TAG_WHITE_BALANCE = OFFSET + 0x07; 278 public static final int TAG_SEQUENCE_NUMBER = OFFSET + 0x09; 279 public static final int TAG_AF_POINT_USED = OFFSET + 0x0E; 280 /** 281 * The value of this tag may be translated into a flash bias value, in EV. 282 * 283 * 0xffc0 = -2 EV 284 * 0xffcc = -1.67 EV 285 * 0xffd0 = -1.5 EV 286 * 0xffd4 = -1.33 EV 287 * 0xffe0 = -1 EV 288 * 0xffec = -0.67 EV 289 * 0xfff0 = -0.5 EV 290 * 0xfff4 = -0.33 EV 291 * 0x0000 = 0 EV 292 * 0x000c = 0.33 EV 293 * 0x0010 = 0.5 EV 294 * 0x0014 = 0.67 EV 295 * 0x0020 = 1 EV 296 * 0x002c = 1.33 EV 297 * 0x0030 = 1.5 EV 298 * 0x0034 = 1.67 EV 299 * 0x0040 = 2 EV 300 */ 301 public static final int TAG_FLASH_BIAS = OFFSET + 0x0F; 302 public static final int TAG_AUTO_EXPOSURE_BRACKETING = OFFSET + 0x10; 303 public static final int TAG_AEB_BRACKET_VALUE = OFFSET + 0x11; 304 public static final int TAG_SUBJECT_DISTANCE = OFFSET + 0x13; 305 } 306 307 public final static class ShotInfo 308 { 309 // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment 310 311 private static final int OFFSET = 0xC400; 312 313 public static final int TAG_AUTO_ISO = OFFSET + 1; 314 public static final int TAG_BASE_ISO = OFFSET + 2; 315 public static final int TAG_MEASURED_EV = OFFSET + 3; 316 public static final int TAG_TARGET_APERTURE = OFFSET + 4; 317 public static final int TAG_TARGET_EXPOSURE_TIME = OFFSET + 5; 318 public static final int TAG_EXPOSURE_COMPENSATION = OFFSET + 6; 319 public static final int TAG_WHITE_BALANCE = OFFSET + 7; 320 public static final int TAG_SLOW_SHUTTER = OFFSET + 8; 321 public static final int TAG_SEQUENCE_NUMBER = OFFSET + 9; 322 public static final int TAG_OPTICAL_ZOOM_CODE = OFFSET + 10; 323 public static final int TAG_CAMERA_TEMPERATURE = OFFSET + 12; 324 public static final int TAG_FLASH_GUIDE_NUMBER = OFFSET + 13; 325 public static final int TAG_AF_POINTS_IN_FOCUS = OFFSET + 14; 326 public static final int TAG_FLASH_EXPOSURE_BRACKETING = OFFSET + 15; 327 public static final int TAG_AUTO_EXPOSURE_BRACKETING = OFFSET + 16; 328 public static final int TAG_AEB_BRACKET_VALUE = OFFSET + 17; 329 public static final int TAG_CONTROL_MODE = OFFSET + 18; 330 public static final int TAG_FOCUS_DISTANCE_UPPER = OFFSET + 19; 331 public static final int TAG_FOCUS_DISTANCE_LOWER = OFFSET + 20; 332 public static final int TAG_F_NUMBER = OFFSET + 21; 333 public static final int TAG_EXPOSURE_TIME = OFFSET + 22; 334 public static final int TAG_MEASURED_EV_2 = OFFSET + 23; 335 public static final int TAG_BULB_DURATION = OFFSET + 24; 336 public static final int TAG_CAMERA_TYPE = OFFSET + 26; 337 public static final int TAG_AUTO_ROTATE = OFFSET + 27; 338 public static final int TAG_ND_FILTER = OFFSET + 28; 339 public static final int TAG_SELF_TIMER_2 = OFFSET + 29; 340 public static final int TAG_FLASH_OUTPUT = OFFSET + 33; 341 } 342 343 public final static class Panorama 344 { 345 // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment 346 347 private static final int OFFSET = 0xC500; 348 349 public static final int TAG_PANORAMA_FRAME_NUMBER = OFFSET + 2; 350 public static final int TAG_PANORAMA_DIRECTION = OFFSET + 5; 351 } 352 353 public final static class AFInfo 354 { 355 // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment 356 357 private static final int OFFSET = 0xD200; 358 359 public static final int TAG_NUM_AF_POINTS = OFFSET; 360 public static final int TAG_VALID_AF_POINTS = OFFSET + 1; 361 public static final int TAG_IMAGE_WIDTH = OFFSET + 2; 362 public static final int TAG_IMAGE_HEIGHT = OFFSET + 3; 363 public static final int TAG_AF_IMAGE_WIDTH = OFFSET + 4; 364 public static final int TAG_AF_IMAGE_HEIGHT = OFFSET + 5; 365 public static final int TAG_AF_AREA_WIDTH = OFFSET + 6; 366 public static final int TAG_AF_AREA_HEIGHT = OFFSET + 7; 367 public static final int TAG_AF_AREA_X_POSITIONS = OFFSET + 8; 368 public static final int TAG_AF_AREA_Y_POSITIONS = OFFSET + 9; 369 public static final int TAG_AF_POINTS_IN_FOCUS = OFFSET + 10; 370 public static final int TAG_PRIMARY_AF_POINT_1 = OFFSET + 11; 371 public static final int TAG_PRIMARY_AF_POINT_2 = OFFSET + 12; // not sure why there are two of these 372 } 373 374 // /** 375 // * Long Exposure Noise Reduction 376 // * 0 = Off 377 // * 1 = On 378 // */ 379 // public static final int TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION = 0xC301; 380 // 381 // /** 382 // * Shutter/Auto Exposure-lock buttons 383 // * 0 = AF/AE lock 384 // * 1 = AE lock/AF 385 // * 2 = AF/AF lock 386 // * 3 = AE+release/AE+AF 387 // */ 388 // public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS = 0xC302; 389 // 390 // /** 391 // * Mirror lockup 392 // * 0 = Disable 393 // * 1 = Enable 394 // */ 395 // public static final int TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP = 0xC303; 396 // 397 // /** 398 // * Tv/Av and exposure level 399 // * 0 = 1/2 stop 400 // * 1 = 1/3 stop 401 // */ 402 // public static final int TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL = 0xC304; 403 // 404 // /** 405 // * AF-assist light 406 // * 0 = On (Auto) 407 // * 1 = Off 408 // */ 409 // public static final int TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT = 0xC305; 410 // 411 // /** 412 // * Shutter speed in Av mode 413 // * 0 = Automatic 414 // * 1 = 1/200 (fixed) 415 // */ 416 // public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE = 0xC306; 417 // 418 // /** 419 // * Auto-Exposure Bracketting sequence/auto cancellation 420 // * 0 = 0,-,+ / Enabled 421 // * 1 = 0,-,+ / Disabled 422 // * 2 = -,0,+ / Enabled 423 // * 3 = -,0,+ / Disabled 424 // */ 425 // public static final int TAG_CANON_CUSTOM_FUNCTION_BRACKETTING = 0xC307; 426 // 427 // /** 428 // * Shutter Curtain Sync 429 // * 0 = 1st Curtain Sync 430 // * 1 = 2nd Curtain Sync 431 // */ 432 // public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC = 0xC308; 433 // 434 // /** 435 // * Lens Auto-Focus stop button Function Switch 436 // * 0 = AF stop 437 // * 1 = Operate AF 438 // * 2 = Lock AE and start timer 439 // */ 440 // public static final int TAG_CANON_CUSTOM_FUNCTION_AF_STOP = 0xC309; 441 // 442 // /** 443 // * Auto reduction of fill flash 444 // * 0 = Enable 445 // * 1 = Disable 446 // */ 447 // public static final int TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION = 0xC30A; 448 // 449 // /** 450 // * Menu button return position 451 // * 0 = Top 452 // * 1 = Previous (volatile) 453 // * 2 = Previous 454 // */ 455 // public static final int TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN = 0xC30B; 456 // 457 // /** 458 // * SET button function when shooting 459 // * 0 = Not Assigned 460 // * 1 = Change Quality 461 // * 2 = Change ISO Speed 462 // * 3 = Select Parameters 463 // */ 464 // public static final int TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION = 0xC30C; 465 // 466 // /** 467 // * Sensor cleaning 468 // * 0 = Disable 469 // * 1 = Enable 470 // */ 471 // public static final int TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING = 0xC30D; 331 472 332 473 // 9 A B C D E F 10 11 12 13 333 474 // 9 10 11 12 13 14 15 16 17 18 19 334 protected static final HashMap _tagNameMap = new HashMap(); 475 @NotNull 476 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 335 477 336 478 static 337 479 { 338 _tagNameMap.put(new Integer(TAG_CANON_FIRMWARE_VERSION), "Firmware Version"); 339 _tagNameMap.put(new Integer(TAG_CANON_IMAGE_NUMBER), "Image Number"); 340 _tagNameMap.put(new Integer(TAG_CANON_IMAGE_TYPE), "Image Type"); 341 _tagNameMap.put(new Integer(TAG_CANON_OWNER_NAME), "Owner Name"); 342 _tagNameMap.put(new Integer(TAG_CANON_UNKNOWN_1), "Makernote Unknown 1"); 343 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTIONS), "Custom Functions"); 344 _tagNameMap.put(new Integer(TAG_CANON_SERIAL_NUMBER), "Camera Serial Number"); 345 _tagNameMap.put(new Integer(TAG_CANON_STATE1_AF_POINT_SELECTED), "AF Point Selected"); 346 _tagNameMap.put(new Integer(TAG_CANON_STATE1_CONTINUOUS_DRIVE_MODE), "Continuous Drive Mode"); 347 _tagNameMap.put(new Integer(TAG_CANON_STATE1_CONTRAST), "Contrast"); 348 _tagNameMap.put(new Integer(TAG_CANON_STATE1_EASY_SHOOTING_MODE), "Easy Shooting Mode"); 349 _tagNameMap.put(new Integer(TAG_CANON_STATE1_EXPOSURE_MODE), "Exposure Mode"); 350 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FLASH_DETAILS), "Flash Details"); 351 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FLASH_MODE), "Flash Mode"); 352 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FOCAL_UNITS_PER_MM), "Focal Units per mm"); 353 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FOCUS_MODE_1), "Focus Mode"); 354 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FOCUS_MODE_2), "Focus Mode"); 355 _tagNameMap.put(new Integer(TAG_CANON_STATE1_IMAGE_SIZE), "Image Size"); 356 _tagNameMap.put(new Integer(TAG_CANON_STATE1_ISO), "Iso"); 357 _tagNameMap.put(new Integer(TAG_CANON_STATE1_LONG_FOCAL_LENGTH), "Long Focal Length"); 358 _tagNameMap.put(new Integer(TAG_CANON_STATE1_MACRO_MODE), "Macro Mode"); 359 _tagNameMap.put(new Integer(TAG_CANON_STATE1_METERING_MODE), "Metering Mode"); 360 _tagNameMap.put(new Integer(TAG_CANON_STATE1_SATURATION), "Saturation"); 361 _tagNameMap.put(new Integer(TAG_CANON_STATE1_SELF_TIMER_DELAY), "Self Timer Delay"); 362 _tagNameMap.put(new Integer(TAG_CANON_STATE1_SHARPNESS), "Sharpness"); 363 _tagNameMap.put(new Integer(TAG_CANON_STATE1_SHORT_FOCAL_LENGTH), "Short Focal Length"); 364 _tagNameMap.put(new Integer(TAG_CANON_STATE1_QUALITY), "Quality"); 365 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_2), "Unknown Camera State 2"); 366 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_3), "Unknown Camera State 3"); 367 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_4), "Unknown Camera State 4"); 368 _tagNameMap.put(new Integer(TAG_CANON_STATE1_DIGITAL_ZOOM), "Digital Zoom"); 369 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FOCUS_TYPE), "Focus Type"); 370 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_7), "Unknown Camera State 7"); 371 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_8), "Unknown Camera State 8"); 372 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_9), "Unknown Camera State 9"); 373 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_10), "Unknown Camera State 10"); 374 _tagNameMap.put(new Integer(TAG_CANON_STATE1_FLASH_ACTIVITY), "Flash Activity"); 375 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_12), "Unknown Camera State 12"); 376 _tagNameMap.put(new Integer(TAG_CANON_STATE1_UNKNOWN_13), "Unknown Camera State 13"); 377 _tagNameMap.put(new Integer(TAG_CANON_STATE2_WHITE_BALANCE), "White Balance"); 378 _tagNameMap.put(new Integer(TAG_CANON_STATE2_SEQUENCE_NUMBER), "Sequence Number"); 379 _tagNameMap.put(new Integer(TAG_CANON_STATE2_AF_POINT_USED), "AF Point Used"); 380 _tagNameMap.put(new Integer(TAG_CANON_STATE2_FLASH_BIAS), "Flash Bias"); 381 _tagNameMap.put(new Integer(TAG_CANON_STATE2_AUTO_EXPOSURE_BRACKETING), "Auto Exposure Bracketing"); 382 _tagNameMap.put(new Integer(TAG_CANON_STATE2_AEB_BRACKET_VALUE), "AEB Bracket Value"); 383 _tagNameMap.put(new Integer(TAG_CANON_STATE2_SUBJECT_DISTANCE), "Subject Distance"); 384 385 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION), "Long Exposure Noise Reduction"); 386 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS), "Shutter/Auto Exposure-lock Buttons"); 387 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP), "Mirror Lockup"); 388 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL), "Tv/Av And Exposure Level"); 389 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT), "AF-Assist Light"); 390 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE), "Shutter Speed in Av Mode"); 391 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_BRACKETTING), "Auto-Exposure Bracketting Sequence/Auto Cancellation"); 392 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC), "Shutter Curtain Sync"); 393 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_AF_STOP), "Lens Auto-Focus Stop Button Function Switch"); 394 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION), "Auto Reduction of Fill Flash"); 395 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN), "Menu Button Return Position"); 396 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION), "SET Button Function When Shooting"); 397 _tagNameMap.put(new Integer(TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING), "Sensor Cleaning"); 480 _tagNameMap.put(TAG_CANON_FIRMWARE_VERSION, "Firmware Version"); 481 _tagNameMap.put(TAG_CANON_IMAGE_NUMBER, "Image Number"); 482 _tagNameMap.put(TAG_CANON_IMAGE_TYPE, "Image Type"); 483 _tagNameMap.put(TAG_CANON_OWNER_NAME, "Owner Name"); 484 _tagNameMap.put(TAG_CANON_SERIAL_NUMBER, "Camera Serial Number"); 485 _tagNameMap.put(TAG_CAMERA_INFO_ARRAY, "Camera Info Array"); 486 _tagNameMap.put(TAG_CANON_FILE_LENGTH, "File Length"); 487 _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTIONS_ARRAY, "Custom Functions"); 488 _tagNameMap.put(TAG_MODEL_ID, "Canon Model ID"); 489 _tagNameMap.put(TAG_MOVIE_INFO_ARRAY, "Movie Info Array"); 490 491 _tagNameMap.put(CameraSettings.TAG_AF_POINT_SELECTED, "AF Point Selected"); 492 _tagNameMap.put(CameraSettings.TAG_CONTINUOUS_DRIVE_MODE, "Continuous Drive Mode"); 493 _tagNameMap.put(CameraSettings.TAG_CONTRAST, "Contrast"); 494 _tagNameMap.put(CameraSettings.TAG_EASY_SHOOTING_MODE, "Easy Shooting Mode"); 495 _tagNameMap.put(CameraSettings.TAG_EXPOSURE_MODE, "Exposure Mode"); 496 _tagNameMap.put(CameraSettings.TAG_FLASH_DETAILS, "Flash Details"); 497 _tagNameMap.put(CameraSettings.TAG_FLASH_MODE, "Flash Mode"); 498 _tagNameMap.put(CameraSettings.TAG_FOCAL_UNITS_PER_MM, "Focal Units per mm"); 499 _tagNameMap.put(CameraSettings.TAG_FOCUS_MODE_1, "Focus Mode"); 500 _tagNameMap.put(CameraSettings.TAG_FOCUS_MODE_2, "Focus Mode"); 501 _tagNameMap.put(CameraSettings.TAG_IMAGE_SIZE, "Image Size"); 502 _tagNameMap.put(CameraSettings.TAG_ISO, "Iso"); 503 _tagNameMap.put(CameraSettings.TAG_LONG_FOCAL_LENGTH, "Long Focal Length"); 504 _tagNameMap.put(CameraSettings.TAG_MACRO_MODE, "Macro Mode"); 505 _tagNameMap.put(CameraSettings.TAG_METERING_MODE, "Metering Mode"); 506 _tagNameMap.put(CameraSettings.TAG_SATURATION, "Saturation"); 507 _tagNameMap.put(CameraSettings.TAG_SELF_TIMER_DELAY, "Self Timer Delay"); 508 _tagNameMap.put(CameraSettings.TAG_SHARPNESS, "Sharpness"); 509 _tagNameMap.put(CameraSettings.TAG_SHORT_FOCAL_LENGTH, "Short Focal Length"); 510 _tagNameMap.put(CameraSettings.TAG_QUALITY, "Quality"); 511 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_2, "Unknown Camera Setting 2"); 512 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_3, "Unknown Camera Setting 3"); 513 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_4, "Unknown Camera Setting 4"); 514 _tagNameMap.put(CameraSettings.TAG_DIGITAL_ZOOM, "Digital Zoom"); 515 _tagNameMap.put(CameraSettings.TAG_FOCUS_TYPE, "Focus Type"); 516 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_7, "Unknown Camera Setting 7"); 517 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_8, "Unknown Camera Setting 8"); 518 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_9, "Unknown Camera Setting 9"); 519 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_10, "Unknown Camera Setting 10"); 520 _tagNameMap.put(CameraSettings.TAG_FLASH_ACTIVITY, "Flash Activity"); 521 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_12, "Unknown Camera Setting 12"); 522 _tagNameMap.put(CameraSettings.TAG_UNKNOWN_13, "Unknown Camera Setting 13"); 523 524 _tagNameMap.put(FocalLength.TAG_WHITE_BALANCE, "White Balance"); 525 _tagNameMap.put(FocalLength.TAG_SEQUENCE_NUMBER, "Sequence Number"); 526 _tagNameMap.put(FocalLength.TAG_AF_POINT_USED, "AF Point Used"); 527 _tagNameMap.put(FocalLength.TAG_FLASH_BIAS, "Flash Bias"); 528 _tagNameMap.put(FocalLength.TAG_AUTO_EXPOSURE_BRACKETING, "Auto Exposure Bracketing"); 529 _tagNameMap.put(FocalLength.TAG_AEB_BRACKET_VALUE, "AEB Bracket Value"); 530 _tagNameMap.put(FocalLength.TAG_SUBJECT_DISTANCE, "Subject Distance"); 531 532 _tagNameMap.put(ShotInfo.TAG_AUTO_ISO, "Auto ISO"); 533 _tagNameMap.put(ShotInfo.TAG_BASE_ISO, "Base ISO"); 534 _tagNameMap.put(ShotInfo.TAG_MEASURED_EV, "Measured EV"); 535 _tagNameMap.put(ShotInfo.TAG_TARGET_APERTURE, "Target Aperture"); 536 _tagNameMap.put(ShotInfo.TAG_TARGET_EXPOSURE_TIME, "Target Exposure Time"); 537 _tagNameMap.put(ShotInfo.TAG_EXPOSURE_COMPENSATION, "Exposure Compensation"); 538 _tagNameMap.put(ShotInfo.TAG_WHITE_BALANCE, "White Balance"); 539 _tagNameMap.put(ShotInfo.TAG_SLOW_SHUTTER, "Slow Shutter"); 540 _tagNameMap.put(ShotInfo.TAG_SEQUENCE_NUMBER, "Sequence Number"); 541 _tagNameMap.put(ShotInfo.TAG_OPTICAL_ZOOM_CODE, "Optical Zoom Code"); 542 _tagNameMap.put(ShotInfo.TAG_CAMERA_TEMPERATURE, "Camera Temperature"); 543 _tagNameMap.put(ShotInfo.TAG_FLASH_GUIDE_NUMBER, "Flash Guide Number"); 544 _tagNameMap.put(ShotInfo.TAG_AF_POINTS_IN_FOCUS, "AF Points in Focus"); 545 _tagNameMap.put(ShotInfo.TAG_FLASH_EXPOSURE_BRACKETING, "Flash Exposure Compensation"); 546 _tagNameMap.put(ShotInfo.TAG_AUTO_EXPOSURE_BRACKETING, "Auto Exposure Bracketing"); 547 _tagNameMap.put(ShotInfo.TAG_AEB_BRACKET_VALUE, "AEB Bracket Value"); 548 _tagNameMap.put(ShotInfo.TAG_CONTROL_MODE, "Control Mode"); 549 _tagNameMap.put(ShotInfo.TAG_FOCUS_DISTANCE_UPPER, "Focus Distance Upper"); 550 _tagNameMap.put(ShotInfo.TAG_FOCUS_DISTANCE_LOWER, "Focus Distance Lower"); 551 _tagNameMap.put(ShotInfo.TAG_F_NUMBER, "F Number"); 552 _tagNameMap.put(ShotInfo.TAG_EXPOSURE_TIME, "Exposure Time"); 553 _tagNameMap.put(ShotInfo.TAG_MEASURED_EV_2, "Measured EV 2"); 554 _tagNameMap.put(ShotInfo.TAG_BULB_DURATION, "Bulb Duration"); 555 _tagNameMap.put(ShotInfo.TAG_CAMERA_TYPE, "Camera Type"); 556 _tagNameMap.put(ShotInfo.TAG_AUTO_ROTATE, "Auto Rotate"); 557 _tagNameMap.put(ShotInfo.TAG_ND_FILTER, "ND Filter"); 558 _tagNameMap.put(ShotInfo.TAG_SELF_TIMER_2, "Self Timer 2"); 559 _tagNameMap.put(ShotInfo.TAG_FLASH_OUTPUT, "Flash Output"); 560 561 _tagNameMap.put(Panorama.TAG_PANORAMA_FRAME_NUMBER, "Panorama Frame Number"); 562 _tagNameMap.put(Panorama.TAG_PANORAMA_DIRECTION, "Panorama Direction"); 563 564 _tagNameMap.put(AFInfo.TAG_NUM_AF_POINTS, "AF Point Count"); 565 _tagNameMap.put(AFInfo.TAG_VALID_AF_POINTS, "Valid AF Point Count"); 566 _tagNameMap.put(AFInfo.TAG_IMAGE_WIDTH, "Image Width"); 567 _tagNameMap.put(AFInfo.TAG_IMAGE_HEIGHT, "Image Height"); 568 _tagNameMap.put(AFInfo.TAG_AF_IMAGE_WIDTH, "AF Image Width"); 569 _tagNameMap.put(AFInfo.TAG_AF_IMAGE_HEIGHT, "AF Image Height"); 570 _tagNameMap.put(AFInfo.TAG_AF_AREA_WIDTH, "AF Area Width"); 571 _tagNameMap.put(AFInfo.TAG_AF_AREA_HEIGHT, "AF Area Height"); 572 _tagNameMap.put(AFInfo.TAG_AF_AREA_X_POSITIONS, "AF Area X Positions"); 573 _tagNameMap.put(AFInfo.TAG_AF_AREA_Y_POSITIONS, "AF Area Y Positions"); 574 _tagNameMap.put(AFInfo.TAG_AF_POINTS_IN_FOCUS, "AF Points in Focus Count"); 575 _tagNameMap.put(AFInfo.TAG_PRIMARY_AF_POINT_1, "Primary AF Point 1"); 576 _tagNameMap.put(AFInfo.TAG_PRIMARY_AF_POINT_2, "Primary AF Point 2"); 577 578 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION, "Long Exposure Noise Reduction"); 579 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS, "Shutter/Auto Exposure-lock Buttons"); 580 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP, "Mirror Lockup"); 581 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL, "Tv/Av And Exposure Level"); 582 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT, "AF-Assist Light"); 583 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE, "Shutter Speed in Av Mode"); 584 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_BRACKETTING, "Auto-Exposure Bracketting Sequence/Auto Cancellation"); 585 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC, "Shutter Curtain Sync"); 586 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_AF_STOP, "Lens Auto-Focus Stop Button Function Switch"); 587 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION, "Auto Reduction of Fill Flash"); 588 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN, "Menu Button Return Position"); 589 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION, "SET Button Function When Shooting"); 590 // _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING, "Sensor Cleaning"); 591 592 _tagNameMap.put(TAG_THUMBNAIL_IMAGE_VALID_AREA, "Thumbnail Image Valid Area"); 593 _tagNameMap.put(TAG_SERIAL_NUMBER_FORMAT, "Serial Number Format"); 594 _tagNameMap.put(TAG_SUPER_MACRO, "Super Macro"); 595 _tagNameMap.put(TAG_DATE_STAMP_MODE, "Date Stamp Mode"); 596 _tagNameMap.put(TAG_MY_COLORS, "My Colors"); 597 _tagNameMap.put(TAG_FIRMWARE_REVISION, "Firmware Revision"); 598 _tagNameMap.put(TAG_CATEGORIES, "Categories"); 599 _tagNameMap.put(TAG_FACE_DETECT_ARRAY_1, "Face Detect Array 1"); 600 _tagNameMap.put(TAG_FACE_DETECT_ARRAY_2, "Face Detect Array 2"); 601 _tagNameMap.put(TAG_AF_INFO_ARRAY_2, "AF Info Array 2"); 602 _tagNameMap.put(TAG_IMAGE_UNIQUE_ID, "Image Unique ID"); 603 _tagNameMap.put(TAG_RAW_DATA_OFFSET, "Raw Data Offset"); 604 _tagNameMap.put(TAG_ORIGINAL_DECISION_DATA_OFFSET, "Original Decision Data Offset"); 605 _tagNameMap.put(TAG_CUSTOM_FUNCTIONS_1D_ARRAY, "Custom Functions (1D) Array"); 606 _tagNameMap.put(TAG_PERSONAL_FUNCTIONS_ARRAY, "Personal Functions Array"); 607 _tagNameMap.put(TAG_PERSONAL_FUNCTION_VALUES_ARRAY, "Personal Function Values Array"); 608 _tagNameMap.put(TAG_FILE_INFO_ARRAY, "File Info Array"); 609 _tagNameMap.put(TAG_AF_POINTS_IN_FOCUS_1D, "AF Points in Focus (1D)"); 610 _tagNameMap.put(TAG_LENS_MODEL, "Lens Model"); 611 _tagNameMap.put(TAG_SERIAL_INFO_ARRAY, "Serial Info Array"); 612 _tagNameMap.put(TAG_DUST_REMOVAL_DATA, "Dust Removal Data"); 613 _tagNameMap.put(TAG_CROP_INFO, "Crop Info"); 614 _tagNameMap.put(TAG_CUSTOM_FUNCTIONS_ARRAY_2, "Custom Functions Array 2"); 615 _tagNameMap.put(TAG_ASPECT_INFO_ARRAY, "Aspect Information Array"); 616 _tagNameMap.put(TAG_PROCESSING_INFO_ARRAY, "Processing Information Array"); 617 _tagNameMap.put(TAG_TONE_CURVE_TABLE, "Tone Curve Table"); 618 _tagNameMap.put(TAG_SHARPNESS_TABLE, "Sharpness Table"); 619 _tagNameMap.put(TAG_SHARPNESS_FREQ_TABLE, "Sharpness Frequency Table"); 620 _tagNameMap.put(TAG_WHITE_BALANCE_TABLE, "White Balance Table"); 621 _tagNameMap.put(TAG_COLOR_BALANCE_ARRAY, "Color Balance Array"); 622 _tagNameMap.put(TAG_MEASURED_COLOR_ARRAY, "Measured Color Array"); 623 _tagNameMap.put(TAG_COLOR_TEMPERATURE, "Color Temperature"); 624 _tagNameMap.put(TAG_CANON_FLAGS_ARRAY, "Canon Flags Array"); 625 _tagNameMap.put(TAG_MODIFIED_INFO_ARRAY, "Modified Information Array"); 626 _tagNameMap.put(TAG_TONE_CURVE_MATCHING, "Tone Curve Matching"); 627 _tagNameMap.put(TAG_WHITE_BALANCE_MATCHING, "White Balance Matching"); 628 _tagNameMap.put(TAG_COLOR_SPACE, "Color Space"); 629 _tagNameMap.put(TAG_PREVIEW_IMAGE_INFO_ARRAY, "Preview Image Info Array"); 630 _tagNameMap.put(TAG_VRD_OFFSET, "VRD Offset"); 631 _tagNameMap.put(TAG_SENSOR_INFO_ARRAY, "Sensor Information Array"); 632 _tagNameMap.put(TAG_COLOR_DATA_ARRAY_2, "Color Data Array 1"); 633 _tagNameMap.put(TAG_COLOR_INFO_ARRAY_2, "Color Data Array 2"); 634 _tagNameMap.put(TAG_CUSTOM_PICTURE_STYLE_FILE_NAME, "Custom Picture Style File Name"); 635 _tagNameMap.put(TAG_COLOR_INFO_ARRAY, "Color Info Array"); 636 _tagNameMap.put(TAG_VIGNETTING_CORRECTION_ARRAY_1, "Vignetting Correction Array 1"); 637 _tagNameMap.put(TAG_VIGNETTING_CORRECTION_ARRAY_2, "Vignetting Correction Array 2"); 638 _tagNameMap.put(TAG_LIGHTING_OPTIMIZER_ARRAY, "Lighting Optimizer Array"); 639 _tagNameMap.put(TAG_LENS_INFO_ARRAY, "Lens Info Array"); 640 _tagNameMap.put(TAG_AMBIANCE_INFO_ARRAY, "Ambiance Info Array"); 641 _tagNameMap.put(TAG_FILTER_INFO_ARRAY, "Filter Info Array"); 398 642 } 399 643 … … 403 647 } 404 648 649 @NotNull 405 650 public String getName() 406 651 { … … 408 653 } 409 654 410 protected HashMap getTagNameMap() 655 @NotNull 656 protected HashMap<Integer, String> getTagNameMap() 411 657 { 412 658 return _tagNameMap; 413 659 } 414 660 415 /** 416 * We need special handling for selected tags. 417 * @param tagType 418 * @param ints 419 */ 420 public void setIntArray(int tagType, int[] ints) 421 { 422 if (tagType == TAG_CANON_CAMERA_STATE_1) { 423 // this single tag has multiple values within 424 int subTagTypeBase = 0xC100; 425 // we intentionally skip the first array member 426 for (int i = 1; i < ints.length; i++) { 427 setInt(subTagTypeBase + i, ints[i]); 428 } 429 } else if (tagType == TAG_CANON_CAMERA_STATE_2) { 430 // this single tag has multiple values within 431 int subTagTypeBase = 0xC200; 432 // we intentionally skip the first array member 433 for (int i = 1; i < ints.length; i++) { 434 setInt(subTagTypeBase + i, ints[i]); 435 } 436 } if (tagType == TAG_CANON_CUSTOM_FUNCTIONS) { 437 // this single tag has multiple values within 438 int subTagTypeBase = 0xC300; 439 // we intentionally skip the first array member 440 for (int i = 1; i < ints.length; i++) { 441 setInt(subTagTypeBase + i + 1, ints[i] & 0x0F); 442 } 443 } else { 444 // no special handling... 445 super.setIntArray(tagType, ints); 661 @Override 662 public void setIntArray(int tagType, @NotNull int[] ints) 663 { 664 // TODO is there some way to drop out 'null' or 'zero' values that are present in the array to reduce the noise? 665 666 // Certain Canon tags contain arrays of values that we split into 'fake' tags as each 667 // index in the array has its own meaning and decoding. 668 // Pick those tags out here and throw away the original array. 669 // Otherwise just add as usual. 670 switch (tagType) { 671 case TAG_CAMERA_SETTINGS_ARRAY: 672 for (int i = 0; i < ints.length; i++) 673 setInt(CameraSettings.OFFSET + i, ints[i]); 674 break; 675 case TAG_FOCAL_LENGTH_ARRAY: 676 for (int i = 0; i < ints.length; i++) 677 setInt(FocalLength.OFFSET + i, ints[i]); 678 break; 679 case TAG_SHOT_INFO_ARRAY: 680 for (int i = 0; i < ints.length; i++) 681 setInt(ShotInfo.OFFSET + i, ints[i]); 682 break; 683 case TAG_PANORAMA_ARRAY: 684 for (int i = 0; i < ints.length; i++) 685 setInt(Panorama.OFFSET + i, ints[i]); 686 break; 687 // TODO the interpretation of the custom functions tag depends upon the camera model 688 // case TAG_CANON_CUSTOM_FUNCTIONS_ARRAY: 689 // int subTagTypeBase = 0xC300; 690 // // we intentionally skip the first array member 691 // for (int i = 1; i < ints.length; i++) 692 // setInt(subTagTypeBase + i + 1, ints[i] & 0x0F); 693 // break; 694 case TAG_AF_INFO_ARRAY: 695 for (int i = 0; i < ints.length; i++) 696 setInt(AFInfo.OFFSET + i, ints[i]); 697 break; 698 default: 699 // no special handling... 700 super.setIntArray(tagType, ints); 701 break; 446 702 } 447 703 } -
trunk/src/com/drew/metadata/exif/CasioType1MakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 14 * 15 * Created by dnoakes on 27-Nov-2002 10:12:05 using IntelliJ IDEA. 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 19 import com.drew. metadata.Directory;20 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 21 25 import com.drew.metadata.TagDescriptor; 22 26 23 27 /** 24 * 28 * Provides human-readable string representations of tag values stored in a <code>CasioType1MakernoteDirectory</code>. 29 * 30 * @author Drew Noakes http://drewnoakes.com 25 31 */ 26 public class CasioType1MakernoteDescriptor extends TagDescriptor 32 public class CasioType1MakernoteDescriptor extends TagDescriptor<CasioType1MakernoteDirectory> 27 33 { 28 public CasioType1MakernoteDescriptor(Directory directory) 34 public CasioType1MakernoteDescriptor(@NotNull CasioType1MakernoteDirectory directory) 29 35 { 30 36 super(directory); 31 37 } 32 38 33 public String getDescription(int tagType) throws MetadataException 39 @Nullable 40 public String getDescription(int tagType) 34 41 { 35 42 switch (tagType) { … … 59 66 return getCcdSensitivityDescription(); 60 67 default: 61 return _directory.getString(tagType); 62 } 63 } 64 65 public String getCcdSensitivityDescription() throws MetadataException 66 { 67 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_CCD_SENSITIVITY)) return null; 68 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_CCD_SENSITIVITY); 68 return super.getDescription(tagType); 69 } 70 } 71 72 @Nullable 73 public String getCcdSensitivityDescription() 74 { 75 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_CCD_SENSITIVITY); 76 77 if (value == null) 78 return null; 79 69 80 switch (value) { 70 81 // these four for QV3000 … … 87 98 } 88 99 89 public String getSaturationDescription() throws MetadataException 90 { 91 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_SATURATION)) return null; 92 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_SATURATION); 100 @Nullable 101 public String getSaturationDescription() 102 { 103 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_SATURATION); 104 105 if (value == null) 106 return null; 107 93 108 switch (value) { 94 109 case 0: … … 103 118 } 104 119 105 public String getContrastDescription() throws MetadataException 106 { 107 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_CONTRAST)) return null; 108 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_CONTRAST); 120 @Nullable 121 public String getContrastDescription() 122 { 123 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_CONTRAST); 124 125 if (value == null) 126 return null; 127 109 128 switch (value) { 110 129 case 0: … … 119 138 } 120 139 121 public String getSharpnessDescription() throws MetadataException 122 { 123 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_SHARPNESS)) return null; 124 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_SHARPNESS); 140 @Nullable 141 public String getSharpnessDescription() 142 { 143 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_SHARPNESS); 144 145 if (value == null) 146 return null; 147 125 148 switch (value) { 126 149 case 0: … … 135 158 } 136 159 137 public String getDigitalZoomDescription() throws MetadataException 138 { 139 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_DIGITAL_ZOOM)) return null; 140 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_DIGITAL_ZOOM); 160 @Nullable 161 public String getDigitalZoomDescription() 162 { 163 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_DIGITAL_ZOOM); 164 165 if (value == null) 166 return null; 167 141 168 switch (value) { 142 169 case 0x10000: … … 153 180 } 154 181 155 public String getWhiteBalanceDescription() throws MetadataException 156 { 157 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_WHITE_BALANCE)) return null; 158 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_WHITE_BALANCE); 182 @Nullable 183 public String getWhiteBalanceDescription() 184 { 185 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_WHITE_BALANCE); 186 187 if (value == null) 188 return null; 189 159 190 switch (value) { 160 191 case 1: … … 165 196 return "Daylight"; 166 197 case 4: 167 return "Flo urescent";198 return "Florescent"; 168 199 case 5: 169 200 return "Shade"; … … 175 206 } 176 207 177 public String getObjectDistanceDescription() throws MetadataException 178 { 179 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_OBJECT_DISTANCE)) return null; 180 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_OBJECT_DISTANCE); 208 @Nullable 209 public String getObjectDistanceDescription() 210 { 211 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_OBJECT_DISTANCE); 212 213 if (value == null) 214 return null; 215 181 216 return value + " mm"; 182 217 } 183 218 184 public String getFlashIntensityDescription() throws MetadataException 185 { 186 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_FLASH_INTENSITY)) return null; 187 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_FLASH_INTENSITY); 219 @Nullable 220 public String getFlashIntensityDescription() 221 { 222 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_FLASH_INTENSITY); 223 224 if (value == null) 225 return null; 226 188 227 switch (value) { 189 228 case 11: … … 198 237 } 199 238 200 public String getFlashModeDescription() throws MetadataException 201 { 202 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_FLASH_MODE)) return null; 203 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_FLASH_MODE); 239 @Nullable 240 public String getFlashModeDescription() 241 { 242 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_FLASH_MODE); 243 244 if (value == null) 245 return null; 246 204 247 switch (value) { 205 248 case 1: … … 218 261 } 219 262 220 public String getFocusingModeDescription() throws MetadataException 221 { 222 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_FOCUSING_MODE)) return null; 223 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_FOCUSING_MODE); 263 @Nullable 264 public String getFocusingModeDescription() 265 { 266 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_FOCUSING_MODE); 267 268 if (value == null) 269 return null; 270 224 271 switch (value) { 225 272 case 2: … … 236 283 } 237 284 238 public String getQualityDescription() throws MetadataException 239 { 240 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_QUALITY)) return null; 241 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_QUALITY); 285 @Nullable 286 public String getQualityDescription() 287 { 288 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_QUALITY); 289 290 if (value == null) 291 return null; 292 242 293 switch (value) { 243 294 case 1: … … 252 303 } 253 304 254 public String getRecordingModeDescription() throws MetadataException 255 { 256 if (!_directory.containsTag(CasioType1MakernoteDirectory.TAG_CASIO_RECORDING_MODE)) return null; 257 int value = _directory.getInt(CasioType1MakernoteDirectory.TAG_CASIO_RECORDING_MODE); 305 @Nullable 306 public String getRecordingModeDescription() 307 { 308 Integer value = _directory.getInteger(CasioType1MakernoteDirectory.TAG_CASIO_RECORDING_MODE); 309 310 if (value == null) 311 return null; 312 258 313 switch (value) { 259 314 case 1: -
trunk/src/com/drew/metadata/exif/CasioType1MakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 29 * Describes tags specific to Casio (type 1) cameras. 30 * 24 31 * A standard TIFF IFD directory but always uses Motorola (Big-Endian) Byte Alignment. 25 32 * Makernote data begins immediately (no header). 33 * 34 * @author Drew Noakes http://drewnoakes.com 26 35 */ 27 36 public class CasioType1MakernoteDirectory extends Directory … … 48 57 public static final int TAG_CASIO_CCD_SENSITIVITY = 0x0014; 49 58 50 protected static final HashMap<Integer, String> tagNameMap = new HashMap<Integer, String>(); 59 @NotNull 60 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 51 61 52 62 static 53 63 { 54 tagNameMap.put (new Integer(TAG_CASIO_CCD_SENSITIVITY), "CCD Sensitivity");55 tagNameMap.put (new Integer(TAG_CASIO_CONTRAST), "Contrast");56 tagNameMap.put (new Integer(TAG_CASIO_DIGITAL_ZOOM), "Digital Zoom");57 tagNameMap.put (new Integer(TAG_CASIO_FLASH_INTENSITY), "Flash Intensity");58 tagNameMap.put (new Integer(TAG_CASIO_FLASH_MODE), "Flash Mode");59 tagNameMap.put (new Integer(TAG_CASIO_FOCUSING_MODE), "Focussing Mode");60 tagNameMap.put (new Integer(TAG_CASIO_OBJECT_DISTANCE), "Object Distance");61 tagNameMap.put (new Integer(TAG_CASIO_QUALITY), "Quality");62 tagNameMap.put (new Integer(TAG_CASIO_RECORDING_MODE), "Recording Mode");63 tagNameMap.put (new Integer(TAG_CASIO_SATURATION), "Saturation");64 tagNameMap.put (new Integer(TAG_CASIO_SHARPNESS), "Sharpness");65 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_1), "Makernote Unknown 1");66 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_2), "Makernote Unknown 2");67 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_3), "Makernote Unknown 3");68 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_4), "Makernote Unknown 4");69 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_5), "Makernote Unknown 5");70 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_6), "Makernote Unknown 6");71 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_7), "Makernote Unknown 7");72 tagNameMap.put (new Integer(TAG_CASIO_UNKNOWN_8), "Makernote Unknown 8");73 tagNameMap.put (new Integer(TAG_CASIO_WHITE_BALANCE), "White Balance");64 _tagNameMap.put(TAG_CASIO_CCD_SENSITIVITY, "CCD Sensitivity"); 65 _tagNameMap.put(TAG_CASIO_CONTRAST, "Contrast"); 66 _tagNameMap.put(TAG_CASIO_DIGITAL_ZOOM, "Digital Zoom"); 67 _tagNameMap.put(TAG_CASIO_FLASH_INTENSITY, "Flash Intensity"); 68 _tagNameMap.put(TAG_CASIO_FLASH_MODE, "Flash Mode"); 69 _tagNameMap.put(TAG_CASIO_FOCUSING_MODE, "Focusing Mode"); 70 _tagNameMap.put(TAG_CASIO_OBJECT_DISTANCE, "Object Distance"); 71 _tagNameMap.put(TAG_CASIO_QUALITY, "Quality"); 72 _tagNameMap.put(TAG_CASIO_RECORDING_MODE, "Recording Mode"); 73 _tagNameMap.put(TAG_CASIO_SATURATION, "Saturation"); 74 _tagNameMap.put(TAG_CASIO_SHARPNESS, "Sharpness"); 75 _tagNameMap.put(TAG_CASIO_UNKNOWN_1, "Makernote Unknown 1"); 76 _tagNameMap.put(TAG_CASIO_UNKNOWN_2, "Makernote Unknown 2"); 77 _tagNameMap.put(TAG_CASIO_UNKNOWN_3, "Makernote Unknown 3"); 78 _tagNameMap.put(TAG_CASIO_UNKNOWN_4, "Makernote Unknown 4"); 79 _tagNameMap.put(TAG_CASIO_UNKNOWN_5, "Makernote Unknown 5"); 80 _tagNameMap.put(TAG_CASIO_UNKNOWN_6, "Makernote Unknown 6"); 81 _tagNameMap.put(TAG_CASIO_UNKNOWN_7, "Makernote Unknown 7"); 82 _tagNameMap.put(TAG_CASIO_UNKNOWN_8, "Makernote Unknown 8"); 83 _tagNameMap.put(TAG_CASIO_WHITE_BALANCE, "White Balance"); 74 84 } 75 85 … … 79 89 } 80 90 91 @NotNull 81 92 public String getName() 82 93 { … … 84 95 } 85 96 86 protected HashMap getTagNameMap() 97 @NotNull 98 protected HashMap<Integer, String> getTagNameMap() 87 99 { 88 return tagNameMap; 100 return _tagNameMap; 89 101 } 90 102 } -
trunk/src/com/drew/metadata/exif/CasioType2MakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 14 * 15 * Created by dnoakes on 27-Nov-2002 10:12:05 using IntelliJ IDEA. 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 19 import com.drew. metadata.Directory;20 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 21 25 import com.drew.metadata.TagDescriptor; 22 26 23 27 /** 24 * 28 * Provides human-readable string representations of tag values stored in a <code>CasioType2MakernoteDirectory</code>. 29 * 30 * @author Drew Noakes http://drewnoakes.com 25 31 */ 26 public class CasioType2MakernoteDescriptor extends TagDescriptor 32 public class CasioType2MakernoteDescriptor extends TagDescriptor<CasioType2MakernoteDirectory> 27 33 { 28 public CasioType2MakernoteDescriptor(Directory directory) 34 public CasioType2MakernoteDescriptor(@NotNull CasioType2MakernoteDirectory directory) 29 35 { 30 36 super(directory); 31 37 } 32 38 33 public String getDescription(int tagType) throws MetadataException 39 @Nullable 40 public String getDescription(int tagType) 34 41 { 35 42 switch (tagType) { … … 91 98 return getFilterDescription(); 92 99 default: 93 return _directory.getString(tagType); 94 } 95 } 96 97 public String getFilterDescription() throws MetadataException 98 { 99 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FILTER)) return null; 100 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FILTER); 101 switch (value) { 102 case 0: 103 return "Off"; 104 default: 105 return "Unknown (" + value + ")"; 106 } 107 } 108 109 public String getEnhancementDescription() throws MetadataException 110 { 111 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_ENHANCEMENT)) return null; 112 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_ENHANCEMENT); 113 switch (value) { 114 case 0: 115 return "Off"; 116 default: 117 return "Unknown (" + value + ")"; 118 } 119 } 120 121 public String getColourModeDescription() throws MetadataException 122 { 123 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_COLOUR_MODE)) return null; 124 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_COLOUR_MODE); 125 switch (value) { 126 case 0: 127 return "Off"; 128 default: 129 return "Unknown (" + value + ")"; 130 } 131 } 132 133 public String getCcdIsoSensitivityDescription() throws MetadataException 134 { 135 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CCD_ISO_SENSITIVITY)) return null; 136 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CCD_ISO_SENSITIVITY); 100 return super.getDescription(tagType); 101 } 102 } 103 104 @Nullable 105 public String getFilterDescription() 106 { 107 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FILTER); 108 if (value==null) 109 return null; 110 switch (value) { 111 case 0: 112 return "Off"; 113 default: 114 return "Unknown (" + value + ")"; 115 } 116 } 117 118 @Nullable 119 public String getEnhancementDescription() 120 { 121 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_ENHANCEMENT); 122 if (value==null) 123 return null; 124 switch (value) { 125 case 0: 126 return "Off"; 127 default: 128 return "Unknown (" + value + ")"; 129 } 130 } 131 132 @Nullable 133 public String getColourModeDescription() 134 { 135 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_COLOUR_MODE); 136 if (value==null) 137 return null; 138 switch (value) { 139 case 0: 140 return "Off"; 141 default: 142 return "Unknown (" + value + ")"; 143 } 144 } 145 146 @Nullable 147 public String getCcdIsoSensitivityDescription() 148 { 149 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CCD_ISO_SENSITIVITY); 150 if (value==null) 151 return null; 137 152 switch (value) { 138 153 case 0: … … 145 160 } 146 161 147 public String getBestShotModeDescription() throws MetadataException 148 { 149 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_BESTSHOT_MODE)) return null; 150 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_BESTSHOT_MODE); 151 switch (value) { 152 default: 153 return "Unknown (" + value + ")"; 154 } 155 } 156 162 @Nullable 163 public String getBestShotModeDescription() 164 { 165 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_BESTSHOT_MODE); 166 if (value==null) 167 return null; 168 switch (value) { 169 default: 170 return "Unknown (" + value + ")"; 171 } 172 } 173 174 @Nullable 157 175 public String getTimeZoneDescription() 158 176 { 159 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_TIME_ZONE)) return null;160 177 return _directory.getString(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_TIME_ZONE); 161 178 } 162 179 163 public String getFocusMode2Description() throws MetadataException 164 { 165 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCUS_MODE_2)) return null; 166 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCUS_MODE_2); 180 @Nullable 181 public String getFocusMode2Description() 182 { 183 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCUS_MODE_2); 184 if (value==null) 185 return null; 167 186 switch (value) { 168 187 case 1: … … 175 194 } 176 195 177 public String getQualityDescription() throws MetadataException 178 { 179 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_QUALITY)) return null; 180 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_QUALITY); 196 @Nullable 197 public String getQualityDescription() 198 { 199 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_QUALITY); 200 if (value==null) 201 return null; 181 202 switch (value) { 182 203 case 3: … … 187 208 } 188 209 189 public String getSelfTimerDescription() throws MetadataException 190 { 191 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SELF_TIMER)) return null; 192 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SELF_TIMER); 193 switch (value) { 194 case 1: 195 return "Off"; 196 default: 197 return "Unknown (" + value + ")"; 198 } 199 } 200 201 public String getRecordModeDescription() throws MetadataException 202 { 203 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_RECORD_MODE)) return null; 204 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_RECORD_MODE); 210 @Nullable 211 public String getSelfTimerDescription() 212 { 213 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SELF_TIMER); 214 if (value==null) 215 return null; 216 switch (value) { 217 case 1: 218 return "Off"; 219 default: 220 return "Unknown (" + value + ")"; 221 } 222 } 223 224 @Nullable 225 public String getRecordModeDescription() 226 { 227 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_RECORD_MODE); 228 if (value==null) 229 return null; 205 230 switch (value) { 206 231 case 2: … … 211 236 } 212 237 213 public String getFlashDistanceDescription() throws MetadataException 214 { 215 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FLASH_DISTANCE)) return null; 216 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FLASH_DISTANCE); 217 switch (value) { 218 case 0: 219 return "Off"; 220 default: 221 return "Unknown (" + value + ")"; 222 } 223 } 224 225 public String getObjectDistanceDescription() throws MetadataException 226 { 227 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_OBJECT_DISTANCE)) return null; 228 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_OBJECT_DISTANCE); 238 @Nullable 239 public String getFlashDistanceDescription() 240 { 241 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FLASH_DISTANCE); 242 if (value==null) 243 return null; 244 switch (value) { 245 case 0: 246 return "Off"; 247 default: 248 return "Unknown (" + value + ")"; 249 } 250 } 251 252 @Nullable 253 public String getObjectDistanceDescription() 254 { 255 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_OBJECT_DISTANCE); 256 if (value==null) 257 return null; 229 258 return Integer.toString(value) + " mm"; 230 259 } 231 260 232 public String getWhiteBalance2Description() throws MetadataException 233 { 234 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_2)) return null; 235 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_2); 261 @Nullable 262 public String getWhiteBalance2Description() 263 { 264 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_2); 265 if (value==null) 266 return null; 236 267 switch (value) { 237 268 case 0: … … 248 279 } 249 280 281 @Nullable 250 282 public String getWhiteBalanceBiasDescription() 251 283 { 252 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_BIAS)) return null;253 284 return _directory.getString(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_BIAS); 254 285 } 255 286 256 public String getCasioPreviewThumbnailDescription() throws MetadataException257 {258 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CASIO_PREVIEW_THUMBNAIL)) return null;287 @Nullable 288 public String getCasioPreviewThumbnailDescription() 289 { 259 290 final byte[] bytes = _directory.getByteArray(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CASIO_PREVIEW_THUMBNAIL); 291 if (bytes==null) 292 return null; 260 293 return "<" + bytes.length + " bytes of image data>"; 261 294 } 262 295 296 @Nullable 263 297 public String getPrintImageMatchingInfoDescription() 264 298 { 265 299 // TODO research PIM specification http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html 266 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_PRINT_IMAGE_MATCHING_INFO)) return null;267 300 return _directory.getString(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_PRINT_IMAGE_MATCHING_INFO); 268 301 } 269 302 270 public String getSharpnessDescription() throws MetadataException 271 { 272 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SHARPNESS)) return null; 273 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SHARPNESS); 303 @Nullable 304 public String getSharpnessDescription() 305 { 306 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SHARPNESS); 307 if (value==null) 308 return null; 274 309 switch (value) { 275 310 case 0: … … 284 319 } 285 320 286 public String getContrastDescription() throws MetadataException 287 { 288 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CONTRAST)) return null; 289 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CONTRAST); 321 @Nullable 322 public String getContrastDescription() 323 { 324 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_CONTRAST); 325 if (value==null) 326 return null; 290 327 switch (value) { 291 328 case 0: … … 300 337 } 301 338 302 public String getSaturationDescription() throws MetadataException 303 { 304 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SATURATION)) return null; 305 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SATURATION); 339 @Nullable 340 public String getSaturationDescription() 341 { 342 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_SATURATION); 343 if (value==null) 344 return null; 306 345 switch (value) { 307 346 case 0: … … 316 355 } 317 356 318 public String getFocalLengthDescription() throws MetadataException 319 { 320 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCAL_LENGTH)) return null; 321 double value = _directory.getDouble(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCAL_LENGTH); 357 @Nullable 358 public String getFocalLengthDescription() 359 { 360 Double value = _directory.getDoubleObject(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCAL_LENGTH); 361 if (value==null) 362 return null; 322 363 return Double.toString(value / 10d) + " mm"; 323 364 } 324 365 325 public String getWhiteBalance1Description() throws MetadataException 326 { 327 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_1)) return null; 328 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_1); 366 @Nullable 367 public String getWhiteBalance1Description() 368 { 369 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_WHITE_BALANCE_1); 370 if (value==null) 371 return null; 329 372 switch (value) { 330 373 case 0: … … 337 380 return "Tungsten"; 338 381 case 4: 339 return "Flo urescent";382 return "Florescent"; 340 383 case 5: 341 384 return "Manual"; … … 345 388 } 346 389 347 public String getIsoSensitivityDescription() throws MetadataException 348 { 349 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_ISO_SENSITIVITY)) return null; 350 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_ISO_SENSITIVITY); 390 @Nullable 391 public String getIsoSensitivityDescription() 392 { 393 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_ISO_SENSITIVITY); 394 if (value==null) 395 return null; 351 396 switch (value) { 352 397 case 3: … … 363 408 } 364 409 365 public String getFocusMode1Description() throws MetadataException 366 { 367 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCUS_MODE_1)) return null; 368 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCUS_MODE_1); 410 @Nullable 411 public String getFocusMode1Description() 412 { 413 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_FOCUS_MODE_1); 414 if (value==null) 415 return null; 369 416 switch (value) { 370 417 case 0: … … 377 424 } 378 425 379 public String getImageSizeDescription() throws MetadataException 380 { 381 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_IMAGE_SIZE)) return null; 382 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_IMAGE_SIZE); 426 @Nullable 427 public String getImageSizeDescription() 428 { 429 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_IMAGE_SIZE); 430 if (value==null) 431 return null; 383 432 switch (value) { 384 433 case 0: return "640 x 480 pixels"; … … 393 442 } 394 443 395 public String getQualityModeDescription() throws MetadataException 396 { 397 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_QUALITY_MODE)) return null; 398 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_QUALITY_MODE); 444 @Nullable 445 public String getQualityModeDescription() 446 { 447 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_QUALITY_MODE); 448 if (value==null) 449 return null; 399 450 switch (value) { 400 451 case 1: … … 407 458 } 408 459 460 @Nullable 409 461 public String getThumbnailOffsetDescription() 410 462 { 411 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_OFFSET)) return null;412 463 return _directory.getString(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_OFFSET); 413 464 } 414 465 415 public String getThumbnailSizeDescription() throws MetadataException 416 { 417 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_SIZE)) return null; 418 int value = _directory.getInt(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_SIZE); 466 @Nullable 467 public String getThumbnailSizeDescription() 468 { 469 Integer value = _directory.getInteger(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_SIZE); 470 if (value==null) 471 return null; 419 472 return Integer.toString(value) + " bytes"; 420 473 } 421 474 422 public String getThumbnailDimensionsDescription() throws MetadataException423 {424 if (!_directory.containsTag(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_DIMENSIONS)) return null;475 @Nullable 476 public String getThumbnailDimensionsDescription() 477 { 425 478 int[] dimensions = _directory.getIntArray(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_DIMENSIONS); 426 if (dimensions.length!=2) 479 if (dimensions==null || dimensions.length!=2) 427 480 return _directory.getString(CasioType2MakernoteDirectory.TAG_CASIO_TYPE2_THUMBNAIL_DIMENSIONS); 428 481 return dimensions[0] + " x " + dimensions[1] + " pixels"; -
trunk/src/com/drew/metadata/exif/CasioType2MakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 14 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 29 * Describes tags specific to Casio (type 2) cameras. 30 * 24 31 * A standard TIFF IFD directory but always uses Motorola (Big-Endian) Byte Alignment. 25 32 * Makernote data begins after a 6-byte header: "QVC\x00\x00\x00" 33 * 34 * @author Drew Noakes http://drewnoakes.com 26 35 */ 27 36 public class CasioType2MakernoteDirectory extends Directory … … 167 176 public static final int TAG_CASIO_TYPE2_FILTER = 0x3017; 168 177 169 protected static final HashMap tagNameMap = new HashMap(); 178 @NotNull 179 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 170 180 171 181 static 172 182 { 173 // TODO add names 174 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_THUMBNAIL_DIMENSIONS), "Thumbnail Dimensions");175 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_THUMBNAIL_SIZE), "Thumbnail Size");176 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_THUMBNAIL_OFFSET), "Thumbnail Offset");177 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_QUALITY_MODE), "Quality Mode");178 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_IMAGE_SIZE), "Image Size");179 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_FOCUS_MODE_1), "Focus Mode");180 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_ISO_SENSITIVITY), "ISO Sensitivity");181 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_WHITE_BALANCE_1), "White Balance");182 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_FOCAL_LENGTH), "Focal Length");183 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_SATURATION), "Saturation");184 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_CONTRAST), "Contrast");185 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_SHARPNESS), "Sharpness");186 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_PRINT_IMAGE_MATCHING_INFO), "Print Image Matching (PIM) Info");187 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_CASIO_PREVIEW_THUMBNAIL), "Casio Preview Thumbnail");188 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_WHITE_BALANCE_BIAS), "White Balance Bias");189 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_WHITE_BALANCE_2), "White Balance");190 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_OBJECT_DISTANCE), "Object Distance");191 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_FLASH_DISTANCE), "Flash Distance");192 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_RECORD_MODE), "Record Mode");193 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_SELF_TIMER), "Self Timer");194 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_QUALITY), "Quality");195 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_FOCUS_MODE_2), "Focus Mode");196 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_TIME_ZONE), "Time Zone");197 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_BESTSHOT_MODE), "BestShot Mode");198 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_CCD_ISO_SENSITIVITY), "CCD ISO Sensitivity");199 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_COLOUR_MODE), "Colour Mode");200 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_ENHANCEMENT), "Enhancement");201 tagNameMap.put (new Integer(TAG_CASIO_TYPE2_FILTER), "Filter");183 // TODO add missing names 184 _tagNameMap.put(TAG_CASIO_TYPE2_THUMBNAIL_DIMENSIONS, "Thumbnail Dimensions"); 185 _tagNameMap.put(TAG_CASIO_TYPE2_THUMBNAIL_SIZE, "Thumbnail Size"); 186 _tagNameMap.put(TAG_CASIO_TYPE2_THUMBNAIL_OFFSET, "Thumbnail Offset"); 187 _tagNameMap.put(TAG_CASIO_TYPE2_QUALITY_MODE, "Quality Mode"); 188 _tagNameMap.put(TAG_CASIO_TYPE2_IMAGE_SIZE, "Image Size"); 189 _tagNameMap.put(TAG_CASIO_TYPE2_FOCUS_MODE_1, "Focus Mode"); 190 _tagNameMap.put(TAG_CASIO_TYPE2_ISO_SENSITIVITY, "ISO Sensitivity"); 191 _tagNameMap.put(TAG_CASIO_TYPE2_WHITE_BALANCE_1, "White Balance"); 192 _tagNameMap.put(TAG_CASIO_TYPE2_FOCAL_LENGTH, "Focal Length"); 193 _tagNameMap.put(TAG_CASIO_TYPE2_SATURATION, "Saturation"); 194 _tagNameMap.put(TAG_CASIO_TYPE2_CONTRAST, "Contrast"); 195 _tagNameMap.put(TAG_CASIO_TYPE2_SHARPNESS, "Sharpness"); 196 _tagNameMap.put(TAG_CASIO_TYPE2_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 197 _tagNameMap.put(TAG_CASIO_TYPE2_CASIO_PREVIEW_THUMBNAIL, "Casio Preview Thumbnail"); 198 _tagNameMap.put(TAG_CASIO_TYPE2_WHITE_BALANCE_BIAS, "White Balance Bias"); 199 _tagNameMap.put(TAG_CASIO_TYPE2_WHITE_BALANCE_2, "White Balance"); 200 _tagNameMap.put(TAG_CASIO_TYPE2_OBJECT_DISTANCE, "Object Distance"); 201 _tagNameMap.put(TAG_CASIO_TYPE2_FLASH_DISTANCE, "Flash Distance"); 202 _tagNameMap.put(TAG_CASIO_TYPE2_RECORD_MODE, "Record Mode"); 203 _tagNameMap.put(TAG_CASIO_TYPE2_SELF_TIMER, "Self Timer"); 204 _tagNameMap.put(TAG_CASIO_TYPE2_QUALITY, "Quality"); 205 _tagNameMap.put(TAG_CASIO_TYPE2_FOCUS_MODE_2, "Focus Mode"); 206 _tagNameMap.put(TAG_CASIO_TYPE2_TIME_ZONE, "Time Zone"); 207 _tagNameMap.put(TAG_CASIO_TYPE2_BESTSHOT_MODE, "BestShot Mode"); 208 _tagNameMap.put(TAG_CASIO_TYPE2_CCD_ISO_SENSITIVITY, "CCD ISO Sensitivity"); 209 _tagNameMap.put(TAG_CASIO_TYPE2_COLOUR_MODE, "Colour Mode"); 210 _tagNameMap.put(TAG_CASIO_TYPE2_ENHANCEMENT, "Enhancement"); 211 _tagNameMap.put(TAG_CASIO_TYPE2_FILTER, "Filter"); 202 212 } 203 213 … … 207 217 } 208 218 219 @NotNull 209 220 public String getName() 210 221 { … … 212 223 } 213 224 214 protected HashMap getTagNameMap() 215 { 216 return tagNameMap; 225 @NotNull 226 protected HashMap<Integer, String> getTagNameMap() 227 { 228 return _tagNameMap; 217 229 } 218 230 } -
trunk/src/com/drew/metadata/exif/DataFormat.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 23 import com.drew.lang.annotations.NotNull; 17 24 import com.drew.metadata.MetadataException; 18 25 19 26 /** 20 27 * An enumeration of data formats used in the TIFF IFDs. 28 * 29 * @author Drew Noakes http://drewnoakes.com 21 30 */ 22 31 public class DataFormat 23 32 { 24 public static final DataFormat BYTE = new DataFormat("BYTE", 1); 25 public static final DataFormat STRING = new DataFormat("STRING", 2); 26 public static final DataFormat USHORT = new DataFormat("USHORT", 3); 27 public static final DataFormat ULONG = new DataFormat("ULONG", 4); 28 public static final DataFormat URATIONAL = new DataFormat("URATIONAL", 5); 29 public static final DataFormat SBYTE = new DataFormat("SBYTE", 6); 30 public static final DataFormat UNDEFINED = new DataFormat("UNDEFINED", 7); 31 public static final DataFormat SSHORT = new DataFormat("SSHORT", 8); 32 public static final DataFormat SLONG = new DataFormat("SLONG", 9); 33 public static final DataFormat SRATIONAL = new DataFormat("SRATIONAL", 10); 34 public static final DataFormat SINGLE = new DataFormat("SINGLE", 11); 35 public static final DataFormat DOUBLE = new DataFormat("DOUBLE", 12); 33 @NotNull public static final DataFormat BYTE = new DataFormat("BYTE", 1); 34 @NotNull public static final DataFormat STRING = new DataFormat("STRING", 2); 35 @NotNull public static final DataFormat USHORT = new DataFormat("USHORT", 3); 36 @NotNull public static final DataFormat ULONG = new DataFormat("ULONG", 4); 37 @NotNull public static final DataFormat URATIONAL = new DataFormat("URATIONAL", 5); 38 @NotNull public static final DataFormat SBYTE = new DataFormat("SBYTE", 6); 39 @NotNull public static final DataFormat UNDEFINED = new DataFormat("UNDEFINED", 7); 40 @NotNull public static final DataFormat SSHORT = new DataFormat("SSHORT", 8); 41 @NotNull public static final DataFormat SLONG = new DataFormat("SLONG", 9); 42 @NotNull public static final DataFormat SRATIONAL = new DataFormat("SRATIONAL", 10); 43 @NotNull public static final DataFormat SINGLE = new DataFormat("SINGLE", 11); 44 @NotNull public static final DataFormat DOUBLE = new DataFormat("DOUBLE", 12); 36 45 37 private final String myName;38 private final int value; 46 @NotNull private final String _name; 47 private final int _value; 39 48 49 @NotNull 40 50 public static DataFormat fromValue(int value) throws MetadataException 41 51 { … … 59 69 } 60 70 61 private DataFormat(String name, int value) 71 private DataFormat(@NotNull String name, int value) 62 72 { 63 myName = name;64 this.value = value;73 _name = name; 74 _value = value; 65 75 } 66 76 67 77 public int getValue() 68 78 { 69 return value; 79 return _value; 70 80 } 71 81 82 @NotNull 72 83 public String toString() 73 84 { 74 return myName;85 return _name; 75 86 } 76 87 } -
trunk/src/com/drew/metadata/exif/ExifInteropDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 12-Nov-2002 22:27:34 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 19 import com.drew. metadata.Directory;20 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 21 25 import com.drew.metadata.TagDescriptor; 22 26 23 27 /** 28 * Provides human-readable string representations of tag values stored in a <code>ExifInteropDirectory</code>. 24 29 * 30 * @author Drew Noakes http://drewnoakes.com 25 31 */ 26 public class ExifInteropDescriptor extends TagDescriptor 32 public class ExifInteropDescriptor extends TagDescriptor<ExifInteropDirectory> 27 33 { 28 public ExifInteropDescriptor(Directory directory) 34 public ExifInteropDescriptor(@NotNull ExifInteropDirectory directory) 29 35 { 30 36 super(directory); 31 37 } 32 38 33 public String getDescription(int tagType) throws MetadataException 39 @Nullable 40 public String getDescription(int tagType) 34 41 { 35 42 switch (tagType) { … … 39 46 return getInteropVersionDescription(); 40 47 default: 41 return _directory.getString(tagType);48 return super.getDescription(tagType); 42 49 } 43 50 } 44 51 45 public String getInteropVersionDescription() throws MetadataException 52 @Nullable 53 public String getInteropVersionDescription() 46 54 { 47 if (!_directory.containsTag(ExifInteropDirectory.TAG_INTEROP_VERSION)) return null;48 55 int[] ints = _directory.getIntArray(ExifInteropDirectory.TAG_INTEROP_VERSION); 49 return ExifDescriptor.convertBytesToVersionString(ints);56 return convertBytesToVersionString(ints, 2); 50 57 } 51 58 59 @Nullable 52 60 public String getInteropIndexDescription() 53 61 { 54 if (!_directory.containsTag(ExifInteropDirectory.TAG_INTEROP_INDEX)) return null; 55 String interopIndex = _directory.getString(ExifInteropDirectory.TAG_INTEROP_INDEX).trim(); 56 if ("R98".equalsIgnoreCase(interopIndex)) { 57 return "Recommended Exif Interoperability Rules (ExifR98)"; 58 } else { 59 return "Unknown (" + interopIndex + ")"; 60 } 62 String value = _directory.getString(ExifInteropDirectory.TAG_INTEROP_INDEX); 63 64 if (value==null) 65 return null; 66 67 return "R98".equalsIgnoreCase(value.trim()) 68 ? "Recommended Exif Interoperability Rules (ExifR98)" 69 : "Unknown (" + value + ")"; 61 70 } 62 71 } -
trunk/src/com/drew/metadata/exif/ExifInteropDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 26-Nov-2002 10:58:13 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 29 * Describes Exif interoperability tags. 24 30 * 31 * @author Drew Noakes http://drewnoakes.com 25 32 */ 26 33 public class ExifInteropDirectory extends Directory … … 32 39 public static final int TAG_RELATED_IMAGE_LENGTH = 0x1002; 33 40 34 protected static final HashMap tagNameMap; 41 @NotNull 42 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 35 43 36 44 static 37 45 { 38 tagNameMap = new HashMap(); 39 tagNameMap.put(new Integer(TAG_INTEROP_INDEX), "Interoperability Index"); 40 tagNameMap.put(new Integer(TAG_INTEROP_VERSION), "Interoperability Version"); 41 tagNameMap.put(new Integer(TAG_RELATED_IMAGE_FILE_FORMAT), "Related Image File Format"); 42 tagNameMap.put(new Integer(TAG_RELATED_IMAGE_WIDTH), "Related Image Width"); 43 tagNameMap.put(new Integer(TAG_RELATED_IMAGE_LENGTH), "Related Image Length"); 46 _tagNameMap.put(TAG_INTEROP_INDEX, "Interoperability Index"); 47 _tagNameMap.put(TAG_INTEROP_VERSION, "Interoperability Version"); 48 _tagNameMap.put(TAG_RELATED_IMAGE_FILE_FORMAT, "Related Image File Format"); 49 _tagNameMap.put(TAG_RELATED_IMAGE_WIDTH, "Related Image Width"); 50 _tagNameMap.put(TAG_RELATED_IMAGE_LENGTH, "Related Image Length"); 44 51 } 45 52 … … 49 56 } 50 57 58 @NotNull 51 59 public String getName() 52 60 { … … 54 62 } 55 63 56 protected HashMap getTagNameMap() 64 @NotNull 65 protected HashMap<Integer, String> getTagNameMap() 57 66 { 58 return tagNameMap; 67 return _tagNameMap; 59 68 } 60 69 } -
trunk/src/com/drew/metadata/exif/ExifReader.java
r4231 r6127 1 1 /* 2 * EXIFExtractor.java2 * Copyright 2002-2012 Drew Noakes 3 3 * 4 * This class based upon code from Jhead, a C program for extracting and5 * manipulating the Exif data within files written by Matthias Wandel.6 * http://www.sentex.net/~mwandel/jhead/4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 7 * 8 * Jhead is public domain software - that is, you can do whatever you want 9 * with it, and include it software that is licensed under the GNU or the 10 * BSD license, or whatever other licence you choose, including proprietary 11 * closed source licenses. Similarly, I release this Java version under the 12 * same license, though I do ask that you leave this header in tact. 8 * http://www.apache.org/licenses/LICENSE-2.0 13 9 * 14 * If you make modifications to this code that you think would benefit the 15 * wider community, please send me a copy and I'll post it on my site. Unlike 16 * Jhead, this code (as it stands) only supports reading of Exif data - no 17 * manipulation, and no thumbnail stuff. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 18 15 * 19 * If you make use of this code, I'd appreciate hearing about it. 20 * drew.noakes@drewnoakes.com 21 * Latest version of this software kept at 22 * http://drewnoakes.com/ 16 * More information about this project is available at: 23 17 * 24 * Created on 28 April 2002, 23:54 25 * Modified 04 Aug 2002 26 * - Renamed constants to be inline with changes to ExifTagValues interface 27 * - Substituted usage of JDK 1.4 features (java.nio package) 28 * Modified 29 Oct 2002 (v1.2) 29 * - Proper traversing of Exif file structure and complete refactor & tidy of 30 * the codebase (a few unnoticed bugs removed) 31 * - Reads makernote data for 6 families of camera (5 makes) 32 * - Tags now stored in directories... use the IFD_* constants to refer to the 33 * image file directory you require (Exif, Interop, GPS and Makernote*) -- 34 * this avoids collisions where two tags share the same code 35 * - Takes componentCount of unknown tags into account 36 * - Now understands GPS tags (thanks to Colin Briton for his help with this) 37 * - Some other bug fixes, pointed out by users around the world. Thanks! 38 * Modified 27 Nov 2002 (v2.0) 39 * - Renamed to ExifReader 40 * - Moved to new package com.drew.metadata.exif 41 * Modified since, however changes have not been logged. See release notes for 42 * library-wide modifications. 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 43 20 */ 44 21 package com.drew.metadata.exif; 45 22 46 import com.drew.imaging.jpeg.JpegProcessingException; 47 import com.drew.imaging.jpeg.JpegSegmentData; 48 import com.drew.imaging.jpeg.JpegSegmentReader; 23 import com.drew.lang.BufferBoundsException; 24 import com.drew.lang.BufferReader; 49 25 import com.drew.lang.Rational; 26 import com.drew.lang.annotations.NotNull; 50 27 import com.drew.metadata.Directory; 51 28 import com.drew.metadata.Metadata; 52 29 import com.drew.metadata.MetadataReader; 53 30 54 import java.io.File; 55 import java.io.InputStream; 56 import java.util.HashMap; 31 import java.util.HashSet; 32 import java.util.Set; 57 33 58 34 /** 59 * Extracts Exifdata from a JPEG header segment, providing information about the60 * camera/scanner/capture device (if available). Information is encapsulated in61 * an <code>Metadata</code> object.62 * @author 35 * Decodes Exif binary data, populating a {@link Metadata} object with tag values in {@link ExifSubIFDDirectory}, 36 * {@link ExifThumbnailDirectory}, {@link ExifInteropDirectory}, {@link GpsDirectory} and one of the many camera makernote directories. 37 * 38 * @author Drew Noakes http://drewnoakes.com 63 39 */ 64 40 public class ExifReader implements MetadataReader 65 41 { 66 /** 67 * The JPEG segment as an array of bytes. 68 */ 69 private final byte[] _data; 70 71 /** 72 * Represents the native byte ordering used in the JPEG segment. If true, 73 * then we're using Motorolla ordering (Big endian), else we're using Intel 74 * ordering (Little endian). 75 */ 76 private boolean _isMotorollaByteOrder; 77 78 /** 79 * Bean instance to store information about the image and camera/scanner/capture 80 * device. 81 */ 82 private Metadata _metadata; 83 84 /** 85 * The number of bytes used per format descriptor. 86 */ 87 private static final int[] BYTES_PER_FORMAT = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8}; 88 89 /** 90 * The number of formats known. 91 */ 42 // TODO extract a reusable TiffReader from this class with hooks for special tag handling and subdir following 43 44 /** The number of bytes used per format descriptor. */ 45 @NotNull 46 private static final int[] BYTES_PER_FORMAT = { 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }; 47 48 /** The number of formats known. */ 92 49 private static final int MAX_FORMAT_CODE = 12; 93 50 94 51 // Format types 95 // Note: Cannot use the DataFormat enumeration in the case statement that uses these tags.96 / / Is there a better way?52 // TODO use an enum for these? 53 /** An 8-bit unsigned integer. */ 97 54 private static final int FMT_BYTE = 1; 55 /** A fixed-length character string. */ 98 56 private static final int FMT_STRING = 2; 57 /** An unsigned 16-bit integer. */ 99 58 private static final int FMT_USHORT = 3; 59 /** An unsigned 32-bit integer. */ 100 60 private static final int FMT_ULONG = 4; 101 61 private static final int FMT_URATIONAL = 5; 62 /** An 8-bit signed integer. */ 102 63 private static final int FMT_SBYTE = 6; 103 64 private static final int FMT_UNDEFINED = 7; 65 /** A signed 16-bit integer. */ 104 66 private static final int FMT_SSHORT = 8; 67 /** A signed 32-bit integer. */ 105 68 private static final int FMT_SLONG = 9; 106 69 private static final int FMT_SRATIONAL = 10; 70 /** A 32-bit floating point number. */ 107 71 private static final int FMT_SINGLE = 11; 72 /** A 64-bit floating point number. */ 108 73 private static final int FMT_DOUBLE = 12; 109 74 110 public static final int TAG_EXIF_OFFSET = 0x8769; 75 /** This tag is a pointer to the Exif SubIFD. */ 76 public static final int TAG_EXIF_SUB_IFD_OFFSET = 0x8769; 77 /** This tag is a pointer to the Exif Interop IFD. */ 111 78 public static final int TAG_INTEROP_OFFSET = 0xA005; 79 /** This tag is a pointer to the Exif GPS IFD. */ 112 80 public static final int TAG_GPS_INFO_OFFSET = 0x8825; 113 public static final int TAG_MAKER_NOTE = 0x927C; 81 /** This tag is a pointer to the Exif Makernote IFD. */ 82 public static final int TAG_MAKER_NOTE_OFFSET = 0x927C; 114 83 115 84 public static final int TIFF_HEADER_START_OFFSET = 6; 116 117 /**118 * Creates an ExifReader for a JpegSegmentData object.119 * @param segmentData120 */121 public ExifReader(JpegSegmentData segmentData)122 {123 this(segmentData.getSegment(JpegSegmentReader.SEGMENT_APP1));124 }125 126 /**127 * Creates an ExifReader for a Jpeg file.128 * @param file129 * @throws JpegProcessingException130 */131 public ExifReader(File file) throws JpegProcessingException132 {133 this(new JpegSegmentReader(file).readSegment(JpegSegmentReader.SEGMENT_APP1));134 }135 136 /**137 * Creates an ExifReader for a Jpeg stream.138 * @param is JPEG stream. Stream will be closed.139 */140 public ExifReader(InputStream is) throws JpegProcessingException141 {142 this(new JpegSegmentReader(is).readSegment(JpegSegmentReader.SEGMENT_APP1));143 }144 145 /**146 * Creates an ExifReader for the given JPEG header segment.147 */148 public ExifReader(byte[] data)149 {150 _data = data;151 }152 153 /**154 * Performs the Exif data extraction, returning a new instance of <code>Metadata</code>.155 */156 public Metadata extract()157 {158 return extract(new Metadata());159 }160 85 161 86 /** 162 87 * Performs the Exif data extraction, adding found values to the specified 163 88 * instance of <code>Metadata</code>. 89 * 90 * @param reader The buffer reader from which Exif data should be read. 91 * @param metadata The Metadata object into which extracted values should be merged. 164 92 */ 165 public Metadata extract(Metadata metadata) 166 { 167 _metadata = metadata; 168 if (_data==null) 169 return _metadata; 170 171 // once we know there's some data, create the directory and start working on it 172 ExifDirectory directory = (ExifDirectory)_metadata.getDirectory(ExifDirectory.class); 93 public void extract(@NotNull final BufferReader reader, @NotNull Metadata metadata) 94 { 95 final ExifSubIFDDirectory directory = metadata.getOrCreateDirectory(ExifSubIFDDirectory.class); 173 96 174 97 // check for the header length 175 if ( _data.length<=14) {98 if (reader.getLength() <= 14) { 176 99 directory.addError("Exif data segment must contain at least 14 bytes"); 177 return _metadata;100 return; 178 101 } 179 102 180 103 // check for the header preamble 181 if (!"Exif\0\0".equals(new String(_data, 0, 6))) { 182 directory.addError("Exif data segment doesn't begin with 'Exif'"); 183 return _metadata; 184 } 185 104 try { 105 if (!reader.getString(0, 6).equals("Exif\0\0")) { 106 directory.addError("Exif data segment doesn't begin with 'Exif'"); 107 return; 108 } 109 110 extractIFD(metadata, metadata.getOrCreateDirectory(ExifIFD0Directory.class), TIFF_HEADER_START_OFFSET, reader); 111 } catch (BufferBoundsException e) { 112 directory.addError("Exif data segment ended prematurely"); 113 } 114 } 115 116 /** 117 * Performs the Exif data extraction on a TIFF/RAW, adding found values to the specified 118 * instance of <code>Metadata</code>. 119 * 120 * @param reader The BufferReader from which TIFF data should be read. 121 * @param metadata The Metadata object into which extracted values should be merged. 122 */ 123 public void extractTiff(@NotNull BufferReader reader, @NotNull Metadata metadata) 124 { 125 final ExifIFD0Directory directory = metadata.getOrCreateDirectory(ExifIFD0Directory.class); 126 127 try { 128 extractIFD(metadata, directory, 0, reader); 129 } catch (BufferBoundsException e) { 130 directory.addError("Exif data segment ended prematurely"); 131 } 132 } 133 134 private void extractIFD(@NotNull Metadata metadata, @NotNull final ExifIFD0Directory directory, int tiffHeaderOffset, @NotNull BufferReader reader) throws BufferBoundsException 135 { 186 136 // this should be either "MM" or "II" 187 String byteOrderIdentifier = new String(_data, 6, 2); 188 if (!setByteOrder(byteOrderIdentifier)) { 137 String byteOrderIdentifier = reader.getString(tiffHeaderOffset, 2); 138 139 if ("MM".equals(byteOrderIdentifier)) { 140 reader.setMotorolaByteOrder(true); 141 } else if ("II".equals(byteOrderIdentifier)) { 142 reader.setMotorolaByteOrder(false); 143 } else { 189 144 directory.addError("Unclear distinction between Motorola/Intel byte ordering: " + byteOrderIdentifier); 190 return _metadata;145 return; 191 146 } 192 147 193 148 // Check the next two values for correctness. 194 if (get16Bits(8)!=0x2a) { 195 directory.addError("Invalid Exif start - should have 0x2A at offset 8 in Exif header"); 196 return _metadata; 197 } 198 199 int firstDirectoryOffset = get32Bits(10) + TIFF_HEADER_START_OFFSET; 200 201 // David Ekholm sent an digital camera image that has this problem 202 if (firstDirectoryOffset>=_data.length - 1) { 149 final int tiffMarker = reader.getUInt16(2 + tiffHeaderOffset); 150 151 final int standardTiffMarker = 0x002A; 152 final int olympusRawTiffMarker = 0x4F52; // for ORF files 153 final int panasonicRawTiffMarker = 0x0055; // for RW2 files 154 155 if (tiffMarker != standardTiffMarker && tiffMarker != olympusRawTiffMarker && tiffMarker != panasonicRawTiffMarker) { 156 directory.addError("Unexpected TIFF marker after byte order identifier: 0x" + Integer.toHexString(tiffMarker)); 157 return; 158 } 159 160 int firstDirectoryOffset = reader.getInt32(4 + tiffHeaderOffset) + tiffHeaderOffset; 161 162 // David Ekholm sent a digital camera image that has this problem 163 if (firstDirectoryOffset >= reader.getLength() - 1) { 203 164 directory.addError("First exif directory offset is beyond end of Exif data segment"); 204 165 // First directory normally starts 14 bytes in -- try it here and catch another error in the worst case … … 206 167 } 207 168 208 HashMap processedDirectoryOffsets = new HashMap(); 209 210 // 0th IFD (we merge with Exif IFD) 211 processDirectory(directory, processedDirectoryOffsets, firstDirectoryOffset, TIFF_HEADER_START_OFFSET); 169 Set<Integer> processedDirectoryOffsets = new HashSet<Integer>(); 170 171 processDirectory(directory, processedDirectoryOffsets, firstDirectoryOffset, tiffHeaderOffset, metadata, reader); 212 172 213 173 // after the extraction process, if we have the correct tags, we may be able to store thumbnail information 214 storeThumbnailBytes(directory, TIFF_HEADER_START_OFFSET); 215 216 return _metadata; 217 } 218 219 private void storeThumbnailBytes(ExifDirectory exifDirectory, int tiffHeaderOffset) 220 { 221 if (!exifDirectory.containsTag(ExifDirectory.TAG_COMPRESSION)) 222 return; 223 224 if (!exifDirectory.containsTag(ExifDirectory.TAG_THUMBNAIL_LENGTH) || 225 !exifDirectory.containsTag(ExifDirectory.TAG_THUMBNAIL_OFFSET)) 226 return; 227 228 try { 229 int offset = exifDirectory.getInt(ExifDirectory.TAG_THUMBNAIL_OFFSET); 230 int length = exifDirectory.getInt(ExifDirectory.TAG_THUMBNAIL_LENGTH); 231 byte[] result = new byte[length]; 232 for (int i = 0; i<result.length; i++) { 233 result[i] = _data[tiffHeaderOffset + offset + i]; 234 } 235 exifDirectory.setByteArray(ExifDirectory.TAG_THUMBNAIL_DATA, result); 236 } catch (Throwable e) { 237 exifDirectory.addError("Unable to extract thumbnail: " + e.getMessage()); 238 } 239 } 240 241 private boolean setByteOrder(String byteOrderIdentifier) 242 { 243 if ("MM".equals(byteOrderIdentifier)) { 244 _isMotorollaByteOrder = true; 245 } else if ("II".equals(byteOrderIdentifier)) { 246 _isMotorollaByteOrder = false; 247 } else { 248 return false; 249 } 250 return true; 174 ExifThumbnailDirectory thumbnailDirectory = metadata.getDirectory(ExifThumbnailDirectory.class); 175 if (thumbnailDirectory!=null && thumbnailDirectory.containsTag(ExifThumbnailDirectory.TAG_THUMBNAIL_COMPRESSION)) { 176 Integer offset = thumbnailDirectory.getInteger(ExifThumbnailDirectory.TAG_THUMBNAIL_OFFSET); 177 Integer length = thumbnailDirectory.getInteger(ExifThumbnailDirectory.TAG_THUMBNAIL_LENGTH); 178 if (offset != null && length != null) { 179 try { 180 byte[] thumbnailData = reader.getBytes(tiffHeaderOffset + offset, length); 181 thumbnailDirectory.setThumbnailData(thumbnailData); 182 } catch (BufferBoundsException ex) { 183 directory.addError("Invalid thumbnail data specification: " + ex.getMessage()); 184 } 185 } 186 } 251 187 } 252 188 253 189 /** 254 190 * Process one of the nested Tiff IFD directories. 191 * <p/> 192 * Header 255 193 * 2 bytes: number of tags 256 * for each tag 257 * 2 bytes: tag type 258 * 2 bytes: format code 259 * 4 bytes: component count 194 * <p/> 195 * Then for each tag 196 * 2 bytes: tag type 197 * 2 bytes: format code 198 * 4 bytes: component count 260 199 */ 261 private void processDirectory(Directory directory, HashMap processedDirectoryOffsets, int dirStartOffset, int tiffHeaderOffset)200 private void processDirectory(@NotNull Directory directory, @NotNull Set<Integer> processedDirectoryOffsets, int dirStartOffset, int tiffHeaderOffset, @NotNull final Metadata metadata, @NotNull final BufferReader reader) throws BufferBoundsException 262 201 { 263 202 // check for directories we've already visited to avoid stack overflows when recursive/cyclic directory structures exist 264 if (processedDirectoryOffsets.contains Key(newInteger(dirStartOffset)))203 if (processedDirectoryOffsets.contains(Integer.valueOf(dirStartOffset))) 265 204 return; 266 205 267 206 // remember that we've visited this directory so that we don't visit it again later 268 processedDirectoryOffsets.put(new Integer(dirStartOffset), "processed"); 269 270 if (dirStartOffset>=_data.length || dirStartOffset<0) { 271 directory.addError("Ignored directory marked to start outside data segement"); 272 return; 273 } 274 275 if (!isDirectoryLengthValid(dirStartOffset, tiffHeaderOffset)) { 207 processedDirectoryOffsets.add(dirStartOffset); 208 209 if (dirStartOffset >= reader.getLength() || dirStartOffset < 0) { 210 directory.addError("Ignored directory marked to start outside data segment"); 211 return; 212 } 213 214 // First two bytes in the IFD are the number of tags in this directory 215 int dirTagCount = reader.getUInt16(dirStartOffset); 216 217 int dirLength = (2 + (12 * dirTagCount) + 4); 218 if (dirLength + dirStartOffset > reader.getLength()) { 276 219 directory.addError("Illegally sized directory"); 277 220 return; 278 221 } 279 222 280 // First two bytes in the IFD are the number of tags in this directory281 int dirTagCount = get16Bits(dirStartOffset);282 283 223 // Handle each tag in this directory 284 for (int tagNumber = 0; tagNumber<dirTagCount; tagNumber++) 285 { 224 for (int tagNumber = 0; tagNumber < dirTagCount; tagNumber++) { 286 225 final int tagOffset = calculateTagOffset(dirStartOffset, tagNumber); 287 226 288 227 // 2 bytes for the tag type 289 final int tagType = get16Bits(tagOffset);228 final int tagType = reader.getUInt16(tagOffset); 290 229 291 230 // 2 bytes for the format code 292 final int formatCode = get16Bits(tagOffset + 2); 293 if (formatCode<1 || formatCode>MAX_FORMAT_CODE) { 294 directory.addError("Invalid format code: " + formatCode); 295 continue; 231 final int formatCode = reader.getUInt16(tagOffset + 2); 232 if (formatCode < 1 || formatCode > MAX_FORMAT_CODE) { 233 // This error suggests that we are processing at an incorrect index and will generate 234 // rubbish until we go out of bounds (which may be a while). Exit now. 235 directory.addError("Invalid TIFF tag format code: " + formatCode); 236 return; 296 237 } 297 238 298 239 // 4 bytes dictate the number of components in this tag's data 299 final int componentCount = get32Bits(tagOffset + 4);300 if (componentCount <0) {301 directory.addError("Negative component count in EXIF");240 final int componentCount = reader.getInt32(tagOffset + 4); 241 if (componentCount < 0) { 242 directory.addError("Negative TIFF tag component count"); 302 243 continue; 303 244 } 304 245 // each component may have more than one byte... calculate the total number of bytes 305 246 final int byteCount = componentCount * BYTES_PER_FORMAT[formatCode]; 306 final int tagValueOffset = calculateTagValueOffset(byteCount, tagOffset, tiffHeaderOffset); 307 if (tagValueOffset<0 || tagValueOffset > _data.length) { 308 directory.addError("Illegal pointer offset value in EXIF"); 247 final int tagValueOffset; 248 if (byteCount > 4) { 249 // If it's bigger than 4 bytes, the dir entry contains an offset. 250 // dirEntryOffset must be passed, as some makernote implementations (e.g. FujiFilm) incorrectly use an 251 // offset relative to the start of the makernote itself, not the TIFF segment. 252 final int offsetVal = reader.getInt32(tagOffset + 8); 253 if (offsetVal + byteCount > reader.getLength()) { 254 // Bogus pointer offset and / or byteCount value 255 directory.addError("Illegal TIFF tag pointer offset"); 256 continue; 257 } 258 tagValueOffset = tiffHeaderOffset + offsetVal; 259 } else { 260 // 4 bytes or less and value is in the dir entry itself 261 tagValueOffset = tagOffset + 8; 262 } 263 264 if (tagValueOffset < 0 || tagValueOffset > reader.getLength()) { 265 directory.addError("Illegal TIFF tag pointer offset"); 309 266 continue; 310 267 } … … 312 269 // Check that this tag isn't going to allocate outside the bounds of the data array. 313 270 // This addresses an uncommon OutOfMemoryError. 314 if (byteCount < 0 || tagValueOffset + byteCount > _data.length) 315 { 271 if (byteCount < 0 || tagValueOffset + byteCount > reader.getLength()) { 316 272 directory.addError("Illegal number of bytes: " + byteCount); 317 273 continue; 318 274 } 319 275 320 // Calculate the value as an offset for cases where the tag represents directory321 final int subdirOffset = tiffHeaderOffset + get32Bits(tagValueOffset);322 323 276 switch (tagType) { 324 case TAG_EXIF_OFFSET: 325 processDirectory(_metadata.getDirectory(ExifDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 277 case TAG_EXIF_SUB_IFD_OFFSET: { 278 final int subdirOffset = tiffHeaderOffset + reader.getInt32(tagValueOffset); 279 processDirectory(metadata.getOrCreateDirectory(ExifSubIFDDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 326 280 continue; 327 case TAG_INTEROP_OFFSET: 328 processDirectory(_metadata.getDirectory(ExifInteropDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 281 } 282 case TAG_INTEROP_OFFSET: { 283 final int subdirOffset = tiffHeaderOffset + reader.getInt32(tagValueOffset); 284 processDirectory(metadata.getOrCreateDirectory(ExifInteropDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 329 285 continue; 330 case TAG_GPS_INFO_OFFSET: 331 processDirectory(_metadata.getDirectory(GpsDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 286 } 287 case TAG_GPS_INFO_OFFSET: { 288 final int subdirOffset = tiffHeaderOffset + reader.getInt32(tagValueOffset); 289 processDirectory(metadata.getOrCreateDirectory(GpsDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 332 290 continue; 333 case TAG_MAKER_NOTE: 334 processMakerNote(tagValueOffset, processedDirectoryOffsets, tiffHeaderOffset); 291 } 292 case TAG_MAKER_NOTE_OFFSET: { 293 processMakerNote(tagValueOffset, processedDirectoryOffsets, tiffHeaderOffset, metadata, reader); 335 294 continue; 336 default: 337 processTag(directory, tagType, tagValueOffset, componentCount, formatCode); 295 } 296 default: { 297 processTag(directory, tagType, tagValueOffset, componentCount, formatCode, reader); 338 298 break; 299 } 339 300 } 340 301 } … … 342 303 // at the end of each IFD is an optional link to the next IFD 343 304 final int finalTagOffset = calculateTagOffset(dirStartOffset, dirTagCount); 344 int nextDirectoryOffset = get32Bits(finalTagOffset);345 if (nextDirectoryOffset !=0) {305 int nextDirectoryOffset = reader.getInt32(finalTagOffset); 306 if (nextDirectoryOffset != 0) { 346 307 nextDirectoryOffset += tiffHeaderOffset; 347 if (nextDirectoryOffset >=_data.length) {308 if (nextDirectoryOffset >= reader.getLength()) { 348 309 // Last 4 bytes of IFD reference another IFD with an address that is out of bounds 349 310 // Note this could have been caused by jhead 1.3 cropping too much … … 353 314 return; 354 315 } 355 // the next directory is of same type as this one 356 processDirectory(directory, processedDirectoryOffsets, nextDirectoryOffset, tiffHeaderOffset); 357 } 358 } 359 360 private void processMakerNote(int subdirOffset, HashMap processedDirectoryOffsets, int tiffHeaderOffset) 316 // TODO in Exif, the only known 'follower' IFD is the thumbnail one, however this may not be the case 317 final ExifThumbnailDirectory nextDirectory = metadata.getOrCreateDirectory(ExifThumbnailDirectory.class); 318 processDirectory(nextDirectory, processedDirectoryOffsets, nextDirectoryOffset, tiffHeaderOffset, metadata, reader); 319 } 320 } 321 322 private void processMakerNote(int subdirOffset, @NotNull Set<Integer> processedDirectoryOffsets, int tiffHeaderOffset, @NotNull final Metadata metadata, @NotNull BufferReader reader) throws BufferBoundsException 361 323 { 362 324 // Determine the camera model and makernote format 363 Directory exifDirectory = _metadata.getDirectory(ExifDirectory.class); 364 365 if (exifDirectory==null) 366 return; 367 368 String cameraModel = exifDirectory.getString(ExifDirectory.TAG_MAKE); 369 final String firstTwoChars = new String(_data, subdirOffset, 2); 370 final String firstThreeChars = new String(_data, subdirOffset, 3); 371 final String firstFourChars = new String(_data, subdirOffset, 4); 372 final String firstFiveChars = new String(_data, subdirOffset, 5); 373 final String firstSixChars = new String(_data, subdirOffset, 6); 374 final String firstSevenChars = new String(_data, subdirOffset, 7); 375 final String firstEightChars = new String(_data, subdirOffset, 8); 376 if ("OLYMP".equals(firstFiveChars) || "EPSON".equals(firstFiveChars) || "AGFA".equals(firstFourChars)) 377 { 325 Directory ifd0Directory = metadata.getDirectory(ExifIFD0Directory.class); 326 327 if (ifd0Directory==null) 328 return; 329 330 String cameraModel = ifd0Directory.getString(ExifIFD0Directory.TAG_MAKE); 331 332 //final String firstTwoChars = reader.getString(subdirOffset, 2); 333 final String firstThreeChars = reader.getString(subdirOffset, 3); 334 final String firstFourChars = reader.getString(subdirOffset, 4); 335 final String firstFiveChars = reader.getString(subdirOffset, 5); 336 final String firstSixChars = reader.getString(subdirOffset, 6); 337 final String firstSevenChars = reader.getString(subdirOffset, 7); 338 final String firstEightChars = reader.getString(subdirOffset, 8); 339 final String firstTwelveChars = reader.getString(subdirOffset, 12); 340 341 if ("OLYMP".equals(firstFiveChars) || "EPSON".equals(firstFiveChars) || "AGFA".equals(firstFourChars)) { 378 342 // Olympus Makernote 379 // Epson and Agfa use Olypus maker note standard, see: 380 // http://www.ozhiker.com/electronics/pjmt/jpeg_info/ 381 processDirectory(_metadata.getDirectory(OlympusMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset); 382 } 383 else if (cameraModel!=null && cameraModel.trim().toUpperCase().startsWith("NIKON")) 384 { 385 if ("Nikon".equals(firstFiveChars)) 386 { 343 // Epson and Agfa use Olympus maker note standard: http://www.ozhiker.com/electronics/pjmt/jpeg_info/ 344 processDirectory(metadata.getOrCreateDirectory(OlympusMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset, metadata, reader); 345 } else if (cameraModel != null && cameraModel.trim().toUpperCase().startsWith("NIKON")) { 346 if ("Nikon".equals(firstFiveChars)) { 387 347 /* There are two scenarios here: 388 348 * Type 1: ** … … 393 353 * :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200 394 354 */ 395 if (_data[subdirOffset+6]==1) 396 processDirectory(_metadata.getDirectory(NikonType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset); 397 else if (_data[subdirOffset+6]==2) 398 processDirectory(_metadata.getDirectory(NikonType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 18, subdirOffset + 10); 399 else 400 exifDirectory.addError("Unsupported makernote data ignored."); 401 } 355 switch (reader.getUInt8(subdirOffset + 6)) { 356 case 1: 357 processDirectory(metadata.getOrCreateDirectory(NikonType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 8, tiffHeaderOffset, metadata, reader); 358 break; 359 case 2: 360 processDirectory(metadata.getOrCreateDirectory(NikonType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 18, subdirOffset + 10, metadata, reader); 361 break; 362 default: 363 ifd0Directory.addError("Unsupported Nikon makernote data ignored."); 364 break; 365 } 366 } else { 367 // The IFD begins with the first MakerNote byte (no ASCII name). This occurs with CoolPix 775, E990 and D1 models. 368 processDirectory(metadata.getOrCreateDirectory(NikonType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 369 } 370 } else if ("SONY CAM".equals(firstEightChars) || "SONY DSC".equals(firstEightChars)) { 371 processDirectory(metadata.getOrCreateDirectory(SonyType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset, metadata, reader); 372 } else if ("SIGMA\u0000\u0000\u0000".equals(firstEightChars) || "FOVEON\u0000\u0000".equals(firstEightChars)) { 373 processDirectory(metadata.getOrCreateDirectory(SigmaMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 10, tiffHeaderOffset, metadata, reader); 374 } else if ("SEMC MS\u0000\u0000\u0000\u0000\u0000".equals(firstTwelveChars)) { 375 // force MM for this directory 376 boolean isMotorola = reader.isMotorolaByteOrder(); 377 reader.setMotorolaByteOrder(true); 378 // skip 12 byte header + 2 for "MM" + 6 379 processDirectory(metadata.getOrCreateDirectory(SonyType6MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 20, tiffHeaderOffset, metadata, reader); 380 reader.setMotorolaByteOrder(isMotorola); 381 } else if ("KDK".equals(firstThreeChars)) { 382 processDirectory(metadata.getOrCreateDirectory(KodakMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 20, tiffHeaderOffset, metadata, reader); 383 } else if ("Canon".equalsIgnoreCase(cameraModel)) { 384 processDirectory(metadata.getOrCreateDirectory(CanonMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 385 } else if (cameraModel != null && cameraModel.toUpperCase().startsWith("CASIO")) { 386 if ("QVC\u0000\u0000\u0000".equals(firstSixChars)) 387 processDirectory(metadata.getOrCreateDirectory(CasioType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 6, tiffHeaderOffset, metadata, reader); 402 388 else 403 { 404 // The IFD begins with the first MakerNote byte (no ASCII name). This occurs with CoolPix 775, E990 and D1 models. 405 processDirectory(_metadata.getDirectory(NikonType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 406 } 407 } 408 else if ("SONY CAM".equals(firstEightChars) || "SONY DSC".equals(firstEightChars)) 409 { 410 processDirectory(_metadata.getDirectory(SonyMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset); 411 } 412 else if ("KDK".equals(firstThreeChars)) 413 { 414 processDirectory(_metadata.getDirectory(KodakMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 20, tiffHeaderOffset); 415 } 416 else if ("Canon".equalsIgnoreCase(cameraModel)) 417 { 418 processDirectory(_metadata.getDirectory(CanonMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 419 } 420 else if (cameraModel!=null && cameraModel.toUpperCase().startsWith("CASIO")) 421 { 422 if ("QVC\u0000\u0000\u0000".equals(firstSixChars)) 423 processDirectory(_metadata.getDirectory(CasioType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 6, tiffHeaderOffset); 424 else 425 processDirectory(_metadata.getDirectory(CasioType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 426 } 427 else if ("FUJIFILM".equals(firstEightChars) || "Fujifilm".equalsIgnoreCase(cameraModel)) 428 { 429 // TODO make this field a passed parameter, to avoid threading issues 430 boolean byteOrderBefore = _isMotorollaByteOrder; 389 processDirectory(metadata.getOrCreateDirectory(CasioType1MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 390 } else if ("FUJIFILM".equals(firstEightChars) || "Fujifilm".equalsIgnoreCase(cameraModel)) { 391 boolean byteOrderBefore = reader.isMotorolaByteOrder(); 431 392 // bug in fujifilm makernote ifd means we temporarily use Intel byte ordering 432 _isMotorollaByteOrder= false;393 reader.setMotorolaByteOrder(false); 433 394 // the 4 bytes after "FUJIFILM" in the makernote point to the start of the makernote 434 395 // IFD, though the offset is relative to the start of the makernote, not the TIFF 435 396 // header (like everywhere else) 436 int ifdStart = subdirOffset + get32Bits(subdirOffset + 8); 437 processDirectory(_metadata.getDirectory(FujifilmMakernoteDirectory.class), processedDirectoryOffsets, ifdStart, tiffHeaderOffset); 438 _isMotorollaByteOrder = byteOrderBefore; 439 } 440 else if (cameraModel!=null && cameraModel.toUpperCase().startsWith("MINOLTA")) 441 { 397 int ifdStart = subdirOffset + reader.getInt32(subdirOffset + 8); 398 processDirectory(metadata.getOrCreateDirectory(FujifilmMakernoteDirectory.class), processedDirectoryOffsets, ifdStart, tiffHeaderOffset, metadata, reader); 399 reader.setMotorolaByteOrder(byteOrderBefore); 400 } else if (cameraModel != null && cameraModel.toUpperCase().startsWith("MINOLTA")) { 442 401 // Cases seen with the model starting with MINOLTA in capitals seem to have a valid Olympus makernote 443 402 // area that commences immediately. 444 processDirectory(_metadata.getDirectory(OlympusMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset); 445 } 446 else if ("KC".equals(firstTwoChars) || "MINOL".equals(firstFiveChars) || "MLY".equals(firstThreeChars) || "+M+M+M+M".equals(firstEightChars)) 447 { 448 // This Konica data is not understood. Header identified in accordance with information at this site: 449 // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html 450 // TODO determine how to process the information described at the above website 451 exifDirectory.addError("Unsupported Konica/Minolta data ignored."); 452 } 453 else if ("KYOCERA".equals(firstSevenChars)) 454 { 403 processDirectory(metadata.getOrCreateDirectory(OlympusMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, tiffHeaderOffset, metadata, reader); 404 } else if ("KYOCERA".equals(firstSevenChars)) { 455 405 // http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html 456 processDirectory(_metadata.getDirectory(KyoceraMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 22, tiffHeaderOffset); 457 } 458 else if ("Panasonic\u0000\u0000\u0000".equals(new String(_data, subdirOffset, 12))) 459 { 406 processDirectory(metadata.getOrCreateDirectory(KyoceraMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 22, tiffHeaderOffset, metadata, reader); 407 } else if ("Panasonic\u0000\u0000\u0000".equals(reader.getString(subdirOffset, 12))) { 460 408 // NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD 461 409 // Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment 462 410 // more information here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html 463 processDirectory(_metadata.getDirectory(PanasonicMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset); 464 } 465 else if ("AOC\u0000".equals(firstFourChars)) 466 { 411 processDirectory(metadata.getOrCreateDirectory(PanasonicMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 12, tiffHeaderOffset, metadata, reader); 412 } else if ("AOC\u0000".equals(firstFourChars)) { 467 413 // NON-Standard TIFF IFD Data using Casio Type 2 Tags 468 414 // IFD has no Next-IFD pointer at end of IFD, and … … 470 416 // Observed for: 471 417 // - Pentax ist D 472 processDirectory(_metadata.getDirectory(CasioType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 6, subdirOffset); 473 } 474 else if (cameraModel!=null && (cameraModel.toUpperCase().startsWith("PENTAX") || cameraModel.toUpperCase().startsWith("ASAHI"))) 475 { 418 processDirectory(metadata.getOrCreateDirectory(CasioType2MakernoteDirectory.class), processedDirectoryOffsets, subdirOffset + 6, subdirOffset, metadata, reader); 419 } else if (cameraModel != null && (cameraModel.toUpperCase().startsWith("PENTAX") || cameraModel.toUpperCase().startsWith("ASAHI"))) { 476 420 // NON-Standard TIFF IFD Data using Pentax Tags 477 421 // IFD has no Next-IFD pointer at end of IFD, and … … 480 424 // - PENTAX Optio 330 481 425 // - PENTAX Optio 430 482 processDirectory(_metadata.getDirectory(PentaxMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, subdirOffset); 483 } 484 else 485 { 426 processDirectory(metadata.getOrCreateDirectory(PentaxMakernoteDirectory.class), processedDirectoryOffsets, subdirOffset, subdirOffset, metadata, reader); 427 // } else if ("KC".equals(firstTwoChars) || "MINOL".equals(firstFiveChars) || "MLY".equals(firstThreeChars) || "+M+M+M+M".equals(firstEightChars)) { 428 // // This Konica data is not understood. Header identified in accordance with information at this site: 429 // // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html 430 // // TODO add support for minolta/konica cameras 431 // exifDirectory.addError("Unsupported Konica/Minolta data ignored."); 432 } else { 486 433 // TODO how to store makernote data when it's not from a supported camera model? 487 434 // this is difficult as the starting offset is not known. we could look for it... 488 exifDirectory.addError("Unsupported makernote data ignored."); 489 } 490 } 491 492 private boolean isDirectoryLengthValid(int dirStartOffset, int tiffHeaderOffset) 493 { 494 int dirTagCount = get16Bits(dirStartOffset); 495 int dirLength = (2 + (12 * dirTagCount) + 4); 496 if (dirLength + dirStartOffset + tiffHeaderOffset>=_data.length) { 497 // Note: Files that had thumbnails trimmed with jhead 1.3 or earlier might trigger this 498 return false; 499 } 500 return true; 501 } 502 503 private void processTag(Directory directory, int tagType, int tagValueOffset, int componentCount, int formatCode) 435 } 436 } 437 438 private void processTag(@NotNull Directory directory, int tagType, int tagValueOffset, int componentCount, int formatCode, @NotNull final BufferReader reader) throws BufferBoundsException 504 439 { 505 440 // Directory simply stores raw values 506 441 // The display side uses a Descriptor class per directory to turn the raw values into 'pretty' descriptions 507 switch (formatCode) 508 { 442 switch (formatCode) { 509 443 case FMT_UNDEFINED: 510 444 // this includes exif user comments 511 final byte[] tagBytes = new byte[componentCount]; 512 final int byteCount = componentCount * BYTES_PER_FORMAT[formatCode]; 513 for (int i=0; i<byteCount; i++) 514 tagBytes[i] = _data[tagValueOffset + i]; 515 directory.setByteArray(tagType, tagBytes); 445 directory.setByteArray(tagType, reader.getBytes(tagValueOffset, componentCount)); 516 446 break; 517 447 case FMT_STRING: 518 directory.setString(tagType, readString(tagValueOffset, componentCount)); 448 String string = reader.getNullTerminatedString(tagValueOffset, componentCount); 449 directory.setString(tagType, string); 450 /* 451 // special handling for certain known tags, proposed by Yuri Binev but left out for now, 452 // as it gives the false impression that the image was captured in the same timezone 453 // in which the string is parsed 454 if (tagType==ExifSubIFDDirectory.TAG_DATETIME || 455 tagType==ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL || 456 tagType==ExifSubIFDDirectory.TAG_DATETIME_DIGITIZED) { 457 String[] datePatterns = { 458 "yyyy:MM:dd HH:mm:ss", 459 "yyyy:MM:dd HH:mm", 460 "yyyy-MM-dd HH:mm:ss", 461 "yyyy-MM-dd HH:mm"}; 462 for (String datePattern : datePatterns) { 463 try { 464 DateFormat parser = new SimpleDateFormat(datePattern); 465 Date date = parser.parse(string); 466 directory.setDate(tagType, date); 467 break; 468 } catch (ParseException ex) { 469 // simply try the next pattern 470 } 471 } 472 } 473 */ 519 474 break; 520 475 case FMT_SRATIONAL: 476 if (componentCount == 1) { 477 directory.setRational(tagType, new Rational(reader.getInt32(tagValueOffset), reader.getInt32(tagValueOffset + 4))); 478 } else if (componentCount > 1) { 479 Rational[] rationals = new Rational[componentCount]; 480 for (int i = 0; i < componentCount; i++) 481 rationals[i] = new Rational(reader.getInt32(tagValueOffset + (8 * i)), reader.getInt32(tagValueOffset + 4 + (8 * i))); 482 directory.setRationalArray(tagType, rationals); 483 } 484 break; 521 485 case FMT_URATIONAL: 522 if (componentCount==1) { 523 Rational rational = new Rational(get32Bits(tagValueOffset), get32Bits(tagValueOffset + 4)); 524 directory.setRational(tagType, rational); 525 } else { 486 if (componentCount == 1) { 487 directory.setRational(tagType, new Rational(reader.getUInt32(tagValueOffset), reader.getUInt32(tagValueOffset + 4))); 488 } else if (componentCount > 1) { 526 489 Rational[] rationals = new Rational[componentCount]; 527 for (int i = 0; i <componentCount; i++)528 rationals[i] = new Rational( get32Bits(tagValueOffset + (8 * i)),get32Bits(tagValueOffset + 4 + (8 * i)));490 for (int i = 0; i < componentCount; i++) 491 rationals[i] = new Rational(reader.getUInt32(tagValueOffset + (8 * i)), reader.getUInt32(tagValueOffset + 4 + (8 * i))); 529 492 directory.setRationalArray(tagType, rationals); 530 493 } 531 494 break; 495 case FMT_SINGLE: 496 if (componentCount == 1) { 497 directory.setFloat(tagType, reader.getFloat32(tagValueOffset)); 498 } else { 499 float[] floats = new float[componentCount]; 500 for (int i = 0; i < componentCount; i++) 501 floats[i] = reader.getFloat32(tagValueOffset + (i * 4)); 502 directory.setFloatArray(tagType, floats); 503 } 504 break; 505 case FMT_DOUBLE: 506 if (componentCount == 1) { 507 directory.setDouble(tagType, reader.getDouble64(tagValueOffset)); 508 } else { 509 double[] doubles = new double[componentCount]; 510 for (int i = 0; i < componentCount; i++) 511 doubles[i] = reader.getDouble64(tagValueOffset + (i * 4)); 512 directory.setDoubleArray(tagType, doubles); 513 } 514 break; 515 516 // 517 // Note that all integral types are stored as int32 internally (the largest supported by TIFF) 518 // 519 532 520 case FMT_SBYTE: 521 if (componentCount == 1) { 522 directory.setInt(tagType, reader.getInt8(tagValueOffset)); 523 } else { 524 int[] bytes = new int[componentCount]; 525 for (int i = 0; i < componentCount; i++) 526 bytes[i] = reader.getInt8(tagValueOffset + i); 527 directory.setIntArray(tagType, bytes); 528 } 529 break; 533 530 case FMT_BYTE: 534 if (componentCount==1) { 535 // this may need to be a byte, but I think casting to int is fine 536 int b = _data[tagValueOffset]; 537 directory.setInt(tagType, b); 531 if (componentCount == 1) { 532 directory.setInt(tagType, reader.getUInt8(tagValueOffset)); 538 533 } else { 539 534 int[] bytes = new int[componentCount]; 540 for (int i = 0; i <componentCount; i++)541 bytes[i] = _data[tagValueOffset + i];535 for (int i = 0; i < componentCount; i++) 536 bytes[i] = reader.getUInt8(tagValueOffset + i); 542 537 directory.setIntArray(tagType, bytes); 543 538 } 544 539 break; 545 case FMT_SINGLE: 546 case FMT_DOUBLE: 547 if (componentCount==1) { 548 int i = _data[tagValueOffset]; 540 case FMT_USHORT: 541 if (componentCount == 1) { 542 int i = reader.getUInt16(tagValueOffset); 549 543 directory.setInt(tagType, i); 550 544 } else { 551 545 int[] ints = new int[componentCount]; 552 for (int i = 0; i <componentCount; i++)553 ints[i] = _data[tagValueOffset +i];546 for (int i = 0; i < componentCount; i++) 547 ints[i] = reader.getUInt16(tagValueOffset + (i * 2)); 554 548 directory.setIntArray(tagType, ints); 555 549 } 556 550 break; 557 case FMT_USHORT:558 551 case FMT_SSHORT: 559 if (componentCount ==1) {560 int i = get16Bits(tagValueOffset);552 if (componentCount == 1) { 553 int i = reader.getInt16(tagValueOffset); 561 554 directory.setInt(tagType, i); 562 555 } else { 563 556 int[] ints = new int[componentCount]; 564 for (int i = 0; i <componentCount; i++)565 ints[i] = get16Bits(tagValueOffset + (i * 2));557 for (int i = 0; i < componentCount; i++) 558 ints[i] = reader.getInt16(tagValueOffset + (i * 2)); 566 559 directory.setIntArray(tagType, ints); 567 560 } … … 569 562 case FMT_SLONG: 570 563 case FMT_ULONG: 571 if (componentCount==1) { 572 int i = get32Bits(tagValueOffset); 564 // NOTE 'long' in this case means 32 bit, not 64 565 if (componentCount == 1) { 566 int i = reader.getInt32(tagValueOffset); 573 567 directory.setInt(tagType, i); 574 568 } else { 575 569 int[] ints = new int[componentCount]; 576 for (int i = 0; i <componentCount; i++)577 ints[i] = get32Bits(tagValueOffset + (i * 4));570 for (int i = 0; i < componentCount; i++) 571 ints[i] = reader.getInt32(tagValueOffset + (i * 4)); 578 572 directory.setIntArray(tagType, ints); 579 573 } … … 584 578 } 585 579 586 private int calculateTagValueOffset(int byteCount, int dirEntryOffset, int tiffHeaderOffset)587 {588 if (byteCount>4) {589 // If its bigger than 4 bytes, the dir entry contains an offset.590 // dirEntryOffset must be passed, as some makernote implementations (e.g. FujiFilm) incorrectly use an591 // offset relative to the start of the makernote itself, not the TIFF segment.592 final int offsetVal = get32Bits(dirEntryOffset + 8);593 if (offsetVal + byteCount>_data.length) {594 // Bogus pointer offset and / or bytecount value595 return -1; // signal error596 }597 return tiffHeaderOffset + offsetVal;598 } else {599 // 4 bytes or less and value is in the dir entry itself600 return dirEntryOffset + 8;601 }602 }603 604 /**605 * Creates a String from the _data buffer starting at the specified offset,606 * and ending where byte=='\0' or where length==maxLength.607 */608 private String readString(int offset, int maxLength)609 {610 int length = 0;611 while ((offset + length)<_data.length && _data[offset + length]!='\0' && length<maxLength)612 length++;613 614 return new String(_data, offset, length);615 }616 617 580 /** 618 581 * Determine the offset at which a given InteropArray entry begins within the specified IFD. 582 * 619 583 * @param dirStartOffset the offset at which the IFD starts 620 * @param entryNumber the zero-based entry number 584 * @param entryNumber the zero-based entry number 621 585 */ 622 586 private int calculateTagOffset(int dirStartOffset, int entryNumber) … … 626 590 return dirStartOffset + 2 + (12 * entryNumber); 627 591 } 628 629 /**630 * Get a 16 bit value from file's native byte order. Between 0x0000 and 0xFFFF.631 */632 private int get16Bits(int offset)633 {634 if (offset<0 || offset+2>_data.length)635 throw new ArrayIndexOutOfBoundsException("attempt to read data outside of exif segment (index " + offset + " where max index is " + (_data.length - 1) + ")");636 637 if (_isMotorollaByteOrder) {638 // Motorola - MSB first639 return (_data[offset] << 8 & 0xFF00) | (_data[offset + 1] & 0xFF);640 } else {641 // Intel ordering - LSB first642 return (_data[offset + 1] << 8 & 0xFF00) | (_data[offset] & 0xFF);643 }644 }645 646 /**647 * Get a 32 bit value from file's native byte order.648 */649 private int get32Bits(int offset)650 {651 if (offset<0 || offset+4>_data.length)652 throw new ArrayIndexOutOfBoundsException("attempt to read data outside of exif segment (index " + offset + " where max index is " + (_data.length - 1) + ")");653 654 if (_isMotorollaByteOrder) {655 // Motorola - MSB first656 return (_data[offset] << 24 & 0xFF000000) |657 (_data[offset + 1] << 16 & 0xFF0000) |658 (_data[offset + 2] << 8 & 0xFF00) |659 (_data[offset + 3] & 0xFF);660 } else {661 // Intel ordering - LSB first662 return (_data[offset + 3] << 24 & 0xFF000000) |663 (_data[offset + 2] << 16 & 0xFF0000) |664 (_data[offset + 1] << 8 & 0xFF00) |665 (_data[offset] & 0xFF);666 }667 }668 592 } -
trunk/src/com/drew/metadata/exif/FujifilmMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 14 * 15 * Created by dnoakes on 27-Nov-2002 10:12:05 using IntelliJ IDEA. 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 19 23 import com.drew.lang.Rational; 20 import com.drew. metadata.Directory;21 import com.drew. metadata.MetadataException;24 import com.drew.lang.annotations.NotNull; 25 import com.drew.lang.annotations.Nullable; 22 26 import com.drew.metadata.TagDescriptor; 23 27 24 28 /** 29 * Provides human-readable string representations of tag values stored in a <code>FujifilmMakernoteDirectory</code>. 30 * <p/> 25 31 * Fujifilm's digicam added the MakerNote tag from the Year2000's model (e.g.Finepix1400, 26 32 * Finepix4700). It uses IFD format and start from ASCII character 'FUJIFILM', and next 4 27 33 * bytes(value 0x000c) points the offset to first IFD entry. Example of actual data 28 34 * structure is shown below. 29 * 35 * <p/> 36 * <pre><code> 30 37 * :0000: 46 55 4A 49 46 49 4C 4D-0C 00 00 00 0F 00 00 00 :0000: FUJIFILM........ 31 38 * :0010: 07 00 04 00 00 00 30 31-33 30 00 10 02 00 08 00 :0010: ......0130...... 32 * 39 * </code></pre> 40 * <p/> 33 41 * There are two big differences to the other manufacturers. 34 42 * - Fujifilm's Exif data uses Motorola align, but MakerNote ignores it and uses Intel … … 37 45 * of TIFF header (same as the other IFD), but Fujifilm counts it from the first byte 38 46 * of MakerNote itself. 47 * 48 * @author Drew Noakes http://drewnoakes.com 39 49 */ 40 public class FujifilmMakernoteDescriptor extends TagDescriptor 50 public class FujifilmMakernoteDescriptor extends TagDescriptor<FujifilmMakernoteDirectory> 41 51 { 42 public FujifilmMakernoteDescriptor(Directory directory) 52 public FujifilmMakernoteDescriptor(@NotNull FujifilmMakernoteDirectory directory) 43 53 { 44 54 super(directory); 45 55 } 46 56 47 public String getDescription(int tagType) throws MetadataException 57 @Nullable 58 public String getDescription(int tagType) 48 59 { 49 60 switch (tagType) { … … 52 63 case FujifilmMakernoteDirectory.TAG_FUJIFILM_WHITE_BALANCE: 53 64 return getWhiteBalanceDescription(); 54 case FujifilmMakernoteDirectory.TAG_FUJIFILM_COLOR: 65 case FujifilmMakernoteDirectory.TAG_FUJIFILM_COLOR_SATURATION: 55 66 return getColorDescription(); 56 67 case FujifilmMakernoteDirectory.TAG_FUJIFILM_TONE: … … 64 75 case FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_MODE: 65 76 return getFocusModeDescription(); 66 case FujifilmMakernoteDirectory.TAG_FUJIFILM_SLOW_SYNCH RO:77 case FujifilmMakernoteDirectory.TAG_FUJIFILM_SLOW_SYNCH: 67 78 return getSlowSyncDescription(); 68 79 case FujifilmMakernoteDirectory.TAG_FUJIFILM_PICTURE_MODE: … … 77 88 return getAutoExposureWarningDescription(); 78 89 default: 79 return _directory.getString(tagType); 80 } 81 } 82 83 public String getAutoExposureWarningDescription() throws MetadataException 84 { 85 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_AE_WARNING)) return null; 86 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_AE_WARNING); 87 switch (value) { 88 case 0: 89 return "AE good"; 90 case 1: 91 return "Over exposed (>1/1000s @ F11)"; 92 default: 93 return "Unknown (" + value + ")"; 94 } 95 } 96 97 public String getFocusWarningDescription() throws MetadataException 98 { 99 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_WARNING)) return null; 100 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_WARNING); 101 switch (value) { 102 case 0: 103 return "Auto focus good"; 104 case 1: 105 return "Out of focus"; 106 default: 107 return "Unknown (" + value + ")"; 108 } 109 } 110 111 public String getBlurWarningDescription() throws MetadataException 112 { 113 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_BLUR_WARNING)) return null; 114 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_BLUR_WARNING); 115 switch (value) { 116 case 0: 117 return "No blur warning"; 118 case 1: 119 return "Blur warning"; 120 default: 121 return "Unknown (" + value + ")"; 122 } 123 } 124 125 public String getContinuousTakingOrAutoBrackettingDescription() throws MetadataException 126 { 127 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING)) return null; 128 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING); 129 switch (value) { 130 case 0: 90 return super.getDescription(tagType); 91 } 92 } 93 94 @Nullable 95 public String getSharpnessDescription() 96 { 97 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_SHARPNESS); 98 if (value==null) 99 return null; 100 switch (value) { 101 case 1: 102 return "Softest"; 103 case 2: 104 return "Soft"; 105 case 3: 106 return "Normal"; 107 case 4: 108 return "Hard"; 109 case 5: 110 return "Hardest"; 111 default: 112 return "Unknown (" + value + ")"; 113 } 114 } 115 116 @Nullable 117 public String getWhiteBalanceDescription() 118 { 119 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_WHITE_BALANCE); 120 if (value==null) 121 return null; 122 switch (value) { 123 case 0: 124 return "Auto"; 125 case 256: 126 return "Daylight"; 127 case 512: 128 return "Cloudy"; 129 case 768: 130 return "DaylightColor-fluorescence"; 131 case 769: 132 return "DaywhiteColor-fluorescence"; 133 case 770: 134 return "White-fluorescence"; 135 case 1024: 136 return "Incandescence"; 137 case 3840: 138 return "Custom white balance"; 139 default: 140 return "Unknown (" + value + ")"; 141 } 142 } 143 144 @Nullable 145 public String getColorDescription() 146 { 147 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_COLOR_SATURATION); 148 if (value==null) 149 return null; 150 switch (value) { 151 case 0: 152 return "Normal (STD)"; 153 case 256: 154 return "High (HARD)"; 155 case 512: 156 return "Low (ORG)"; 157 default: 158 return "Unknown (" + value + ")"; 159 } 160 } 161 162 @Nullable 163 public String getToneDescription() 164 { 165 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_TONE); 166 if (value==null) 167 return null; 168 switch (value) { 169 case 0: 170 return "Normal (STD)"; 171 case 256: 172 return "High (HARD)"; 173 case 512: 174 return "Low (ORG)"; 175 default: 176 return "Unknown (" + value + ")"; 177 } 178 } 179 180 @Nullable 181 public String getFlashModeDescription() 182 { 183 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_FLASH_MODE); 184 if (value==null) 185 return null; 186 switch (value) { 187 case 0: 188 return "Auto"; 189 case 1: 190 return "On"; 191 case 2: 131 192 return "Off"; 132 case 1: 133 return "On"; 134 default: 135 return "Unknown (" + value + ")"; 136 } 137 } 138 139 public String getPictureModeDescription() throws MetadataException 140 { 141 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_PICTURE_MODE)) return null; 142 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_PICTURE_MODE); 193 case 3: 194 return "Red-eye reduction"; 195 default: 196 return "Unknown (" + value + ")"; 197 } 198 } 199 200 @Nullable 201 public String getFlashStrengthDescription() 202 { 203 Rational value = _directory.getRational(FujifilmMakernoteDirectory.TAG_FUJIFILM_FLASH_STRENGTH); 204 if (value==null) 205 return null; 206 return value.toSimpleString(false) + " EV (Apex)"; 207 } 208 209 @Nullable 210 public String getMacroDescription() 211 { 212 return getOnOffDescription(FujifilmMakernoteDirectory.TAG_FUJIFILM_MACRO); 213 } 214 215 @Nullable 216 public String getFocusModeDescription() 217 { 218 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_MODE); 219 if (value==null) 220 return null; 221 switch (value) { 222 case 0: 223 return "Auto focus"; 224 case 1: 225 return "Manual focus"; 226 default: 227 return "Unknown (" + value + ")"; 228 } 229 } 230 231 @Nullable 232 public String getSlowSyncDescription() 233 { 234 return getOnOffDescription(FujifilmMakernoteDirectory.TAG_FUJIFILM_SLOW_SYNCH); 235 } 236 237 @Nullable 238 public String getPictureModeDescription() 239 { 240 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_PICTURE_MODE); 241 if (value==null) 242 return null; 143 243 switch (value) { 144 244 case 0: … … 165 265 } 166 266 167 public String getSlowSyncDescription() throws MetadataException 168 { 169 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_SLOW_SYNCHRO)) return null; 170 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_SLOW_SYNCHRO); 267 @Nullable 268 public String getContinuousTakingOrAutoBrackettingDescription() 269 { 270 return getOnOffDescription(FujifilmMakernoteDirectory.TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING); 271 } 272 273 @Nullable 274 public String getBlurWarningDescription() 275 { 276 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_BLUR_WARNING); 277 if (value==null) 278 return null; 279 switch (value) { 280 case 0: 281 return "No blur warning"; 282 case 1: 283 return "Blur warning"; 284 default: 285 return "Unknown (" + value + ")"; 286 } 287 } 288 289 @Nullable 290 public String getFocusWarningDescription() 291 { 292 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_WARNING); 293 if (value==null) 294 return null; 295 switch (value) { 296 case 0: 297 return "Auto focus good"; 298 case 1: 299 return "Out of focus"; 300 default: 301 return "Unknown (" + value + ")"; 302 } 303 } 304 305 @Nullable 306 public String getAutoExposureWarningDescription() 307 { 308 final Integer value = _directory.getInteger(FujifilmMakernoteDirectory.TAG_FUJIFILM_AE_WARNING); 309 if (value==null) 310 return null; 311 switch (value) { 312 case 0: 313 return "AE good"; 314 case 1: 315 return "Over exposed (>1/1000s @ F11)"; 316 default: 317 return "Unknown (" + value + ")"; 318 } 319 } 320 321 322 @Nullable 323 private String getOnOffDescription(final int tagType) 324 { 325 final Integer value = _directory.getInteger(tagType); 326 if (value==null) 327 return null; 171 328 switch (value) { 172 329 case 0: … … 178 335 } 179 336 } 180 181 public String getFocusModeDescription() throws MetadataException182 {183 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_MODE)) return null;184 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_FOCUS_MODE);185 switch (value) {186 case 0:187 return "Auto focus";188 case 1:189 return "Manual focus";190 default:191 return "Unknown (" + value + ")";192 }193 }194 195 public String getMacroDescription() throws MetadataException196 {197 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_MACRO)) return null;198 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_MACRO);199 switch (value) {200 case 0:201 return "Off";202 case 1:203 return "On";204 default:205 return "Unknown (" + value + ")";206 }207 }208 209 public String getFlashStrengthDescription() throws MetadataException210 {211 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_FLASH_STRENGTH)) return null;212 Rational value = _directory.getRational(FujifilmMakernoteDirectory.TAG_FUJIFILM_FLASH_STRENGTH);213 return value.toSimpleString(false) + " EV (Apex)";214 }215 216 public String getFlashModeDescription() throws MetadataException217 {218 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_FLASH_MODE)) return null;219 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_FLASH_MODE);220 switch (value) {221 case 0:222 return "Auto";223 case 1:224 return "On";225 case 2:226 return "Off";227 case 3:228 return "Red-eye reduction";229 default:230 return "Unknown (" + value + ")";231 }232 }233 234 public String getToneDescription() throws MetadataException235 {236 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_TONE)) return null;237 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_TONE);238 switch (value) {239 case 0:240 return "Normal (STD)";241 case 256:242 return "High (HARD)";243 case 512:244 return "Low (ORG)";245 default:246 return "Unknown (" + value + ")";247 }248 }249 250 public String getColorDescription() throws MetadataException251 {252 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_COLOR)) return null;253 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_COLOR);254 switch (value) {255 case 0:256 return "Normal (STD)";257 case 256:258 return "High";259 case 512:260 return "Low (ORG)";261 default:262 return "Unknown (" + value + ")";263 }264 }265 266 public String getWhiteBalanceDescription() throws MetadataException267 {268 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_WHITE_BALANCE)) return null;269 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_WHITE_BALANCE);270 switch (value) {271 case 0:272 return "Auto";273 case 256:274 return "Daylight";275 case 512:276 return "Cloudy";277 case 768:278 return "DaylightColor-fluorescence";279 case 769:280 return "DaywhiteColor-fluorescence";281 case 770:282 return "White-fluorescence";283 case 1024:284 return "Incandenscense";285 case 3840:286 return "Custom white balance";287 default:288 return "Unknown (" + value + ")";289 }290 }291 292 public String getSharpnessDescription() throws MetadataException293 {294 if (!_directory.containsTag(FujifilmMakernoteDirectory.TAG_FUJIFILM_SHARPNESS)) return null;295 int value = _directory.getInt(FujifilmMakernoteDirectory.TAG_FUJIFILM_SHARPNESS);296 switch (value) {297 case 1:298 return "Softest";299 case 2:300 return "Soft";301 case 3:302 return "Normal";303 case 4:304 return "Hard";305 case 5:306 return "Hardest";307 default:308 return "Unknown (" + value + ")";309 }310 }311 337 } -
trunk/src/com/drew/metadata/exif/FujifilmMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 29 * Describes tags specific to Fujifilm cameras. 24 30 * 31 * @author Drew Noakes http://drewnoakes.com 25 32 */ 26 33 public class FujifilmMakernoteDirectory extends Directory 27 34 { 28 35 public static final int TAG_FUJIFILM_MAKERNOTE_VERSION = 0x0000; 29 public static final int TAG_FUJIFILM_QUALITY = 0x1000; 30 public static final int TAG_FUJIFILM_SHARPNESS = 0x1001; 31 public static final int TAG_FUJIFILM_WHITE_BALANCE = 0x1002; 32 public static final int TAG_FUJIFILM_COLOR = 0x1003; 33 public static final int TAG_FUJIFILM_TONE = 0x1004; 34 public static final int TAG_FUJIFILM_FLASH_MODE = 0x1010; 35 public static final int TAG_FUJIFILM_FLASH_STRENGTH = 0x1011; 36 public static final int TAG_FUJIFILM_MACRO = 0x1020; 37 public static final int TAG_FUJIFILM_FOCUS_MODE = 0x1021; 38 public static final int TAG_FUJIFILM_SLOW_SYNCH RO= 0x1030;39 public static final int TAG_FUJIFILM_PICTURE_MODE = 0x1031; 40 public static final int TAG_FUJIFILM_UNKNOWN_1 = 0x1032; 41 public static final int TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING = 0x1100; 42 public static final int TAG_FUJIFILM_UNKNOWN_2 = 0x1200; 43 public static final int TAG_FUJIFILM_BLUR_WARNING = 0x1300; 44 public static final int TAG_FUJIFILM_FOCUS_WARNING = 0x1301; 45 public static final int TAG_FUJIFILM_AE_WARNING = 0x1302; 36 public static final int TAG_FUJIFILM_QUALITY = 0x1000; // 4096 37 public static final int TAG_FUJIFILM_SHARPNESS = 0x1001; // 4097 38 public static final int TAG_FUJIFILM_WHITE_BALANCE = 0x1002; // 4098 39 public static final int TAG_FUJIFILM_COLOR_SATURATION = 0x1003; // 4099 40 public static final int TAG_FUJIFILM_TONE = 0x1004; // 4100 41 public static final int TAG_FUJIFILM_FLASH_MODE = 0x1010; // 4112 42 public static final int TAG_FUJIFILM_FLASH_STRENGTH = 0x1011; // 4113 43 public static final int TAG_FUJIFILM_MACRO = 0x1020; // 4128 44 public static final int TAG_FUJIFILM_FOCUS_MODE = 0x1021; // 4129 45 public static final int TAG_FUJIFILM_SLOW_SYNCH = 0x1030; // 4144 46 public static final int TAG_FUJIFILM_PICTURE_MODE = 0x1031; // 4145 47 public static final int TAG_FUJIFILM_UNKNOWN_1 = 0x1032; // 4146 48 public static final int TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING = 0x1100; // 4352 49 public static final int TAG_FUJIFILM_UNKNOWN_2 = 0x1200; // 4608 50 public static final int TAG_FUJIFILM_BLUR_WARNING = 0x1300; // 4864 51 public static final int TAG_FUJIFILM_FOCUS_WARNING = 0x1301; // 4865 52 public static final int TAG_FUJIFILM_AE_WARNING = 0x1302; // 4866 46 53 47 protected static final HashMap tagNameMap = new HashMap(); 54 @NotNull 55 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 48 56 49 57 static 50 58 { 51 tagNameMap.put( new Integer(TAG_FUJIFILM_AE_WARNING), "AE Warning");52 tagNameMap.put( new Integer(TAG_FUJIFILM_BLUR_WARNING), "Blur Warning");53 tagNameMap.put( new Integer(TAG_FUJIFILM_COLOR), "Color");54 tagNameMap.put( new Integer(TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING), "Continuous Taking Or Auto Bracketting");55 tagNameMap.put( new Integer(TAG_FUJIFILM_FLASH_MODE), "Flash Mode");56 tagNameMap.put( new Integer(TAG_FUJIFILM_FLASH_STRENGTH), "Flash Strength");57 tagNameMap.put( new Integer(TAG_FUJIFILM_FOCUS_MODE), "FocusMode");58 tagNameMap.put( new Integer(TAG_FUJIFILM_FOCUS_WARNING), "Focus Warning");59 tagNameMap.put (new Integer(TAG_FUJIFILM_MACRO), "Macro");60 tagNameMap.put( new Integer(TAG_FUJIFILM_MAKERNOTE_VERSION), "Makernote Version");61 tagNameMap.put( new Integer(TAG_FUJIFILM_PICTURE_MODE), "Picture Mode");62 tagNameMap.put( new Integer(TAG_FUJIFILM_QUALITY), "Quality");63 tagNameMap.put( new Integer(TAG_FUJIFILM_SHARPNESS), "Sharpness");64 tagNameMap.put( new Integer(TAG_FUJIFILM_SLOW_SYNCHRO), "Slow Synchro");65 tagNameMap.put( new Integer(TAG_FUJIFILM_TONE), "Tone");66 tagNameMap.put( new Integer(TAG_FUJIFILM_UNKNOWN_1), "Makernote Unknown 1");67 tagNameMap.put( new Integer(TAG_FUJIFILM_UNKNOWN_2), "Makernote Unknown 2");68 tagNameMap.put( new Integer(TAG_FUJIFILM_WHITE_BALANCE), "White Balance");59 _tagNameMap.put(TAG_FUJIFILM_MAKERNOTE_VERSION, "Makernote Version"); 60 _tagNameMap.put(TAG_FUJIFILM_QUALITY, "Quality"); 61 _tagNameMap.put(TAG_FUJIFILM_SHARPNESS, "Sharpness"); 62 _tagNameMap.put(TAG_FUJIFILM_WHITE_BALANCE, "White Balance"); 63 _tagNameMap.put(TAG_FUJIFILM_COLOR_SATURATION, "Color Saturation"); 64 _tagNameMap.put(TAG_FUJIFILM_TONE, "Tone (Contrast)"); 65 _tagNameMap.put(TAG_FUJIFILM_FLASH_MODE, "Flash Mode"); 66 _tagNameMap.put(TAG_FUJIFILM_FLASH_STRENGTH, "Flash Strength"); 67 _tagNameMap.put(TAG_FUJIFILM_MACRO, "Macro"); 68 _tagNameMap.put(TAG_FUJIFILM_FOCUS_MODE, "Focus Mode"); 69 _tagNameMap.put(TAG_FUJIFILM_SLOW_SYNCH, "Slow Synch"); 70 _tagNameMap.put(TAG_FUJIFILM_PICTURE_MODE, "Picture Mode"); 71 _tagNameMap.put(TAG_FUJIFILM_UNKNOWN_1, "Makernote Unknown 1"); 72 _tagNameMap.put(TAG_FUJIFILM_CONTINUOUS_TAKING_OR_AUTO_BRACKETTING, "Continuous Taking Or Auto Bracketting"); 73 _tagNameMap.put(TAG_FUJIFILM_UNKNOWN_2, "Makernote Unknown 2"); 74 _tagNameMap.put(TAG_FUJIFILM_BLUR_WARNING, "Blur Warning"); 75 _tagNameMap.put(TAG_FUJIFILM_FOCUS_WARNING, "Focus Warning"); 76 _tagNameMap.put(TAG_FUJIFILM_AE_WARNING, "AE Warning"); 69 77 } 70 78 … … 74 82 } 75 83 84 @NotNull 76 85 public String getName() 77 86 { … … 79 88 } 80 89 81 protected HashMap getTagNameMap() 90 @NotNull 91 protected HashMap<Integer, String> getTagNameMap() 82 92 { 83 return tagNameMap; 93 return _tagNameMap; 84 94 } 85 95 } -
trunk/src/com/drew/metadata/exif/GpsDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 14 * 15 * Created by dnoakes on 12-Nov-2002 22:27:52 using IntelliJ IDEA. 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.GeoLocation; 19 24 import com.drew.lang.Rational; 20 import com.drew. metadata.Directory;21 import com.drew. metadata.MetadataException;25 import com.drew.lang.annotations.NotNull; 26 import com.drew.lang.annotations.Nullable; 22 27 import com.drew.metadata.TagDescriptor; 23 28 29 import java.text.DecimalFormat; 30 24 31 /** 25 * 32 * Provides human-readable string representations of tag values stored in a <code>GpsDirectory</code>. 33 * 34 * @author Drew Noakes http://drewnoakes.com 26 35 */ 27 public class GpsDescriptor extends TagDescriptor 36 public class GpsDescriptor extends TagDescriptor<GpsDirectory> 28 37 { 29 public GpsDescriptor(Directory directory) 38 public GpsDescriptor(@NotNull GpsDirectory directory) 30 39 { 31 40 super(directory); 32 41 } 33 42 34 public String getDescription(int tagType) throws MetadataException 43 @Nullable 44 public String getDescription(int tagType) 35 45 { 36 46 switch (tagType) { 47 case GpsDirectory.TAG_GPS_VERSION_ID: 48 return getGpsVersionIdDescription(); 37 49 case GpsDirectory.TAG_GPS_ALTITUDE: 38 50 return getGpsAltitudeDescription(); … … 57 69 case GpsDirectory.TAG_GPS_TIME_STAMP: 58 70 return getGpsTimeStampDescription(); 71 case GpsDirectory.TAG_GPS_LONGITUDE: 59 72 // three rational numbers -- displayed in HH"MM"SS.ss 60 case GpsDirectory.TAG_GPS_LONGITUDE:61 73 return getGpsLongitudeDescription(); 62 74 case GpsDirectory.TAG_GPS_LATITUDE: 75 // three rational numbers -- displayed in HH"MM"SS.ss 63 76 return getGpsLatitudeDescription(); 77 case GpsDirectory.TAG_GPS_DIFFERENTIAL: 78 return getGpsDifferentialDescription(); 64 79 default: 65 return _directory.getString(tagType); 66 } 67 } 68 69 public String getGpsLatitudeDescription() throws MetadataException 70 { 71 if (!_directory.containsTag(GpsDirectory.TAG_GPS_LATITUDE)) return null; 72 return getHoursMinutesSecondsDescription(GpsDirectory.TAG_GPS_LATITUDE); 73 } 74 75 public String getGpsLongitudeDescription() throws MetadataException 76 { 77 if (!_directory.containsTag(GpsDirectory.TAG_GPS_LONGITUDE)) return null; 78 return getHoursMinutesSecondsDescription(GpsDirectory.TAG_GPS_LONGITUDE); 79 } 80 81 public String getHoursMinutesSecondsDescription(int tagType) throws MetadataException 82 { 83 Rational[] components = _directory.getRationalArray(tagType); 84 // TODO create an HoursMinutesSecods class ?? 85 int deg = components[0].intValue(); 86 float min = components[1].floatValue(); 87 float sec = components[2].floatValue(); 88 // carry fractions of minutes into seconds -- thanks Colin Briton 89 sec += (min % 1) * 60; 90 return String.valueOf(deg) + "\"" + String.valueOf((int)min) + "'" + String.valueOf(sec); 91 } 92 93 public String getGpsTimeStampDescription() throws MetadataException 80 return super.getDescription(tagType); 81 } 82 } 83 84 @Nullable 85 private String getGpsVersionIdDescription() 86 { 87 return convertBytesToVersionString(_directory.getIntArray(GpsDirectory.TAG_GPS_VERSION_ID), 1); 88 } 89 90 @Nullable 91 public String getGpsLatitudeDescription() 92 { 93 GeoLocation location = _directory.getGeoLocation(); 94 95 if (location == null) 96 return null; 97 98 return GeoLocation.decimalToDegreesMinutesSecondsString(location.getLatitude()); 99 } 100 101 @Nullable 102 public String getGpsLongitudeDescription() 103 { 104 GeoLocation location = _directory.getGeoLocation(); 105 106 if (location == null) 107 return null; 108 109 return GeoLocation.decimalToDegreesMinutesSecondsString(location.getLongitude()); 110 } 111 112 @Nullable 113 public String getGpsTimeStampDescription() 94 114 { 95 115 // time in hour, min, sec 96 if (!_directory.containsTag(GpsDirectory.TAG_GPS_TIME_STAMP)) return null;97 116 int[] timeComponents = _directory.getIntArray(GpsDirectory.TAG_GPS_TIME_STAMP); 98 StringBuffer sbuffer = new StringBuffer(); 99 sbuffer.append(timeComponents[0]); 100 sbuffer.append(":"); 101 sbuffer.append(timeComponents[1]); 102 sbuffer.append(":"); 103 sbuffer.append(timeComponents[2]); 104 sbuffer.append(" UTC"); 105 return sbuffer.toString(); 106 } 107 117 if (timeComponents==null) 118 return null; 119 StringBuilder description = new StringBuilder(); 120 description.append(timeComponents[0]); 121 description.append(":"); 122 description.append(timeComponents[1]); 123 description.append(":"); 124 description.append(timeComponents[2]); 125 description.append(" UTC"); 126 return description.toString(); 127 } 128 129 @Nullable 108 130 public String getGpsDestinationReferenceDescription() 109 131 { 110 if (!_directory.containsTag(GpsDirectory.TAG_GPS_DEST_DISTANCE_REF)) return null; 111 String destRef = _directory.getString(GpsDirectory.TAG_GPS_DEST_DISTANCE_REF).trim(); 112 if ("K".equalsIgnoreCase(destRef)) { 132 final String value = _directory.getString(GpsDirectory.TAG_GPS_DEST_DISTANCE_REF); 133 if (value==null) 134 return null; 135 String distanceRef = value.trim(); 136 if ("K".equalsIgnoreCase(distanceRef)) { 113 137 return "kilometers"; 114 } else if ("M".equalsIgnoreCase(d estRef)) {138 } else if ("M".equalsIgnoreCase(distanceRef)) { 115 139 return "miles"; 116 } else if ("N".equalsIgnoreCase(d estRef)) {140 } else if ("N".equalsIgnoreCase(distanceRef)) { 117 141 return "knots"; 118 142 } else { 119 return "Unknown (" + destRef + ")"; 120 } 121 } 122 143 return "Unknown (" + distanceRef + ")"; 144 } 145 } 146 147 @Nullable 123 148 public String getGpsDirectionDescription(int tagType) 124 149 { 125 if (!_directory.containsTag(tagType)) return null; 126 String gpsDirection = _directory.getString(tagType).trim(); 127 return gpsDirection + " degrees"; 128 } 129 150 Rational angle = _directory.getRational(tagType); 151 // provide a decimal version of rational numbers in the description, to avoid strings like "35334/199 degrees" 152 String value = angle != null 153 ? new DecimalFormat("0.##").format(angle.doubleValue()) 154 : _directory.getString(tagType); 155 if (value==null || value.trim().length()==0) 156 return null; 157 return value.trim() + " degrees"; 158 } 159 160 @Nullable 130 161 public String getGpsDirectionReferenceDescription(int tagType) 131 162 { 132 if (!_directory.containsTag(tagType)) return null; 133 String gpsDistRef = _directory.getString(tagType).trim(); 163 final String value = _directory.getString(tagType); 164 if (value==null) 165 return null; 166 String gpsDistRef = value.trim(); 134 167 if ("T".equalsIgnoreCase(gpsDistRef)) { 135 168 return "True direction"; … … 141 174 } 142 175 176 @Nullable 143 177 public String getGpsSpeedRefDescription() 144 178 { 145 if (!_directory.containsTag(GpsDirectory.TAG_GPS_SPEED_REF)) return null; 146 String gpsSpeedRef = _directory.getString(GpsDirectory.TAG_GPS_SPEED_REF).trim(); 179 final String value = _directory.getString(GpsDirectory.TAG_GPS_SPEED_REF); 180 if (value==null) 181 return null; 182 String gpsSpeedRef = value.trim(); 147 183 if ("K".equalsIgnoreCase(gpsSpeedRef)) { 148 184 return "kph"; … … 156 192 } 157 193 194 @Nullable 158 195 public String getGpsMeasureModeDescription() 159 196 { 160 if (!_directory.containsTag(GpsDirectory.TAG_GPS_MEASURE_MODE)) return null; 161 String gpsSpeedMeasureMode = _directory.getString(GpsDirectory.TAG_GPS_MEASURE_MODE).trim(); 197 final String value = _directory.getString(GpsDirectory.TAG_GPS_MEASURE_MODE); 198 if (value==null) 199 return null; 200 String gpsSpeedMeasureMode = value.trim(); 162 201 if ("2".equalsIgnoreCase(gpsSpeedMeasureMode)) { 163 202 return "2-dimensional measurement"; … … 169 208 } 170 209 210 @Nullable 171 211 public String getGpsStatusDescription() 172 212 { 173 if (!_directory.containsTag(GpsDirectory.TAG_GPS_STATUS)) return null; 174 String gpsStatus = _directory.getString(GpsDirectory.TAG_GPS_STATUS).trim(); 213 final String value = _directory.getString(GpsDirectory.TAG_GPS_STATUS); 214 if (value==null) 215 return null; 216 String gpsStatus = value.trim(); 175 217 if ("A".equalsIgnoreCase(gpsStatus)) { 176 return "Measurement in prog ess";218 return "Active (Measurement in progress)"; 177 219 } else if ("V".equalsIgnoreCase(gpsStatus)) { 178 return "Measurement Interoperability"; 220 return "Void (Measurement Interoperability)"; 179 221 } else { 180 222 return "Unknown (" + gpsStatus + ")"; … … 182 224 } 183 225 184 public String getGpsAltitudeRefDescription() throws MetadataException 185 { 186 if (!_directory.containsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF)) return null; 187 int alititudeRef = _directory.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF); 188 if (alititudeRef == 0) { 226 @Nullable 227 public String getGpsAltitudeRefDescription() 228 { 229 Integer value = _directory.getInteger(GpsDirectory.TAG_GPS_ALTITUDE_REF); 230 if (value==null) 231 return null; 232 if (value == 0) 189 233 return "Sea level"; 190 } else { 191 return "Unknown (" + alititudeRef + ")"; 192 } 193 } 194 195 public String getGpsAltitudeDescription() throws MetadataException 196 { 197 if (!_directory.containsTag(GpsDirectory.TAG_GPS_ALTITUDE)) return null; 198 String alititude = _directory.getRational(GpsDirectory.TAG_GPS_ALTITUDE).toSimpleString(true); 199 return alititude + " metres"; 234 if (value == 1) 235 return "Below sea level"; 236 return "Unknown (" + value + ")"; 237 } 238 239 @Nullable 240 public String getGpsAltitudeDescription() 241 { 242 final Rational value = _directory.getRational(GpsDirectory.TAG_GPS_ALTITUDE); 243 if (value==null) 244 return null; 245 return value.intValue() + " metres"; 246 } 247 248 @Nullable 249 public String getGpsDifferentialDescription() 250 { 251 final Integer value = _directory.getInteger(GpsDirectory.TAG_GPS_DIFFERENTIAL); 252 if (value==null) 253 return null; 254 if (value == 0) 255 return "No Correction"; 256 if (value == 1) 257 return "Differential Corrected"; 258 return "Unknown (" + value + ")"; 259 } 260 261 @Nullable 262 public String getDegreesMinutesSecondsDescription() 263 { 264 GeoLocation location = _directory.getGeoLocation(); 265 266 if (location == null) 267 return null; 268 269 return location.toDMSString(); 200 270 } 201 271 } -
trunk/src/com/drew/metadata/exif/GpsDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 26-Nov-2002 11:00:52 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.GeoLocation; 24 import com.drew.lang.Rational; 25 import com.drew.lang.annotations.NotNull; 26 import com.drew.lang.annotations.Nullable; 19 27 import com.drew.metadata.Directory; 20 28 … … 22 30 23 31 /** 32 * Describes Exif tags that contain Global Positioning System (GPS) data. 24 33 * 34 * @author Drew Noakes http://drewnoakes.com 25 35 */ 26 36 public class GpsDirectory extends Directory … … 81 91 public static final int TAG_GPS_DEST_DISTANCE = 0x001A; 82 92 83 protected static final HashMap tagNameMap = new HashMap(); 93 /** Values of "GPS", "CELLID", "WLAN" or "MANUAL" by the EXIF spec. */ 94 public static final int TAG_GPS_PROCESSING_METHOD = 0x001B; 95 public static final int TAG_GPS_AREA_INFORMATION = 0x001C; 96 public static final int TAG_GPS_DATE_STAMP = 0x001D; 97 public static final int TAG_GPS_DIFFERENTIAL = 0x001E; 98 99 @NotNull 100 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 84 101 85 102 static 86 103 { 87 tagNameMap.put(new Integer(TAG_GPS_VERSION_ID), "GPS Version ID"); 88 tagNameMap.put(new Integer(TAG_GPS_LATITUDE_REF), "GPS Latitude Ref"); 89 tagNameMap.put(new Integer(TAG_GPS_LATITUDE), "GPS Latitude"); 90 tagNameMap.put(new Integer(TAG_GPS_LONGITUDE_REF), "GPS Longitude Ref"); 91 tagNameMap.put(new Integer(TAG_GPS_LONGITUDE), "GPS Longitude"); 92 tagNameMap.put(new Integer(TAG_GPS_ALTITUDE_REF), "GPS Altitude Ref"); 93 tagNameMap.put(new Integer(TAG_GPS_ALTITUDE), "GPS Altitude"); 94 tagNameMap.put(new Integer(TAG_GPS_TIME_STAMP), "GPS Time-Stamp"); 95 tagNameMap.put(new Integer(TAG_GPS_SATELLITES), "GPS Satellites"); 96 tagNameMap.put(new Integer(TAG_GPS_STATUS), "GPS Status"); 97 tagNameMap.put(new Integer(TAG_GPS_MEASURE_MODE), "GPS Measure Mode"); 98 tagNameMap.put(new Integer(TAG_GPS_DOP), "GPS DOP"); 99 tagNameMap.put(new Integer(TAG_GPS_SPEED_REF), "GPS Speed Ref"); 100 tagNameMap.put(new Integer(TAG_GPS_SPEED), "GPS Speed"); 101 tagNameMap.put(new Integer(TAG_GPS_TRACK_REF), "GPS Track Ref"); 102 tagNameMap.put(new Integer(TAG_GPS_TRACK), "GPS Track"); 103 tagNameMap.put(new Integer(TAG_GPS_IMG_DIRECTION_REF), "GPS Img Direction Ref"); 104 tagNameMap.put(new Integer(TAG_GPS_IMG_DIRECTION_REF), "GPS Img Direction"); 105 tagNameMap.put(new Integer(TAG_GPS_MAP_DATUM), "GPS Map Datum"); 106 tagNameMap.put(new Integer(TAG_GPS_DEST_LATITUDE_REF), "GPS Dest Latitude Ref"); 107 tagNameMap.put(new Integer(TAG_GPS_DEST_LATITUDE), "GPS Dest Latitude"); 108 tagNameMap.put(new Integer(TAG_GPS_DEST_LONGITUDE_REF), "GPS Dest Longitude Ref"); 109 tagNameMap.put(new Integer(TAG_GPS_DEST_LONGITUDE), "GPS Dest Longitude"); 110 tagNameMap.put(new Integer(TAG_GPS_DEST_BEARING_REF), "GPS Dest Bearing Ref"); 111 tagNameMap.put(new Integer(TAG_GPS_DEST_BEARING), "GPS Dest Bearing"); 112 tagNameMap.put(new Integer(TAG_GPS_DEST_DISTANCE_REF), "GPS Dest Distance Ref"); 113 tagNameMap.put(new Integer(TAG_GPS_DEST_DISTANCE), "GPS Dest Distance"); 104 _tagNameMap.put(TAG_GPS_VERSION_ID, "GPS Version ID"); 105 _tagNameMap.put(TAG_GPS_LATITUDE_REF, "GPS Latitude Ref"); 106 _tagNameMap.put(TAG_GPS_LATITUDE, "GPS Latitude"); 107 _tagNameMap.put(TAG_GPS_LONGITUDE_REF, "GPS Longitude Ref"); 108 _tagNameMap.put(TAG_GPS_LONGITUDE, "GPS Longitude"); 109 _tagNameMap.put(TAG_GPS_ALTITUDE_REF, "GPS Altitude Ref"); 110 _tagNameMap.put(TAG_GPS_ALTITUDE, "GPS Altitude"); 111 _tagNameMap.put(TAG_GPS_TIME_STAMP, "GPS Time-Stamp"); 112 _tagNameMap.put(TAG_GPS_SATELLITES, "GPS Satellites"); 113 _tagNameMap.put(TAG_GPS_STATUS, "GPS Status"); 114 _tagNameMap.put(TAG_GPS_MEASURE_MODE, "GPS Measure Mode"); 115 _tagNameMap.put(TAG_GPS_DOP, "GPS DOP"); 116 _tagNameMap.put(TAG_GPS_SPEED_REF, "GPS Speed Ref"); 117 _tagNameMap.put(TAG_GPS_SPEED, "GPS Speed"); 118 _tagNameMap.put(TAG_GPS_TRACK_REF, "GPS Track Ref"); 119 _tagNameMap.put(TAG_GPS_TRACK, "GPS Track"); 120 _tagNameMap.put(TAG_GPS_IMG_DIRECTION_REF, "GPS Img Direction Ref"); 121 _tagNameMap.put(TAG_GPS_IMG_DIRECTION, "GPS Img Direction"); 122 _tagNameMap.put(TAG_GPS_MAP_DATUM, "GPS Map Datum"); 123 _tagNameMap.put(TAG_GPS_DEST_LATITUDE_REF, "GPS Dest Latitude Ref"); 124 _tagNameMap.put(TAG_GPS_DEST_LATITUDE, "GPS Dest Latitude"); 125 _tagNameMap.put(TAG_GPS_DEST_LONGITUDE_REF, "GPS Dest Longitude Ref"); 126 _tagNameMap.put(TAG_GPS_DEST_LONGITUDE, "GPS Dest Longitude"); 127 _tagNameMap.put(TAG_GPS_DEST_BEARING_REF, "GPS Dest Bearing Ref"); 128 _tagNameMap.put(TAG_GPS_DEST_BEARING, "GPS Dest Bearing"); 129 _tagNameMap.put(TAG_GPS_DEST_DISTANCE_REF, "GPS Dest Distance Ref"); 130 _tagNameMap.put(TAG_GPS_DEST_DISTANCE, "GPS Dest Distance"); 131 _tagNameMap.put(TAG_GPS_PROCESSING_METHOD, "GPS Processing Method"); 132 _tagNameMap.put(TAG_GPS_AREA_INFORMATION, "GPS Area Information"); 133 _tagNameMap.put(TAG_GPS_DATE_STAMP, "GPS Date Stamp"); 134 _tagNameMap.put(TAG_GPS_DIFFERENTIAL, "GPS Differential"); 114 135 } 115 136 … … 119 140 } 120 141 142 @NotNull 121 143 public String getName() 122 144 { … … 124 146 } 125 147 126 protected HashMap getTagNameMap() 148 @NotNull 149 protected HashMap<Integer, String> getTagNameMap() 127 150 { 128 return tagNameMap; 151 return _tagNameMap; 152 } 153 154 /** 155 * Parses various tags in an attempt to obtain a single object representing the latitude and longitude 156 * at which this image was captured. 157 * 158 * @return The geographical location of this image, if possible, otherwise null 159 */ 160 @Nullable 161 public GeoLocation getGeoLocation() 162 { 163 Rational[] latitudes = getRationalArray(GpsDirectory.TAG_GPS_LATITUDE); 164 Rational[] longitudes = getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE); 165 String latitudeRef = getString(GpsDirectory.TAG_GPS_LATITUDE_REF); 166 String longitudeRef = getString(GpsDirectory.TAG_GPS_LONGITUDE_REF); 167 168 // Make sure we have the required values 169 if (latitudes == null || latitudes.length != 3) 170 return null; 171 if (longitudes == null || longitudes.length != 3) 172 return null; 173 if (latitudeRef == null || longitudeRef == null) 174 return null; 175 176 Double lat = GeoLocation.degreesMinutesSecondsToDecimal(latitudes[0], latitudes[1], latitudes[2], latitudeRef.equalsIgnoreCase("S")); 177 Double lon = GeoLocation.degreesMinutesSecondsToDecimal(longitudes[0], longitudes[1], longitudes[2], longitudeRef.equalsIgnoreCase("W")); 178 179 // This can return null, in cases where the conversion was not possible 180 if (lat == null || lon == null) 181 return null; 182 183 return new GeoLocation(lat, lon); 129 184 } 130 185 } -
trunk/src/com/drew/metadata/exif/KodakMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 import com.drew.metadata.Directory; 18 import com.drew.metadata.MetadataException; 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.TagDescriptor; 20 25 21 26 /** 22 * Provides human-readable string versions of the tags stored in a KodakMakernoteDirectory. 27 * Provides human-readable string representations of tag values stored in a <code>KodakMakernoteDirectory</code>. 28 * 23 29 * Thanks to David Carson for the initial version of this class. 30 * 31 * @author Drew Noakes http://drewnoakes.com 24 32 */ 25 public class KodakMakernoteDescriptor extends TagDescriptor 33 public class KodakMakernoteDescriptor extends TagDescriptor<KodakMakernoteDirectory> 26 34 { 27 public KodakMakernoteDescriptor(Directory directory) 28 { 29 super(directory); 30 } 31 32 public String getDescription(int tagType) throws MetadataException 35 public KodakMakernoteDescriptor(@NotNull KodakMakernoteDirectory directory) 33 36 { 34 return _directory.getString(tagType);35 37 super(directory); 38 } 36 39 } -
trunk/src/com/drew/metadata/exif/KodakMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 23 import com.drew.lang.annotations.NotNull; 17 24 import com.drew.metadata.Directory; 18 25 … … 21 28 /** 22 29 * Describes tags specific to Kodak cameras. 30 * 31 * @author Drew Noakes http://drewnoakes.com 23 32 */ 24 33 public class KodakMakernoteDirectory extends Directory 25 34 { 26 protected static final HashMap _tagNameMap = new HashMap(); 27 28 public String getName() 35 @NotNull 36 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 37 38 public KodakMakernoteDirectory() 29 39 { 30 return "KodakMakernote";31 40 this.setDescriptor(new KodakMakernoteDescriptor(this)); 41 } 32 42 33 protected HashMap getTagNameMap() 43 @NotNull 44 public String getName() 34 45 { 35 return _tagNameMap; 36 } 46 return "Kodak Makernote"; 47 } 48 49 @NotNull 50 protected HashMap<Integer, String> getTagNameMap() 51 { 52 return _tagNameMap; 53 } 37 54 } -
trunk/src/com/drew/metadata/exif/KyoceraMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 import com.drew. metadata.Directory;18 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 19 25 import com.drew.metadata.TagDescriptor; 20 26 21 27 /** 22 * Provides human-readable string versions of the tags stored in a KyoceraMakernoteDirectory.23 * 28 * Provides human-readable string representations of tag values stored in a <code>KyoceraMakernoteDirectory</code>. 29 * <p/> 24 30 * Some information about this makernote taken from here: 25 31 * http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html 26 * 32 * <p/> 27 33 * Most manufacturer's MakerNote counts the "offset to data" from the first byte 28 34 * of TIFF header (same as the other IFD), but Kyocera (along with Fujifilm) counts 29 35 * it from the first byte of MakerNote itself. 36 * 37 * @author Drew Noakes http://drewnoakes.com 30 38 */ 31 public class KyoceraMakernoteDescriptor extends TagDescriptor 39 public class KyoceraMakernoteDescriptor extends TagDescriptor<KyoceraMakernoteDirectory> 32 40 { 33 public KyoceraMakernoteDescriptor(Directory directory) 41 public KyoceraMakernoteDescriptor(@NotNull KyoceraMakernoteDirectory directory) 34 42 { 35 43 super(directory); 36 44 } 37 45 38 public String getDescription(int tagType) throws MetadataException 46 @Nullable 47 public String getDescription(int tagType) 39 48 { 40 49 switch (tagType) { … … 44 53 return getProprietaryThumbnailDataDescription(); 45 54 default: 46 return _directory.getString(tagType);55 return super.getDescription(tagType); 47 56 } 48 57 } 49 58 50 public String getPrintImageMatchingInfoDescription() throws MetadataException 59 @Nullable 60 public String getPrintImageMatchingInfoDescription() 51 61 { 52 if (!_directory.containsTag(KyoceraMakernoteDirectory.TAG_KYOCERA_PRINT_IMAGE_MATCHING_INFO)) return null;53 62 byte[] bytes = _directory.getByteArray(KyoceraMakernoteDirectory.TAG_KYOCERA_PRINT_IMAGE_MATCHING_INFO); 63 if (bytes==null) 64 return null; 54 65 return "(" + bytes.length + " bytes)"; 55 66 } 56 67 57 public String getProprietaryThumbnailDataDescription() throws MetadataException 68 @Nullable 69 public String getProprietaryThumbnailDataDescription() 58 70 { 59 if (!_directory.containsTag(KyoceraMakernoteDirectory.TAG_KYOCERA_PROPRIETARY_THUMBNAIL)) return null;60 71 byte[] bytes = _directory.getByteArray(KyoceraMakernoteDirectory.TAG_KYOCERA_PROPRIETARY_THUMBNAIL); 72 if (bytes==null) 73 return null; 61 74 return "(" + bytes.length + " bytes)"; 62 75 } -
trunk/src/com/drew/metadata/exif/KyoceraMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 29 * Describes tags specific to Kyocera and Contax cameras. 24 30 * 31 * @author Drew Noakes http://drewnoakes.com 25 32 */ 26 33 public class KyoceraMakernoteDirectory extends Directory … … 29 36 public static final int TAG_KYOCERA_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 30 37 31 protected static final HashMap tagNameMap = new HashMap(); 38 @NotNull 39 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 32 40 33 41 static 34 42 { 35 tagNameMap.put (new Integer(TAG_KYOCERA_PROPRIETARY_THUMBNAIL), "Proprietary Thumbnail Format Data");36 tagNameMap.put (new Integer(TAG_KYOCERA_PRINT_IMAGE_MATCHING_INFO), "Print Image Matching (PIM) Info");43 _tagNameMap.put(TAG_KYOCERA_PROPRIETARY_THUMBNAIL, "Proprietary Thumbnail Format Data"); 44 _tagNameMap.put(TAG_KYOCERA_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 37 45 } 38 46 … … 42 50 } 43 51 52 @NotNull 44 53 public String getName() 45 54 { … … 47 56 } 48 57 49 protected HashMap getTagNameMap() 58 @NotNull 59 protected HashMap<Integer, String> getTagNameMap() 50 60 { 51 return tagNameMap; 61 return _tagNameMap; 52 62 } 53 63 } -
trunk/src/com/drew/metadata/exif/NikonType1MakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 23 import com.drew.lang.Rational; 18 import com.drew. metadata.Directory;19 import com.drew. metadata.MetadataException;24 import com.drew.lang.annotations.NotNull; 25 import com.drew.lang.annotations.Nullable; 20 26 import com.drew.metadata.TagDescriptor; 21 27 22 28 /** 23 * Provides human-readable string versions of the tags stored in a NikonType1MakernoteDirectory. 29 * Provides human-readable string representations of tag values stored in a <code>NikonType1MakernoteDirectory</code>. 30 * <p/> 24 31 * Type-1 is for E-Series cameras prior to (not including) E990. For example: E700, E800, E900, 25 32 * E900S, E910, E950. 26 * 33 * <p/> 27 34 * MakerNote starts from ASCII string "Nikon". Data format is the same as IFD, but it starts from 28 35 * offset 0x08. This is the same as Olympus except start string. Example of actual data … … 32 39 * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................ 33 40 * </code></pre> 41 * 42 * @author Drew Noakes http://drewnoakes.com 34 43 */ 35 public class NikonType1MakernoteDescriptor extends TagDescriptor 44 public class NikonType1MakernoteDescriptor extends TagDescriptor<NikonType1MakernoteDirectory> 36 45 { 37 public NikonType1MakernoteDescriptor(Directory directory) 46 public NikonType1MakernoteDescriptor(@NotNull NikonType1MakernoteDirectory directory) 38 47 { 39 48 super(directory); 40 49 } 41 50 42 public String getDescription(int tagType) throws MetadataException 51 @Nullable 52 public String getDescription(int tagType) 43 53 { 44 54 switch (tagType) { … … 60 70 return getConverterDescription(); 61 71 default: 62 return _directory.getString(tagType); 63 } 64 } 65 66 public String getConverterDescription() throws MetadataException 67 { 68 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_CONVERTER)) return null; 69 int value = _directory.getInt(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_CONVERTER); 72 return super.getDescription(tagType); 73 } 74 } 75 76 @Nullable 77 public String getConverterDescription() 78 { 79 Integer value = _directory.getInteger(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_CONVERTER); 80 if (value == null) 81 return null; 70 82 switch (value) { 71 83 case 0: … … 78 90 } 79 91 80 public String getDigitalZoomDescription() throws MetadataException81 {82 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_DIGITAL_ZOOM)) return null;92 @Nullable 93 public String getDigitalZoomDescription() 94 { 83 95 Rational value = _directory.getRational(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_DIGITAL_ZOOM); 96 if (value == null) 97 return null; 84 98 if (value.getNumerator() == 0) { 85 99 return "No digital zoom"; … … 88 102 } 89 103 90 public String getFocusDescription() throws MetadataException91 {92 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_FOCUS)) return null;104 @Nullable 105 public String getFocusDescription() 106 { 93 107 Rational value = _directory.getRational(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_FOCUS); 108 if (value == null) 109 return null; 94 110 if (value.getNumerator() == 1 && value.getDenominator() == 0) { 95 111 return "Infinite"; … … 98 114 } 99 115 100 public String getWhiteBalanceDescription() throws MetadataException 101 { 102 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_WHITE_BALANCE)) return null; 103 int value = _directory.getInt(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_WHITE_BALANCE); 116 @Nullable 117 public String getWhiteBalanceDescription() 118 { 119 Integer value = _directory.getInteger(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_WHITE_BALANCE); 120 if (value == null) 121 return null; 104 122 switch (value) { 105 123 case 0: … … 110 128 return "Daylight"; 111 129 case 3: 112 return "Incandescen se";113 case 4: 114 return "Flo urescence";130 return "Incandescence"; 131 case 4: 132 return "Florescence"; 115 133 case 5: 116 134 return "Cloudy"; … … 122 140 } 123 141 124 public String getCcdSensitivityDescription() throws MetadataException 125 { 126 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_CCD_SENSITIVITY)) return null; 127 int value = _directory.getInt(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_CCD_SENSITIVITY); 142 @Nullable 143 public String getCcdSensitivityDescription() 144 { 145 Integer value = _directory.getInteger(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_CCD_SENSITIVITY); 146 if (value == null) 147 return null; 128 148 switch (value) { 129 149 case 0: … … 140 160 } 141 161 142 public String getImageAdjustmentDescription() throws MetadataException 143 { 144 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_IMAGE_ADJUSTMENT)) return null; 145 int value = _directory.getInt(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_IMAGE_ADJUSTMENT); 162 @Nullable 163 public String getImageAdjustmentDescription() 164 { 165 Integer value = _directory.getInteger(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_IMAGE_ADJUSTMENT); 166 if (value == null) 167 return null; 146 168 switch (value) { 147 169 case 0: … … 160 182 } 161 183 162 public String getColorModeDescription() throws MetadataException 163 { 164 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_COLOR_MODE)) return null; 165 int value = _directory.getInt(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_COLOR_MODE); 184 @Nullable 185 public String getColorModeDescription() 186 { 187 Integer value = _directory.getInteger(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_COLOR_MODE); 188 if (value == null) 189 return null; 166 190 switch (value) { 167 191 case 1: … … 174 198 } 175 199 176 public String getQualityDescription() throws MetadataException 177 { 178 if (!_directory.containsTag(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_QUALITY)) return null; 179 int value = _directory.getInt(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_QUALITY); 200 @Nullable 201 public String getQualityDescription() 202 { 203 Integer value = _directory.getInteger(NikonType1MakernoteDirectory.TAG_NIKON_TYPE1_QUALITY); 204 if (value == null) 205 return null; 180 206 switch (value) { 181 207 case 1: -
trunk/src/com/drew/metadata/exif/NikonType1MakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 24 * Contains values specific to Nikon cameras. Type-1 is for E-Series cameras prior to (not including) E990.29 * Describes tags specific to Nikon (type 1) cameras. Type-1 is for E-Series cameras prior to (not including) E990. 25 30 * 26 31 * There are 3 formats of Nikon's MakerNote. MakerNote of E700/E800/E900/E900S/E910/E950 … … 32 37 * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................ 33 38 * </code></pre> 39 * 40 * @author Drew Noakes http://drewnoakes.com 34 41 */ 35 42 public class NikonType1MakernoteDirectory extends Directory … … 47 54 public static final int TAG_NIKON_TYPE1_UNKNOWN_3 = 0x0F00; 48 55 49 protected static final HashMap _tagNameMap = new HashMap(); 56 @NotNull 57 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 50 58 51 59 static 52 60 { 53 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_CCD_SENSITIVITY), "CCD Sensitivity");54 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_COLOR_MODE), "Color Mode");55 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_DIGITAL_ZOOM), "Digital Zoom");56 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_CONVERTER), "Fisheye Converter");57 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_FOCUS), "Focus");58 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_IMAGE_ADJUSTMENT), "Image Adjustment");59 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_QUALITY), "Quality");60 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_UNKNOWN_1), "Makernote Unknown 1");61 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_UNKNOWN_2), "Makernote Unknown 2");62 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_UNKNOWN_3), "Makernote Unknown 3");63 _tagNameMap.put( new Integer(TAG_NIKON_TYPE1_WHITE_BALANCE), "White Balance");61 _tagNameMap.put(TAG_NIKON_TYPE1_CCD_SENSITIVITY, "CCD Sensitivity"); 62 _tagNameMap.put(TAG_NIKON_TYPE1_COLOR_MODE, "Color Mode"); 63 _tagNameMap.put(TAG_NIKON_TYPE1_DIGITAL_ZOOM, "Digital Zoom"); 64 _tagNameMap.put(TAG_NIKON_TYPE1_CONVERTER, "Fisheye Converter"); 65 _tagNameMap.put(TAG_NIKON_TYPE1_FOCUS, "Focus"); 66 _tagNameMap.put(TAG_NIKON_TYPE1_IMAGE_ADJUSTMENT, "Image Adjustment"); 67 _tagNameMap.put(TAG_NIKON_TYPE1_QUALITY, "Quality"); 68 _tagNameMap.put(TAG_NIKON_TYPE1_UNKNOWN_1, "Makernote Unknown 1"); 69 _tagNameMap.put(TAG_NIKON_TYPE1_UNKNOWN_2, "Makernote Unknown 2"); 70 _tagNameMap.put(TAG_NIKON_TYPE1_UNKNOWN_3, "Makernote Unknown 3"); 71 _tagNameMap.put(TAG_NIKON_TYPE1_WHITE_BALANCE, "White Balance"); 64 72 } 65 73 … … 69 77 } 70 78 79 @NotNull 71 80 public String getName() 72 81 { … … 74 83 } 75 84 76 protected HashMap getTagNameMap() 85 @NotNull 86 protected HashMap<Integer, String> getTagNameMap() 77 87 { 78 88 return _tagNameMap; -
trunk/src/com/drew/metadata/exif/NikonType2MakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 23 import com.drew.lang.Rational; 18 import com.drew.metadata.Directory; 19 import com.drew.metadata.MetadataException; 24 import com.drew.lang.StringUtil; 25 import com.drew.lang.annotations.NotNull; 26 import com.drew.lang.annotations.Nullable; 20 27 import com.drew.metadata.TagDescriptor; 21 28 22 29 import java.text.DecimalFormat; 30 import java.util.ArrayList; 31 import java.util.Collection; 32 import java.util.Date; 23 33 24 34 /** 25 * Provides human-readable string versions of the tags stored in a NikonType2MakernoteDirectory. 35 * Provides human-readable string representations of tag values stored in a <code>NikonType2MakernoteDirectory</code>. 36 * 26 37 * Type-2 applies to the E990 and D-series cameras such as the D1, D70 and D100. 38 * 39 * @author Drew Noakes http://drewnoakes.com 27 40 */ 28 public class NikonType2MakernoteDescriptor extends TagDescriptor 41 public class NikonType2MakernoteDescriptor extends TagDescriptor<NikonType2MakernoteDirectory> 29 42 { 30 public NikonType2MakernoteDescriptor(Directory directory) 43 public NikonType2MakernoteDescriptor(@NotNull NikonType2MakernoteDirectory directory) 31 44 { 32 45 super(directory); 33 46 } 34 47 35 private NikonType2MakernoteDirectory getMakernoteDirectory() 36 { 37 return (NikonType2MakernoteDirectory)_directory; 38 } 39 40 public String getDescription(int tagType) throws MetadataException 48 @Nullable 49 public String getDescription(int tagType) 41 50 { 42 51 switch (tagType) 43 52 { 53 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_PROGRAM_SHIFT: 54 return getProgramShiftDescription(); 55 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_EXPOSURE_DIFFERENCE: 56 return getExposureDifferenceDescription(); 44 57 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS: 45 58 return getLensDescription(); … … 50 63 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION: 51 64 return getAutoFlashCompensationDescription(); 65 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FLASH_EXPOSURE_COMPENSATION: 66 return getFlashExposureCompensationDescription(); 67 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FLASH_BRACKET_COMPENSATION: 68 return getFlashBracketCompensationDescription(); 69 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_EXPOSURE_TUNING: 70 return getExposureTuningDescription(); 71 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS_STOPS: 72 return getLensStopsDescription(); 73 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_COLOR_SPACE: 74 return getColorSpaceDescription(); 75 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_ACTIVE_D_LIGHTING: 76 return getActiveDLightingDescription(); 77 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_VIGNETTE_CONTROL: 78 return getVignetteControlDescription(); 52 79 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_ISO_1: 53 80 return getIsoSettingDescription(); 54 81 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_DIGITAL_ZOOM: 55 82 return getDigitalZoomDescription(); 83 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FLASH_USED: 84 return getFlashUsedDescription(); 56 85 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AF_FOCUS_POSITION: 57 86 return getAutoFocusPositionDescription(); 58 87 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FIRMWARE_VERSION: 59 return getAutoFirmwareVersionDescription(); 88 return getFirmwareVersionDescription(); 89 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS_TYPE: 90 return getLensTypeDescription(); 91 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_SHOOTING_MODE: 92 return getShootingModeDescription(); 93 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_NEF_COMPRESSION: 94 return getNEFCompressionDescription(); 95 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_HIGH_ISO_NOISE_REDUCTION: 96 return getHighISONoiseReductionDescription(); 97 case NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_POWER_UP_TIME: 98 return getPowerUpTimeDescription(); 60 99 default: 61 return _directory.getString(tagType); 62 } 63 } 64 65 public String getAutoFocusPositionDescription() throws MetadataException 66 { 67 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AF_FOCUS_POSITION)) return null; 100 return super.getDescription(tagType); 101 } 102 } 103 104 @Nullable 105 public String getPowerUpTimeDescription() 106 { 107 Long value = _directory.getLongObject(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_POWER_UP_TIME); 108 if (value==null) 109 return null; // TODO have observed a byte[8] here which is likely some kind of date (ticks as long?) 110 return new Date(value).toString(); 111 } 112 113 @Nullable 114 public String getHighISONoiseReductionDescription() 115 { 116 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_HIGH_ISO_NOISE_REDUCTION); 117 if (value==null) 118 return null; 119 switch (value) { 120 case 0: return "Off"; 121 case 1: return "Minimal"; 122 case 2: return "Low"; 123 case 4: return "Normal"; 124 case 6: return "High"; 125 default: return "Unknown (" + value + ")"; 126 } 127 } 128 129 @Nullable 130 public String getFlashUsedDescription() 131 { 132 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FLASH_USED); 133 if (value==null) 134 return null; 135 switch (value) { 136 case 0: return "Flash Not Used"; 137 case 1: return "Manual Flash"; 138 case 3: return "Flash Not Ready"; 139 case 7: return "External Flash"; 140 case 8: return "Fired, Commander Mode"; 141 case 9: return "Fired, TTL Mode"; 142 default: return "Unknown (" + value + ")"; 143 } 144 } 145 146 @Nullable 147 public String getNEFCompressionDescription() 148 { 149 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_NEF_COMPRESSION); 150 if (value==null) 151 return null; 152 switch (value) { 153 case 1: return "Lossy (Type 1)"; 154 case 3: return "Uncompressed"; 155 case 7: return "Lossless"; 156 case 8: return "Lossy (Type 2)"; 157 default: return "Unknown (" + value + ")"; 158 } 159 } 160 161 @Nullable 162 public String getShootingModeDescription() 163 { 164 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_SHOOTING_MODE); 165 if (value==null) 166 return null; 167 Collection<String> bits = new ArrayList<String>(); 168 169 if ((value&1)==1) 170 bits.add("Continuous"); 171 else 172 bits.add("Single Frame"); 173 174 if ((value&2)==2) 175 bits.add("Delay"); 176 // Don't know about 3 177 if ((value&8)==8) 178 bits.add("PC Control"); 179 if ((value&16)==16) 180 bits.add("Exposure Bracketing"); 181 if ((value&32)==32) 182 bits.add("Auto ISO"); 183 if ((value&64)==64) 184 bits.add("White-Balance Bracketing"); 185 if ((value&128)==128) 186 bits.add("IR Control"); 187 188 return StringUtil.join(bits, ", "); 189 } 190 191 @Nullable 192 public String getLensTypeDescription() 193 { 194 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS_TYPE); 195 if (value==null) 196 return null; 197 198 Collection<String> bits = new ArrayList<String>(); 199 200 // TODO validate these values, as 14 is labelled as AF-C elsewhere but appears here as AF-D-G-VR 201 202 if ((value&1)==1) 203 bits.add("MF"); 204 else 205 bits.add("AF"); 206 207 if ((value&2)==2) 208 bits.add("D"); 209 210 if ((value&4)==4) 211 bits.add("G"); 212 213 if ((value&8)==8) 214 bits.add("VR"); 215 216 return StringUtil.join(bits, ", "); 217 } 218 219 @Nullable 220 public String getColorSpaceDescription() 221 { 222 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_COLOR_SPACE); 223 if (value==null) 224 return null; 225 switch (value) { 226 case 1: return "sRGB"; 227 case 2: return "Adobe RGB"; 228 default: return "Unknown (" + value + ")"; 229 } 230 } 231 232 @Nullable 233 public String getActiveDLightingDescription() 234 { 235 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_ACTIVE_D_LIGHTING); 236 if (value==null) 237 return null; 238 switch (value) { 239 case 0: return "Off"; 240 case 1: return "Light"; 241 case 3: return "Normal"; 242 case 5: return "High"; 243 case 7: return "Extra High"; 244 case 65535: return "Auto"; 245 default: return "Unknown (" + value + ")"; 246 } 247 } 248 249 @Nullable 250 public String getVignetteControlDescription() 251 { 252 Integer value = _directory.getInteger(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_VIGNETTE_CONTROL); 253 if (value==null) 254 return null; 255 switch (value) { 256 case 0: return "Off"; 257 case 1: return "Low"; 258 case 3: return "Normal"; 259 case 5: return "High"; 260 default: return "Unknown (" + value + ")"; 261 } 262 } 263 264 @Nullable 265 public String getAutoFocusPositionDescription() 266 { 68 267 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AF_FOCUS_POSITION); 268 if (values==null) 269 return null; 69 270 if (values.length != 4 || values[0] != 0 || values[2] != 0 || values[3] != 0) { 70 271 return "Unknown (" + _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AF_FOCUS_POSITION) + ")"; … … 86 287 } 87 288 88 public String getDigitalZoomDescription() throws MetadataException 89 { 90 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_DIGITAL_ZOOM)) return null; 91 Rational rational = _directory.getRational(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_DIGITAL_ZOOM); 92 if (rational.intValue() == 1) { 93 return "No digital zoom"; 94 } 95 return rational.toSimpleString(true) + "x digital zoom"; 96 } 97 98 public String getIsoSettingDescription() throws MetadataException 99 { 100 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_ISO_1)) return null; 289 @Nullable 290 public String getDigitalZoomDescription() 291 { 292 Rational value = _directory.getRational(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_DIGITAL_ZOOM); 293 if (value==null) 294 return null; 295 return value.intValue() == 1 296 ? "No digital zoom" 297 : value.toSimpleString(true) + "x digital zoom"; 298 } 299 300 @Nullable 301 public String getProgramShiftDescription() 302 { 303 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_PROGRAM_SHIFT); 304 return getEVDescription(values); 305 } 306 307 @Nullable 308 public String getExposureDifferenceDescription() 309 { 310 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_EXPOSURE_DIFFERENCE); 311 return getEVDescription(values); 312 } 313 314 @NotNull 315 public String getAutoFlashCompensationDescription() 316 { 317 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION); 318 return getEVDescription(values); 319 } 320 321 @NotNull 322 public String getFlashExposureCompensationDescription() 323 { 324 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FLASH_EXPOSURE_COMPENSATION); 325 return getEVDescription(values); 326 } 327 328 @NotNull 329 public String getFlashBracketCompensationDescription() 330 { 331 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FLASH_BRACKET_COMPENSATION); 332 return getEVDescription(values); 333 } 334 335 @NotNull 336 public String getExposureTuningDescription() 337 { 338 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_EXPOSURE_TUNING); 339 return getEVDescription(values); 340 } 341 342 @NotNull 343 public String getLensStopsDescription() 344 { 345 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS_STOPS); 346 return getEVDescription(values); 347 } 348 349 @Nullable 350 private static String getEVDescription(@Nullable int[] values) 351 { 352 if (values==null) 353 return null; 354 if (values.length<3 || values[2]==0) 355 return null; 356 final DecimalFormat decimalFormat = new DecimalFormat("0.##"); 357 double ev = values[0] * values[1] / (double)values[2]; 358 return decimalFormat.format(ev) + " EV"; 359 } 360 361 @Nullable 362 public String getIsoSettingDescription() 363 { 101 364 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_ISO_1); 102 if (values[0] != 0 || values[1] == 0) { 365 if (values==null) 366 return null; 367 if (values[0] != 0 || values[1] == 0) 103 368 return "Unknown (" + _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_ISO_1) + ")"; 104 }105 369 return "ISO " + values[1]; 106 370 } 107 371 108 public String getAutoFlashCompensationDescription() throws MetadataException 109 { 110 Rational ev = getMakernoteDirectory().getAutoFlashCompensation(); 111 112 if (ev==null) 113 return "Unknown"; 114 115 DecimalFormat decimalFormat = new DecimalFormat("0.##"); 116 return decimalFormat.format(ev.floatValue()) + " EV"; 117 } 118 119 public String getLensDescription() throws MetadataException 120 { 121 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS)) 122 return null; 123 124 Rational[] lensValues = _directory.getRationalArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS); 125 126 if (lensValues.length!=4) 372 @Nullable 373 public String getLensDescription() 374 { 375 Rational[] values = _directory.getRationalArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS); 376 377 if (values==null) 378 return null; 379 380 if (values.length<4) 127 381 return _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_LENS); 128 382 129 StringBu ffer description = new StringBuffer();130 description.append( lensValues[0].intValue());383 StringBuilder description = new StringBuilder(); 384 description.append(values[0].intValue()); 131 385 description.append('-'); 132 description.append( lensValues[1].intValue());386 description.append(values[1].intValue()); 133 387 description.append("mm f/"); 134 description.append( lensValues[2].floatValue());388 description.append(values[2].floatValue()); 135 389 description.append('-'); 136 description.append( lensValues[3].floatValue());390 description.append(values[3].floatValue()); 137 391 138 392 return description.toString(); 139 393 } 140 394 395 @Nullable 141 396 public String getHueAdjustmentDescription() 142 397 { 143 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT)) 144 return null; 145 146 return _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT) + " degrees"; 147 } 148 398 final String value = _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT); 399 if (value==null) 400 return null; 401 return value + " degrees"; 402 } 403 404 @Nullable 149 405 public String getColorModeDescription() 150 406 { 151 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_CAMERA_COLOR_MODE)) 152 return null; 153 154 String raw = _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_CAMERA_COLOR_MODE); 155 if (raw.startsWith("MODE1")) 407 String value = _directory.getString(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_CAMERA_COLOR_MODE); 408 if (value==null) 409 return null; 410 if (value.startsWith("MODE1")) 156 411 return "Mode I (sRGB)"; 157 158 return raw; 159 } 160 161 public String getAutoFirmwareVersionDescription() throws MetadataException 162 { 163 if (!_directory.containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FIRMWARE_VERSION)) 164 return null; 165 166 int[] ints = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FIRMWARE_VERSION); 167 return ExifDescriptor.convertBytesToVersionString(ints); 412 return value; 413 } 414 415 @Nullable 416 public String getFirmwareVersionDescription() 417 { 418 int[] values = _directory.getIntArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_FIRMWARE_VERSION); 419 if (values==null) 420 return null; 421 return ExifSubIFDDescriptor.convertBytesToVersionString(values, 2); 168 422 } 169 423 } -
trunk/src/com/drew/metadata/exif/NikonType2MakernoteDirectory.java
r4258 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * metadata_extractor [at] drewnoakes [dot] com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 3-Oct-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 19 import com.drew.lang. Rational;23 import com.drew.lang.annotations.NotNull; 20 24 import com.drew.metadata.Directory; 21 import com.drew.metadata.MetadataException;22 25 23 26 import java.util.HashMap; … … 26 29 * Describes tags specific to Nikon (type 2) cameras. Type-2 applies to the E990 and D-series cameras such as the E990, D1, 27 30 * D70 and D100. 28 * 31 * <p/> 29 32 * Thanks to Fabrizio Giudici for publishing his reverse-engineering of the D100 makernote data. 30 33 * http://www.timelesswanderings.net/equipment/D100/NEF.html 31 * 34 * <p/> 32 35 * Note that the camera implements image protection (locking images) via the file's 'readonly' attribute. Similarly 33 36 * image hiding uses the 'hidden' attribute (observed on the D70). Consequently, these values are not available here. 34 * 37 * <p/> 35 38 * Additional sample images have been observed, and their tag values recorded in javadoc comments for each tag's field. 36 39 * New tags have subsequently been added since Fabrizio's observations. 37 * 40 * <p/> 38 41 * In earlier models (such as the E990 and D1), this directory begins at the first byte of the makernote IFD. In 39 42 * later models, the IFD was given the standard prefix to indicate the camera models (most other manufacturers also 40 43 * provide this prefix to aid in software decoding). 44 * 45 * @author Drew Noakes http://drewnoakes.com 41 46 */ 42 47 public class NikonType2MakernoteDirectory extends Directory … … 57 62 58 63 /** 59 * Values observed 60 * - COLOR (seen in the D1X) 64 * The camera's color mode, as an uppercase string. Examples include: 65 * <ul> 66 * <li><code>B & W</code></li> 67 * <li><code>COLOR</code></li> 68 * <li><code>COOL</code></li> 69 * <li><code>SEPIA</code></li> 70 * <li><code>VIVID</code></li> 71 * </ul> 61 72 */ 62 73 public static final int TAG_NIKON_TYPE2_COLOR_MODE = 0x0003; 63 74 64 75 /** 65 * Values observed 66 * - FILE 67 * - RAW 68 * - NORMAL 69 * - FINE 76 * The camera's quality setting, as an uppercase string. Examples include: 77 * <ul> 78 * <li><code>BASIC</code></li> 79 * <li><code>FINE</code></li> 80 * <li><code>NORMAL</code></li> 81 * <li><code>RAW</code></li> 82 * <li><code>RAW2.7M</code></li> 83 * </ul> 70 84 */ 71 85 public static final int TAG_NIKON_TYPE2_QUALITY_AND_FILE_FORMAT = 0x0004; 72 86 73 87 /** 74 * The white balance as set in the camera. 75 * 76 * Values observed 77 * - AUTO 78 * - SUNNY (D70) 79 * - FLASH (D1X) 80 * (presumably also SHADOW / INCANDESCENT / FLUORESCENT / CLOUDY) 88 * The camera's white balance setting, as an uppercase string. Examples include: 89 * 90 * <ul> 91 * <li><code>AUTO</code></li> 92 * <li><code>CLOUDY</code></li> 93 * <li><code>FLASH</code></li> 94 * <li><code>FLUORESCENT</code></li> 95 * <li><code>INCANDESCENT</code></li> 96 * <li><code>PRESET</code></li> 97 * <li><code>PRESET0</code></li> 98 * <li><code>PRESET1</code></li> 99 * <li><code>PRESET3</code></li> 100 * <li><code>SUNNY</code></li> 101 * <li><code>WHITE PRESET</code></li> 102 * <li><code>4350K</code></li> 103 * <li><code>5000K</code></li> 104 * <li><code>DAY WHITE FL</code></li> 105 * <li><code>SHADE</code></li> 106 * </ul> 81 107 */ 82 108 public static final int TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE = 0x0005; 83 109 84 110 /** 85 * The sharpening as set in the camera. 86 * 87 * Values observed 88 * - AUTO 89 * - NORMAL (D70) 90 * - NONE (D1X) 111 * The camera's sharpening setting, as an uppercase string. Examples include: 112 * 113 * <ul> 114 * <li><code>AUTO</code></li> 115 * <li><code>HIGH</code></li> 116 * <li><code>LOW</code></li> 117 * <li><code>NONE</code></li> 118 * <li><code>NORMAL</code></li> 119 * <li><code>MED.H</code></li> 120 * <li><code>MED.L</code></li> 121 * </ul> 91 122 */ 92 123 public static final int TAG_NIKON_TYPE2_CAMERA_SHARPENING = 0x0006; 93 124 94 125 /** 95 * The auto-focus type used by the camera. 96 * 97 * Values observed 98 * - AF-S 99 * - AF-C 100 * - MANUAL 126 * The camera's auto-focus mode, as an uppercase string. Examples include: 127 * 128 * <ul> 129 * <li><code>AF-C</code></li> 130 * <li><code>AF-S</code></li> 131 * <li><code>MANUAL</code></li> 132 * <li><code>AF-A</code></li> 133 * </ul> 101 134 */ 102 135 public static final int TAG_NIKON_TYPE2_AF_TYPE = 0x0007; 103 136 104 137 /** 105 * Values observed 106 * - NORMAL 107 * - RED-EYE 108 * 109 * Note: when TAG_NIKON_TYPE2_AUTO_FLASH_MODE is blank, Nikon Browser displays "Flash Sync Mode: Not Attached" 138 * The camera's flash setting, as an uppercase string. Examples include: 139 * 140 * <ul> 141 * <li><code></code></li> 142 * <li><code>NORMAL</code></li> 143 * <li><code>RED-EYE</code></li> 144 * <li><code>SLOW</code></li> 145 * <li><code>NEW_TTL</code></li> 146 * <li><code>REAR</code></li> 147 * <li><code>REAR SLOW</code></li> 148 * </ul> 149 * Note: when TAG_NIKON_TYPE2_AUTO_FLASH_MODE is blank (whitespace), Nikon Browser displays "Flash Sync Mode: Not Attached" 110 150 */ 111 151 public static final int TAG_NIKON_TYPE2_FLASH_SYNC_MODE = 0x0008; 112 152 113 153 /** 114 * Values observed 115 * - Built-in,TTL 116 * - Optional,TTL (with speedlight SB800, flash sync mode as NORMAL. NikonBrowser reports Auto Flash Comp: 0 EV -- which tag is that?) (D70) 117 * - NEW_TTL (Nikon Browser interprets as "D-TTL") 118 * - (blank -- accompanied FlashSyncMode of NORMAL) (D70) 154 * The type of flash used in the photograph, as a string. Examples include: 155 * 156 * <ul> 157 * <li><code></code></li> 158 * <li><code>Built-in,TTL</code></li> 159 * <li><code>NEW_TTL</code> Nikon Browser interprets as "D-TTL"</li> 160 * <li><code>Built-in,M</code></li> 161 * <li><code>Optional,TTL</code> with speedlight SB800, flash sync mode as "NORMAL"</li> 162 * </ul> 119 163 */ 120 164 public static final int TAG_NIKON_TYPE2_AUTO_FLASH_MODE = 0x0009; 121 165 122 166 /** 123 * Added during merge of Type2 & Type3. May apply to earlier models, such as E990 and D1. 167 * An unknown tag, as a rational. Several values given here: 168 * http://gvsoft.homedns.org/exif/makernote-nikon-type2.html#0x000b 124 169 */ 125 170 public static final int TAG_NIKON_TYPE2_UNKNOWN_34 = 0x000A; 126 171 127 172 /** 128 * Values observed 129 * - 0 173 * The camera's white balance bias setting, as an uint16 array having either one or two elements. 174 * 175 * <ul> 176 * <li><code>0</code></li> 177 * <li><code>1</code></li> 178 * <li><code>-3</code></li> 179 * <li><code>-2</code></li> 180 * <li><code>-1</code></li> 181 * <li><code>0,0</code></li> 182 * <li><code>1,0</code></li> 183 * <li><code>5,-5</code></li> 184 * </ul> 130 185 */ 131 186 public static final int TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE_FINE = 0x000B; … … 143 198 144 199 /** 145 * Values observed 146 * - 0,1,6,0 (hex) 147 */ 148 public static final int TAG_NIKON_TYPE2_UNKNOWN_1 = 0x000D; 149 150 /** 151 * Values observed 152 * - 0,1,c,0 (hex) 153 */ 154 public static final int TAG_NIKON_TYPE2_UNKNOWN_2 = 0x000E; 200 * The camera's program shift setting, as an array of four integers. 201 * The value, in EV, is calculated as <code>a*b/c</code>. 202 * 203 * <ul> 204 * <li><code>0,1,3,0</code> = 0 EV</li> 205 * <li><code>1,1,3,0</code> = 0.33 EV</li> 206 * <li><code>-3,1,3,0</code> = -1 EV</li> 207 * <li><code>1,1,2,0</code> = 0.5 EV</li> 208 * <li><code>2,1,6,0</code> = 0.33 EV</li> 209 * </ul> 210 */ 211 public static final int TAG_NIKON_TYPE2_PROGRAM_SHIFT = 0x000D; 212 213 /** 214 * The exposure difference, as an array of four integers. 215 * The value, in EV, is calculated as <code>a*b/c</code>. 216 * 217 * <ul> 218 * <li><code>-105,1,12,0</code> = -8.75 EV</li> 219 * <li><code>-72,1,12,0</code> = -6.00 EV</li> 220 * <li><code>-11,1,12,0</code> = -0.92 EV</li> 221 * </ul> 222 */ 223 public static final int TAG_NIKON_TYPE2_EXPOSURE_DIFFERENCE = 0x000E; 224 225 /** 226 * The camera's ISO mode, as an uppercase string. 227 * 228 * <ul> 229 * <li><code>AUTO</code></code></li> 230 * <li><code>MANUAL</code></li> 231 * </ul> 232 */ 233 public static final int TAG_NIKON_TYPE2_ISO_MODE = 0x000F; 155 234 156 235 /** 157 236 * Added during merge of Type2 & Type3. May apply to earlier models, such as E990 and D1. 158 237 */ 159 public static final int TAG_NIKON_TYPE2_ISO_SELECTION = 0x000F;160 161 /**162 * Added during merge of Type2 & Type3. May apply to earlier models, such as E990 and D1.163 */164 238 public static final int TAG_NIKON_TYPE2_DATA_DUMP = 0x0010; 165 239 166 240 /** 167 * Values observed 168 * - 914 169 * - 1379 (D70) 170 * - 2781 (D1X) 171 * - 6942 (D100) 172 */ 173 public static final int TAG_NIKON_TYPE2_UNKNOWN_3 = 0x0011; 174 175 /** 176 * Values observed 177 * - (no value -- blank) 241 * Preview to another IFD (?) 242 * <p/> 243 * Details here: http://gvsoft.homedns.org/exif/makernote-nikon-2-tag0x0011.html 244 * // TODO if this is another IFD, decode it 245 */ 246 public static final int TAG_NIKON_TYPE2_PREVIEW_IFD = 0x0011; 247 248 /** 249 * The flash compensation, as an array of four integers. 250 * The value, in EV, is calculated as <code>a*b/c</code>. 251 * 252 * <ul> 253 * <li><code>-18,1,6,0</code> = -3 EV</li> 254 * <li><code>4,1,6,0</code> = 0.67 EV</li> 255 * <li><code>6,1,6,0</code> = 1 EV</li> 256 * </ul> 178 257 */ 179 258 public static final int TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION = 0x0012; 180 259 181 260 /** 182 * Values observed 183 * - 0 250 184 * - 0 400 185 */ 186 public static final int TAG_NIKON_TYPE2_ISO_2 = 0x0013; 187 188 /** 189 * Values observed 261 * The requested ISO value, as an array of two integers. 262 * 263 * <ul> 264 * <li><code>0,0</code></li> 265 * <li><code>0,125</code></li> 266 * <li><code>1,2500</code></li> 267 * </ul> 268 */ 269 public static final int TAG_NIKON_TYPE2_ISO_REQUESTED = 0x0013; 270 271 /** 272 * Defines the photo corner coordinates, in 8 bytes. Treated as four 16-bit integers, they 273 * decode as: top-left (x,y); bot-right (x,y) 190 274 * - 0 0 49163 53255 191 275 * - 0 0 3008 2000 (the image dimensions were 3008x2000) (D70) 192 */ 193 public static final int TAG_NIKON_TYPE2_UNKNOWN_21 = 0x0016; 194 195 /** 196 * Values observed 197 * - (blank) 198 */ 199 public static final int TAG_NIKON_TYPE2_UNKNOWN_22 = 0x0017; 200 201 /** 202 * Values observed 203 * - (blank) 204 */ 205 public static final int TAG_NIKON_TYPE2_UNKNOWN_23 = 0x0018; 206 207 /** 208 * Values observed 209 * - 0 210 */ 211 public static final int TAG_NIKON_TYPE2_UNKNOWN_24 = 0x0019; 212 213 /** 214 * Added during merge of Type2 & Type3. May apply to earlier models, such as E990 and D1. 276 * <ul> 277 * <li><code>0,0,4288,2848</code> The max resolution of the D300 camera</li> 278 * <li><code>0,0,3008,2000</code> The max resolution of the D70 camera</li> 279 * <li><code>0,0,4256,2832</code> The max resolution of the D3 camera</li> 280 * </ul> 281 */ 282 public static final int TAG_NIKON_TYPE2_IMAGE_BOUNDARY = 0x0016; 283 284 /** 285 * The flash exposure compensation, as an array of four integers. 286 * The value, in EV, is calculated as <code>a*b/c</code>. 287 * 288 * <ul> 289 * <li><code>0,0,0,0</code> = 0 EV</li> 290 * <li><code>0,1,6,0</code> = 0 EV</li> 291 * <li><code>4,1,6,0</code> = 0.67 EV</li> 292 * </ul> 293 */ 294 public static final int TAG_NIKON_TYPE2_FLASH_EXPOSURE_COMPENSATION = 0x0017; 295 296 /** 297 * The flash bracket compensation, as an array of four integers. 298 * The value, in EV, is calculated as <code>a*b/c</code>. 299 * 300 * <ul> 301 * <li><code>0,0,0,0</code> = 0 EV</li> 302 * <li><code>0,1,6,0</code> = 0 EV</li> 303 * <li><code>4,1,6,0</code> = 0.67 EV</li> 304 * </ul> 305 */ 306 public static final int TAG_NIKON_TYPE2_FLASH_BRACKET_COMPENSATION = 0x0018; 307 308 /** 309 * The AE bracket compensation, as a rational number. 310 * 311 * <ul> 312 * <li><code>0/0</code></li> 313 * <li><code>0/1</code></li> 314 * <li><code>0/6</code></li> 315 * <li><code>4/6</code></li> 316 * <li><code>6/6</code></li> 317 * </ul> 318 */ 319 public static final int TAG_NIKON_TYPE2_AE_BRACKET_COMPENSATION = 0x0019; 320 321 /** 322 * Flash mode, as a string. 323 * 324 * <ul> 325 * <li><code></code></li> 326 * <li><code>Red Eye Reduction</code></li> 327 * <li><code>D-Lighting</code></li> 328 * <li><code>Distortion control</code></li> 329 * </ul> 330 */ 331 public static final int TAG_NIKON_TYPE2_FLASH_MODE = 0x001a; 332 333 public static final int TAG_NIKON_TYPE2_CROP_HIGH_SPEED = 0x001b; 334 public static final int TAG_NIKON_TYPE2_EXPOSURE_TUNING = 0x001c; 335 336 /** 337 * The camera's serial number, as a string. 338 * Note that D200 is always blank, and D50 is always <code>"D50"</code>. 339 */ 340 public static final int TAG_NIKON_TYPE2_CAMERA_SERIAL_NUMBER = 0x001d; 341 342 /** 343 * The camera's color space setting. 344 * 345 * <ul> 346 * <li><code>1</code> sRGB</li> 347 * <li><code>2</code> Adobe RGB</li> 348 * </ul> 349 */ 350 public static final int TAG_NIKON_TYPE2_COLOR_SPACE = 0x001e; 351 public static final int TAG_NIKON_TYPE2_VR_INFO = 0x001f; 352 public static final int TAG_NIKON_TYPE2_IMAGE_AUTHENTICATION = 0x0020; 353 public static final int TAG_NIKON_TYPE2_UNKNOWN_35 = 0x0021; 354 355 /** 356 * The active D-Lighting setting. 357 * 358 * <ul> 359 * <li><code>0</code> Off</li> 360 * <li><code>1</code> Low</li> 361 * <li><code>3</code> Normal</li> 362 * <li><code>5</code> High</li> 363 * <li><code>7</code> Extra High</li> 364 * <li><code>65535</code> Auto</li> 365 * </ul> 366 */ 367 public static final int TAG_NIKON_TYPE2_ACTIVE_D_LIGHTING = 0x0022; 368 public static final int TAG_NIKON_TYPE2_PICTURE_CONTROL = 0x0023; 369 public static final int TAG_NIKON_TYPE2_WORLD_TIME = 0x0024; 370 public static final int TAG_NIKON_TYPE2_ISO_INFO = 0x0025; 371 public static final int TAG_NIKON_TYPE2_UNKNOWN_36 = 0x0026; 372 public static final int TAG_NIKON_TYPE2_UNKNOWN_37 = 0x0027; 373 public static final int TAG_NIKON_TYPE2_UNKNOWN_38 = 0x0028; 374 public static final int TAG_NIKON_TYPE2_UNKNOWN_39 = 0x0029; 375 376 /** 377 * The camera's vignette control setting. 378 * 379 * <ul> 380 * <li><code>0</code> Off</li> 381 * <li><code>1</code> Low</li> 382 * <li><code>3</code> Normal</li> 383 * <li><code>5</code> High</li> 384 * </ul> 385 */ 386 public static final int TAG_NIKON_TYPE2_VIGNETTE_CONTROL = 0x002a; 387 public static final int TAG_NIKON_TYPE2_UNKNOWN_40 = 0x002b; 388 public static final int TAG_NIKON_TYPE2_UNKNOWN_41 = 0x002c; 389 public static final int TAG_NIKON_TYPE2_UNKNOWN_42 = 0x002d; 390 public static final int TAG_NIKON_TYPE2_UNKNOWN_43 = 0x002e; 391 public static final int TAG_NIKON_TYPE2_UNKNOWN_44 = 0x002f; 392 public static final int TAG_NIKON_TYPE2_UNKNOWN_45 = 0x0030; 393 public static final int TAG_NIKON_TYPE2_UNKNOWN_46 = 0x0031; 394 395 /** 396 * The camera's image adjustment setting, as a string. 397 * 398 * <ul> 399 * <li><code>AUTO</code></li> 400 * <li><code>CONTRAST(+)</code></li> 401 * <li><code>CONTRAST(-)</code></li> 402 * <li><code>NORMAL</code></li> 403 * <li><code>B & W</code></li> 404 * <li><code>BRIGHTNESS(+)</code></li> 405 * <li><code>BRIGHTNESS(-)</code></li> 406 * <li><code>SEPIA</code></li> 407 * </ul> 215 408 */ 216 409 public static final int TAG_NIKON_TYPE2_IMAGE_ADJUSTMENT = 0x0080; 217 410 218 411 /** 219 * The tone compensation as set in the camera. 220 * 221 * Values observed 222 * - AUTO 223 * - NORMAL (D1X, D100) 412 * The camera's tone compensation setting, as a string. 413 * 414 * <ul> 415 * <li><code>NORMAL</code></li> 416 * <li><code>LOW</code></li> 417 * <li><code>MED.L</code></li> 418 * <li><code>MED.H</code></li> 419 * <li><code>HIGH</code></li> 420 * <li><code>AUTO</code></li> 421 * </ul> 224 422 */ 225 423 public static final int TAG_NIKON_TYPE2_CAMERA_TONE_COMPENSATION = 0x0081; 226 424 227 425 /** 228 * Added during merge of Type2 & Type3. May apply to earlier models, such as E990 and D1. 426 * A description of any auxiliary lens, as a string. 427 * 428 * <ul> 429 * <li><code>OFF</code></li> 430 * <li><code>FISHEYE 1</code></li> 431 * <li><code>FISHEYE 2</code></li> 432 * <li><code>TELEPHOTO 2</code></li> 433 * <li><code>WIDE ADAPTER</code></li> 434 * </ul> 229 435 */ 230 436 public static final int TAG_NIKON_TYPE2_ADAPTER = 0x0082; 231 437 232 438 /** 233 * Values observed 234 * - 6 235 * - 6 (D70) 236 * - 2 (D1X) 237 */ 238 public static final int TAG_NIKON_TYPE2_UNKNOWN_4 = 0x0083; 439 * The type of lens used, as a byte. 440 * 441 * <ul> 442 * <li><code>0x00</code> AF</li> 443 * <li><code>0x01</code> MF</li> 444 * <li><code>0x02</code> D</li> 445 * <li><code>0x06</code> G, D</li> 446 * <li><code>0x08</code> VR</li> 447 * <li><code>0x0a</code> VR, D</li> 448 * <li><code>0x0e</code> VR, G, D</li> 449 * </ul> 450 */ 451 public static final int TAG_NIKON_TYPE2_LENS_TYPE = 0x0083; 239 452 240 453 /** … … 260 473 261 474 /** 262 * Added during merge of Type2 & Type3. May apply to earlier models, such as E990 and D1.475 * The amount of digital zoom used. 263 476 */ 264 477 public static final int TAG_NIKON_TYPE2_DIGITAL_ZOOM = 0x0086; 265 478 266 479 /** 480 * Whether the flash was used in this image. 481 * 482 * <ul> 483 * <li><code>0</code> Flash Not Used</li> 484 * <li><code>1</code> Manual Flash</li> 485 * <li><code>3</code> Flash Not Ready</li> 486 * <li><code>7</code> External Flash</li> 487 * <li><code>8</code> Fired, Commander Mode</li> 488 * <li><code>9</code> Fired, TTL Mode</li> 489 * </ul> 490 */ 491 public static final int TAG_NIKON_TYPE2_FLASH_USED = 0x0087; 492 493 /** 494 * The position of the autofocus target. 495 */ 496 public static final int TAG_NIKON_TYPE2_AF_FOCUS_POSITION = 0x0088; 497 498 /** 499 * The camera's shooting mode. 500 * <p/> 501 * A bit-array with: 502 * <ul> 503 * <li><code>0</code> Single Frame</li> 504 * <li><code>1</code> Continuous</li> 505 * <li><code>2</code> Delay</li> 506 * <li><code>8</code> PC Control</li> 507 * <li><code>16</code> Exposure Bracketing</li> 508 * <li><code>32</code> Auto ISO</li> 509 * <li><code>64</code> White-Balance Bracketing</li> 510 * <li><code>128</code> IR Control</li> 511 * </ul> 512 */ 513 public static final int TAG_NIKON_TYPE2_SHOOTING_MODE = 0x0089; 514 515 public static final int TAG_NIKON_TYPE2_UNKNOWN_20 = 0x008A; 516 517 /** 518 * Lens stops, as an array of four integers. 519 * The value, in EV, is calculated as <code>a*b/c</code>. 520 * 521 * <ul> 522 * <li><code>64,1,12,0</code> = 5.33 EV</li> 523 * <li><code>72,1,12,0</code> = 6 EV</li> 524 * </ul> 525 */ 526 public static final int TAG_NIKON_TYPE2_LENS_STOPS = 0x008B; 527 528 public static final int TAG_NIKON_TYPE2_CONTRAST_CURVE = 0x008C; 529 530 /** 531 * The color space as set in the camera, as a string. 532 * 533 * <ul> 534 * <li><code>MODE1</code> = Mode 1 (sRGB)</li> 535 * <li><code>MODE1a</code> = Mode 1 (sRGB)</li> 536 * <li><code>MODE2</code> = Mode 2 (Adobe RGB)</li> 537 * <li><code>MODE3</code> = Mode 2 (sRGB): Higher Saturation</li> 538 * <li><code>MODE3a</code> = Mode 2 (sRGB): Higher Saturation</li> 539 * <li><code>B & W</code> = B & W</li> 540 * </ul> 541 */ 542 public static final int TAG_NIKON_TYPE2_CAMERA_COLOR_MODE = 0x008D; 543 public static final int TAG_NIKON_TYPE2_UNKNOWN_47 = 0x008E; 544 545 /** 546 * The camera's scene mode, as a string. Examples include: 547 * <ul> 548 * <li><code>BEACH/SNOW</code></li> 549 * <li><code>CLOSE UP</code></li> 550 * <li><code>NIGHT PORTRAIT</code></li> 551 * <li><code>PORTRAIT</code></li> 552 * <li><code>ANTI-SHAKE</code></li> 553 * <li><code>BACK LIGHT</code></li> 554 * <li><code>BEST FACE</code></li> 555 * <li><code>BEST</code></li> 556 * <li><code>COPY</code></li> 557 * <li><code>DAWN/DUSK</code></li> 558 * <li><code>FACE-PRIORITY</code></li> 559 * <li><code>FIREWORKS</code></li> 560 * <li><code>FOOD</code></li> 561 * <li><code>HIGH SENS.</code></li> 562 * <li><code>LAND SCAPE</code></li> 563 * <li><code>MUSEUM</code></li> 564 * <li><code>PANORAMA ASSIST</code></li> 565 * <li><code>PARTY/INDOOR</code></li> 566 * <li><code>SCENE AUTO</code></li> 567 * <li><code>SMILE</code></li> 568 * <li><code>SPORT</code></li> 569 * <li><code>SPORT CONT.</code></li> 570 * <li><code>SUNSET</code></li> 571 * </ul> 572 */ 573 public static final int TAG_NIKON_TYPE2_SCENE_MODE = 0x008F; 574 575 /** 576 * The lighting type, as a string. Examples include: 577 * <ul> 578 * <li><code></code></li> 579 * <li><code>NATURAL</code></li> 580 * <li><code>SPEEDLIGHT</code></li> 581 * <li><code>COLORED</code></li> 582 * <li><code>MIXED</code></li> 583 * <li><code>NORMAL</code></li> 584 * </ul> 585 */ 586 public static final int TAG_NIKON_TYPE2_LIGHT_SOURCE = 0x0090; 587 588 /** 589 * Advertised as ASCII, but actually isn't. A variable number of bytes (eg. 18 to 533). Actual number of bytes 590 * appears fixed for a given camera model. 591 */ 592 public static final int TAG_NIKON_TYPE2_SHOT_INFO = 0x0091; 593 594 /** 595 * The hue adjustment as set in the camera. Values observed are either 0 or 3. 596 */ 597 public static final int TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT = 0x0092; 598 /** 599 * The NEF (RAW) compression. Examples include: 600 * <ul> 601 * <li><code>1</code> Lossy (Type 1)</li> 602 * <li><code>2</code> Uncompressed</li> 603 * <li><code>3</code> Lossless</li> 604 * <li><code>4</code> Lossy (Type 2)</li> 605 * </ul> 606 */ 607 public static final int TAG_NIKON_TYPE2_NEF_COMPRESSION = 0x0093; 608 609 /** 610 * The saturation level, as a signed integer. Examples include: 611 * <ul> 612 * <li><code>+3</code></li> 613 * <li><code>+2</code></li> 614 * <li><code>+1</code></li> 615 * <li><code>0</code> Normal</li> 616 * <li><code>-1</code></li> 617 * <li><code>-2</code></li> 618 * <li><code>-3</code> (B&W)</li> 619 * </ul> 620 */ 621 public static final int TAG_NIKON_TYPE2_SATURATION = 0x0094; 622 623 /** 624 * The type of noise reduction, as a string. Examples include: 625 * <ul> 626 * <li><code>OFF</code></li> 627 * <li><code>FPNR</code></li> 628 * </ul> 629 */ 630 public static final int TAG_NIKON_TYPE2_NOISE_REDUCTION = 0x0095; 631 public static final int TAG_NIKON_TYPE2_LINEARIZATION_TABLE = 0x0096; 632 public static final int TAG_NIKON_TYPE2_COLOR_BALANCE = 0x0097; 633 public static final int TAG_NIKON_TYPE2_LENS_DATA = 0x0098; 634 635 /** The NEF (RAW) thumbnail size, as an integer array with two items representing [width,height]. */ 636 public static final int TAG_NIKON_TYPE2_NEF_THUMBNAIL_SIZE = 0x0099; 637 638 /** The sensor pixel size, as a pair of rational numbers. */ 639 public static final int TAG_NIKON_TYPE2_SENSOR_PIXEL_SIZE = 0x009A; 640 public static final int TAG_NIKON_TYPE2_UNKNOWN_10 = 0x009B; 641 public static final int TAG_NIKON_TYPE2_SCENE_ASSIST = 0x009C; 642 public static final int TAG_NIKON_TYPE2_UNKNOWN_11 = 0x009D; 643 public static final int TAG_NIKON_TYPE2_RETOUCH_HISTORY = 0x009E; 644 public static final int TAG_NIKON_TYPE2_UNKNOWN_12 = 0x009F; 645 646 /** 647 * The camera serial number, as a string. 648 * <ul> 649 * <li><code>NO= 00002539</code></li> 650 * <li><code>NO= -1000d71</code></li> 651 * <li><code>PKG597230621263</code></li> 652 * <li><code>PKG5995671330625116</code></li> 653 * <li><code>PKG49981281631130677</code></li> 654 * <li><code>BU672230725063</code></li> 655 * <li><code>NO= 200332c7</code></li> 656 * <li><code>NO= 30045efe</code></li> 657 * </ul> 658 */ 659 public static final int TAG_NIKON_TYPE2_CAMERA_SERIAL_NUMBER_2 = 0x00A0; 660 661 public static final int TAG_NIKON_TYPE2_IMAGE_DATA_SIZE = 0x00A2; 662 663 public static final int TAG_NIKON_TYPE2_UNKNOWN_27 = 0x00A3; 664 public static final int TAG_NIKON_TYPE2_UNKNOWN_28 = 0x00A4; 665 public static final int TAG_NIKON_TYPE2_IMAGE_COUNT = 0x00A5; 666 public static final int TAG_NIKON_TYPE2_DELETED_IMAGE_COUNT = 0x00A6; 667 668 /** The number of total shutter releases. This value increments for each exposure (observed on D70). */ 669 public static final int TAG_NIKON_TYPE2_EXPOSURE_SEQUENCE_NUMBER = 0x00A7; 670 671 public static final int TAG_NIKON_TYPE2_FLASH_INFO = 0x00A8; 672 /** 673 * The camera's image optimisation, as a string. 674 * <ul> 675 * <li><code></code></li> 676 * <li><code>NORMAL</code></li> 677 * <li><code>CUSTOM</code></li> 678 * <li><code>BLACK AND WHITE</code></li> 679 * <li><code>LAND SCAPE</code></li> 680 * <li><code>MORE VIVID</code></li> 681 * <li><code>PORTRAIT</code></li> 682 * <li><code>SOFT</code></li> 683 * <li><code>VIVID</code></li> 684 * </ul> 685 */ 686 public static final int TAG_NIKON_TYPE2_IMAGE_OPTIMISATION = 0x00A9; 687 688 /** 689 * The camera's saturation level, as a string. 690 * <ul> 691 * <li><code></code></li> 692 * <li><code>NORMAL</code></li> 693 * <li><code>AUTO</code></li> 694 * <li><code>ENHANCED</code></li> 695 * <li><code>MODERATE</code></li> 696 * </ul> 697 */ 698 public static final int TAG_NIKON_TYPE2_SATURATION_2 = 0x00AA; 699 700 /** 701 * The camera's digital vari-program setting, as a string. 702 * <ul> 703 * <li><code></code></li> 704 * <li><code>AUTO</code></li> 705 * <li><code>AUTO(FLASH OFF)</code></li> 706 * <li><code>CLOSE UP</code></li> 707 * <li><code>LANDSCAPE</code></li> 708 * <li><code>NIGHT PORTRAIT</code></li> 709 * <li><code>PORTRAIT</code></li> 710 * <li><code>SPORT</code></li> 711 * </ul> 712 */ 713 public static final int TAG_NIKON_TYPE2_DIGITAL_VARI_PROGRAM = 0x00AB; 714 715 /** 716 * The camera's digital vari-program setting, as a string. 717 * <ul> 718 * <li><code></code></li> 719 * <li><code>VR-ON</code></li> 720 * <li><code>VR-OFF</code></li> 721 * <li><code>VR-HYBRID</code></li> 722 * <li><code>VR-ACTIVE</code></li> 723 * </ul> 724 */ 725 public static final int TAG_NIKON_TYPE2_IMAGE_STABILISATION = 0x00AC; 726 727 /** 728 * The camera's digital vari-program setting, as a string. 729 * <ul> 730 * <li><code></code></li> 731 * <li><code>HYBRID</code></li> 732 * <li><code>STANDARD</code></li> 733 * </ul> 734 */ 735 public static final int TAG_NIKON_TYPE2_AF_RESPONSE = 0x00AD; 736 public static final int TAG_NIKON_TYPE2_UNKNOWN_29 = 0x00AE; 737 public static final int TAG_NIKON_TYPE2_UNKNOWN_30 = 0x00AF; 738 public static final int TAG_NIKON_TYPE2_MULTI_EXPOSURE = 0x00B0; 739 740 /** 741 * The camera's high ISO noise reduction setting, as an integer. 742 * <ul> 743 * <li><code>0</code> Off</li> 744 * <li><code>1</code> Minimal</li> 745 * <li><code>2</code> Low</li> 746 * <li><code>4</code> Normal</li> 747 * <li><code>6</code> High</li> 748 * </ul> 749 */ 750 public static final int TAG_NIKON_TYPE2_HIGH_ISO_NOISE_REDUCTION = 0x00B1; 751 public static final int TAG_NIKON_TYPE2_UNKNOWN_31 = 0x00B2; 752 public static final int TAG_NIKON_TYPE2_UNKNOWN_32 = 0x00B3; 753 public static final int TAG_NIKON_TYPE2_UNKNOWN_33 = 0x00B4; 754 public static final int TAG_NIKON_TYPE2_UNKNOWN_48 = 0x00B5; 755 public static final int TAG_NIKON_TYPE2_POWER_UP_TIME = 0x00B6; 756 public static final int TAG_NIKON_TYPE2_AF_INFO_2 = 0x00B7; 757 public static final int TAG_NIKON_TYPE2_FILE_INFO = 0x00B8; 758 public static final int TAG_NIKON_TYPE2_AF_TUNE = 0x00B9; 759 public static final int TAG_NIKON_TYPE2_UNKNOWN_49 = 0x00BB; 760 public static final int TAG_NIKON_TYPE2_UNKNOWN_50 = 0x00BD; 761 public static final int TAG_NIKON_TYPE2_UNKNOWN_51 = 0x0103; 762 public static final int TAG_NIKON_TYPE2_PRINT_IM = 0x0E00; 763 764 /** 765 * Data about changes set by Nikon Capture Editor. 766 * 267 767 * Values observed 268 * - 0 269 * - 9 270 * - 3 (D1X) 271 */ 272 public static final int TAG_NIKON_TYPE2_UNKNOWN_5 = 0x0087; 273 274 /** 275 * Values observed 276 * - 277 */ 278 public static final int TAG_NIKON_TYPE2_AF_FOCUS_POSITION = 0x0088; 279 280 /** 281 * Values observed 282 * - 0 283 * - 1 284 */ 285 public static final int TAG_NIKON_TYPE2_UNKNOWN_7 = 0x0089; 286 287 /** 288 * Values observed 289 * - 0 290 * - 0 291 */ 292 public static final int TAG_NIKON_TYPE2_UNKNOWN_20 = 0x008A; 293 294 /** 295 * Values observed 296 * - 48,1,c,0 (hex) (D100) 297 * - @ <hex> 298 */ 299 public static final int TAG_NIKON_TYPE2_UNKNOWN_8 = 0x008B; 300 301 /** 302 * Unknown. Fabrizio believes this may be a lookup table for the user-defined curve. 303 * 304 * Values observed 305 * - (blank) (D1X) 306 */ 307 public static final int TAG_NIKON_TYPE2_UNKNOWN_9 = 0x008C; 308 309 /** 310 * The color space as set in the camera. 311 * 312 * Values observed 313 * - MODE1 314 * - Mode I (sRGB) (D70) 315 * - MODE2 (D1X, D100) 316 */ 317 public static final int TAG_NIKON_TYPE2_CAMERA_COLOR_MODE = 0x008D; 318 319 /** 320 * Values observed 321 * - NATURAL 322 * - SPEEDLIGHT (D70, D1X) 323 */ 324 public static final int TAG_NIKON_TYPE2_LIGHT_SOURCE = 0x0090; 325 326 /** 327 * Values observed 328 * - 0100 <hex> 329 * - 0103 (D70) 330 * - 0100 (D1X) 331 */ 332 public static final int TAG_NIKON_TYPE2_UNKNOWN_11 = 0x0091; 333 334 /** 335 * The hue adjustment as set in the camera. 336 * 337 * Values observed 338 * - 0 339 */ 340 public static final int TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT = 0x0092; 341 342 /** 343 * Values observed 344 * - OFF 345 */ 346 public static final int TAG_NIKON_TYPE2_NOISE_REDUCTION = 0x0095; 347 348 /** 349 * Values observed 350 * - 0100 <hex> 351 * - 0103 <hex> 352 */ 353 public static final int TAG_NIKON_TYPE2_UNKNOWN_12 = 0x0097; 354 355 /** 356 * Values observed 357 * - 0100 <hex> 358 * - 0101 <hex> 359 * - 0100 <hex> (D1X) 360 * - 30,31,30,30,0,0,b,48,7c,7c,24,24,5,15,24,0,0,0,0,0 (hex) (D100) 361 */ 362 public static final int TAG_NIKON_TYPE2_UNKNOWN_13 = 0x0098; 363 364 /** 365 * Values observed 366 * - 2014 662 (D1X) 367 * - 1517,1012 (D100) 368 */ 369 public static final int TAG_NIKON_TYPE2_UNKNOWN_14 = 0x0099; 370 371 /** 372 * Values observed 373 * - 78/10 78/10 374 * - 78/10 78/10 (D70) 375 * - 59/10 59/5 (D1X) 376 * - 7.8,7.8 (D100) 377 */ 378 public static final int TAG_NIKON_TYPE2_UNKNOWN_15 = 0x009A; 379 380 /** 381 * Values observed 382 * - NO= 00002539 383 */ 384 public static final int TAG_NIKON_TYPE2_UNKNOWN_25 = 0x00A0; 385 386 /** 387 * Values observed 388 * - 1564851 389 */ 390 public static final int TAG_NIKON_TYPE2_UNKNOWN_26 = 0x00A2; 391 392 /** 393 * Values observed 394 * - 0 395 */ 396 public static final int TAG_NIKON_TYPE2_UNKNOWN_27 = 0x00A3; 397 398 /** 399 * This appears to be a sequence number to indentify the exposure. This value seems to increment 400 * for consecutive exposures (observed on D70). 401 * 402 * Values observed 403 * - 5062 404 */ 405 public static final int TAG_NIKON_TYPE2_EXPOSURE_SEQUENCE_NUMBER = 0x00A7; 406 407 /** 408 * Values observed 409 * - 0100 (D70) 410 */ 411 public static final int TAG_NIKON_TYPE2_UNKNOWN_32 = 0x00A8; 412 413 /** 414 * Values observed 415 * - NORMAL (D70) 416 */ 417 public static final int TAG_NIKON_TYPE2_UNKNOWN_33 = 0x00A9; 418 419 /** 420 * Nikon Browser suggests this value represents Saturation... 421 * Values observed 422 * - NORMAL (D70) 423 */ 424 public static final int TAG_NIKON_TYPE2_UNKNOWN_29 = 0x00AA; 425 426 /** 427 * Values observed 428 * - AUTO (D70) 429 * - (blank) (D70) 430 */ 431 public static final int TAG_NIKON_TYPE2_UNKNOWN_30 = 0x00AB; 432 433 /** 434 * Data about changes set by Nikon Capture Editor. 435 * 436 * Values observed 437 */ 438 public static final int TAG_NIKON_TYPE2_CAPTURE_EDITOR_DATA = 0x0E01; 439 440 /** 441 * Values observed 442 * - 1473 443 * - 7036 (D100) 444 */ 445 public static final int TAG_NIKON_TYPE2_UNKNOWN_16 = 0x0E10; 446 447 protected static final HashMap _tagNameMap = new HashMap(); 768 */ 769 public static final int TAG_NIKON_TYPE2_NIKON_CAPTURE_DATA = 0x0E01; 770 public static final int TAG_NIKON_TYPE2_UNKNOWN_52 = 0x0E05; 771 public static final int TAG_NIKON_TYPE2_UNKNOWN_53 = 0x0E08; 772 public static final int TAG_NIKON_TYPE2_NIKON_CAPTURE_VERSION = 0x0E09; 773 public static final int TAG_NIKON_TYPE2_NIKON_CAPTURE_OFFSETS = 0x0E0E; 774 public static final int TAG_NIKON_TYPE2_NIKON_SCAN = 0x0E10; 775 public static final int TAG_NIKON_TYPE2_UNKNOWN_54 = 0x0E19; 776 public static final int TAG_NIKON_TYPE2_NEF_BIT_DEPTH = 0x0E22; 777 public static final int TAG_NIKON_TYPE2_UNKNOWN_55 = 0x0E23; 778 779 @NotNull 780 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 448 781 449 782 static 450 783 { 451 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_FIRMWARE_VERSION), "Firmware Version"); 452 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_ISO_1), "ISO"); 453 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_QUALITY_AND_FILE_FORMAT), "Quality & File Format"); 454 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE), "White Balance"); 455 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_SHARPENING), "Sharpening"); 456 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_AF_TYPE), "AF Type"); 457 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE_FINE), "White Balance Fine"); 458 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE_RB_COEFF), "White Balance RB Coefficients"); 459 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_ISO_2), "ISO"); 460 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_ISO_SELECTION), "ISO Selection"); 461 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_DATA_DUMP), "Data Dump"); 462 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_IMAGE_ADJUSTMENT), "Image Adjustment"); 463 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_TONE_COMPENSATION), "Tone Compensation"); 464 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_ADAPTER), "Adapter"); 465 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_LENS), "Lens"); 466 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_MANUAL_FOCUS_DISTANCE), "Manual Focus Distance"); 467 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_DIGITAL_ZOOM), "Digital Zoom"); 468 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_COLOR_MODE), "Colour Mode"); 469 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT), "Camera Hue Adjustment"); 470 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_NOISE_REDUCTION), "Noise Reduction"); 471 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_CAPTURE_EDITOR_DATA), "Capture Editor Data"); 472 473 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_1), "Unknown 01"); 474 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_2), "Unknown 02"); 475 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_3), "Unknown 03"); 476 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_4), "Unknown 04"); 477 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_5), "Unknown 05"); 478 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_AF_FOCUS_POSITION), "AF Focus Position"); 479 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_7), "Unknown 07"); 480 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_8), "Unknown 08"); 481 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_9), "Unknown 09"); 482 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_LIGHT_SOURCE), "Light source"); 483 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_11), "Unknown 11"); 484 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_12), "Unknown 12"); 485 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_13), "Unknown 13"); 486 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_14), "Unknown 14"); 487 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_15), "Unknown 15"); 488 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_16), "Unknown 16"); 489 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_FLASH_SYNC_MODE), "Flash Sync Mode"); 490 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_AUTO_FLASH_MODE), "Auto Flash Mode"); 491 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION), "Auto Flash Compensation"); 492 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_EXPOSURE_SEQUENCE_NUMBER), "Exposure Sequence Number"); 493 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_COLOR_MODE), "Color Mode"); 494 495 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_20), "Unknown 20"); 496 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_21), "Unknown 21"); 497 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_22), "Unknown 22"); 498 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_23), "Unknown 23"); 499 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_24), "Unknown 24"); 500 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_25), "Unknown 25"); 501 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_26), "Unknown 26"); 502 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_27), "Unknown 27"); 503 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_29), "Unknown 29"); 504 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_30), "Unknown 30"); 505 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_32), "Unknown 32"); 506 _tagNameMap.put(new Integer(TAG_NIKON_TYPE2_UNKNOWN_33), "Unknown 33"); 784 _tagNameMap.put(TAG_NIKON_TYPE2_FIRMWARE_VERSION, "Firmware Version"); 785 _tagNameMap.put(TAG_NIKON_TYPE2_ISO_1, "ISO"); 786 _tagNameMap.put(TAG_NIKON_TYPE2_QUALITY_AND_FILE_FORMAT, "Quality & File Format"); 787 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE, "White Balance"); 788 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_SHARPENING, "Sharpening"); 789 _tagNameMap.put(TAG_NIKON_TYPE2_AF_TYPE, "AF Type"); 790 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE_FINE, "White Balance Fine"); 791 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_WHITE_BALANCE_RB_COEFF, "White Balance RB Coefficients"); 792 _tagNameMap.put(TAG_NIKON_TYPE2_ISO_REQUESTED, "ISO"); 793 _tagNameMap.put(TAG_NIKON_TYPE2_ISO_MODE, "ISO Mode"); 794 _tagNameMap.put(TAG_NIKON_TYPE2_DATA_DUMP, "Data Dump"); 795 796 _tagNameMap.put(TAG_NIKON_TYPE2_PROGRAM_SHIFT, "Program Shift"); 797 _tagNameMap.put(TAG_NIKON_TYPE2_EXPOSURE_DIFFERENCE, "Exposure Difference"); 798 _tagNameMap.put(TAG_NIKON_TYPE2_PREVIEW_IFD, "Preview IFD"); 799 _tagNameMap.put(TAG_NIKON_TYPE2_LENS_TYPE, "Lens Type"); 800 _tagNameMap.put(TAG_NIKON_TYPE2_FLASH_USED, "Flash Used"); 801 _tagNameMap.put(TAG_NIKON_TYPE2_AF_FOCUS_POSITION, "AF Focus Position"); 802 _tagNameMap.put(TAG_NIKON_TYPE2_SHOOTING_MODE, "Shooting Mode"); 803 _tagNameMap.put(TAG_NIKON_TYPE2_LENS_STOPS, "Lens Stops"); 804 _tagNameMap.put(TAG_NIKON_TYPE2_CONTRAST_CURVE, "Contrast Curve"); 805 _tagNameMap.put(TAG_NIKON_TYPE2_LIGHT_SOURCE, "Light source"); 806 _tagNameMap.put(TAG_NIKON_TYPE2_SHOT_INFO, "Shot Info"); 807 _tagNameMap.put(TAG_NIKON_TYPE2_COLOR_BALANCE, "Color Balance"); 808 _tagNameMap.put(TAG_NIKON_TYPE2_LENS_DATA, "Lens Data"); 809 _tagNameMap.put(TAG_NIKON_TYPE2_NEF_THUMBNAIL_SIZE, "NEF Thumbnail Size"); 810 _tagNameMap.put(TAG_NIKON_TYPE2_SENSOR_PIXEL_SIZE, "Sensor Pixel Size"); 811 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_10, "Unknown 10"); 812 _tagNameMap.put(TAG_NIKON_TYPE2_SCENE_ASSIST, "Scene Assist"); 813 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_11, "Unknown 11"); 814 _tagNameMap.put(TAG_NIKON_TYPE2_RETOUCH_HISTORY, "Retouch History"); 815 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_12, "Unknown 12"); 816 _tagNameMap.put(TAG_NIKON_TYPE2_FLASH_SYNC_MODE, "Flash Sync Mode"); 817 _tagNameMap.put(TAG_NIKON_TYPE2_AUTO_FLASH_MODE, "Auto Flash Mode"); 818 _tagNameMap.put(TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION, "Auto Flash Compensation"); 819 _tagNameMap.put(TAG_NIKON_TYPE2_EXPOSURE_SEQUENCE_NUMBER, "Exposure Sequence Number"); 820 _tagNameMap.put(TAG_NIKON_TYPE2_COLOR_MODE, "Color Mode"); 821 822 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_20, "Unknown 20"); 823 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_BOUNDARY, "Image Boundary"); 824 _tagNameMap.put(TAG_NIKON_TYPE2_FLASH_EXPOSURE_COMPENSATION, "Flash Exposure Compensation"); 825 _tagNameMap.put(TAG_NIKON_TYPE2_FLASH_BRACKET_COMPENSATION, "Flash Bracket Compensation"); 826 _tagNameMap.put(TAG_NIKON_TYPE2_AE_BRACKET_COMPENSATION, "AE Bracket Compensation"); 827 _tagNameMap.put(TAG_NIKON_TYPE2_FLASH_MODE, "Flash Mode"); 828 _tagNameMap.put(TAG_NIKON_TYPE2_CROP_HIGH_SPEED, "Crop High Speed"); 829 _tagNameMap.put(TAG_NIKON_TYPE2_EXPOSURE_TUNING, "Exposure Tuning"); 830 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_SERIAL_NUMBER, "Camera Serial Number"); 831 _tagNameMap.put(TAG_NIKON_TYPE2_COLOR_SPACE, "Color Space"); 832 _tagNameMap.put(TAG_NIKON_TYPE2_VR_INFO, "VR Info"); 833 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_AUTHENTICATION, "Image Authentication"); 834 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_35, "Unknown 35"); 835 _tagNameMap.put(TAG_NIKON_TYPE2_ACTIVE_D_LIGHTING, "Active D-Lighting"); 836 _tagNameMap.put(TAG_NIKON_TYPE2_PICTURE_CONTROL, "Picture Control"); 837 _tagNameMap.put(TAG_NIKON_TYPE2_WORLD_TIME, "World Time"); 838 _tagNameMap.put(TAG_NIKON_TYPE2_ISO_INFO, "ISO Info"); 839 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_36, "Unknown 36"); 840 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_37, "Unknown 37"); 841 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_38, "Unknown 38"); 842 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_39, "Unknown 39"); 843 _tagNameMap.put(TAG_NIKON_TYPE2_VIGNETTE_CONTROL, "Vignette Control"); 844 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_40, "Unknown 40"); 845 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_41, "Unknown 41"); 846 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_42, "Unknown 42"); 847 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_43, "Unknown 43"); 848 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_44, "Unknown 44"); 849 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_45, "Unknown 45"); 850 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_46, "Unknown 46"); 851 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_47, "Unknown 47"); 852 _tagNameMap.put(TAG_NIKON_TYPE2_SCENE_MODE, "Scene Mode"); 853 854 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_SERIAL_NUMBER_2, "Camera Serial Number"); 855 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_DATA_SIZE, "Image Data Size"); 856 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_27, "Unknown 27"); 857 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_28, "Unknown 28"); 858 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_COUNT, "Image Count"); 859 _tagNameMap.put(TAG_NIKON_TYPE2_DELETED_IMAGE_COUNT, "Deleted Image Count"); 860 _tagNameMap.put(TAG_NIKON_TYPE2_SATURATION_2, "Saturation"); 861 _tagNameMap.put(TAG_NIKON_TYPE2_DIGITAL_VARI_PROGRAM, "Digital Vari Program"); 862 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_STABILISATION, "Image Stabilisation"); 863 _tagNameMap.put(TAG_NIKON_TYPE2_AF_RESPONSE, "AF Response"); 864 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_29, "Unknown 29"); 865 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_30, "Unknown 30"); 866 _tagNameMap.put(TAG_NIKON_TYPE2_MULTI_EXPOSURE, "Multi Exposure"); 867 _tagNameMap.put(TAG_NIKON_TYPE2_HIGH_ISO_NOISE_REDUCTION, "High ISO Noise Reduction"); 868 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_31, "Unknown 31"); 869 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_32, "Unknown 32"); 870 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_33, "Unknown 33"); 871 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_48, "Unknown 48"); 872 _tagNameMap.put(TAG_NIKON_TYPE2_POWER_UP_TIME, "Power Up Time"); 873 _tagNameMap.put(TAG_NIKON_TYPE2_AF_INFO_2, "AF Info 2"); 874 _tagNameMap.put(TAG_NIKON_TYPE2_FILE_INFO, "File Info"); 875 _tagNameMap.put(TAG_NIKON_TYPE2_AF_TUNE, "AF Tune"); 876 _tagNameMap.put(TAG_NIKON_TYPE2_FLASH_INFO, "Flash Info"); 877 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_OPTIMISATION, "Image Optimisation"); 878 879 _tagNameMap.put(TAG_NIKON_TYPE2_IMAGE_ADJUSTMENT, "Image Adjustment"); 880 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_TONE_COMPENSATION, "Tone Compensation"); 881 _tagNameMap.put(TAG_NIKON_TYPE2_ADAPTER, "Adapter"); 882 _tagNameMap.put(TAG_NIKON_TYPE2_LENS, "Lens"); 883 _tagNameMap.put(TAG_NIKON_TYPE2_MANUAL_FOCUS_DISTANCE, "Manual Focus Distance"); 884 _tagNameMap.put(TAG_NIKON_TYPE2_DIGITAL_ZOOM, "Digital Zoom"); 885 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_COLOR_MODE, "Colour Mode"); 886 _tagNameMap.put(TAG_NIKON_TYPE2_CAMERA_HUE_ADJUSTMENT, "Camera Hue Adjustment"); 887 _tagNameMap.put(TAG_NIKON_TYPE2_NEF_COMPRESSION, "NEF Compression"); 888 _tagNameMap.put(TAG_NIKON_TYPE2_SATURATION, "Saturation"); 889 _tagNameMap.put(TAG_NIKON_TYPE2_NOISE_REDUCTION, "Noise Reduction"); 890 _tagNameMap.put(TAG_NIKON_TYPE2_LINEARIZATION_TABLE, "Linearization Table"); 891 _tagNameMap.put(TAG_NIKON_TYPE2_NIKON_CAPTURE_DATA, "Nikon Capture Data"); 892 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_49, "Unknown 49"); 893 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_50, "Unknown 50"); 894 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_51, "Unknown 51"); 895 _tagNameMap.put(TAG_NIKON_TYPE2_PRINT_IM, "Print IM"); 896 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_52, "Unknown 52"); 897 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_53, "Unknown 53"); 898 _tagNameMap.put(TAG_NIKON_TYPE2_NIKON_CAPTURE_VERSION, "Nikon Capture Version"); 899 _tagNameMap.put(TAG_NIKON_TYPE2_NIKON_CAPTURE_OFFSETS, "Nikon Capture Offsets"); 900 _tagNameMap.put(TAG_NIKON_TYPE2_NIKON_SCAN, "Nikon Scan"); 901 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_54, "Unknown 54"); 902 _tagNameMap.put(TAG_NIKON_TYPE2_NEF_BIT_DEPTH, "NEF Bit Depth"); 903 _tagNameMap.put(TAG_NIKON_TYPE2_UNKNOWN_55, "Unknown 55"); 507 904 } 508 905 … … 512 909 } 513 910 514 public Rational getAutoFlashCompensation() throws MetadataException 515 { 516 if (!containsTag(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION)) 517 return null; 518 519 byte[] bytes = getByteArray(NikonType2MakernoteDirectory.TAG_NIKON_TYPE2_AUTO_FLASH_COMPENSATION); 520 return CalculateFlashCompensationFromBytes(bytes); 521 } 522 523 public static Rational CalculateFlashCompensationFromBytes(byte[] bytes) 524 { 525 if (bytes.length==3) 526 { 527 byte denominator = bytes[2]; 528 int numerator = (int)bytes[0] * bytes[1]; 529 return new Rational(numerator, denominator); 530 } 531 return null; 532 } 533 911 @NotNull 534 912 public String getName() 535 913 { … … 537 915 } 538 916 539 protected HashMap getTagNameMap() 917 @NotNull 918 protected HashMap<Integer, String> getTagNameMap() 540 919 { 541 920 return _tagNameMap; -
trunk/src/com/drew/metadata/exif/OlympusMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 import com.drew. metadata.Directory;18 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 19 25 import com.drew.metadata.TagDescriptor; 20 26 21 27 /** 22 * Provides human-readable string versions of the tags stored in an OlympusMakernoteDirectory. 28 * Provides human-readable string representations of tag values stored in a <code>OlympusMakernoteDirectory</code>. 29 * 30 * @author Drew Noakes http://drewnoakes.com 23 31 */ 24 public class OlympusMakernoteDescriptor extends TagDescriptor 32 public class OlympusMakernoteDescriptor extends TagDescriptor<OlympusMakernoteDirectory> 25 33 { 26 public OlympusMakernoteDescriptor(Directory directory) 34 public OlympusMakernoteDescriptor(@NotNull OlympusMakernoteDirectory directory) 27 35 { 28 36 super(directory); 29 37 } 30 38 31 public String getDescription(int tagType) throws MetadataException 39 @Nullable 40 public String getDescription(int tagType) 32 41 { 33 42 switch (tagType) { … … 41 50 return getDigiZoomRatioDescription(); 42 51 default: 43 return _directory.getString(tagType);52 return super.getDescription(tagType); 44 53 } 45 54 } 46 55 47 public String getDigiZoomRatioDescription() throws MetadataException 56 @Nullable 57 public String getDigiZoomRatioDescription() 48 58 { 49 if (!_directory.containsTag(OlympusMakernoteDirectory.TAG_OLYMPUS_DIGI_ZOOM_RATIO)) return null; 50 int value = _directory.getInt(OlympusMakernoteDirectory.TAG_OLYMPUS_DIGI_ZOOM_RATIO); 59 Integer value = _directory.getInteger(OlympusMakernoteDirectory.TAG_OLYMPUS_DIGI_ZOOM_RATIO); 60 if (value==null) 61 return null; 51 62 switch (value) { 52 63 case 0: … … 59 70 } 60 71 61 public String getMacroModeDescription() throws MetadataException 72 @Nullable 73 public String getMacroModeDescription() 62 74 { 63 if (!_directory.containsTag(OlympusMakernoteDirectory.TAG_OLYMPUS_MACRO_MODE)) return null; 64 int value = _directory.getInt(OlympusMakernoteDirectory.TAG_OLYMPUS_MACRO_MODE); 75 Integer value = _directory.getInteger(OlympusMakernoteDirectory.TAG_OLYMPUS_MACRO_MODE); 76 if (value==null) 77 return null; 65 78 switch (value) { 66 79 case 0: … … 73 86 } 74 87 75 public String getJpegQualityDescription() throws MetadataException 88 @Nullable 89 public String getJpegQualityDescription() 76 90 { 77 if (!_directory.containsTag(OlympusMakernoteDirectory.TAG_OLYMPUS_JPEG_QUALITY)) return null; 78 int value = _directory.getInt(OlympusMakernoteDirectory.TAG_OLYMPUS_JPEG_QUALITY); 91 Integer value = _directory.getInteger(OlympusMakernoteDirectory.TAG_OLYMPUS_JPEG_QUALITY); 92 if (value==null) 93 return null; 79 94 switch (value) { 80 95 case 1: … … 89 104 } 90 105 91 public String getSpecialModeDescription() throws MetadataException 106 @Nullable 107 public String getSpecialModeDescription() 92 108 { 93 if (!_directory.containsTag(OlympusMakernoteDirectory.TAG_OLYMPUS_SPECIAL_MODE)) return null;94 109 int[] values = _directory.getIntArray(OlympusMakernoteDirectory.TAG_OLYMPUS_SPECIAL_MODE); 95 StringBuffer desc = new StringBuffer(); 110 if (values==null) 111 return null; 112 if (values.length < 1) 113 return ""; 114 StringBuilder desc = new StringBuilder(); 96 115 switch (values[0]) { 97 116 case 0: … … 111 130 break; 112 131 } 132 133 if (values.length < 2) 134 return desc.toString(); 113 135 desc.append(" - "); 114 136 switch (values[1]) { … … 117 139 break; 118 140 case 1: 119 desc.append("1st in a sequnce"); 141 desc.append("1st in a sequence"); 120 142 break; 121 143 case 2: … … 130 152 break; 131 153 } 154 if (values.length < 3) 155 return desc.toString(); 156 desc.append(" - "); 132 157 switch (values[2]) { 133 158 case 1: -
trunk/src/com/drew/metadata/exif/OlympusMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 14 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 24 * The Olympus makernote is used by many manufacturers, and as such contains some tags that appear specific to 25 * those manufacturers. Other users include Konica, Minolta and Epson. 29 * The Olympus makernote is used by many manufacturers (Konica, Minolta and Epson...), and as such contains some tags 30 * that appear specific to those manufacturers. 31 * 32 * @author Drew Noakes http://drewnoakes.com 26 33 */ 27 34 public class OlympusMakernoteDirectory extends Directory 28 35 { 29 /** 30 * Used by Konica / Minolta cameras. 31 */ 36 /** Used by Konica / Minolta cameras. */ 32 37 public static final int TAG_OLYMPUS_MAKERNOTE_VERSION = 0x0000; 33 34 /** 35 * Used by Konica / Minolta cameras. 36 */ 38 /** Used by Konica / Minolta cameras. */ 37 39 public static final int TAG_OLYMPUS_CAMERA_SETTINGS_1 = 0x0001; 38 39 /** 40 * Alternate Camera Settings Tag. Used by Konica / Minolta cameras. 41 */ 40 /** Alternate Camera Settings Tag. Used by Konica / Minolta cameras. */ 42 41 public static final int TAG_OLYMPUS_CAMERA_SETTINGS_2 = 0x0003; 43 44 /** 45 * Used by Konica / Minolta cameras. 46 */ 42 /** Used by Konica / Minolta cameras. */ 47 43 public static final int TAG_OLYMPUS_COMPRESSED_IMAGE_SIZE = 0x0040; 48 49 /** 50 * Used by Konica / Minolta cameras. 51 */ 44 /** Used by Konica / Minolta cameras. */ 52 45 public static final int TAG_OLYMPUS_MINOLTA_THUMBNAIL_OFFSET_1 = 0x0081; 53 54 /** 55 * Alternate Thumbnail Offset. Used by Konica / Minolta cameras. 56 */ 46 /** Alternate Thumbnail Offset. Used by Konica / Minolta cameras. */ 57 47 public static final int TAG_OLYMPUS_MINOLTA_THUMBNAIL_OFFSET_2 = 0x0088; 58 59 /** 60 * Length of thumbnail in bytes. Used by Konica / Minolta cameras. 61 */ 48 /** Length of thumbnail in bytes. Used by Konica / Minolta cameras. */ 62 49 public static final int TAG_OLYMPUS_MINOLTA_THUMBNAIL_LENGTH = 0x0089; 63 50 … … 84 71 /** 85 72 * Not 100% sure about this tag. 86 * 73 * <p/> 87 74 * Used by Konica / Minolta cameras. 88 75 * 0 = Raw … … 119 106 public static final int TAG_OLYMPUS_MACRO_MODE = 0x0202; 120 107 121 /**122 *123 */124 108 public static final int TAG_OLYMPUS_UNKNOWN_1 = 0x0203; 125 109 126 /** 127 * Zoom Factor (0 or 1 = normal) 128 */ 110 /** Zoom Factor (0 or 1 = normal) */ 129 111 public static final int TAG_OLYMPUS_DIGI_ZOOM_RATIO = 0x0204; 130 131 /**132 *133 */134 112 public static final int TAG_OLYMPUS_UNKNOWN_2 = 0x0205; 135 136 /**137 *138 */139 113 public static final int TAG_OLYMPUS_UNKNOWN_3 = 0x0206; 140 141 /**142 *143 */144 114 public static final int TAG_OLYMPUS_FIRMWARE_VERSION = 0x0207; 145 146 /**147 *148 */149 115 public static final int TAG_OLYMPUS_PICT_INFO = 0x0208; 150 151 /**152 *153 */154 116 public static final int TAG_OLYMPUS_CAMERA_ID = 0x0209; 155 117 … … 166 128 public static final int TAG_OLYMPUS_IMAGE_HEIGHT = 0x020C; 167 129 168 /** 169 * A string. Used by Epson cameras. 170 */ 130 /** A string. Used by Epson cameras. */ 171 131 public static final int TAG_OLYMPUS_ORIGINAL_MANUFACTURER_MODEL = 0x020D; 172 132 … … 177 137 public static final int TAG_OLYMPUS_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 178 138 179 /**180 *181 */182 139 public static final int TAG_OLYMPUS_DATA_DUMP = 0x0F00; 183 184 /**185 *186 */187 140 public static final int TAG_OLYMPUS_FLASH_MODE = 0x1004; 188 189 /**190 *191 */192 141 public static final int TAG_OLYMPUS_BRACKET = 0x1006; 193 194 /**195 *196 */197 142 public static final int TAG_OLYMPUS_FOCUS_MODE = 0x100B; 198 199 /**200 *201 */202 143 public static final int TAG_OLYMPUS_FOCUS_DISTANCE = 0x100C; 203 204 /**205 *206 */207 144 public static final int TAG_OLYMPUS_ZOOM = 0x100D; 208 209 /**210 *211 */212 145 public static final int TAG_OLYMPUS_MACRO_FOCUS = 0x100E; 213 214 /**215 *216 */217 146 public static final int TAG_OLYMPUS_SHARPNESS = 0x100F; 218 219 /**220 *221 */222 147 public static final int TAG_OLYMPUS_COLOUR_MATRIX = 0x1011; 223 224 /**225 *226 */227 148 public static final int TAG_OLYMPUS_BLACK_LEVEL = 0x1012; 228 229 /**230 *231 */232 149 public static final int TAG_OLYMPUS_WHITE_BALANCE = 0x1015; 233 234 /**235 *236 */237 150 public static final int TAG_OLYMPUS_RED_BIAS = 0x1017; 238 239 /**240 *241 */242 151 public static final int TAG_OLYMPUS_BLUE_BIAS = 0x1018; 243 244 /**245 *246 */247 152 public static final int TAG_OLYMPUS_SERIAL_NUMBER = 0x101A; 248 249 /**250 *251 */252 153 public static final int TAG_OLYMPUS_FLASH_BIAS = 0x1023; 253 254 /**255 *256 */257 154 public static final int TAG_OLYMPUS_CONTRAST = 0x1029; 258 259 /**260 *261 */262 155 public static final int TAG_OLYMPUS_SHARPNESS_FACTOR = 0x102A; 263 264 /**265 *266 */267 156 public static final int TAG_OLYMPUS_COLOUR_CONTROL = 0x102B; 268 269 /**270 *271 */272 157 public static final int TAG_OLYMPUS_VALID_BITS = 0x102C; 273 274 /**275 *276 */277 158 public static final int TAG_OLYMPUS_CORING_FILTER = 0x102D; 278 279 /**280 *281 */282 159 public static final int TAG_OLYMPUS_FINAL_WIDTH = 0x102E; 283 284 /**285 *286 */287 160 public static final int TAG_OLYMPUS_FINAL_HEIGHT = 0x102F; 288 289 /**290 *291 */292 161 public static final int TAG_OLYMPUS_COMPRESSION_RATIO = 0x1034; 293 162 294 protected static final HashMap tagNameMap = new HashMap(); 295 296 static 297 { 298 tagNameMap.put(new Integer(TAG_OLYMPUS_SPECIAL_MODE), "Special Mode"); 299 tagNameMap.put(new Integer(TAG_OLYMPUS_JPEG_QUALITY), "Jpeg Quality"); 300 tagNameMap.put(new Integer(TAG_OLYMPUS_MACRO_MODE), "Macro"); 301 tagNameMap.put(new Integer(TAG_OLYMPUS_UNKNOWN_1), "Makernote Unknown 1"); 302 tagNameMap.put(new Integer(TAG_OLYMPUS_DIGI_ZOOM_RATIO), "DigiZoom Ratio"); 303 tagNameMap.put(new Integer(TAG_OLYMPUS_UNKNOWN_2), "Makernote Unknown 2"); 304 tagNameMap.put(new Integer(TAG_OLYMPUS_UNKNOWN_3), "Makernote Unknown 3"); 305 tagNameMap.put(new Integer(TAG_OLYMPUS_FIRMWARE_VERSION), "Firmware Version"); 306 tagNameMap.put(new Integer(TAG_OLYMPUS_PICT_INFO), "Pict Info"); 307 tagNameMap.put(new Integer(TAG_OLYMPUS_CAMERA_ID), "Camera Id"); 308 tagNameMap.put(new Integer(TAG_OLYMPUS_DATA_DUMP), "Data Dump"); 309 tagNameMap.put(new Integer(TAG_OLYMPUS_MAKERNOTE_VERSION), "Makernote Version"); 310 tagNameMap.put(new Integer(TAG_OLYMPUS_CAMERA_SETTINGS_1), "Camera Settings"); 311 tagNameMap.put(new Integer(TAG_OLYMPUS_CAMERA_SETTINGS_2), "Camera Settings"); 312 tagNameMap.put(new Integer(TAG_OLYMPUS_COMPRESSED_IMAGE_SIZE), "Compressed Image Size"); 313 tagNameMap.put(new Integer(TAG_OLYMPUS_MINOLTA_THUMBNAIL_OFFSET_1), "Thumbnail Offset"); 314 tagNameMap.put(new Integer(TAG_OLYMPUS_MINOLTA_THUMBNAIL_OFFSET_2), "Thumbnail Offset"); 315 tagNameMap.put(new Integer(TAG_OLYMPUS_MINOLTA_THUMBNAIL_LENGTH), "Thumbnail Length"); 316 tagNameMap.put(new Integer(TAG_OLYMPUS_COLOUR_MODE), "Colour Mode"); 317 tagNameMap.put(new Integer(TAG_OLYMPUS_IMAGE_QUALITY_1), "Image Quality"); 318 tagNameMap.put(new Integer(TAG_OLYMPUS_IMAGE_QUALITY_2), "Image Quality"); 319 tagNameMap.put(new Integer(TAG_OLYMPUS_IMAGE_HEIGHT), "Image Height"); 320 tagNameMap.put(new Integer(TAG_OLYMPUS_ORIGINAL_MANUFACTURER_MODEL), "Original Manufacturer Model"); 321 tagNameMap.put(new Integer(TAG_OLYMPUS_PRINT_IMAGE_MATCHING_INFO), "Print Image Matching (PIM) Info"); 322 tagNameMap.put(new Integer(TAG_OLYMPUS_FLASH_MODE), "Flash Mode"); 323 tagNameMap.put(new Integer(TAG_OLYMPUS_BRACKET), "Bracket"); 324 tagNameMap.put(new Integer(TAG_OLYMPUS_FOCUS_MODE), "Focus Mode"); 325 tagNameMap.put(new Integer(TAG_OLYMPUS_FOCUS_DISTANCE), "Focus Distance"); 326 tagNameMap.put(new Integer(TAG_OLYMPUS_ZOOM), "Zoom"); 327 tagNameMap.put(new Integer(TAG_OLYMPUS_MACRO_FOCUS), "Macro Focus"); 328 tagNameMap.put(new Integer(TAG_OLYMPUS_SHARPNESS), "Sharpness"); 329 tagNameMap.put(new Integer(TAG_OLYMPUS_COLOUR_MATRIX), "Colour Matrix"); 330 tagNameMap.put(new Integer(TAG_OLYMPUS_BLACK_LEVEL), "Black Level"); 331 tagNameMap.put(new Integer(TAG_OLYMPUS_WHITE_BALANCE), "White Balance"); 332 tagNameMap.put(new Integer(TAG_OLYMPUS_RED_BIAS), "Red Bias"); 333 tagNameMap.put(new Integer(TAG_OLYMPUS_BLUE_BIAS), "Blue Bias"); 334 tagNameMap.put(new Integer(TAG_OLYMPUS_SERIAL_NUMBER), "Serial Number"); 335 tagNameMap.put(new Integer(TAG_OLYMPUS_FLASH_BIAS), "Flash Bias"); 336 tagNameMap.put(new Integer(TAG_OLYMPUS_CONTRAST), "Contrast"); 337 tagNameMap.put(new Integer(TAG_OLYMPUS_SHARPNESS_FACTOR), "Sharpness Factor"); 338 tagNameMap.put(new Integer(TAG_OLYMPUS_COLOUR_CONTROL), "Colour Control"); 339 tagNameMap.put(new Integer(TAG_OLYMPUS_VALID_BITS), "Valid Bits"); 340 tagNameMap.put(new Integer(TAG_OLYMPUS_CORING_FILTER), "Coring Filter"); 341 tagNameMap.put(new Integer(TAG_OLYMPUS_FINAL_WIDTH), "Final Width"); 342 tagNameMap.put(new Integer(TAG_OLYMPUS_FINAL_HEIGHT), "Final Height"); 343 tagNameMap.put(new Integer(TAG_OLYMPUS_COMPRESSION_RATIO), "Compression Ratio"); 163 @NotNull 164 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 165 166 static { 167 _tagNameMap.put(TAG_OLYMPUS_SPECIAL_MODE, "Special Mode"); 168 _tagNameMap.put(TAG_OLYMPUS_JPEG_QUALITY, "Jpeg Quality"); 169 _tagNameMap.put(TAG_OLYMPUS_MACRO_MODE, "Macro"); 170 _tagNameMap.put(TAG_OLYMPUS_UNKNOWN_1, "Makernote Unknown 1"); 171 _tagNameMap.put(TAG_OLYMPUS_DIGI_ZOOM_RATIO, "DigiZoom Ratio"); 172 _tagNameMap.put(TAG_OLYMPUS_UNKNOWN_2, "Makernote Unknown 2"); 173 _tagNameMap.put(TAG_OLYMPUS_UNKNOWN_3, "Makernote Unknown 3"); 174 _tagNameMap.put(TAG_OLYMPUS_FIRMWARE_VERSION, "Firmware Version"); 175 _tagNameMap.put(TAG_OLYMPUS_PICT_INFO, "Pict Info"); 176 _tagNameMap.put(TAG_OLYMPUS_CAMERA_ID, "Camera Id"); 177 _tagNameMap.put(TAG_OLYMPUS_DATA_DUMP, "Data Dump"); 178 _tagNameMap.put(TAG_OLYMPUS_MAKERNOTE_VERSION, "Makernote Version"); 179 _tagNameMap.put(TAG_OLYMPUS_CAMERA_SETTINGS_1, "Camera Settings"); 180 _tagNameMap.put(TAG_OLYMPUS_CAMERA_SETTINGS_2, "Camera Settings"); 181 _tagNameMap.put(TAG_OLYMPUS_COMPRESSED_IMAGE_SIZE, "Compressed Image Size"); 182 _tagNameMap.put(TAG_OLYMPUS_MINOLTA_THUMBNAIL_OFFSET_1, "Thumbnail Offset"); 183 _tagNameMap.put(TAG_OLYMPUS_MINOLTA_THUMBNAIL_OFFSET_2, "Thumbnail Offset"); 184 _tagNameMap.put(TAG_OLYMPUS_MINOLTA_THUMBNAIL_LENGTH, "Thumbnail Length"); 185 _tagNameMap.put(TAG_OLYMPUS_COLOUR_MODE, "Colour Mode"); 186 _tagNameMap.put(TAG_OLYMPUS_IMAGE_QUALITY_1, "Image Quality"); 187 _tagNameMap.put(TAG_OLYMPUS_IMAGE_QUALITY_2, "Image Quality"); 188 _tagNameMap.put(TAG_OLYMPUS_IMAGE_HEIGHT, "Image Height"); 189 _tagNameMap.put(TAG_OLYMPUS_IMAGE_WIDTH, "Image Width"); 190 _tagNameMap.put(TAG_OLYMPUS_ORIGINAL_MANUFACTURER_MODEL, "Original Manufacturer Model"); 191 _tagNameMap.put(TAG_OLYMPUS_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 192 _tagNameMap.put(TAG_OLYMPUS_FLASH_MODE, "Flash Mode"); 193 _tagNameMap.put(TAG_OLYMPUS_BRACKET, "Bracket"); 194 _tagNameMap.put(TAG_OLYMPUS_FOCUS_MODE, "Focus Mode"); 195 _tagNameMap.put(TAG_OLYMPUS_FOCUS_DISTANCE, "Focus Distance"); 196 _tagNameMap.put(TAG_OLYMPUS_ZOOM, "Zoom"); 197 _tagNameMap.put(TAG_OLYMPUS_MACRO_FOCUS, "Macro Focus"); 198 _tagNameMap.put(TAG_OLYMPUS_SHARPNESS, "Sharpness"); 199 _tagNameMap.put(TAG_OLYMPUS_COLOUR_MATRIX, "Colour Matrix"); 200 _tagNameMap.put(TAG_OLYMPUS_BLACK_LEVEL, "Black Level"); 201 _tagNameMap.put(TAG_OLYMPUS_WHITE_BALANCE, "White Balance"); 202 _tagNameMap.put(TAG_OLYMPUS_RED_BIAS, "Red Bias"); 203 _tagNameMap.put(TAG_OLYMPUS_BLUE_BIAS, "Blue Bias"); 204 _tagNameMap.put(TAG_OLYMPUS_SERIAL_NUMBER, "Serial Number"); 205 _tagNameMap.put(TAG_OLYMPUS_FLASH_BIAS, "Flash Bias"); 206 _tagNameMap.put(TAG_OLYMPUS_CONTRAST, "Contrast"); 207 _tagNameMap.put(TAG_OLYMPUS_SHARPNESS_FACTOR, "Sharpness Factor"); 208 _tagNameMap.put(TAG_OLYMPUS_COLOUR_CONTROL, "Colour Control"); 209 _tagNameMap.put(TAG_OLYMPUS_VALID_BITS, "Valid Bits"); 210 _tagNameMap.put(TAG_OLYMPUS_CORING_FILTER, "Coring Filter"); 211 _tagNameMap.put(TAG_OLYMPUS_FINAL_WIDTH, "Final Width"); 212 _tagNameMap.put(TAG_OLYMPUS_FINAL_HEIGHT, "Final Height"); 213 _tagNameMap.put(TAG_OLYMPUS_COMPRESSION_RATIO, "Compression Ratio"); 344 214 } 345 215 … … 349 219 } 350 220 221 @NotNull 351 222 public String getName() 352 223 { … … 354 225 } 355 226 356 protected HashMap getTagNameMap() 227 @NotNull 228 protected HashMap<Integer, String> getTagNameMap() 357 229 { 358 return tagNameMap; 230 return _tagNameMap; 359 231 } 360 232 } -
trunk/src/com/drew/metadata/exif/PanasonicMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 import com.drew.metadata.Directory; 18 import com.drew.metadata.MetadataException; 23 import com.drew.lang.BufferBoundsException; 24 import com.drew.lang.BufferReader; 25 import com.drew.lang.ByteArrayReader; 26 import com.drew.lang.annotations.NotNull; 27 import com.drew.lang.annotations.Nullable; 28 import com.drew.metadata.Age; 29 import com.drew.metadata.Face; 19 30 import com.drew.metadata.TagDescriptor; 20 31 32 import java.io.UnsupportedEncodingException; 33 21 34 /** 22 * Provides human-readable string versions of the tags stored in a PanasonicMakernoteDirectory. 35 * Provides human-readable string representations of tag values stored in a <code>PanasonicMakernoteDirectory</code>. 36 * <p/> 37 * Some information about this makernote taken from here: 38 * <ul> 39 * <li><a href="http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html">http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html</a></li> 40 * <li><a href="http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Panasonic.html">http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Panasonic.html</a></li> 41 * </ul> 23 42 * 24 * Some information about this makernote taken from here: 25 * http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html 43 * @author Drew Noakes http://drewnoakes.com, Philipp Sandhaus 26 44 */ 27 public class PanasonicMakernoteDescriptor extends TagDescriptor 45 public class PanasonicMakernoteDescriptor extends TagDescriptor<PanasonicMakernoteDirectory> 28 46 { 29 public PanasonicMakernoteDescriptor(Directory directory) 47 public PanasonicMakernoteDescriptor(@NotNull PanasonicMakernoteDirectory directory) 30 48 { 31 49 super(directory); 32 50 } 33 51 34 public String getDescription(int tagType) throws MetadataException 35 { 36 switch (tagType) 52 @Nullable 53 public String getDescription(int tagType) 54 { 55 switch (tagType) { 56 case PanasonicMakernoteDirectory.TAG_QUALITY_MODE: 57 return getQualityModeDescription(); 58 case PanasonicMakernoteDirectory.TAG_VERSION: 59 return getVersionDescription(); 60 case PanasonicMakernoteDirectory.TAG_WHITE_BALANCE: 61 return getWhiteBalanceDescription(); 62 case PanasonicMakernoteDirectory.TAG_FOCUS_MODE: 63 return getFocusModeDescription(); 64 case PanasonicMakernoteDirectory.TAG_AF_AREA_MODE: 65 return getAfAreaModeDescription(); 66 case PanasonicMakernoteDirectory.TAG_IMAGE_STABILIZATION: 67 return getImageStabilizationDescription(); 68 case PanasonicMakernoteDirectory.TAG_MACRO_MODE: 69 return getMacroModeDescription(); 70 case PanasonicMakernoteDirectory.TAG_RECORD_MODE: 71 return getRecordModeDescription(); 72 case PanasonicMakernoteDirectory.TAG_AUDIO: 73 return getAudioDescription(); 74 case PanasonicMakernoteDirectory.TAG_UNKNOWN_DATA_DUMP: 75 return getUnknownDataDumpDescription(); 76 case PanasonicMakernoteDirectory.TAG_COLOR_EFFECT: 77 return getColorEffectDescription(); 78 case PanasonicMakernoteDirectory.TAG_UPTIME: 79 return getUptimeDescription(); 80 case PanasonicMakernoteDirectory.TAG_BURST_MODE: 81 return getBurstModeDescription(); 82 case PanasonicMakernoteDirectory.TAG_CONTRAST_MODE: 83 return getContrastModeDescription(); 84 case PanasonicMakernoteDirectory.TAG_NOISE_REDUCTION: 85 return getNoiseReductionDescription(); 86 case PanasonicMakernoteDirectory.TAG_SELF_TIMER: 87 return getSelfTimerDescription(); 88 case PanasonicMakernoteDirectory.TAG_ROTATION: 89 return getRotationDescription(); 90 case PanasonicMakernoteDirectory.TAG_AF_ASSIST_LAMP: 91 return getAfAssistLampDescription(); 92 case PanasonicMakernoteDirectory.TAG_COLOR_MODE: 93 return getColorModeDescription(); 94 case PanasonicMakernoteDirectory.TAG_OPTICAL_ZOOM_MODE: 95 return getOpticalZoomModeDescription(); 96 case PanasonicMakernoteDirectory.TAG_CONVERSION_LENS: 97 return getConversionLensDescription(); 98 case PanasonicMakernoteDirectory.TAG_CONTRAST: 99 return getContrastDescription(); 100 case PanasonicMakernoteDirectory.TAG_WORLD_TIME_LOCATION: 101 return getWorldTimeLocationDescription(); 102 case PanasonicMakernoteDirectory.TAG_ADVANCED_SCENE_MODE: 103 return getAdvancedSceneModeDescription(); 104 case PanasonicMakernoteDirectory.TAG_FACE_DETECTION_INFO: 105 return getDetectedFacesDescription(); 106 case PanasonicMakernoteDirectory.TAG_TRANSFORM: 107 return getTransformDescription(); 108 case PanasonicMakernoteDirectory.TAG_TRANSFORM_1: 109 return getTransform1Description(); 110 case PanasonicMakernoteDirectory.TAG_INTELLIGENT_EXPOSURE: 111 return getIntelligentExposureDescription(); 112 case PanasonicMakernoteDirectory.TAG_FLASH_WARNING: 113 return getFlashWarningDescription(); 114 case PanasonicMakernoteDirectory.TAG_COUNTRY: 115 return getCountryDescription(); 116 case PanasonicMakernoteDirectory.TAG_STATE: 117 return getStateDescription(); 118 case PanasonicMakernoteDirectory.TAG_CITY: 119 return getCityDescription(); 120 case PanasonicMakernoteDirectory.TAG_LANDMARK: 121 return getLandmarkDescription(); 122 case PanasonicMakernoteDirectory.TAG_INTELLIGENT_RESOLUTION: 123 return getIntelligentResolutionDescription(); 124 case PanasonicMakernoteDirectory.TAG_FACE_RECOGNITION_INFO: 125 return getRecognizedFacesDescription(); 126 case PanasonicMakernoteDirectory.TAG_PRINT_IMAGE_MATCHING_INFO: 127 return getPrintImageMatchingInfoDescription(); 128 case PanasonicMakernoteDirectory.TAG_SCENE_MODE: 129 return getSceneModeDescription(); 130 case PanasonicMakernoteDirectory.TAG_FLASH_FIRED: 131 return getFlashFiredDescription(); 132 case PanasonicMakernoteDirectory.TAG_TEXT_STAMP: 133 return getTextStampDescription(); 134 case PanasonicMakernoteDirectory.TAG_TEXT_STAMP_1: 135 return getTextStamp1Description(); 136 case PanasonicMakernoteDirectory.TAG_TEXT_STAMP_2: 137 return getTextStamp2Description(); 138 case PanasonicMakernoteDirectory.TAG_TEXT_STAMP_3: 139 return getTextStamp3Description(); 140 case PanasonicMakernoteDirectory.TAG_MAKERNOTE_VERSION: 141 return getMakernoteVersionDescription(); 142 case PanasonicMakernoteDirectory.TAG_EXIF_VERSION: 143 return getExifVersionDescription(); 144 case PanasonicMakernoteDirectory.TAG_INTERNAL_SERIAL_NUMBER: 145 return getInternalSerialNumberDescription(); 146 case PanasonicMakernoteDirectory.TAG_TITLE: 147 return getTitleDescription(); 148 case PanasonicMakernoteDirectory.TAG_BABY_NAME: 149 return getBabyNameDescription(); 150 case PanasonicMakernoteDirectory.TAG_LOCATION: 151 return getLocationDescription(); 152 case PanasonicMakernoteDirectory.TAG_BABY_AGE: 153 return getBabyAgeDescription(); 154 case PanasonicMakernoteDirectory.TAG_BABY_AGE_1: 155 return getBabyAge1Description(); 156 default: 157 return super.getDescription(tagType); 158 } 159 } 160 161 @Nullable 162 public String getPrintImageMatchingInfoDescription() 163 { 164 byte[] values = _directory.getByteArray(PanasonicMakernoteDirectory.TAG_PRINT_IMAGE_MATCHING_INFO); 165 if (values == null) 166 return null; 167 return "(" + values.length + " bytes)"; 168 } 169 170 @Nullable 171 public String getTextStampDescription() 172 { 173 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_TEXT_STAMP); 174 } 175 176 @Nullable 177 public String getTextStamp1Description() 178 { 179 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_TEXT_STAMP_1); 180 } 181 182 @Nullable 183 public String getTextStamp2Description() 184 { 185 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_TEXT_STAMP_2); 186 } 187 188 @Nullable 189 public String getTextStamp3Description() 190 { 191 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_TEXT_STAMP_3); 192 } 193 194 @Nullable 195 public String getMacroModeDescription() 196 { 197 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_MACRO_MODE); 198 } 199 200 @Nullable 201 public String getFlashFiredDescription() 202 { 203 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_FLASH_FIRED); 204 } 205 206 @Nullable 207 public String getImageStabilizationDescription() 208 { 209 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_IMAGE_STABILIZATION); 210 if (value == null) 211 return null; 212 switch (value) { 213 case 2: 214 return "On, Mode 1"; 215 case 3: 216 return "Off"; 217 case 4: 218 return "On, Mode 2"; 219 default: 220 return "Unknown (" + value + ")"; 221 } 222 } 223 224 @Nullable 225 public String getAudioDescription() 226 { 227 return getOnOffDescription(PanasonicMakernoteDirectory.TAG_AUDIO); 228 } 229 230 @Nullable 231 public String getTransformDescription() 232 { 233 return getTransformDescription(PanasonicMakernoteDirectory.TAG_TRANSFORM); 234 } 235 236 @Nullable 237 public String getTransform1Description() 238 { 239 return getTransformDescription(PanasonicMakernoteDirectory.TAG_TRANSFORM_1); 240 } 241 242 @Nullable 243 private String getTransformDescription(int tag) 244 { 245 byte[] values = _directory.getByteArray(tag); 246 if (values == null) 247 return null; 248 249 BufferReader reader = new ByteArrayReader(values); 250 251 try 37 252 { 38 case PanasonicMakernoteDirectory.TAG_PANASONIC_MACRO_MODE: 39 return getMacroModeDescription(); 40 case PanasonicMakernoteDirectory.TAG_PANASONIC_RECORD_MODE: 41 return getRecordModeDescription(); 42 case PanasonicMakernoteDirectory.TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO: 43 return getPrintImageMatchingInfoDescription(); 44 default: 45 return _directory.getString(tagType); 46 } 47 } 48 49 public String getPrintImageMatchingInfoDescription() throws MetadataException 50 { 51 if (!_directory.containsTag(PanasonicMakernoteDirectory.TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO)) return null; 52 byte[] bytes = _directory.getByteArray(PanasonicMakernoteDirectory.TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO); 53 return "(" + bytes.length + " bytes)"; 54 } 55 56 public String getMacroModeDescription() throws MetadataException 57 { 58 if (!_directory.containsTag(PanasonicMakernoteDirectory.TAG_PANASONIC_MACRO_MODE)) return null; 59 int value = _directory.getInt(PanasonicMakernoteDirectory.TAG_PANASONIC_MACRO_MODE); 60 switch (value) { 61 case 1: 253 int val1 = reader.getUInt16(0); 254 int val2 = reader.getUInt16(2); 255 256 if (val1 == -1 && val2 == 1) 257 return "Slim Low"; 258 if (val1 == -3 && val2 == 2) 259 return "Slim High"; 260 if (val1 == 0 && val2 == 0) 261 return "Off"; 262 if (val1 == 1 && val2 == 1) 263 return "Stretch Low"; 264 if (val1 == 3 && val2 == 2) 265 return "Stretch High"; 266 267 return "Unknown (" + val1 + " " + val2 + ")"; 268 } catch (BufferBoundsException e) { 269 return null ; 270 } 271 } 272 273 @Nullable 274 public String getIntelligentExposureDescription() 275 { 276 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_INTELLIGENT_EXPOSURE); 277 if (value == null) 278 return null; 279 switch (value) { 280 case 0: 281 return "Off"; 282 case 1: 283 return "Low"; 284 case 2: 285 return "Standard"; 286 case 3: 287 return "High"; 288 289 default: 290 return "Unknown (" + value + ")"; 291 } 292 } 293 294 @Nullable 295 public String getFlashWarningDescription() 296 { 297 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_FLASH_WARNING); 298 if (value == null) 299 return null; 300 switch (value) { 301 case 0: 302 return "No"; 303 case 1: 304 return "Yes (Flash required but disabled)"; 305 default: 306 return "Unknown (" + value + ")"; 307 } 308 } 309 310 @Nullable 311 public String getCountryDescription() 312 { 313 return getTextDescription(PanasonicMakernoteDirectory.TAG_COUNTRY); 314 } 315 316 @Nullable 317 public String getStateDescription() 318 { 319 return getTextDescription(PanasonicMakernoteDirectory.TAG_STATE); 320 } 321 322 @Nullable 323 public String getCityDescription() 324 { 325 return getTextDescription(PanasonicMakernoteDirectory.TAG_CITY); 326 } 327 328 @Nullable 329 public String getLandmarkDescription() 330 { 331 return getTextDescription(PanasonicMakernoteDirectory.TAG_LANDMARK); 332 } 333 334 @Nullable 335 public String getTitleDescription() 336 { 337 return getTextDescription(PanasonicMakernoteDirectory.TAG_TITLE); 338 } 339 340 @Nullable 341 public String getBabyNameDescription() 342 { 343 return getTextDescription(PanasonicMakernoteDirectory.TAG_BABY_NAME); 344 } 345 346 @Nullable 347 public String getLocationDescription() 348 { 349 return getTextDescription(PanasonicMakernoteDirectory.TAG_LOCATION); 350 } 351 352 @Nullable 353 public String getIntelligentResolutionDescription() 354 { 355 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_INTELLIGENT_RESOLUTION); 356 if (value == null) 357 return null; 358 switch (value) { 359 case 0: 360 return "Off"; 361 case 2: 362 return "Auto"; 363 case 3: 62 364 return "On"; 63 case 2: 365 default: 366 return "Unknown (" + value + ")"; 367 } 368 } 369 370 @Nullable 371 public String getContrastDescription() 372 { 373 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_CONTRAST); 374 if (value == null) 375 return null; 376 switch (value) { 377 case 0: 378 return "Normal"; 379 default: 380 return "Unknown (" + value + ")"; 381 } 382 } 383 384 @Nullable 385 public String getWorldTimeLocationDescription() 386 { 387 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_WORLD_TIME_LOCATION); 388 if (value == null) 389 return null; 390 switch (value) { 391 case 1: 392 return "Home"; 393 case 2: 394 return "Destination"; 395 default: 396 return "Unknown (" + value + ")"; 397 } 398 } 399 400 @Nullable 401 public String getAdvancedSceneModeDescription() 402 { 403 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_ADVANCED_SCENE_MODE); 404 if (value == null) 405 return null; 406 switch (value) { 407 case 1: 408 return "Normal"; 409 case 2: 410 return "Outdoor/Illuminations/Flower/HDR Art"; 411 case 3: 412 return "Indoor/Architecture/Objects/HDR B&W"; 413 case 4: 414 return "Creative"; 415 case 5: 416 return "Auto"; 417 case 7: 418 return "Expressive"; 419 case 8: 420 return "Retro"; 421 case 9: 422 return "Pure"; 423 case 10: 424 return "Elegant"; 425 case 12: 426 return "Monochrome"; 427 case 13: 428 return "Dynamic Art"; 429 case 14: 430 return "Silhouette"; 431 default: 432 return "Unknown (" + value + ")"; 433 } 434 } 435 436 @Nullable 437 public String getUnknownDataDumpDescription() 438 { 439 byte[] value = _directory.getByteArray(PanasonicMakernoteDirectory.TAG_UNKNOWN_DATA_DUMP); 440 if (value == null) 441 return null; 442 return "[" + value.length + " bytes]"; 443 } 444 445 @Nullable 446 public String getColorEffectDescription() 447 { 448 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_COLOR_EFFECT); 449 if (value == null) 450 return null; 451 switch (value) { 452 case 1: 64 453 return "Off"; 65 default: 66 return "Unknown (" + value + ")"; 67 } 68 } 69 70 public String getRecordModeDescription() throws MetadataException 71 { 72 if (!_directory.containsTag(PanasonicMakernoteDirectory.TAG_PANASONIC_RECORD_MODE)) return null; 73 int value = _directory.getInt(PanasonicMakernoteDirectory.TAG_PANASONIC_RECORD_MODE); 74 switch (value) { 75 case 1: 454 case 2: 455 return "Warm"; 456 case 3: 457 return "Cool"; 458 case 4: 459 return "Black & White"; 460 case 5: 461 return "Sepia"; 462 default: 463 return "Unknown (" + value + ")"; 464 } 465 } 466 467 @Nullable 468 public String getUptimeDescription() 469 { 470 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_UPTIME); 471 if (value == null) 472 return null; 473 return value / 100f + " s"; 474 } 475 476 @Nullable 477 public String getBurstModeDescription() 478 { 479 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_BURST_MODE); 480 if (value == null) 481 return null; 482 switch (value) { 483 case 0: 484 return "Off"; 485 case 1: 486 return "On"; 487 case 2: 488 return "Infinite"; 489 case 4: 490 return "Unlimited"; 491 default: 492 return "Unknown (" + value + ")"; 493 } 494 } 495 496 @Nullable 497 public String getContrastModeDescription() 498 { 499 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_CONTRAST_MODE); 500 if (value == null) 501 return null; 502 switch (value) { 503 case 0x0: 76 504 return "Normal"; 505 case 0x1: 506 return "Low"; 507 case 0x2: 508 return "High"; 509 case 0x6: 510 return "Medium Low"; 511 case 0x7: 512 return "Medium High"; 513 case 0x100: 514 return "Low"; 515 case 0x110: 516 return "Normal"; 517 case 0x120: 518 return "High"; 519 520 default: 521 return "Unknown (" + value + ")"; 522 } 523 } 524 525 @Nullable 526 public String getNoiseReductionDescription() 527 { 528 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_NOISE_REDUCTION); 529 if (value == null) 530 return null; 531 switch (value) { 532 case 0: 533 return "Standard (0)"; 534 case 1: 535 return "Low (-1)"; 536 case 2: 537 return "High (+1)"; 538 case 3: 539 return "Lowest (-2)"; 540 case 4: 541 return "Highest (+2)"; 542 default: 543 return "Unknown (" + value + ")"; 544 } 545 } 546 547 548 @Nullable 549 public String getSelfTimerDescription() 550 { 551 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_SELF_TIMER); 552 if (value == null) 553 return null; 554 switch (value) { 555 case 1: 556 return "Off"; 557 case 2: 558 return "10 s"; 559 case 3: 560 return "2 s"; 561 default: 562 return "Unknown (" + value + ")"; 563 } 564 } 565 566 @Nullable 567 public String getRotationDescription() 568 { 569 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_ROTATION); 570 if (value == null) 571 return null; 572 switch (value) { 573 case 1: 574 return "Horizontal"; 575 case 3: 576 return "Rotate 180"; 577 case 6: 578 return "Rotate 90 CW"; 579 case 8: 580 return "Rotate 270 CW"; 581 default: 582 return "Unknown (" + value + ")"; 583 } 584 } 585 586 @Nullable 587 public String getAfAssistLampDescription() 588 { 589 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_AF_ASSIST_LAMP); 590 if (value == null) 591 return null; 592 switch (value) { 593 case 1: 594 return "Fired"; 595 case 2: 596 return "Enabled but not used"; 597 case 3: 598 return "Disabled but required"; 599 case 4: 600 return "Disabled and not required"; 601 default: 602 return "Unknown (" + value + ")"; 603 } 604 } 605 606 @Nullable 607 public String getColorModeDescription() 608 { 609 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_COLOR_MODE); 610 if (value == null) 611 return null; 612 switch (value) { 613 case 0: 614 return "Normal"; 615 case 1: 616 return "Natural"; 617 case 2: 618 return "Vivid"; 619 default: 620 return "Unknown (" + value + ")"; 621 } 622 } 623 624 @Nullable 625 public String getOpticalZoomModeDescription() 626 { 627 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_OPTICAL_ZOOM_MODE); 628 if (value == null) 629 return null; 630 switch (value) { 631 case 1: 632 return "Standard"; 633 case 2: 634 return "Extended"; 635 default: 636 return "Unknown (" + value + ")"; 637 } 638 } 639 640 @Nullable 641 public String getConversionLensDescription() 642 { 643 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_CONVERSION_LENS); 644 if (value == null) 645 return null; 646 switch (value) { 647 case 1: 648 return "Off"; 649 case 2: 650 return "Wide"; 651 case 3: 652 return "Telephoto"; 653 case 4: 654 return "Macro"; 655 default: 656 return "Unknown (" + value + ")"; 657 } 658 } 659 660 @Nullable 661 public String getDetectedFacesDescription() 662 { 663 return buildFacesDescription(_directory.getDetectedFaces()); 664 } 665 666 @Nullable 667 public String getRecognizedFacesDescription() 668 { 669 return buildFacesDescription(_directory.getRecognizedFaces()); 670 } 671 672 @Nullable 673 private String buildFacesDescription(@Nullable Face[] faces) 674 { 675 if (faces == null) 676 return null; 677 678 StringBuilder result = new StringBuilder(); 679 680 for (int i = 0; i < faces.length; i++) 681 result.append("Face ").append(i + 1).append(": ").append(faces[i].toString()).append("\n"); 682 683 if (result.length() > 0) 684 return result.substring(0, result.length() - 1); 685 686 return null; 687 } 688 689 @Nullable 690 public String getRecordModeDescription() 691 { 692 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_RECORD_MODE); 693 if (value == null) 694 return null; 695 switch (value) { 696 case 1: 697 return "Normal"; 77 698 case 2: 78 699 return "Portrait"; 700 case 3: 701 return "Scenery"; 702 case 4: 703 return "Sports"; 704 case 5: 705 return "Night Portrait"; 706 case 6: 707 return "Program"; 708 case 7: 709 return "Aperture Priority"; 710 case 8: 711 return "Shutter Priority"; 79 712 case 9: 80 713 return "Macro"; 714 case 10: 715 return "Spot"; 716 case 11: 717 return "Manual"; 718 case 12: 719 return "Movie Preview"; 720 case 13: 721 return "Panning"; 722 case 14: 723 return "Simple"; 724 case 15: 725 return "Color Effects"; 726 case 16: 727 return "Self Portrait"; 728 case 17: 729 return "Economy"; 730 case 18: 731 return "Fireworks"; 732 case 19: 733 return "Party"; 734 case 20: 735 return "Snow"; 736 case 21: 737 return "Night Scenery"; 738 case 22: 739 return "Food"; 740 case 23: 741 return "Baby"; 742 case 24: 743 return "Soft Skin"; 744 case 25: 745 return "Candlelight"; 746 case 26: 747 return "Starry Night"; 748 case 27: 749 return "High Sensitivity"; 750 case 28: 751 return "Panorama Assist"; 752 case 29: 753 return "Underwater"; 754 case 30: 755 return "Beach"; 756 case 31: 757 return "Aerial Photo"; 758 case 32: 759 return "Sunset"; 760 case 33: 761 return "Pet"; 762 case 34: 763 return "Intelligent ISO"; 764 case 35: 765 return "Clipboard"; 766 case 36: 767 return "High Speed Continuous Shooting"; 768 case 37: 769 return "Intelligent Auto"; 770 case 39: 771 return "Multi-aspect"; 772 case 41: 773 return "Transform"; 774 case 42: 775 return "Flash Burst"; 776 case 43: 777 return "Pin Hole"; 778 case 44: 779 return "Film Grain"; 780 case 45: 781 return "My Color"; 782 case 46: 783 return "Photo Frame"; 784 case 51: 785 return "HDR"; 786 default: 787 return "Unknown (" + value + ")"; 788 } 789 } 790 791 @Nullable 792 public String getSceneModeDescription() 793 { 794 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_SCENE_MODE); 795 if (value == null) 796 return null; 797 switch (value) { 798 case 1: 799 return "Normal"; 800 case 2: 801 return "Portrait"; 802 case 3: 803 return "Scenery"; 804 case 4: 805 return "Sports"; 806 case 5: 807 return "Night Portrait"; 808 case 6: 809 return "Program"; 810 case 7: 811 return "Aperture Priority"; 812 case 8: 813 return "Shutter Priority"; 814 case 9: 815 return "Macro"; 816 case 10: 817 return "Spot"; 818 case 11: 819 return "Manual"; 820 case 12: 821 return "Movie Preview"; 822 case 13: 823 return "Panning"; 824 case 14: 825 return "Simple"; 826 case 15: 827 return "Color Effects"; 828 case 16: 829 return "Self Portrait"; 830 case 17: 831 return "Economy"; 832 case 18: 833 return "Fireworks"; 834 case 19: 835 return "Party"; 836 case 20: 837 return "Snow"; 838 case 21: 839 return "Night Scenery"; 840 case 22: 841 return "Food"; 842 case 23: 843 return "Baby"; 844 case 24: 845 return "Soft Skin"; 846 case 25: 847 return "Candlelight"; 848 case 26: 849 return "Starry Night"; 850 case 27: 851 return "High Sensitivity"; 852 case 28: 853 return "Panorama Assist"; 854 case 29: 855 return "Underwater"; 856 case 30: 857 return "Beach"; 858 case 31: 859 return "Aerial Photo"; 860 case 32: 861 return "Sunset"; 862 case 33: 863 return "Pet"; 864 case 34: 865 return "Intelligent ISO"; 866 case 35: 867 return "Clipboard"; 868 case 36: 869 return "High Speed Continuous Shooting"; 870 case 37: 871 return "Intelligent Auto"; 872 case 39: 873 return "Multi-aspect"; 874 case 41: 875 return "Transform"; 876 case 42: 877 return "Flash Burst"; 878 case 43: 879 return "Pin Hole"; 880 case 44: 881 return "Film Grain"; 882 case 45: 883 return "My Color"; 884 case 46: 885 return "Photo Frame"; 886 case 51: 887 return "HDR"; 888 default: 889 return "Unknown (" + value + ")"; 890 } 891 } 892 893 @Nullable 894 public String getFocusModeDescription() 895 { 896 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_FOCUS_MODE); 897 if (value == null) 898 return null; 899 switch (value) { 900 case 1: 901 return "Auto"; 902 case 2: 903 return "Manual"; 904 case 4: 905 return "Auto, Focus Button"; 906 case 5: 907 return "Auto, Continuous"; 908 default: 909 return "Unknown (" + value + ")"; 910 } 911 } 912 913 @Nullable 914 public String getAfAreaModeDescription() 915 { 916 int[] value = _directory.getIntArray(PanasonicMakernoteDirectory.TAG_AF_AREA_MODE); 917 if (value == null || value.length < 2) 918 return null; 919 switch (value[0]) { 920 case 0: 921 switch (value[1]) { 922 case 1: 923 return "Spot Mode On"; 924 case 16: 925 return "Spot Mode Off"; 926 default: 927 return "Unknown (" + value[0] + " " + value[1] + ")"; 928 } 929 case 1: 930 switch (value[1]) { 931 case 0: 932 return "Spot Focusing"; 933 case 1: 934 return "5-area"; 935 default: 936 return "Unknown (" + value[0] + " " + value[1] + ")"; 937 } 938 case 16: 939 switch (value[1]) { 940 case 0: 941 return "1-area"; 942 case 16: 943 return "1-area (high speed)"; 944 default: 945 return "Unknown (" + value[0] + " " + value[1] + ")"; 946 } 947 case 32: 948 switch (value[1]) { 949 case 0: 950 return "Auto or Face Detect"; 951 case 1: 952 return "3-area (left)"; 953 case 2: 954 return "3-area (center)"; 955 case 3: 956 return "3-area (right)"; 957 default: 958 return "Unknown (" + value[0] + " " + value[1] + ")"; 959 } 960 case 64: 961 return "Face Detect"; 962 default: 963 return "Unknown (" + value[0] + " " + value[1] + ")"; 964 } 965 } 966 967 @Nullable 968 public String getQualityModeDescription() 969 { 970 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_QUALITY_MODE); 971 if (value == null) 972 return null; 973 switch (value) { 974 case 2: 975 return "High"; 976 case 3: 977 return "Normal"; 978 case 6: 979 return "Very High"; 980 case 7: 981 return "Raw"; 982 case 9: 983 return "Motion Picture"; 984 default: 985 return "Unknown (" + value + ")"; 986 } 987 } 988 989 @Nullable 990 public String getVersionDescription() 991 { 992 return convertBytesToVersionString(_directory.getIntArray(PanasonicMakernoteDirectory.TAG_VERSION), 2); 993 } 994 995 @Nullable 996 public String getMakernoteVersionDescription() 997 { 998 return convertBytesToVersionString(_directory.getIntArray(PanasonicMakernoteDirectory.TAG_MAKERNOTE_VERSION), 2); 999 } 1000 1001 @Nullable 1002 public String getExifVersionDescription() 1003 { 1004 return convertBytesToVersionString(_directory.getIntArray(PanasonicMakernoteDirectory.TAG_EXIF_VERSION), 2); 1005 } 1006 1007 @Nullable 1008 public String getInternalSerialNumberDescription() 1009 { 1010 final byte[] bytes = _directory.getByteArray(PanasonicMakernoteDirectory.TAG_INTERNAL_SERIAL_NUMBER); 1011 1012 if (bytes==null) 1013 return null; 1014 1015 int length = bytes.length; 1016 for (int index = 0; index < bytes.length; index++) { 1017 int i = bytes[index] & 0xFF; 1018 if (i == 0 || i > 0x7F) { 1019 length = index; 1020 break; 1021 } 1022 } 1023 1024 return new String(bytes, 0, length); 1025 } 1026 1027 @Nullable 1028 public String getWhiteBalanceDescription() 1029 { 1030 Integer value = _directory.getInteger(PanasonicMakernoteDirectory.TAG_WHITE_BALANCE); 1031 if (value == null) 1032 return null; 1033 switch (value) { 1034 case 1: 1035 return "Auto"; 1036 case 2: 1037 return "Daylight"; 1038 case 3: 1039 return "Cloudy"; 1040 case 4: 1041 return "Incandescent"; 1042 case 5: 1043 return "Manual"; 1044 case 8: 1045 return "Flash"; 1046 case 10: 1047 return "Black & White"; 1048 case 11: 1049 return "Manual"; 1050 case 12: 1051 return "Shade"; 1052 default: 1053 return "Unknown (" + value + ")"; 1054 } 1055 } 1056 1057 @Nullable 1058 public String getBabyAgeDescription() 1059 { 1060 final Age age = _directory.getAge(PanasonicMakernoteDirectory.TAG_BABY_AGE); 1061 if (age==null) 1062 return null; 1063 return age.toFriendlyString(); 1064 } 1065 1066 @Nullable 1067 public String getBabyAge1Description() 1068 { 1069 final Age age = _directory.getAge(PanasonicMakernoteDirectory.TAG_BABY_AGE_1); 1070 if (age==null) 1071 return null; 1072 return age.toFriendlyString(); 1073 } 1074 1075 @Nullable 1076 private String getTextDescription(int tag) 1077 { 1078 byte[] values = _directory.getByteArray(tag); 1079 if (values == null) 1080 return null; 1081 try { 1082 return new String(values, "ASCII").trim(); 1083 } catch (UnsupportedEncodingException e) { 1084 return null; 1085 } 1086 } 1087 1088 @Nullable 1089 private String getOnOffDescription(int tag) 1090 { 1091 Integer value = _directory.getInteger(tag); 1092 if (value == null) 1093 return null; 1094 switch (value) { 1095 case 1: 1096 return "Off"; 1097 case 2: 1098 return "On"; 81 1099 default: 82 1100 return "Unknown (" + value + ")"; -
trunk/src/com/drew/metadata/exif/PanasonicMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.BufferBoundsException; 24 import com.drew.lang.BufferReader; 25 import com.drew.lang.ByteArrayReader; 26 import com.drew.lang.annotations.NotNull; 27 import com.drew.lang.annotations.Nullable; 28 import com.drew.metadata.Age; 19 29 import com.drew.metadata.Directory; 30 import com.drew.metadata.Face; 20 31 21 32 import java.util.HashMap; 22 33 23 34 /** 35 * Describes tags specific to Panasonic and Leica cameras. 24 36 * 37 * @author Drew Noakes http://drewnoakes.com, Philipp Sandhaus 25 38 */ 26 39 public class PanasonicMakernoteDirectory extends Directory 27 40 { 28 public static final int TAG_PANASONIC_QUALITY_MODE = 0x0001; 29 public static final int TAG_PANASONIC_VERSION = 0x0002; 30 /** 31 * 1 = On 32 * 2 = Off 33 */ 34 public static final int TAG_PANASONIC_MACRO_MODE = 0x001C; 35 /** 36 * 1 = Normal 37 * 2 = Portrait 38 * 9 = Macro 39 */ 40 public static final int TAG_PANASONIC_RECORD_MODE = 0x001F; 41 public static final int TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 42 43 protected static final HashMap tagNameMap = new HashMap(); 41 42 /** 43 * <br> 44 * 2 = High <br> 45 * 3 = Normal <br> 46 * 6 = Very High <br> 47 * 7 = Raw <br> 48 * 9 = Motion Picture <br> 49 */ 50 public static final int TAG_QUALITY_MODE = 0x0001; 51 public static final int TAG_VERSION = 0x0002; 52 53 /** 54 * <br> 55 * 1 = Auto <br> 56 * 2 = Daylight <br> 57 * 3 = Cloudy <br> 58 * 4 = Incandescent <br> 59 * 5 = Manual <br> 60 * 8 = Flash <br> 61 * 10 = Black & White <br> 62 * 11 = Manual <br> 63 * 12 = Shade <br> 64 */ 65 public static final int TAG_WHITE_BALANCE = 0x0003; 66 67 68 /** 69 * <br> 70 * 1 = Auto <br> 71 * 2 = Manual <br> 72 * 4 = Auto, Focus Button <br> 73 * 5 = Auto, Continuous <br> 74 */ 75 public static final int TAG_FOCUS_MODE = 0x0007; 76 77 /** 78 * <br> 79 * 2 bytes <br> 80 * (DMC-FZ10) <br> 81 * '0 1' = Spot Mode On <br> 82 * '0 16' = Spot Mode Off <br> 83 * '(other models) <br> 84 * 16 = Normal? <br> 85 * '0 1' = 9-area <br> 86 * '0 16' = 3-area (high speed) <br> 87 * '1 0' = Spot Focusing <br> 88 * '1 1' = 5-area <br> 89 * '16 0' = 1-area <br> 90 * '16 16' = 1-area (high speed) <br> 91 * '32 0' = Auto or Face Detect <br> 92 * '32 1' = 3-area (left)? <br> 93 * '32 2' = 3-area (center)? <br> 94 * '32 3' = 3-area (right)? <br> 95 * '64 0' = Face Detect <br> 96 */ 97 public static final int TAG_AF_AREA_MODE = 0x000f; 98 99 /** 100 * <br> 101 * 2 = On, Mode 1 <br> 102 * 3 = Off <br> 103 * 4 = On, Mode 2 <br> 104 */ 105 public static final int TAG_IMAGE_STABILIZATION = 0x001a; 106 107 /** 108 * <br> 109 * 1 = On <br> 110 * 2 = Off <br> 111 */ 112 public static final int TAG_MACRO_MODE = 0x001C; 113 114 /** 115 * <br> 116 * 1 = Normal <br> 117 * 2 = Portrait <br> 118 * 3 = Scenery <br> 119 * 4 = Sports <br> 120 * 5 = Night Portrait <br> 121 * 6 = Program <br> 122 * 7 = Aperture Priority <br> 123 * 8 = Shutter Priority <br> 124 * 9 = Macro <br> 125 * 10= Spot <br> 126 * 11= Manual <br> 127 * 12= Movie Preview <br> 128 * 13= Panning <br> 129 * 14= Simple <br> 130 * 15= Color Effects <br> 131 * 16= Self Portrait <br> 132 * 17= Economy <br> 133 * 18= Fireworks <br> 134 * 19= Party <br> 135 * 20= Snow <br> 136 * 21= Night Scenery <br> 137 * 22= Food <br> 138 * 23= Baby <br> 139 * 24= Soft Skin <br> 140 * 25= Candlelight <br> 141 * 26= Starry Night <br> 142 * 27= High Sensitivity <br> 143 * 28= Panorama Assist <br> 144 * 29= Underwater <br> 145 * 30= Beach <br> 146 * 31= Aerial Photo <br> 147 * 32= Sunset <br> 148 * 33= Pet <br> 149 * 34= Intelligent ISO <br> 150 * 35= Clipboard <br> 151 * 36= High Speed Continuous Shooting <br> 152 * 37= Intelligent Auto <br> 153 * 39= Multi-aspect <br> 154 * 41= Transform <br> 155 * 42= Flash Burst <br> 156 * 43= Pin Hole <br> 157 * 44= Film Grain <br> 158 * 45= My Color <br> 159 * 46= Photo Frame <br> 160 * 51= HDR <br> 161 */ 162 public static final int TAG_RECORD_MODE = 0x001F; 163 164 /** 165 * 1 = Yes <br> 166 * 2 = No <br> 167 */ 168 public static final int TAG_AUDIO = 0x0020; 169 170 /** 171 * No idea, what this is 172 */ 173 public static final int TAG_UNKNOWN_DATA_DUMP = 0x0021; 174 175 public static final int TAG_WHITE_BALANCE_BIAS = 0x0023; 176 public static final int TAG_FLASH_BIAS = 0x0024; 177 178 /** 179 * this number is unique, and contains the date of manufacture, 180 * but is not the same as the number printed on the camera body 181 */ 182 public static final int TAG_INTERNAL_SERIAL_NUMBER = 0x0025; 183 184 /** 185 * Panasonic Exif Version 186 */ 187 public static final int TAG_EXIF_VERSION = 0x0026; 188 189 190 /** 191 * 1 = Off <br> 192 * 2 = Warm <br> 193 * 3 = Cool <br> 194 * 4 = Black & White <br> 195 * 5 = Sepia <br> 196 */ 197 public static final int TAG_COLOR_EFFECT = 0x0028; 198 199 /** 200 * 4 Bytes <br> 201 * Time in 1/100 s from when the camera was powered on to when the 202 * image is written to memory card 203 */ 204 public static final int TAG_UPTIME = 0x0029; 205 206 207 /** 208 * 0 = Off <br> 209 * 1 = On <br> 210 * 2 = Infinite <br> 211 * 4 = Unlimited <br> 212 */ 213 public static final int TAG_BURST_MODE = 0x002a; 214 215 public static final int TAG_SEQUENCE_NUMBER = 0x002b; 216 217 /** 218 * (this decoding seems to work for some models such as the LC1, LX2, FZ7, FZ8, FZ18 and FZ50, but may not be correct for other models such as the FX10, G1, L1, L10 and LC80) <br> 219 * 0x0 = Normal <br> 220 * 0x1 = Low <br> 221 * 0x2 = High <br> 222 * 0x6 = Medium Low <br> 223 * 0x7 = Medium High <br> 224 * 0x100 = Low <br> 225 * 0x110 = Normal <br> 226 * 0x120 = High <br> 227 * (these values are used by the GF1) <br> 228 * 0 = -2 <br> 229 * 1 = -1 <br> 230 * 2 = Normal <br> 231 * 3 = +1 <br> 232 * 4 = +2 <br> 233 * 7 = Nature (Color Film) <br> 234 * 12 = Smooth (Color Film) or Pure (My Color) <br> 235 * 17 = Dynamic (B&W Film) <br> 236 * 22 = Smooth (B&W Film) <br> 237 * 27 = Dynamic (Color Film) <br> 238 * 32 = Vibrant (Color Film) or Expressive (My Color) <br> 239 * 33 = Elegant (My Color) <br> 240 * 37 = Nostalgic (Color Film) <br> 241 * 41 = Dynamic Art (My Color) <br> 242 * 42 = Retro (My Color) <br> 243 */ 244 public static final int TAG_CONTRAST_MODE = 0x002c; 245 246 247 /** 248 * 0 = Standard <br> 249 * 1 = Low (-1) <br> 250 * 2 = High (+1) <br> 251 * 3 = Lowest (-2) <br> 252 * 4 = Highest (+2) <br> 253 */ 254 public static final int TAG_NOISE_REDUCTION = 0x002d; 255 256 /** 257 * 1 = Off <br> 258 * 2 = 10 s <br> 259 * 3 = 2 s <br> 260 */ 261 public static final int TAG_SELF_TIMER = 0x002e; 262 263 /** 264 * 1 = 0 DG <br> 265 * 3 = 180 DG <br> 266 * 6 = 90 DG <br> 267 * 8 = 270 DG <br> 268 */ 269 public static final int TAG_ROTATION = 0x0030; 270 271 /** 272 * 1 = Fired <br> 273 * 2 = Enabled nut not used <br> 274 * 3 = Disabled but required <br> 275 * 4 = Disabled and not required 276 */ 277 public static final int TAG_AF_ASSIST_LAMP = 0x0031; 278 279 /** 280 * 0 = Normal <br> 281 * 1 = Natural<br> 282 * 2 = Vivid 283 * 284 */ 285 public static final int TAG_COLOR_MODE = 0x0032; 286 287 public static final int TAG_BABY_AGE = 0x0033; 288 289 /** 290 * 1 = Standard <br> 291 * 2 = Extended 292 */ 293 public static final int TAG_OPTICAL_ZOOM_MODE = 0x0034; 294 295 /** 296 * 1 = Off <br> 297 * 2 = Wide <br> 298 * 3 = Telephoto <br> 299 * 4 = Macro 300 */ 301 public static final int TAG_CONVERSION_LENS = 0x0035; 302 303 public static final int TAG_TRAVEL_DAY = 0x0036; 304 305 /** 306 * 0 = Normal 307 */ 308 public static final int TAG_CONTRAST = 0x0039; 309 310 /** 311 * <br> 312 * 1 = Home <br> 313 * 2 = Destination 314 */ 315 public static final int TAG_WORLD_TIME_LOCATION = 0x003a; 316 317 /** 318 * 1 = Off <br> 319 * 2 = On 320 */ 321 public static final int TAG_TEXT_STAMP = 0x003b; 322 323 public static final int TAG_PROGRAM_ISO = 0x003c; 324 325 /** 326 * <br> 327 * 1 = Normal <br> 328 * 2 = Outdoor/Illuminations/Flower/HDR Art <br> 329 * 3 = Indoor/Architecture/Objects/HDR B&W <br> 330 * 4 = Creative <br> 331 * 5 = Auto <br> 332 * 7 = Expressive <br> 333 * 8 = Retro <br> 334 * 9 = Pure <br> 335 * 10 = Elegant <br> 336 * 12 = Monochrome <br> 337 * 13 = Dynamic Art <br> 338 * 14 = Silhouette <br> 339 */ 340 public static final int TAG_ADVANCED_SCENE_MODE = 0x003d; 341 342 /** 343 * 1 = Off <br> 344 * 2 = On 345 */ 346 public static final int TAG_TEXT_STAMP_1 = 0x003e; 347 348 public static final int TAG_FACES_DETECTED = 0x003f; 349 350 public static final int TAG_SATURATION = 0x0040; 351 public static final int TAG_SHARPNESS = 0x0041; 352 public static final int TAG_FILM_MODE = 0x0042; 353 354 /** 355 * WB adjust AB. Positive is a shift toward blue. 356 */ 357 public static final int TAG_WB_ADJUST_AB = 0x0046; 358 /** 359 * WB adjust GM. Positive is a shift toward green. 360 */ 361 public static final int TAG_WB_ADJUST_GM = 0x0047; 362 363 364 public static final int TAG_AF_POINT_POSITION = 0x004d; 365 366 367 /** 368 * <br> 369 * Integer (16Bit) Indexes: <br> 370 * 0 Number Face Positions (maybe less than Faces Detected) <br> 371 * 1-4 Face Position 1 <br> 372 * 5-8 Face Position 2 <br> 373 * and so on <br> 374 * <br> 375 * The four Integers are interpreted as follows: <br> 376 * (XYWH) X,Y Center of Face, (W,H) Width and Height <br> 377 * All values are in respect to double the size of the thumbnail image <br> 378 * 379 */ 380 public static final int TAG_FACE_DETECTION_INFO = 0x004e; 381 public static final int TAG_LENS_TYPE = 0x0051; 382 public static final int TAG_LENS_SERIAL_NUMBER = 0x0052; 383 public static final int TAG_ACCESSORY_TYPE = 0x0053; 384 385 /** 386 * (decoded as two 16-bit signed integers) 387 * '-1 1' = Slim Low 388 * '-3 2' = Slim High 389 * '0 0' = Off 390 * '1 1' = Stretch Low 391 * '3 2' = Stretch High 392 */ 393 public static final int TAG_TRANSFORM = 0x0059; 394 395 /** 396 * 0 = Off <br> 397 * 1 = Low <br> 398 * 2 = Standard <br> 399 * 3 = High 400 */ 401 public static final int TAG_INTELLIGENT_EXPOSURE = 0x005d; 402 403 /** 404 * Info at http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html 405 * 406 */ 407 public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00; 408 409 410 411 /** 412 * Byte Indexes: <br> 413 * 0 Int (2 Byte) Number of Recognized Faces <br> 414 * 4 String(20 Byte) Recognized Face 1 Name <br> 415 * 24 4 Int (8 Byte) Recognized Face 1 Position (Same Format as Face Detection) <br> 416 * 32 String(20 Byte) Recognized Face 1 Age <br> 417 * 52 String(20 Byte) Recognized Face 2 Name <br> 418 * 72 4 Int (8 Byte) Recognized Face 2 Position (Same Format as Face Detection) <br> 419 * 80 String(20 Byte) Recognized Face 2 Age <br> 420 * <br> 421 * And so on <br> 422 * <br> 423 * The four Integers are interpreted as follows: <br> 424 * (XYWH) X,Y Center of Face, (W,H) Width and Height <br> 425 * All values are in respect to double the size of the thumbnail image <br> 426 * 427 */ 428 public static final int TAG_FACE_RECOGNITION_INFO = 0x0061; 429 430 /** 431 * 0 = No <br> 432 * 1 = Yes 433 */ 434 public static final int TAG_FLASH_WARNING = 0x0062; 435 public static final int TAG_RECOGNIZED_FACE_FLAGS = 0x0063; 436 public static final int TAG_TITLE = 0x0065; 437 public static final int TAG_BABY_NAME = 0x0066; 438 public static final int TAG_LOCATION = 0x0067; 439 public static final int TAG_COUNTRY = 0x0069; 440 public static final int TAG_STATE = 0x006b; 441 public static final int TAG_CITY = 0x006d; 442 public static final int TAG_LANDMARK = 0x006f; 443 444 /** 445 * 0 = Off <br> 446 * 2 = Auto <br> 447 * 3 = On 448 */ 449 public static final int TAG_INTELLIGENT_RESOLUTION = 0x0070; 450 451 public static final int TAG_MAKERNOTE_VERSION = 0x8000; 452 public static final int TAG_SCENE_MODE = 0x8001; 453 public static final int TAG_WB_RED_LEVEL = 0x8004; 454 public static final int TAG_WB_GREEN_LEVEL = 0x8005; 455 public static final int TAG_WB_BLUE_LEVEL = 0x8006; 456 public static final int TAG_FLASH_FIRED = 0x8007; 457 public static final int TAG_TEXT_STAMP_2 = 0x8008; 458 public static final int TAG_TEXT_STAMP_3 = 0x8009; 459 public static final int TAG_BABY_AGE_1 = 0x8010; 460 461 /** 462 * (decoded as two 16-bit signed integers) 463 * '-1 1' = Slim Low 464 * '-3 2' = Slim High 465 * '0 0' = Off 466 * '1 1' = Stretch Low 467 * '3 2' = Stretch High 468 */ 469 public static final int TAG_TRANSFORM_1 = 0x8012; 470 471 @NotNull 472 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 44 473 45 474 static 46 475 { 47 tagNameMap.put(new Integer(TAG_PANASONIC_QUALITY_MODE), "Quality Mode"); 48 tagNameMap.put(new Integer(TAG_PANASONIC_VERSION), "Version"); 49 tagNameMap.put(new Integer(TAG_PANASONIC_MACRO_MODE), "Macro Mode"); 50 tagNameMap.put(new Integer(TAG_PANASONIC_RECORD_MODE), "Record Mode"); 51 tagNameMap.put(new Integer(TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO), "Print Image Matching (PIM) Info"); 476 _tagNameMap.put(TAG_QUALITY_MODE, "Quality Mode"); 477 _tagNameMap.put(TAG_VERSION, "Version"); 478 _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance"); 479 _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode"); 480 _tagNameMap.put(TAG_AF_AREA_MODE, "AF Area Mode"); 481 _tagNameMap.put(TAG_IMAGE_STABILIZATION, "Image Stabilization"); 482 _tagNameMap.put(TAG_MACRO_MODE, "Macro Mode"); 483 _tagNameMap.put(TAG_RECORD_MODE, "Record Mode"); 484 _tagNameMap.put(TAG_AUDIO, "Audio"); 485 _tagNameMap.put(TAG_INTERNAL_SERIAL_NUMBER, "Internal Serial Number"); 486 _tagNameMap.put(TAG_UNKNOWN_DATA_DUMP, "Unknown Data Dump"); 487 _tagNameMap.put(TAG_WHITE_BALANCE_BIAS, "White Balance Bias"); 488 _tagNameMap.put(TAG_FLASH_BIAS, "Flash Bias"); 489 _tagNameMap.put(TAG_EXIF_VERSION, "Exif Version"); 490 _tagNameMap.put(TAG_COLOR_EFFECT, "Color Effect"); 491 _tagNameMap.put(TAG_UPTIME, "Camera Uptime"); 492 _tagNameMap.put(TAG_BURST_MODE, "Burst Mode"); 493 _tagNameMap.put(TAG_SEQUENCE_NUMBER, "Sequence Number"); 494 _tagNameMap.put(TAG_CONTRAST_MODE, "Contrast Mode"); 495 _tagNameMap.put(TAG_NOISE_REDUCTION, "Noise Reduction"); 496 _tagNameMap.put(TAG_SELF_TIMER, "Self Timer"); 497 _tagNameMap.put(TAG_ROTATION, "Rotation"); 498 _tagNameMap.put(TAG_AF_ASSIST_LAMP, "AF Assist Lamp"); 499 _tagNameMap.put(TAG_COLOR_MODE, "Color Mode"); 500 _tagNameMap.put(TAG_BABY_AGE, "Baby Age"); 501 _tagNameMap.put(TAG_OPTICAL_ZOOM_MODE, "Optical Zoom Mode"); 502 _tagNameMap.put(TAG_CONVERSION_LENS, "Conversion Lens"); 503 _tagNameMap.put(TAG_TRAVEL_DAY, "Travel Day"); 504 _tagNameMap.put(TAG_CONTRAST, "Contrast"); 505 _tagNameMap.put(TAG_WORLD_TIME_LOCATION, "World Time Location"); 506 _tagNameMap.put(TAG_TEXT_STAMP, "Text Stamp"); 507 _tagNameMap.put(TAG_PROGRAM_ISO, "Program ISO"); 508 _tagNameMap.put(TAG_ADVANCED_SCENE_MODE, "Advanced Scene Mode"); 509 _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 510 _tagNameMap.put(TAG_FACES_DETECTED, "Number of Detected Faces"); 511 _tagNameMap.put(TAG_SATURATION, "Saturation"); 512 _tagNameMap.put(TAG_SHARPNESS, "Sharpness"); 513 _tagNameMap.put(TAG_FILM_MODE, "Film Mode"); 514 _tagNameMap.put(TAG_WB_ADJUST_AB, "White Balance Adjust (AB)"); 515 _tagNameMap.put(TAG_WB_ADJUST_GM, "White Balance Adjust (GM)"); 516 _tagNameMap.put(TAG_AF_POINT_POSITION, "Af Point Position"); 517 _tagNameMap.put(TAG_FACE_DETECTION_INFO, "Face Detection Info"); 518 _tagNameMap.put(TAG_LENS_TYPE, "Lens Type"); 519 _tagNameMap.put(TAG_LENS_SERIAL_NUMBER, "Lens Serial Number"); 520 _tagNameMap.put(TAG_ACCESSORY_TYPE, "Accessory Type"); 521 _tagNameMap.put(TAG_TRANSFORM, "Transform"); 522 _tagNameMap.put(TAG_INTELLIGENT_EXPOSURE, "Intelligent Exposure"); 523 _tagNameMap.put(TAG_FACE_RECOGNITION_INFO, "Face Recognition Info"); 524 _tagNameMap.put(TAG_FLASH_WARNING, "Flash Warning"); 525 _tagNameMap.put(TAG_RECOGNIZED_FACE_FLAGS, "Recognized Face Flags"); 526 _tagNameMap.put(TAG_TITLE, "Title"); 527 _tagNameMap.put(TAG_BABY_NAME, "Baby Name"); 528 _tagNameMap.put(TAG_LOCATION, "Location"); 529 _tagNameMap.put(TAG_COUNTRY, "Country"); 530 _tagNameMap.put(TAG_STATE, "State"); 531 _tagNameMap.put(TAG_CITY, "City"); 532 _tagNameMap.put(TAG_LANDMARK, "Landmark"); 533 _tagNameMap.put(TAG_INTELLIGENT_RESOLUTION, "Intelligent Resolution"); 534 _tagNameMap.put(TAG_MAKERNOTE_VERSION, "Makernote Version"); 535 _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode"); 536 _tagNameMap.put(TAG_WB_RED_LEVEL, "White Balance (Red)"); 537 _tagNameMap.put(TAG_WB_GREEN_LEVEL, "White Balance (Green)"); 538 _tagNameMap.put(TAG_WB_BLUE_LEVEL, "White Balance (Blue)"); 539 _tagNameMap.put(TAG_FLASH_FIRED, "Flash Fired"); 540 _tagNameMap.put(TAG_TEXT_STAMP_1, "Text Stamp 1"); 541 _tagNameMap.put(TAG_TEXT_STAMP_2, "Text Stamp 2"); 542 _tagNameMap.put(TAG_TEXT_STAMP_3, "Text Stamp 3"); 543 _tagNameMap.put(TAG_BABY_AGE_1, "Baby Age 1"); 544 _tagNameMap.put(TAG_TRANSFORM_1, "Transform 1"); 52 545 } 53 546 … … 57 550 } 58 551 552 @NotNull 59 553 public String getName() 60 554 { … … 62 556 } 63 557 64 protected HashMap getTagNameMap() 558 @NotNull 559 protected HashMap<Integer, String> getTagNameMap() 65 560 { 66 return tagNameMap; 561 return _tagNameMap; 67 562 } 563 564 @Nullable 565 public Face[] getDetectedFaces() 566 { 567 byte[] bytes = getByteArray(PanasonicMakernoteDirectory.TAG_FACE_DETECTION_INFO); 568 if (bytes==null) 569 return null; 570 571 BufferReader reader = new ByteArrayReader(bytes); 572 reader.setMotorolaByteOrder(false); 573 574 try { 575 int faceCount = reader.getUInt16(0); 576 if (faceCount==0) 577 return null; 578 Face[] faces = new Face[faceCount]; 579 580 for (int i = 0; i < faceCount; i++) { 581 int offset = 2 + i * 8; 582 faces[i] = new Face( 583 reader.getUInt16(offset), 584 reader.getUInt16(offset + 2), 585 reader.getUInt16(offset + 4), 586 reader.getUInt16(offset + 6) 587 , null, null); 588 } 589 return faces; 590 } catch (BufferBoundsException e) { 591 return null; 592 } 593 } 594 595 @Nullable 596 public Face[] getRecognizedFaces() 597 { 598 byte[] bytes = getByteArray(PanasonicMakernoteDirectory.TAG_FACE_RECOGNITION_INFO); 599 if (bytes == null) 600 return null; 601 602 BufferReader reader = new ByteArrayReader(bytes); 603 reader.setMotorolaByteOrder(false); 604 605 try { 606 int faceCount = reader.getUInt16(0); 607 if (faceCount==0) 608 return null; 609 Face[] faces = new Face[faceCount]; 610 611 for (int i = 0; i < faceCount; i++) { 612 int offset = 4 + i * 44; 613 String name = reader.getString(offset, 20, "ASCII").trim(); 614 String age = reader.getString(offset + 28, 20, "ASCII").trim(); 615 faces[i] = new Face( 616 reader.getUInt16(offset + 20), 617 reader.getUInt16(offset + 22), 618 reader.getUInt16(offset + 24), 619 reader.getUInt16(offset + 26), 620 name, 621 Age.fromPanasonicString(age)); 622 } 623 return faces; 624 } catch (BufferBoundsException e) { 625 return null; 626 } 627 } 628 629 /** 630 * Attempts to convert the underlying string value (as stored in the directory) into an Age object. 631 * @param tag The tag identifier. 632 * @return The parsed Age object, or null if the tag was empty of the value unable to be parsed. 633 */ 634 @Nullable 635 public Age getAge(int tag) 636 { 637 final String ageString = getString(tag); 638 if (ageString==null) 639 return null; 640 return Age.fromPanasonicString(ageString); 641 } 68 642 } -
trunk/src/com/drew/metadata/exif/PentaxMakernoteDescriptor.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 6 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 9 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 2 * Copyright 2002-2012 Drew Noakes 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 14 20 */ 15 21 package com.drew.metadata.exif; 16 22 17 import com.drew. metadata.Directory;18 import com.drew. metadata.MetadataException;23 import com.drew.lang.annotations.NotNull; 24 import com.drew.lang.annotations.Nullable; 19 25 import com.drew.metadata.TagDescriptor; 20 26 21 27 /** 22 * Provides human-readable string versions of the tags stored in PentaxMakernoteDirectory.23 * 28 * Provides human-readable string representations of tag values stored in a <code>PentaxMakernoteDirectory</code>. 29 * <p/> 24 30 * Some information about this makernote taken from here: 25 31 * http://www.ozhiker.com/electronics/pjmt/jpeg_info/pentax_mn.html 32 * 33 * @author Drew Noakes http://drewnoakes.com 26 34 */ 27 public class PentaxMakernoteDescriptor extends TagDescriptor 35 public class PentaxMakernoteDescriptor extends TagDescriptor<PentaxMakernoteDirectory> 28 36 { 29 public PentaxMakernoteDescriptor(Directory directory) 37 public PentaxMakernoteDescriptor(@NotNull PentaxMakernoteDirectory directory) 30 38 { 31 39 super(directory); 32 40 } 33 41 34 public String getDescription(int tagType) throws MetadataException 42 @Nullable 43 public String getDescription(int tagType) 35 44 { 36 45 switch (tagType) … … 59 68 return getColourDescription(); 60 69 default: 61 return _directory.getString(tagType); 62 } 63 } 64 65 public String getColourDescription() throws MetadataException 66 { 67 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_COLOUR)) return null; 68 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_COLOUR); 70 return super.getDescription(tagType); 71 } 72 } 73 74 @Nullable 75 public String getColourDescription() 76 { 77 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_COLOUR); 78 if (value==null) 79 return null; 69 80 switch (value) 70 81 { … … 76 87 } 77 88 78 public String getIsoSpeedDescription() throws MetadataException 79 { 80 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_ISO_SPEED)) return null; 81 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_ISO_SPEED); 89 @Nullable 90 public String getIsoSpeedDescription() 91 { 92 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_ISO_SPEED); 93 if (value==null) 94 return null; 82 95 switch (value) 83 96 { … … 91 104 } 92 105 93 public String getSaturationDescription() throws MetadataException 94 { 95 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_SATURATION)) return null; 96 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_SATURATION); 106 @Nullable 107 public String getSaturationDescription() 108 { 109 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_SATURATION); 110 if (value==null) 111 return null; 97 112 switch (value) 98 113 { … … 104 119 } 105 120 106 public String getContrastDescription() throws MetadataException 107 { 108 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_CONTRAST)) return null; 109 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_CONTRAST); 121 @Nullable 122 public String getContrastDescription() 123 { 124 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_CONTRAST); 125 if (value==null) 126 return null; 110 127 switch (value) 111 128 { … … 117 134 } 118 135 119 public String getSharpnessDescription() throws MetadataException 120 { 121 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_SHARPNESS)) return null; 122 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_SHARPNESS); 136 @Nullable 137 public String getSharpnessDescription() 138 { 139 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_SHARPNESS); 140 if (value==null) 141 return null; 123 142 switch (value) 124 143 { … … 130 149 } 131 150 132 public String getDigitalZoomDescription() throws MetadataException 133 { 134 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_DIGITAL_ZOOM)) return null; 135 float value = _directory.getFloat(PentaxMakernoteDirectory.TAG_PENTAX_DIGITAL_ZOOM); 151 @Nullable 152 public String getDigitalZoomDescription() 153 { 154 Float value = _directory.getFloatObject(PentaxMakernoteDirectory.TAG_PENTAX_DIGITAL_ZOOM); 155 if (value==null) 156 return null; 136 157 if (value==0) 137 158 return "Off"; … … 139 160 } 140 161 141 public String getWhiteBalanceDescription() throws MetadataException 142 { 143 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_WHITE_BALANCE)) return null; 144 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_WHITE_BALANCE); 162 @Nullable 163 public String getWhiteBalanceDescription() 164 { 165 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_WHITE_BALANCE); 166 if (value==null) 167 return null; 145 168 switch (value) 146 169 { … … 155 178 } 156 179 157 public String getFlashModeDescription() throws MetadataException 158 { 159 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_FLASH_MODE)) return null; 160 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_FLASH_MODE); 180 @Nullable 181 public String getFlashModeDescription() 182 { 183 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_FLASH_MODE); 184 if (value==null) 185 return null; 161 186 switch (value) 162 187 { … … 169 194 } 170 195 171 public String getFocusModeDescription() throws MetadataException 172 { 173 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_FOCUS_MODE)) return null; 174 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_FOCUS_MODE); 196 @Nullable 197 public String getFocusModeDescription() 198 { 199 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_FOCUS_MODE); 200 if (value==null) 201 return null; 175 202 switch (value) 176 203 { … … 181 208 } 182 209 183 public String getQualityLevelDescription() throws MetadataException 184 { 185 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_QUALITY_LEVEL)) return null; 186 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_QUALITY_LEVEL); 210 @Nullable 211 public String getQualityLevelDescription() 212 { 213 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_QUALITY_LEVEL); 214 if (value==null) 215 return null; 187 216 switch (value) 188 217 { … … 194 223 } 195 224 196 public String getCaptureModeDescription() throws MetadataException 197 { 198 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PENTAX_CAPTURE_MODE)) return null; 199 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PENTAX_CAPTURE_MODE); 225 @Nullable 226 public String getCaptureModeDescription() 227 { 228 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PENTAX_CAPTURE_MODE); 229 if (value==null) 230 return null; 200 231 switch (value) 201 232 { … … 209 240 210 241 /* 211 public String getPrintImageMatchingInfoDescription() throws MetadataException 212 { 213 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO)) return null; 242 public String getPrintImageMatchingInfoDescription() 243 { 214 244 byte[] bytes = _directory.getByteArray(PentaxMakernoteDirectory.TAG_PANASONIC_PRINT_IMAGE_MATCHING_INFO); 245 if (bytes==null) 246 return null; 215 247 return "(" + bytes.length + " bytes)"; 216 248 } 217 249 218 public String getMacroModeDescription() throws MetadataException 219 { 220 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PANASONIC_MACRO_MODE)) return null; 221 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PANASONIC_MACRO_MODE); 250 public String getMacroModeDescription() 251 { 252 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PANASONIC_MACRO_MODE); 253 if (value==null) 254 return null; 222 255 switch (value) { 223 256 case 1: … … 230 263 } 231 264 232 public String getRecordModeDescription() throws MetadataException 233 { 234 if (!_directory.containsTag(PentaxMakernoteDirectory.TAG_PANASONIC_RECORD_MODE)) return null; 235 int value = _directory.getInt(PentaxMakernoteDirectory.TAG_PANASONIC_RECORD_MODE); 265 public String getRecordModeDescription() 266 { 267 Integer value = _directory.getInteger(PentaxMakernoteDirectory.TAG_PANASONIC_RECORD_MODE); 268 if (value==null) 269 return null; 236 270 switch (value) { 237 271 case 1: -
trunk/src/com/drew/metadata/exif/PentaxMakernoteDirectory.java
r4231 r6127 1 1 /* 2 * This is public domain software - that is, you can do whatever you want 3 * with it, and include it software that is licensed under the GNU or the 4 * BSD license, or whatever other licence you choose, including proprietary 5 * closed source licenses. I do ask that you leave this header in tact. 2 * Copyright 2002-2012 Drew Noakes 6 3 * 7 * If you make modifications to this code that you think would benefit the 8 * wider community, please send me a copy and I'll post it on my site. 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 9 7 * 10 * If you make use of this code, I'd appreciate hearing about it. 11 * drew@drewnoakes.com 12 * Latest version of this software kept at 13 * http://drewnoakes.com/ 8 * http://www.apache.org/licenses/LICENSE-2.0 14 9 * 15 * Created by dnoakes on 27-Nov-2002 10:10:47 using IntelliJ IDEA. 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * More information about this project is available at: 17 * 18 * http://drewnoakes.com/code/exif/ 19 * http://code.google.com/p/metadata-extractor/ 16 20 */ 17 21 package com.drew.metadata.exif; 18 22 23 import com.drew.lang.annotations.NotNull; 19 24 import com.drew.metadata.Directory; 20 25 … … 22 27 23 28 /** 24 * Directory for metadata specific to Pentax and Asahi cameras. 29 * Describes tags specific to Pentax and Asahi cameras. 30 * 31 * @author Drew Noakes http://drewnoakes.com 25 32 */ 26 33 public class PentaxMakernoteDirectory extends Directory … … 122 129 public static final int TAG_PENTAX_DAYLIGHT_SAVINGS = 0x1001; 123 130 124 protected static final HashMap tagNameMap = new HashMap(); 131 @NotNull 132 protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>(); 125 133 126 134 static 127 135 { 128 tagNameMap.put (new Integer(TAG_PENTAX_CAPTURE_MODE), "Capture Mode");129 tagNameMap.put (new Integer(TAG_PENTAX_QUALITY_LEVEL), "Quality Level");130 tagNameMap.put (new Integer(TAG_PENTAX_FOCUS_MODE), "Focus Mode");131 tagNameMap.put (new Integer(TAG_PENTAX_FLASH_MODE), "Flash Mode");132 tagNameMap.put (new Integer(TAG_PENTAX_WHITE_BALANCE), "White Balance");133 tagNameMap.put (new Integer(TAG_PENTAX_DIGITAL_ZOOM), "Digital Zoom");134 tagNameMap.put (new Integer(TAG_PENTAX_SHARPNESS), "Sharpness");135 tagNameMap.put (new Integer(TAG_PENTAX_CONTRAST), "Contrast");136 tagNameMap.put (new Integer(TAG_PENTAX_SATURATION), "Saturation");137 tagNameMap.put (new Integer(TAG_PENTAX_ISO_SPEED), "ISO Speed");138 tagNameMap.put (new Integer(TAG_PENTAX_COLOUR), "Colour");139 tagNameMap.put (new Integer(TAG_PENTAX_PRINT_IMAGE_MATCHING_INFO), "Print Image Matching (PIM) Info");140 tagNameMap.put (new Integer(TAG_PENTAX_TIME_ZONE), "Time Zone");141 tagNameMap.put (new Integer(TAG_PENTAX_DAYLIGHT_SAVINGS), "Daylight Savings");136 _tagNameMap.put(TAG_PENTAX_CAPTURE_MODE, "Capture Mode"); 137 _tagNameMap.put(TAG_PENTAX_QUALITY_LEVEL, "Quality Level"); 138 _tagNameMap.put(TAG_PENTAX_FOCUS_MODE, "Focus Mode"); 139 _tagNameMap.put(TAG_PENTAX_FLASH_MODE, "Flash Mode"); 140 _tagNameMap.put(TAG_PENTAX_WHITE_BALANCE, "White Balance"); 141 _tagNameMap.put(TAG_PENTAX_DIGITAL_ZOOM, "Digital Zoom"); 142 _tagNameMap.put(TAG_PENTAX_SHARPNESS, "Sharpness"); 143 _tagNameMap.put(TAG_PENTAX_CONTRAST, "Contrast"); 144 _tagNameMap.put(TAG_PENTAX_SATURATION, "Saturation"); 145 _tagNameMap.put(TAG_PENTAX_ISO_SPEED, "ISO Speed"); 146 _tagNameMap.put(TAG_PENTAX_COLOUR, "Colour"); 147 _tagNameMap.put(TAG_PENTAX_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info"); 148 _tagNameMap.put(TAG_PENTAX_TIME_ZONE, "Time Zone"); 149 _tagNameMap.put(TAG_PENTAX_DAYLIGHT_SAVINGS, "Daylight Savings"); 142 150 } 143 151 … … 147 155 } 148 156 157 @NotNull 149 158 public String getName() 150 159 { … … 152 161 } 153 162 154 protected HashMap getTagNameMap() 163 @NotNull 164 protected HashMap<Integer, String> getTagNameMap() 155 165 { 156 return tagNameMap; 166 return _tagNameMap; 157 167 } 158 168 }
Note:
See TracChangeset
for help on using the changeset viewer.