1 /*****************************************************************************/ 2 // Copyright 2006-2008 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_parse_utils.cpp#3 $ */ 10 /* $DateTime: 2012/06/06 12:08:58 $ */ 11 /* $Change: 833617 $ */ 12 /* $Author: tknoll $ */ 13 14 /*****************************************************************************/ 15 16 #include "dng_parse_utils.h" 17 18 #include "dng_date_time.h" 19 #include "dng_globals.h" 20 #include "dng_ifd.h" 21 #include "dng_tag_codes.h" 22 #include "dng_tag_types.h" 23 #include "dng_tag_values.h" 24 #include "dng_types.h" 25 #include "dng_stream.h" 26 #include "dng_exceptions.h" 27 #include "dng_utils.h" 28 29 /*****************************************************************************/ 30 31 #if qDNGValidate 32 33 /*****************************************************************************/ 34 35 struct dng_name_table 36 { 37 uint32 key; 38 const char *name; 39 }; 40 41 /*****************************************************************************/ 42 43 static const char * LookupName (uint32 key, 44 const dng_name_table *table, 45 uint32 table_entries) 46 { 47 48 for (uint32 index = 0; index < table_entries; index++) 49 { 50 51 if (key == table [index] . key) 52 { 53 54 return table [index] . name; 55 56 } 57 58 } 59 60 return NULL; 61 62 } 63 64 /*****************************************************************************/ 65 66 const char * LookupParentCode (uint32 parentCode) 67 { 68 69 const dng_name_table kParentCodeNames [] = 70 { 71 { 0, "IFD 0" }, 72 { tcExifIFD, "Exif IFD" }, 73 { tcGPSInfo, "GPS IFD" }, 74 { tcInteroperabilityIFD, "Interoperability IFD" }, 75 { tcKodakDCRPrivateIFD, "Kodak DCR Private IFD" }, 76 { tcKodakKDCPrivateIFD, "Kodak KDC Private IFD" }, 77 { tcCanonMakerNote, "Canon MakerNote" }, 78 { tcEpsonMakerNote, "Epson MakerNote" }, 79 { tcFujiMakerNote, "Fuji MakerNote" }, 80 { tcHasselbladMakerNote, "Hasselblad MakerNote" }, 81 { tcKodakMakerNote, "Kodak MakerNote" }, 82 { tcKodakMakerNote65280, "Kodak MakerNote 65280" }, 83 { tcLeicaMakerNote, "Leica MakerNote" }, 84 { tcMamiyaMakerNote, "Mamiya MakerNote" }, 85 { tcMinoltaMakerNote, "Minolta MakerNote" }, 86 { tcNikonMakerNote, "Nikon MakerNote" }, 87 { tcOlympusMakerNote, "Olympus MakerNote" }, 88 { tcOlympusMakerNote8208, "Olympus MakerNote 8208" }, 89 { tcOlympusMakerNote8224, "Olympus MakerNote 8224" }, 90 { tcOlympusMakerNote8240, "Olympus MakerNote 8240" }, 91 { tcOlympusMakerNote8256, "Olympus MakerNote 8256" }, 92 { tcOlympusMakerNote8272, "Olympus MakerNote 8272" }, 93 { tcOlympusMakerNote12288, "Olympus MakerNote 12288" }, 94 { tcPanasonicMakerNote, "Panasonic MakerNote" }, 95 { tcPentaxMakerNote, "Pentax MakerNote" }, 96 { tcPhaseOneMakerNote, "Phase One MakerNote" }, 97 { tcRicohMakerNote, "Ricoh MakerNote" }, 98 { tcRicohMakerNoteCameraInfo, "Ricoh MakerNote Camera Info" }, 99 { tcSonyMakerNote, "Sony MakerNote" }, 100 { tcSonyMakerNoteSubInfo, "Sony MakerNote SubInfo" }, 101 { tcSonyPrivateIFD1, "Sony Private IFD 1" }, 102 { tcSonyPrivateIFD2, "Sony Private IFD 2" }, 103 { tcSonyPrivateIFD3A, "Sony Private IFD 3A" }, 104 { tcSonyPrivateIFD3B, "Sony Private IFD 3B" }, 105 { tcSonyPrivateIFD3C, "Sony Private IFD 3C" }, 106 { tcCanonCRW, "Canon CRW" }, 107 { tcContaxRAW, "Contax RAW" }, 108 { tcFujiRAF, "Fuji RAF" }, 109 { tcLeafMOS, "Leaf MOS" }, 110 { tcMinoltaMRW, "Minolta MRW" }, 111 { tcPanasonicRAW, "Panasonic RAW" }, 112 { tcFoveonX3F, "Foveon X3F" }, 113 { tcJPEG, "JPEG" }, 114 { tcAdobePSD, "Adobe PSD" } 115 }; 116 117 const char *name = LookupName (parentCode, 118 kParentCodeNames, 119 sizeof (kParentCodeNames ) / 120 sizeof (kParentCodeNames [0])); 121 122 if (name) 123 { 124 return name; 125 } 126 127 static char s [32]; 128 129 if (parentCode >= tcFirstSubIFD && 130 parentCode <= tcLastSubIFD) 131 { 132 133 sprintf (s, "SubIFD %u", (unsigned) (parentCode - tcFirstSubIFD + 1)); 134 135 } 136 137 else if (parentCode >= tcFirstChainedIFD && 138 parentCode <= tcLastChainedIFD) 139 { 140 141 sprintf (s, "Chained IFD %u", (unsigned) (parentCode - tcFirstChainedIFD + 1)); 142 143 } 144 145 else 146 { 147 148 sprintf (s, "ParentIFD %u", (unsigned) parentCode); 149 150 } 151 152 return s; 153 154 } 155 156 /*****************************************************************************/ 157 158 const char * LookupTagCode (uint32 parentCode, 159 uint32 tagCode) 160 { 161 162 const dng_name_table kTagNames [] = 163 { 164 { tcNewSubFileType, "NewSubFileType" }, 165 { tcSubFileType, "SubFileType" }, 166 { tcImageWidth, "ImageWidth" }, 167 { tcImageLength, "ImageLength" }, 168 { tcBitsPerSample, "BitsPerSample" }, 169 { tcCompression, "Compression" }, 170 { tcPhotometricInterpretation, "PhotometricInterpretation" }, 171 { tcThresholding, "Thresholding" }, 172 { tcCellWidth, "CellWidth" }, 173 { tcCellLength, "CellLength" }, 174 { tcFillOrder, "FillOrder" }, 175 { tcImageDescription, "ImageDescription" }, 176 { tcMake, "Make" }, 177 { tcModel, "Model" }, 178 { tcStripOffsets, "StripOffsets" }, 179 { tcOrientation, "Orientation" }, 180 { tcSamplesPerPixel, "SamplesPerPixel" }, 181 { tcRowsPerStrip, "RowsPerStrip" }, 182 { tcStripByteCounts, "StripByteCounts" }, 183 { tcMinSampleValue, "MinSampleValue" }, 184 { tcMaxSampleValue, "MaxSampleValue" }, 185 { tcXResolution, "XResolution" }, 186 { tcYResolution, "YResolution" }, 187 { tcPlanarConfiguration, "PlanarConfiguration" }, 188 { tcFreeOffsets, "FreeOffsets" }, 189 { tcFreeByteCounts, "FreeByteCounts" }, 190 { tcGrayResponseUnit, "GrayResponseUnit" }, 191 { tcGrayResponseCurve, "GrayResponseCurve" }, 192 { tcResolutionUnit, "ResolutionUnit" }, 193 { tcTransferFunction, "TransferFunction" }, 194 { tcSoftware, "Software" }, 195 { tcDateTime, "DateTime" }, 196 { tcArtist, "Artist" }, 197 { tcHostComputer, "HostComputer" }, 198 { tcWhitePoint, "WhitePoint" }, 199 { tcPrimaryChromaticities, "PrimaryChromaticities" }, 200 { tcColorMap, "ColorMap" }, 201 { tcTileWidth, "TileWidth" }, 202 { tcTileLength, "TileLength" }, 203 { tcTileOffsets, "TileOffsets" }, 204 { tcTileByteCounts, "TileByteCounts" }, 205 { tcSubIFDs, "SubIFDs" }, 206 { tcExtraSamples, "ExtraSamples" }, 207 { tcSampleFormat, "SampleFormat" }, 208 { tcJPEGTables, "JPEGTables" }, 209 { tcJPEGProc, "JPEGProc" }, 210 { tcJPEGInterchangeFormat, "JPEGInterchangeFormat" }, 211 { tcJPEGInterchangeFormatLength, "JPEGInterchangeFormatLength" }, 212 { tcYCbCrCoefficients, "YCbCrCoefficients" }, 213 { tcYCbCrSubSampling, "YCbCrSubSampling" }, 214 { tcYCbCrPositioning, "YCbCrPositioning" }, 215 { tcReferenceBlackWhite, "ReferenceBlackWhite" }, 216 { tcXMP, "XMP" }, 217 { tcKodakCameraSerialNumber, "KodakCameraSerialNumber" }, 218 { tcCFARepeatPatternDim, "CFARepeatPatternDim" }, 219 { tcCFAPattern, "CFAPattern" }, 220 { tcBatteryLevel, "BatteryLevel" }, 221 { tcKodakDCRPrivateIFD, "KodakDCRPrivateIFD" }, 222 { tcCopyright, "Copyright" }, 223 { tcExposureTime, "ExposureTime" }, 224 { tcFNumber, "FNumber" }, 225 { tcIPTC_NAA, "IPTC/NAA" }, 226 { tcLeafPKTS, "LeafPKTS" }, 227 { tcAdobeData, "AdobeData" }, 228 { tcExifIFD, "ExifIFD" }, 229 { tcICCProfile, "ICCProfile" }, 230 { tcExposureProgram, "ExposureProgram" }, 231 { tcSpectralSensitivity, "SpectralSensitivity" }, 232 { tcGPSInfo, "GPSInfo" }, 233 { tcISOSpeedRatings, "ISOSpeedRatings" }, 234 { tcOECF, "OECF" }, 235 { tcInterlace, "Interlace" }, 236 { tcTimeZoneOffset, "TimeZoneOffset" }, 237 { tcSelfTimerMode, "SelfTimerMode" }, 238 { tcSensitivityType, "SensitivityType" }, 239 { tcStandardOutputSensitivity, "StandardOutputSensitivity" }, 240 { tcRecommendedExposureIndex, "RecommendedExposureIndex" }, 241 { tcISOSpeed, "ISOSpeed" }, 242 { tcISOSpeedLatitudeyyy, "ISOSpeedLatitudeyyy" }, 243 { tcISOSpeedLatitudezzz, "ISOSpeedLatitudezzz" }, 244 { tcExifVersion, "ExifVersion" }, 245 { tcDateTimeOriginal, "DateTimeOriginal" }, 246 { tcDateTimeDigitized, "DateTimeDigitized" }, 247 { tcComponentsConfiguration, "ComponentsConfiguration" }, 248 { tcCompressedBitsPerPixel, "CompressedBitsPerPixel" }, 249 { tcShutterSpeedValue, "ShutterSpeedValue" }, 250 { tcApertureValue, "ApertureValue" }, 251 { tcBrightnessValue, "BrightnessValue" }, 252 { tcExposureBiasValue, "ExposureBiasValue" }, 253 { tcMaxApertureValue, "MaxApertureValue" }, 254 { tcSubjectDistance, "SubjectDistance" }, 255 { tcMeteringMode, "MeteringMode" }, 256 { tcLightSource, "LightSource" }, 257 { tcFlash, "Flash" }, 258 { tcFocalLength, "FocalLength" }, 259 { tcFlashEnergy, "FlashEnergy" }, 260 { tcSpatialFrequencyResponse, "SpatialFrequencyResponse" }, 261 { tcNoise, "Noise" }, 262 { tcFocalPlaneXResolution, "FocalPlaneXResolution" }, 263 { tcFocalPlaneYResolution, "FocalPlaneYResolution" }, 264 { tcFocalPlaneResolutionUnit, "FocalPlaneResolutionUnit" }, 265 { tcImageNumber, "ImageNumber" }, 266 { tcSecurityClassification, "SecurityClassification" }, 267 { tcImageHistory, "ImageHistory" }, 268 { tcSubjectArea, "SubjectArea" }, 269 { tcExposureIndex, "ExposureIndex" }, 270 { tcTIFF_EP_StandardID, "TIFF/EPStandardID" }, 271 { tcSensingMethod, "SensingMethod" }, 272 { tcMakerNote, "MakerNote" }, 273 { tcUserComment, "UserComment" }, 274 { tcSubsecTime, "SubsecTime" }, 275 { tcSubsecTimeOriginal, "SubsecTimeOriginal" }, 276 { tcSubsecTimeDigitized, "SubsecTimeDigitized" }, 277 { tcAdobeLayerData, "AdobeLayerData" }, 278 { tcFlashPixVersion, "FlashPixVersion" }, 279 { tcColorSpace, "ColorSpace" }, 280 { tcPixelXDimension, "PixelXDimension" }, 281 { tcPixelYDimension, "PixelYDimension" }, 282 { tcRelatedSoundFile, "RelatedSoundFile" }, 283 { tcInteroperabilityIFD, "InteroperabilityIFD" }, 284 { tcFlashEnergyExif, "FlashEnergyExif" }, 285 { tcSpatialFrequencyResponseExif, "SpatialFrequencyResponseExif" }, 286 { tcFocalPlaneXResolutionExif, "FocalPlaneXResolutionExif" }, 287 { tcFocalPlaneYResolutionExif, "FocalPlaneYResolutionExif" }, 288 { tcFocalPlaneResolutionUnitExif, "FocalPlaneResolutionUnitExif" }, 289 { tcSubjectLocation, "SubjectLocation" }, 290 { tcExposureIndexExif, "ExposureIndexExif" }, 291 { tcSensingMethodExif, "SensingMethodExif" }, 292 { tcFileSource, "FileSource" }, 293 { tcSceneType, "SceneType" }, 294 { tcCFAPatternExif, "CFAPatternExif" }, 295 { tcCustomRendered, "CustomRendered" }, 296 { tcExposureMode, "ExposureMode" }, 297 { tcWhiteBalance, "WhiteBalance" }, 298 { tcDigitalZoomRatio, "DigitalZoomRatio" }, 299 { tcFocalLengthIn35mmFilm, "FocalLengthIn35mmFilm" }, 300 { tcSceneCaptureType, "SceneCaptureType" }, 301 { tcGainControl, "GainControl" }, 302 { tcContrast, "Contrast" }, 303 { tcSaturation, "Saturation" }, 304 { tcSharpness, "Sharpness" }, 305 { tcDeviceSettingDescription, "DeviceSettingDescription" }, 306 { tcSubjectDistanceRange, "SubjectDistanceRange" }, 307 { tcImageUniqueID, "ImageUniqueID" }, 308 { tcCameraOwnerNameExif, "CameraOwnerNameExif" }, 309 { tcCameraSerialNumberExif, "CameraSerialNumberExif" }, 310 { tcLensSpecificationExif, "LensSpecificationExif" }, 311 { tcLensMakeExif, "LensMakeExif" }, 312 { tcLensModelExif, "LensModelExif" }, 313 { tcLensSerialNumberExif, "LensSerialNumberExif" }, 314 { tcGamma, "Gamma" }, 315 { tcPrintImageMatchingInfo, "PrintImageMatchingInfo" }, 316 { tcDNGVersion, "DNGVersion" }, 317 { tcDNGBackwardVersion, "DNGBackwardVersion" }, 318 { tcUniqueCameraModel, "UniqueCameraModel" }, 319 { tcLocalizedCameraModel, "LocalizedCameraModel" }, 320 { tcCFAPlaneColor, "CFAPlaneColor" }, 321 { tcCFALayout, "CFALayout" }, 322 { tcLinearizationTable, "LinearizationTable" }, 323 { tcBlackLevelRepeatDim, "BlackLevelRepeatDim" }, 324 { tcBlackLevel, "BlackLevel" }, 325 { tcBlackLevelDeltaH, "BlackLevelDeltaH" }, 326 { tcBlackLevelDeltaV, "BlackLevelDeltaV" }, 327 { tcWhiteLevel, "WhiteLevel" }, 328 { tcDefaultScale, "DefaultScale" }, 329 { tcDefaultCropOrigin, "DefaultCropOrigin" }, 330 { tcDefaultCropSize, "DefaultCropSize" }, 331 { tcDefaultUserCrop, "DefaultUserCrop" }, 332 { tcColorMatrix1, "ColorMatrix1" }, 333 { tcColorMatrix2, "ColorMatrix2" }, 334 { tcCameraCalibration1, "CameraCalibration1" }, 335 { tcCameraCalibration2, "CameraCalibration2" }, 336 { tcReductionMatrix1, "ReductionMatrix1" }, 337 { tcReductionMatrix2, "ReductionMatrix2" }, 338 { tcAnalogBalance, "AnalogBalance" }, 339 { tcAsShotNeutral, "AsShotNeutral" }, 340 { tcAsShotWhiteXY, "AsShotWhiteXY" }, 341 { tcBaselineExposure, "BaselineExposure" }, 342 { tcBaselineNoise, "BaselineNoise" }, 343 { tcBaselineSharpness, "BaselineSharpness" }, 344 { tcBayerGreenSplit, "BayerGreenSplit" }, 345 { tcLinearResponseLimit, "LinearResponseLimit" }, 346 { tcCameraSerialNumber, "CameraSerialNumber" }, 347 { tcLensInfo, "LensInfo" }, 348 { tcChromaBlurRadius, "ChromaBlurRadius" }, 349 { tcAntiAliasStrength, "AntiAliasStrength" }, 350 { tcShadowScale, "ShadowScale" }, 351 { tcDNGPrivateData, "DNGPrivateData" }, 352 { tcMakerNoteSafety, "MakerNoteSafety" }, 353 { tcCalibrationIlluminant1, "CalibrationIlluminant1" }, 354 { tcCalibrationIlluminant2, "CalibrationIlluminant2" }, 355 { tcBestQualityScale, "BestQualityScale" }, 356 { tcRawDataUniqueID, "RawDataUniqueID" }, 357 { tcOriginalRawFileName, "OriginalRawFileName" }, 358 { tcOriginalRawFileData, "OriginalRawFileData" }, 359 { tcActiveArea, "ActiveArea" }, 360 { tcMaskedAreas, "MaskedAreas" }, 361 { tcAsShotICCProfile, "AsShotICCProfile" }, 362 { tcAsShotPreProfileMatrix, "AsShotPreProfileMatrix" }, 363 { tcCurrentICCProfile, "CurrentICCProfile" }, 364 { tcCurrentPreProfileMatrix, "CurrentPreProfileMatrix" }, 365 { tcColorimetricReference, "ColorimetricReference" }, 366 { tcCameraCalibrationSignature, "CameraCalibrationSignature" }, 367 { tcProfileCalibrationSignature, "ProfileCalibrationSignature" }, 368 { tcExtraCameraProfiles, "ExtraCameraProfiles" }, 369 { tcAsShotProfileName, "AsShotProfileName" }, 370 { tcNoiseReductionApplied, "NoiseReductionApplied" }, 371 { tcProfileName, "ProfileName" }, 372 { tcProfileHueSatMapDims, "ProfileHueSatMapDims" }, 373 { tcProfileHueSatMapData1, "ProfileHueSatMapData1" }, 374 { tcProfileHueSatMapData2, "ProfileHueSatMapData2" }, 375 { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" }, 376 { tcProfileToneCurve, "ProfileToneCurve" }, 377 { tcProfileEmbedPolicy, "ProfileEmbedPolicy" }, 378 { tcProfileCopyright, "ProfileCopyright" }, 379 { tcForwardMatrix1, "ForwardMatrix1" }, 380 { tcForwardMatrix2, "ForwardMatrix2" }, 381 { tcPreviewApplicationName, "PreviewApplicationName" }, 382 { tcPreviewApplicationVersion, "PreviewApplicationVersion" }, 383 { tcPreviewSettingsName, "PreviewSettingsName" }, 384 { tcPreviewSettingsDigest, "PreviewSettingsDigest" }, 385 { tcPreviewColorSpace, "PreviewColorSpace" }, 386 { tcPreviewDateTime, "PreviewDateTime" }, 387 { tcRawImageDigest, "RawImageDigest" }, 388 { tcOriginalRawFileDigest, "OriginalRawFileDigest" }, 389 { tcSubTileBlockSize, "SubTileBlockSize" }, 390 { tcRowInterleaveFactor, "RowInterleaveFactor" }, 391 { tcProfileLookTableDims, "ProfileLookTableDims" }, 392 { tcProfileLookTableData, "ProfileLookTableData" }, 393 { tcProfileLookTableEncoding, "ProfileLookTableEncoding" }, 394 { tcBaselineExposureOffset, "BaselineExposureOffset" }, 395 { tcDefaultBlackRender, "DefaultBlackRender" }, 396 { tcOpcodeList1, "OpcodeList1" }, 397 { tcOpcodeList2, "OpcodeList2" }, 398 { tcOpcodeList3, "OpcodeList3" }, 399 { tcNoiseProfile, "NoiseProfile" }, 400 { tcOriginalDefaultFinalSize, "OriginalDefaultFinalSize" }, 401 { tcOriginalBestQualityFinalSize, "OriginalBestQualityFinalSize" }, 402 { tcOriginalDefaultCropSize, "OriginalDefaultCropSize" }, 403 { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" }, 404 { tcProfileLookTableEncoding, "ProfileLookTableEncoding" }, 405 { tcBaselineExposureOffset, "BaselineExposureOffset" }, 406 { tcDefaultBlackRender, "DefaultBlackRender" }, 407 { tcNewRawImageDigest, "NewRawImageDigest" }, 408 { tcRawToPreviewGain, "RawToPreviewGain" }, 409 { tcCacheBlob, "CacheBlob" }, 410 { tcKodakKDCPrivateIFD, "KodakKDCPrivateIFD" } 411 }; 412 413 const dng_name_table kGPSTagNames [] = 414 { 415 { tcGPSVersionID, "GPSVersionID" }, 416 { tcGPSLatitudeRef, "GPSLatitudeRef" }, 417 { tcGPSLatitude, "GPSLatitude" }, 418 { tcGPSLongitudeRef, "GPSLongitudeRef" }, 419 { tcGPSLongitude, "GPSLongitude" }, 420 { tcGPSAltitudeRef, "GPSAltitudeRef" }, 421 { tcGPSAltitude, "GPSAltitude" }, 422 { tcGPSTimeStamp, "GPSTimeStamp" }, 423 { tcGPSSatellites, "GPSSatellites" }, 424 { tcGPSStatus, "GPSStatus" }, 425 { tcGPSMeasureMode, "GPSMeasureMode" }, 426 { tcGPSDOP, "GPSDOP" }, 427 { tcGPSSpeedRef, "GPSSpeedRef" }, 428 { tcGPSSpeed, "GPSSpeed" }, 429 { tcGPSTrackRef, "GPSTrackRef" }, 430 { tcGPSTrack, "GPSTrack" }, 431 { tcGPSImgDirectionRef, "GPSImgDirectionRef" }, 432 { tcGPSImgDirection, "GPSImgDirection" }, 433 { tcGPSMapDatum, "GPSMapDatum" }, 434 { tcGPSDestLatitudeRef, "GPSDestLatitudeRef" }, 435 { tcGPSDestLatitude, "GPSDestLatitude" }, 436 { tcGPSDestLongitudeRef, "GPSDestLongitudeRef" }, 437 { tcGPSDestLongitude, "GPSDestLongitude" }, 438 { tcGPSDestBearingRef, "GPSDestBearingRef" }, 439 { tcGPSDestBearing, "GPSDestBearing" }, 440 { tcGPSDestDistanceRef, "GPSDestDistanceRef" }, 441 { tcGPSDestDistance, "GPSDestDistance" }, 442 { tcGPSProcessingMethod, "GPSProcessingMethod" }, 443 { tcGPSAreaInformation, "GPSAreaInformation" }, 444 { tcGPSDateStamp, "GPSDateStamp" }, 445 { tcGPSDifferential, "GPSDifferential" }, 446 { tcGPSHPositioningError, "GPSHPositioningError" }, 447 }; 448 449 const dng_name_table kInteroperabilityTagNames [] = 450 { 451 { tcInteroperabilityIndex, "InteroperabilityIndex" }, 452 { tcInteroperabilityVersion, "InteroperabilityVersion" }, 453 { tcRelatedImageFileFormat, "RelatedImageFileFormat" }, 454 { tcRelatedImageWidth, "RelatedImageWidth" }, 455 { tcRelatedImageLength, "RelatedImageLength" } 456 }; 457 458 const dng_name_table kFujiTagNames [] = 459 { 460 { tcFujiHeader, "FujiHeader" }, 461 { tcFujiRawInfo1, "FujiRawInfo1" }, 462 { tcFujiRawInfo2, "FujiRawInfo2" } 463 }; 464 465 const dng_name_table kContaxTagNames [] = 466 { 467 { tcContaxHeader, "ContaxHeader" } 468 }; 469 470 const char *name = NULL; 471 472 if (parentCode == 0 || 473 parentCode == tcExifIFD || 474 parentCode == tcLeafMOS || 475 (parentCode >= tcFirstSubIFD && parentCode <= tcLastSubIFD) || 476 (parentCode >= tcFirstChainedIFD && parentCode <= tcLastChainedIFD)) 477 { 478 479 name = LookupName (tagCode, 480 kTagNames, 481 sizeof (kTagNames ) / 482 sizeof (kTagNames [0])); 483 484 } 485 486 else if (parentCode == tcGPSInfo) 487 { 488 489 name = LookupName (tagCode, 490 kGPSTagNames, 491 sizeof (kGPSTagNames ) / 492 sizeof (kGPSTagNames [0])); 493 494 } 495 496 else if (parentCode == tcInteroperabilityIFD) 497 { 498 499 name = LookupName (tagCode, 500 kInteroperabilityTagNames, 501 sizeof (kInteroperabilityTagNames ) / 502 sizeof (kInteroperabilityTagNames [0])); 503 504 } 505 506 else if (parentCode == tcFujiRAF) 507 { 508 509 name = LookupName (tagCode, 510 kFujiTagNames, 511 sizeof (kFujiTagNames ) / 512 sizeof (kFujiTagNames [0])); 513 514 } 515 516 else if (parentCode == tcContaxRAW) 517 { 518 519 name = LookupName (tagCode, 520 kContaxTagNames, 521 sizeof (kContaxTagNames ) / 522 sizeof (kContaxTagNames [0])); 523 524 } 525 526 if (name) 527 { 528 return name; 529 } 530 531 static char s [32]; 532 533 if (parentCode == tcCanonCRW) 534 { 535 sprintf (s, "CRW_%04X", (unsigned) tagCode); 536 } 537 538 else if (parentCode == tcMinoltaMRW) 539 { 540 541 char c1 = (char) ((tagCode >> 24) & 0xFF); 542 char c2 = (char) ((tagCode >> 16) & 0xFF); 543 char c3 = (char) ((tagCode >> 8) & 0xFF); 544 char c4 = (char) ((tagCode ) & 0xFF); 545 546 if (c1 < ' ') c1 = '_'; 547 if (c2 < ' ') c2 = '_'; 548 if (c3 < ' ') c3 = '_'; 549 if (c4 < ' ') c4 = '_'; 550 551 sprintf (s, "MRW%c%c%c%c", c1, c2, c3, c4); 552 553 } 554 555 else if (parentCode == tcFujiRawInfo1) 556 { 557 sprintf (s, "RAF1_%04X", (unsigned) tagCode); 558 } 559 560 else if (parentCode == tcFujiRawInfo2) 561 { 562 sprintf (s, "RAF2_%04X", (unsigned) tagCode); 563 } 564 565 else 566 { 567 sprintf (s, "Tag%u", (unsigned) tagCode); 568 } 569 570 return s; 571 572 } 573 574 /*****************************************************************************/ 575 576 const char * LookupTagType (uint32 tagType) 577 { 578 579 const dng_name_table kTagTypeNames [] = 580 { 581 { ttByte, "Byte" }, 582 { ttAscii, "ASCII" }, 583 { ttShort, "Short" }, 584 { ttLong, "Long" }, 585 { ttRational, "Rational" }, 586 { ttSByte, "SByte" }, 587 { ttUndefined, "Undefined" }, 588 { ttSShort, "SShort" }, 589 { ttSLong, "SLong" }, 590 { ttSRational, "SRational" }, 591 { ttFloat, "Float" }, 592 { ttDouble, "Double" }, 593 { ttIFD, "IFD" }, 594 { ttUnicode, "Unicode" }, 595 { ttComplex, "Complex" } 596 }; 597 598 const char *name = LookupName (tagType, 599 kTagTypeNames, 600 sizeof (kTagTypeNames ) / 601 sizeof (kTagTypeNames [0])); 602 603 if (name) 604 { 605 return name; 606 } 607 608 static char s [32]; 609 610 sprintf (s, "Type%u", (unsigned) tagType); 611 612 return s; 613 614 } 615 616 /*****************************************************************************/ 617 618 const char * LookupNewSubFileType (uint32 key) 619 { 620 621 const dng_name_table kNewSubFileTypeNames [] = 622 { 623 { sfMainImage , "Main Image" }, 624 { sfPreviewImage , "Preview Image" }, 625 { sfTransparencyMask , "Transparency Mask" }, 626 { sfPreviewMask , "Preview Mask" }, 627 { sfAltPreviewImage , "Alt Preview Image" } 628 }; 629 630 const char *name = LookupName (key, 631 kNewSubFileTypeNames, 632 sizeof (kNewSubFileTypeNames ) / 633 sizeof (kNewSubFileTypeNames [0])); 634 635 if (name) 636 { 637 return name; 638 } 639 640 static char s [32]; 641 642 sprintf (s, "%u", (unsigned) key); 643 644 return s; 645 646 } 647 648 /*****************************************************************************/ 649 650 const char * LookupCompression (uint32 key) 651 { 652 653 const dng_name_table kCompressionNames [] = 654 { 655 { ccUncompressed, "Uncompressed" }, 656 { ccLZW, "LZW" }, 657 { ccOldJPEG, "Old JPEG" }, 658 { ccJPEG, "JPEG" }, 659 { ccDeflate, "Deflate" }, 660 { ccPackBits, "PackBits" }, 661 { ccOldDeflate, "OldDeflate" }, 662 { ccLossyJPEG, "Lossy JPEG" } 663 }; 664 665 const char *name = LookupName (key, 666 kCompressionNames, 667 sizeof (kCompressionNames ) / 668 sizeof (kCompressionNames [0])); 669 670 if (name) 671 { 672 return name; 673 } 674 675 static char s [32]; 676 677 sprintf (s, "%u", (unsigned) key); 678 679 return s; 680 681 } 682 683 /*****************************************************************************/ 684 685 const char * LookupPredictor (uint32 key) 686 { 687 688 const dng_name_table kPredictorNames [] = 689 { 690 { cpNullPredictor, "NullPredictor" }, 691 { cpHorizontalDifference, "HorizontalDifference" }, 692 { cpFloatingPoint, "FloatingPoint" }, 693 { cpHorizontalDifferenceX2, "HorizontalDifferenceX2" }, 694 { cpHorizontalDifferenceX4, "HorizontalDifferenceX4" }, 695 { cpFloatingPointX2, "FloatingPointX2" }, 696 { cpFloatingPointX4, "FloatingPointX4" } 697 }; 698 699 const char *name = LookupName (key, 700 kPredictorNames, 701 sizeof (kPredictorNames ) / 702 sizeof (kPredictorNames [0])); 703 704 if (name) 705 { 706 return name; 707 } 708 709 static char s [32]; 710 711 sprintf (s, "%u", (unsigned) key); 712 713 return s; 714 715 } 716 717 /*****************************************************************************/ 718 719 const char * LookupSampleFormat (uint32 key) 720 { 721 722 const dng_name_table kSampleFormatNames [] = 723 { 724 { sfUnsignedInteger, "UnsignedInteger" }, 725 { sfSignedInteger, "SignedInteger" }, 726 { sfFloatingPoint, "FloatingPoint" }, 727 { sfUndefined, "Undefined" } 728 }; 729 730 const char *name = LookupName (key, 731 kSampleFormatNames, 732 sizeof (kSampleFormatNames ) / 733 sizeof (kSampleFormatNames [0])); 734 735 if (name) 736 { 737 return name; 738 } 739 740 static char s [32]; 741 742 sprintf (s, "%u", (unsigned) key); 743 744 return s; 745 746 } 747 748 /*****************************************************************************/ 749 750 const char * LookupPhotometricInterpretation (uint32 key) 751 { 752 753 const dng_name_table kPhotometricInterpretationNames [] = 754 { 755 { piWhiteIsZero, "WhiteIsZero" }, 756 { piBlackIsZero, "BlackIsZero" }, 757 { piRGB, "RGB" }, 758 { piRGBPalette, "RGBPalette" }, 759 { piTransparencyMask, "TransparencyMask" }, 760 { piCMYK, "CMYK" }, 761 { piYCbCr, "YCbCr" }, 762 { piCIELab, "CIELab" }, 763 { piICCLab, "ICCLab" }, 764 { piCFA, "CFA" }, 765 { piLinearRaw, "LinearRaw" } 766 }; 767 768 const char *name = LookupName (key, 769 kPhotometricInterpretationNames, 770 sizeof (kPhotometricInterpretationNames ) / 771 sizeof (kPhotometricInterpretationNames [0])); 772 773 if (name) 774 { 775 return name; 776 } 777 778 static char s [32]; 779 780 sprintf (s, "%u", (unsigned) key); 781 782 return s; 783 784 } 785 786 /*****************************************************************************/ 787 788 const char * LookupOrientation (uint32 key) 789 { 790 791 const dng_name_table kOrientationNames [] = 792 { 793 { 1, "1 - 0th row is top, 0th column is left" }, 794 { 2, "2 - 0th row is top, 0th column is right" }, 795 { 3, "3 - 0th row is bottom, 0th column is right" }, 796 { 4, "4 - 0th row is bottom, 0th column is left" }, 797 { 5, "5 - 0th row is left, 0th column is top" }, 798 { 6, "6 - 0th row is right, 0th column is top" }, 799 { 7, "7 - 0th row is right, 0th column is bottom" }, 800 { 8, "8 - 0th row is left, 0th column is bottom" }, 801 { 9, "9 - unknown" } 802 }; 803 804 const char *name = LookupName (key, 805 kOrientationNames, 806 sizeof (kOrientationNames ) / 807 sizeof (kOrientationNames [0])); 808 809 if (name) 810 { 811 return name; 812 } 813 814 static char s [32]; 815 816 sprintf (s, "%u", (unsigned) key); 817 818 return s; 819 820 } 821 822 /*****************************************************************************/ 823 824 const char * LookupResolutionUnit (uint32 key) 825 { 826 827 const dng_name_table kResolutionUnitNames [] = 828 { 829 { ruNone, "None" }, 830 { ruInch, "Inch" }, 831 { ruCM, "cm" }, 832 { ruMM, "mm" }, 833 { ruMicroM, "Micrometer" } 834 }; 835 836 const char *name = LookupName (key, 837 kResolutionUnitNames, 838 sizeof (kResolutionUnitNames ) / 839 sizeof (kResolutionUnitNames [0])); 840 841 if (name) 842 { 843 return name; 844 } 845 846 static char s [32]; 847 848 sprintf (s, "%u", (unsigned) key); 849 850 return s; 851 852 } 853 854 /*****************************************************************************/ 855 856 const char * LookupCFAColor (uint32 key) 857 { 858 859 const dng_name_table kCFAColorNames [] = 860 { 861 { 0, "Red" }, 862 { 1, "Green" }, 863 { 2, "Blue" }, 864 { 3, "Cyan" }, 865 { 4, "Magenta" }, 866 { 5, "Yellow" }, 867 { 6, "White" } 868 }; 869 870 const char *name = LookupName (key, 871 kCFAColorNames, 872 sizeof (kCFAColorNames ) / 873 sizeof (kCFAColorNames [0])); 874 875 if (name) 876 { 877 return name; 878 } 879 880 static char s [32]; 881 882 sprintf (s, "Color%u", (unsigned) key); 883 884 return s; 885 886 } 887 888 /*****************************************************************************/ 889 890 const char * LookupSensingMethod (uint32 key) 891 { 892 893 const dng_name_table kSensingMethodNames [] = 894 { 895 { 0, "Undefined" }, 896 { 1, "MonochromeArea" }, 897 { 2, "OneChipColorArea" }, 898 { 3, "TwoChipColorArea" }, 899 { 4, "ThreeChipColorArea" }, 900 { 5, "ColorSequentialArea" }, 901 { 6, "MonochromeLinear" }, 902 { 7, "TriLinear" }, 903 { 8, "ColorSequentialLinear" } 904 }; 905 906 const char *name = LookupName (key, 907 kSensingMethodNames, 908 sizeof (kSensingMethodNames ) / 909 sizeof (kSensingMethodNames [0])); 910 911 if (name) 912 { 913 return name; 914 } 915 916 static char s [32]; 917 918 sprintf (s, "%u", (unsigned) key); 919 920 return s; 921 922 } 923 924 /*****************************************************************************/ 925 926 const char * LookupExposureProgram (uint32 key) 927 { 928 929 const dng_name_table kExposureProgramNames [] = 930 { 931 { epUnidentified, "Unidentified" }, 932 { epManual, "Manual" }, 933 { epProgramNormal, "Program Normal" }, 934 { epAperturePriority, "Aperture Priority" }, 935 { epShutterPriority, "Shutter Priority" }, 936 { epProgramCreative, "Program Creative" }, 937 { epProgramAction, "Program Action" }, 938 { epPortraitMode, "Portrait Mode" }, 939 { epLandscapeMode, "Landscape Mode" } 940 }; 941 942 const char *name = LookupName (key, 943 kExposureProgramNames, 944 sizeof (kExposureProgramNames ) / 945 sizeof (kExposureProgramNames [0])); 946 947 if (name) 948 { 949 return name; 950 } 951 952 static char s [32]; 953 954 sprintf (s, "%u", (unsigned) key); 955 956 return s; 957 958 } 959 960 /*****************************************************************************/ 961 962 const char * LookupMeteringMode (uint32 key) 963 { 964 965 const dng_name_table kMeteringModeNames [] = 966 { 967 { mmUnidentified, "Unknown" }, 968 { mmAverage, "Average" }, 969 { mmCenterWeightedAverage, "CenterWeightedAverage" }, 970 { mmSpot, "Spot" }, 971 { mmMultiSpot, "MultiSpot" }, 972 { mmPattern, "Pattern" }, 973 { mmPartial, "Partial" }, 974 { mmOther, "Other" } 975 }; 976 977 const char *name = LookupName (key, 978 kMeteringModeNames, 979 sizeof (kMeteringModeNames ) / 980 sizeof (kMeteringModeNames [0])); 981 982 if (name) 983 { 984 return name; 985 } 986 987 static char s [32]; 988 989 sprintf (s, "%u", (unsigned) key); 990 991 return s; 992 993 } 994 995 /*****************************************************************************/ 996 997 const char * LookupLightSource (uint32 key) 998 { 999 1000 const dng_name_table kLightSourceNames [] = 1001 { 1002 { lsUnknown, "Unknown" }, 1003 { lsDaylight, "Daylight" }, 1004 { lsFluorescent, "Fluorescent" }, 1005 { lsTungsten, "Tungsten (incandescent light)" }, 1006 { lsFlash, "Flash" }, 1007 { lsFineWeather, "Fine weather" }, 1008 { lsCloudyWeather, "Cloudy weather" }, 1009 { lsShade, "Shade" }, 1010 { lsDaylightFluorescent, "Daylight fluorescent (D 5700 - 7100K)" }, 1011 { lsDayWhiteFluorescent, "Day white fluorescent (N 4600 - 5500K)" }, 1012 { lsCoolWhiteFluorescent, "Cool white fluorescent (W 3800 - 4500K)" }, 1013 { lsWhiteFluorescent, "White fluorescent (WW 3250 - 3800K)" }, 1014 { lsWarmWhiteFluorescent, "Warm white fluorescent (L 2600 - 3250K)" }, 1015 { lsStandardLightA, "Standard light A" }, 1016 { lsStandardLightB, "Standard light B" }, 1017 { lsStandardLightC, "Standard light C" }, 1018 { lsD55, "D55" }, 1019 { lsD65, "D65" }, 1020 { lsD75, "D75" }, 1021 { lsD50, "D50" }, 1022 { lsISOStudioTungsten, "ISO studio tungsten" }, 1023 { lsOther, "Other" } 1024 }; 1025 1026 const char *name = LookupName (key, 1027 kLightSourceNames, 1028 sizeof (kLightSourceNames ) / 1029 sizeof (kLightSourceNames [0])); 1030 1031 if (name) 1032 { 1033 return name; 1034 } 1035 1036 static char s [32]; 1037 1038 if (key & 0x08000) 1039 { 1040 1041 sprintf (s, "%uK", (unsigned) (key & 0x7FFF)); 1042 1043 } 1044 1045 else 1046 { 1047 1048 sprintf (s, "%u", (unsigned) key); 1049 1050 } 1051 1052 return s; 1053 1054 } 1055 1056 /*****************************************************************************/ 1057 1058 const char * LookupColorSpace (uint32 key) 1059 { 1060 1061 const dng_name_table kColorSpaceNames [] = 1062 { 1063 { 1, "sRGB" }, 1064 { 0xFFFF, "Uncalibrated" } 1065 }; 1066 1067 const char *name = LookupName (key, 1068 kColorSpaceNames, 1069 sizeof (kColorSpaceNames ) / 1070 sizeof (kColorSpaceNames [0])); 1071 1072 if (name) 1073 { 1074 return name; 1075 } 1076 1077 static char s [32]; 1078 1079 sprintf (s, "%u", (unsigned) key); 1080 1081 return s; 1082 1083 } 1084 1085 /*****************************************************************************/ 1086 1087 const char * LookupFileSource (uint32 key) 1088 { 1089 1090 const dng_name_table kFileSourceNames [] = 1091 { 1092 { 3, "DSC" } 1093 }; 1094 1095 const char *name = LookupName (key, 1096 kFileSourceNames, 1097 sizeof (kFileSourceNames ) / 1098 sizeof (kFileSourceNames [0])); 1099 1100 if (name) 1101 { 1102 return name; 1103 } 1104 1105 static char s [32]; 1106 1107 sprintf (s, "%u", (unsigned) key); 1108 1109 return s; 1110 1111 } 1112 1113 /*****************************************************************************/ 1114 1115 const char * LookupSceneType (uint32 key) 1116 { 1117 1118 const dng_name_table kSceneTypeNames [] = 1119 { 1120 { 1, "A directly photographed image" } 1121 }; 1122 1123 const char *name = LookupName (key, 1124 kSceneTypeNames, 1125 sizeof (kSceneTypeNames ) / 1126 sizeof (kSceneTypeNames [0])); 1127 1128 if (name) 1129 { 1130 return name; 1131 } 1132 1133 static char s [32]; 1134 1135 sprintf (s, "%u", (unsigned) key); 1136 1137 return s; 1138 1139 } 1140 1141 /*****************************************************************************/ 1142 1143 const char * LookupCustomRendered (uint32 key) 1144 { 1145 1146 const dng_name_table kCustomRenderedNames [] = 1147 { 1148 { 0, "Normal process" }, 1149 { 1, "Custom process" } 1150 }; 1151 1152 const char *name = LookupName (key, 1153 kCustomRenderedNames, 1154 sizeof (kCustomRenderedNames ) / 1155 sizeof (kCustomRenderedNames [0])); 1156 1157 if (name) 1158 { 1159 return name; 1160 } 1161 1162 static char s [32]; 1163 1164 sprintf (s, "%u", (unsigned) key); 1165 1166 return s; 1167 1168 } 1169 1170 /*****************************************************************************/ 1171 1172 const char * LookupExposureMode (uint32 key) 1173 { 1174 1175 const dng_name_table kExposureModeNames [] = 1176 { 1177 { 0, "Auto exposure" }, 1178 { 1, "Manual exposure" }, 1179 { 2, "Auto bracket" } 1180 }; 1181 1182 const char *name = LookupName (key, 1183 kExposureModeNames, 1184 sizeof (kExposureModeNames ) / 1185 sizeof (kExposureModeNames [0])); 1186 1187 if (name) 1188 { 1189 return name; 1190 } 1191 1192 static char s [32]; 1193 1194 sprintf (s, "%u", (unsigned) key); 1195 1196 return s; 1197 1198 } 1199 1200 /*****************************************************************************/ 1201 1202 const char * LookupWhiteBalance (uint32 key) 1203 { 1204 1205 const dng_name_table kWhiteBalanceNames [] = 1206 { 1207 { 0, "Auto white balance" }, 1208 { 1, "Manual white balance" } 1209 }; 1210 1211 const char *name = LookupName (key, 1212 kWhiteBalanceNames, 1213 sizeof (kWhiteBalanceNames ) / 1214 sizeof (kWhiteBalanceNames [0])); 1215 1216 if (name) 1217 { 1218 return name; 1219 } 1220 1221 static char s [32]; 1222 1223 sprintf (s, "%u", (unsigned) key); 1224 1225 return s; 1226 1227 } 1228 1229 /*****************************************************************************/ 1230 1231 const char * LookupSceneCaptureType (uint32 key) 1232 { 1233 1234 const dng_name_table kSceneCaptureTypeNames [] = 1235 { 1236 { 0, "Standard" }, 1237 { 1, "Landscape" }, 1238 { 2, "Portrait" }, 1239 { 3, "Night scene" } 1240 }; 1241 1242 const char *name = LookupName (key, 1243 kSceneCaptureTypeNames, 1244 sizeof (kSceneCaptureTypeNames ) / 1245 sizeof (kSceneCaptureTypeNames [0])); 1246 1247 if (name) 1248 { 1249 return name; 1250 } 1251 1252 static char s [32]; 1253 1254 sprintf (s, "%u", (unsigned) key); 1255 1256 return s; 1257 1258 } 1259 1260 /*****************************************************************************/ 1261 1262 const char * LookupGainControl (uint32 key) 1263 { 1264 1265 const dng_name_table kGainControlNames [] = 1266 { 1267 { 0, "None" }, 1268 { 1, "Low gain up" }, 1269 { 2, "High gain up" }, 1270 { 3, "Low gain down" }, 1271 { 4, "High gain down" } 1272 }; 1273 1274 const char *name = LookupName (key, 1275 kGainControlNames, 1276 sizeof (kGainControlNames ) / 1277 sizeof (kGainControlNames [0])); 1278 1279 if (name) 1280 { 1281 return name; 1282 } 1283 1284 static char s [32]; 1285 1286 sprintf (s, "%u", (unsigned) key); 1287 1288 return s; 1289 1290 } 1291 1292 /*****************************************************************************/ 1293 1294 const char * LookupContrast (uint32 key) 1295 { 1296 1297 const dng_name_table kContrastNames [] = 1298 { 1299 { 0, "Normal" }, 1300 { 1, "Soft" }, 1301 { 2, "Hard" } 1302 }; 1303 1304 const char *name = LookupName (key, 1305 kContrastNames, 1306 sizeof (kContrastNames ) / 1307 sizeof (kContrastNames [0])); 1308 1309 if (name) 1310 { 1311 return name; 1312 } 1313 1314 static char s [32]; 1315 1316 sprintf (s, "%u", (unsigned) key); 1317 1318 return s; 1319 1320 } 1321 1322 /*****************************************************************************/ 1323 1324 const char * LookupSaturation (uint32 key) 1325 { 1326 1327 const dng_name_table kSaturationNames [] = 1328 { 1329 { 0, "Normal" }, 1330 { 1, "Low saturation" }, 1331 { 2, "High saturation" } 1332 }; 1333 1334 const char *name = LookupName (key, 1335 kSaturationNames, 1336 sizeof (kSaturationNames ) / 1337 sizeof (kSaturationNames [0])); 1338 1339 if (name) 1340 { 1341 return name; 1342 } 1343 1344 static char s [32]; 1345 1346 sprintf (s, "%u", (unsigned) key); 1347 1348 return s; 1349 1350 } 1351 1352 /*****************************************************************************/ 1353 1354 const char * LookupSharpness (uint32 key) 1355 { 1356 1357 const dng_name_table kSharpnessNames [] = 1358 { 1359 { 0, "Normal" }, 1360 { 1, "Soft" }, 1361 { 2, "Hard" } 1362 }; 1363 1364 const char *name = LookupName (key, 1365 kSharpnessNames, 1366 sizeof (kSharpnessNames ) / 1367 sizeof (kSharpnessNames [0])); 1368 1369 if (name) 1370 { 1371 return name; 1372 } 1373 1374 static char s [32]; 1375 1376 sprintf (s, "%u", (unsigned) key); 1377 1378 return s; 1379 1380 } 1381 1382 /*****************************************************************************/ 1383 1384 const char * LookupSubjectDistanceRange (uint32 key) 1385 { 1386 1387 const dng_name_table kSubjectDistanceRangeNames [] = 1388 { 1389 { 0, "Unknown" }, 1390 { 1, "Macro" }, 1391 { 2, "Close view" }, 1392 { 3, "Distant view" } 1393 }; 1394 1395 const char *name = LookupName (key, 1396 kSubjectDistanceRangeNames, 1397 sizeof (kSubjectDistanceRangeNames ) / 1398 sizeof (kSubjectDistanceRangeNames [0])); 1399 1400 if (name) 1401 { 1402 return name; 1403 } 1404 1405 static char s [32]; 1406 1407 sprintf (s, "%u", (unsigned) key); 1408 1409 return s; 1410 1411 } 1412 1413 /*****************************************************************************/ 1414 1415 const char * LookupComponent (uint32 key) 1416 { 1417 1418 const dng_name_table kComponentNames [] = 1419 { 1420 { 0, "-" }, 1421 { 1, "Y" }, 1422 { 2, "Cb" }, 1423 { 3, "Cr" }, 1424 { 4, "R" }, 1425 { 5, "G" }, 1426 { 6, "B" } 1427 }; 1428 1429 const char *name = LookupName (key, 1430 kComponentNames, 1431 sizeof (kComponentNames ) / 1432 sizeof (kComponentNames [0])); 1433 1434 if (name) 1435 { 1436 return name; 1437 } 1438 1439 static char s [32]; 1440 1441 sprintf (s, "%u", (unsigned) key); 1442 1443 return s; 1444 1445 } 1446 1447 /*****************************************************************************/ 1448 1449 const char * LookupCFALayout (uint32 key) 1450 { 1451 1452 const dng_name_table kCFALayoutNames [] = 1453 { 1454 { 1, "Rectangular (or square) layout" }, 1455 { 2, "Staggered layout A: even columns are offset down by 1/2 row" }, 1456 { 3, "Staggered layout B: even columns are offset up by 1/2 row" }, 1457 { 4, "Staggered layout C: even rows are offset right by 1/2 column" }, 1458 { 5, "Staggered layout D: even rows are offset left by 1/2 column" }, 1459 { 6, "Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column" }, 1460 { 7, "Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column" }, 1461 { 8, "Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column" }, 1462 { 9, "Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column" } 1463 }; 1464 1465 const char *name = LookupName (key, 1466 kCFALayoutNames, 1467 sizeof (kCFALayoutNames ) / 1468 sizeof (kCFALayoutNames [0])); 1469 1470 if (name) 1471 { 1472 return name; 1473 } 1474 1475 static char s [32]; 1476 1477 sprintf (s, "%u", (unsigned) key); 1478 1479 return s; 1480 1481 } 1482 1483 /*****************************************************************************/ 1484 1485 const char * LookupMakerNoteSafety (uint32 key) 1486 { 1487 1488 const dng_name_table kMakerNoteSafetyNames [] = 1489 { 1490 { 0, "Unsafe" }, 1491 { 1, "Safe" } 1492 }; 1493 1494 const char *name = LookupName (key, 1495 kMakerNoteSafetyNames, 1496 sizeof (kMakerNoteSafetyNames ) / 1497 sizeof (kMakerNoteSafetyNames [0])); 1498 1499 if (name) 1500 { 1501 return name; 1502 } 1503 1504 static char s [32]; 1505 1506 sprintf (s, "%u", (unsigned) key); 1507 1508 return s; 1509 1510 } 1511 1512 /*****************************************************************************/ 1513 1514 const char * LookupColorimetricReference (uint32 key) 1515 { 1516 1517 const dng_name_table kColorimetricReferenceNames [] = 1518 { 1519 { crSceneReferred, "Scene Referred" }, 1520 { crICCProfilePCS, "ICC Profile PCS" } 1521 }; 1522 1523 const char *name = LookupName (key, 1524 kColorimetricReferenceNames, 1525 sizeof (kColorimetricReferenceNames ) / 1526 sizeof (kColorimetricReferenceNames [0])); 1527 1528 if (name) 1529 { 1530 return name; 1531 } 1532 1533 static char s [32]; 1534 1535 sprintf (s, "%u", (unsigned) key); 1536 1537 return s; 1538 1539 } 1540 1541 /*****************************************************************************/ 1542 1543 const char * LookupPreviewColorSpace (uint32 key) 1544 { 1545 1546 const dng_name_table kPreviewColorSpaceNames [] = 1547 { 1548 { previewColorSpace_Unknown , "Unknown" }, 1549 { previewColorSpace_GrayGamma22, "Gray Gamma 2.2" }, 1550 { previewColorSpace_sRGB , "sRGB" }, 1551 { previewColorSpace_AdobeRGB , "Adobe RGB (1998)" }, 1552 { previewColorSpace_ProPhotoRGB, "Pro Photo RGB" } 1553 }; 1554 1555 const char *name = LookupName (key, 1556 kPreviewColorSpaceNames, 1557 sizeof (kPreviewColorSpaceNames ) / 1558 sizeof (kPreviewColorSpaceNames [0])); 1559 1560 if (name) 1561 { 1562 return name; 1563 } 1564 1565 static char s [32]; 1566 1567 sprintf (s, "%u", (unsigned) key); 1568 1569 return s; 1570 1571 } 1572 1573 /*****************************************************************************/ 1574 1575 const char * LookupJPEGMarker (uint32 key) 1576 { 1577 1578 const dng_name_table kJPEGMarkerNames [] = 1579 { 1580 { M_TEM, "TEM" }, 1581 { M_SOF0, "SOF0" }, 1582 { M_SOF1, "SOF1" }, 1583 { M_SOF2, "SOF2" }, 1584 { M_SOF3, "SOF3" }, 1585 { M_DHT, "DHT" }, 1586 { M_SOF5, "SOF5" }, 1587 { M_SOF6, "SOF6" }, 1588 { M_SOF7, "SOF7" }, 1589 { M_JPG, "JPG" }, 1590 { M_SOF9, "SOF9" }, 1591 { M_SOF10, "SOF10" }, 1592 { M_SOF11, "SOF11" }, 1593 { M_DAC, "DAC" }, 1594 { M_SOF13, "SOF13" }, 1595 { M_SOF14, "SOF14" }, 1596 { M_SOF15, "SOF15" }, 1597 { M_RST0, "RST0" }, 1598 { M_RST1, "RST1" }, 1599 { M_RST2, "RST2" }, 1600 { M_RST3, "RST3" }, 1601 { M_RST4, "RST4" }, 1602 { M_RST5, "RST5" }, 1603 { M_RST6, "RST6" }, 1604 { M_RST7, "RST7" }, 1605 { M_SOI, "SOI" }, 1606 { M_EOI, "EOI" }, 1607 { M_SOS, "SOS" }, 1608 { M_DQT, "DQT" }, 1609 { M_DNL, "DNL" }, 1610 { M_DRI, "DRI" }, 1611 { M_DHP, "DHP" }, 1612 { M_EXP, "EXP" }, 1613 { M_APP0, "APP0" }, 1614 { M_APP1, "APP1" }, 1615 { M_APP2, "APP2" }, 1616 { M_APP3, "APP3" }, 1617 { M_APP4, "APP4" }, 1618 { M_APP5, "APP5" }, 1619 { M_APP6, "APP6" }, 1620 { M_APP7, "APP7" }, 1621 { M_APP8, "APP8" }, 1622 { M_APP9, "APP9" }, 1623 { M_APP10, "APP10" }, 1624 { M_APP11, "APP11" }, 1625 { M_APP12, "APP12" }, 1626 { M_APP13, "APP13" }, 1627 { M_APP14, "APP14" }, 1628 { M_APP15, "APP15" }, 1629 { M_JPG0, "JPG0" }, 1630 { M_JPG1, "JPG1" }, 1631 { M_JPG2, "JPG2" }, 1632 { M_JPG3, "JPG3" }, 1633 { M_JPG4, "JPG4" }, 1634 { M_JPG5, "JPG5" }, 1635 { M_JPG6, "JPG6" }, 1636 { M_JPG7, "JPG7" }, 1637 { M_JPG8, "JPG8" }, 1638 { M_JPG9, "JPG9" }, 1639 { M_JPG10, "JPG10" }, 1640 { M_JPG11, "JPG11" }, 1641 { M_JPG12, "JPG12" }, 1642 { M_JPG13, "JPG13" }, 1643 { M_COM, "COM" }, 1644 { M_ERROR, "ERROR" } 1645 }; 1646 1647 const char *name = LookupName (key, 1648 kJPEGMarkerNames, 1649 sizeof (kJPEGMarkerNames ) / 1650 sizeof (kJPEGMarkerNames [0])); 1651 1652 if (name) 1653 { 1654 return name; 1655 } 1656 1657 static char s [32]; 1658 1659 sprintf (s, "0x%02X", (unsigned) key); 1660 1661 return s; 1662 1663 } 1664 1665 /*****************************************************************************/ 1666 1667 const char * LookupSensitivityType (uint32 key) 1668 { 1669 1670 const dng_name_table kSensitivityTypeNames [] = 1671 { 1672 { stUnknown, "Unknown" }, 1673 { stStandardOutputSensitivity, "Standard Output Sensitivity (SOS)" }, 1674 { stRecommendedExposureIndex, "Recommended Exposure Index (REI)" }, 1675 { stISOSpeed, "ISO Speed" }, 1676 { stSOSandREI, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI)" }, 1677 { stSOSandISOSpeed, "Standard Output Sensitivity (SOS) and ISO Speed" }, 1678 { stREIandISOSpeed, "Recommended Exposure Index (REI) and ISO Speed" }, 1679 { stSOSandREIandISOSpeed, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI) and ISO Speed" }, 1680 }; 1681 1682 const char *name = LookupName (key, 1683 kSensitivityTypeNames, 1684 sizeof (kSensitivityTypeNames ) / 1685 sizeof (kSensitivityTypeNames [0])); 1686 1687 if (name) 1688 { 1689 return name; 1690 } 1691 1692 static char s [32]; 1693 1694 sprintf (s, "%u", (unsigned) key); 1695 1696 return s; 1697 1698 } 1699 1700 /*****************************************************************************/ 1701 1702 void DumpHexAscii (dng_stream &stream, 1703 uint32 count) 1704 { 1705 1706 uint32 rows = (count + 15) >> 4; 1707 1708 if (rows > gDumpLineLimit) 1709 rows = gDumpLineLimit; 1710 1711 for (uint32 row = 0; row < rows; row++) 1712 { 1713 1714 printf (" "); 1715 1716 uint32 col; 1717 1718 uint32 cols = count - (row << 4); 1719 1720 if (cols > 16) 1721 cols = 16; 1722 1723 uint8 x [16]; 1724 1725 for (col = 0; col < 16; col++) 1726 { 1727 1728 x [col] = ' '; 1729 1730 if (col < cols) 1731 { 1732 1733 x [col] = stream.Get_uint8 (); 1734 1735 printf ("%02x ", x [col]); 1736 1737 } 1738 1739 else 1740 { 1741 printf (" "); 1742 } 1743 1744 } 1745 1746 printf (" "); 1747 1748 for (col = 0; col < 16; col++) 1749 { 1750 1751 if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~') 1752 { 1753 printf ("%c", x [col]); 1754 } 1755 1756 else 1757 { 1758 printf ("."); 1759 } 1760 1761 } 1762 1763 printf ("\n"); 1764 1765 } 1766 1767 if (count > rows * 16) 1768 { 1769 printf (" ... %u more bytes\n", (unsigned) (count - rows * 16)); 1770 } 1771 1772 } 1773 1774 /*****************************************************************************/ 1775 1776 void DumpHexAscii (const uint8 *buf, 1777 uint32 count) 1778 { 1779 1780 uint32 rows = (count + 15) >> 4; 1781 1782 if (rows > gDumpLineLimit) 1783 rows = gDumpLineLimit; 1784 1785 for (uint32 row = 0; row < rows; row++) 1786 { 1787 1788 printf (" "); 1789 1790 uint32 col; 1791 1792 uint32 cols = count - (row << 4); 1793 1794 if (cols > 16) 1795 cols = 16; 1796 1797 uint8 x [16]; 1798 1799 for (col = 0; col < 16; col++) 1800 { 1801 1802 x [col] = ' '; 1803 1804 if (col < cols) 1805 { 1806 1807 x [col] = *(buf++); 1808 1809 printf ("%02x ", x [col]); 1810 1811 } 1812 1813 else 1814 { 1815 printf (" "); 1816 } 1817 1818 } 1819 1820 printf (" "); 1821 1822 for (col = 0; col < 16; col++) 1823 { 1824 1825 if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~') 1826 { 1827 printf ("%c", x [col]); 1828 } 1829 1830 else 1831 { 1832 printf ("."); 1833 } 1834 1835 } 1836 1837 printf ("\n"); 1838 1839 } 1840 1841 if (count > rows * 16) 1842 { 1843 printf (" ... %u more bytes\n", (unsigned) (count - rows * 16)); 1844 } 1845 1846 } 1847 1848 /*****************************************************************************/ 1849 1850 void DumpXMP (dng_stream &stream, 1851 uint32 count) 1852 { 1853 1854 uint32 lineLength = 0; 1855 1856 while (count > 0) 1857 { 1858 1859 uint32 x = stream.Get_uint8 (); 1860 1861 if (x == 0) break; 1862 1863 count--; 1864 1865 if (lineLength == 0) 1866 { 1867 1868 printf ("XMP: "); 1869 1870 lineLength = 5; 1871 1872 } 1873 1874 if (x == '\n' || 1875 x == '\r') 1876 { 1877 1878 printf ("\n"); 1879 1880 lineLength = 0; 1881 1882 } 1883 1884 else 1885 { 1886 1887 if (lineLength >= 128) 1888 { 1889 1890 printf ("\nXMP: "); 1891 1892 lineLength = 5; 1893 1894 } 1895 1896 if (x >= ' ' && x <= '~') 1897 { 1898 1899 printf ("%c", (char) x); 1900 1901 lineLength += 1; 1902 1903 } 1904 1905 else 1906 { 1907 1908 printf ("\\%03o", (unsigned) x); 1909 1910 lineLength += 4; 1911 1912 } 1913 1914 } 1915 1916 } 1917 1918 if (lineLength != 0) 1919 { 1920 1921 printf ("\n"); 1922 1923 } 1924 1925 } 1926 1927 /*****************************************************************************/ 1928 1929 void DumpString (const dng_string &s) 1930 { 1931 1932 const uint32 kMaxDumpString = gDumpLineLimit * 64; 1933 1934 printf ("\""); 1935 1936 const char *ss = s.Get (); 1937 1938 uint32 total = 0; 1939 1940 while (*ss != 0 && total++ < kMaxDumpString) 1941 { 1942 1943 uint32 c = dng_string::DecodeUTF8 (ss); 1944 1945 if (c >= ' ' && c <= '~') 1946 { 1947 printf ("%c", (char) c); 1948 } 1949 1950 else switch (c) 1951 { 1952 1953 case '\t': 1954 { 1955 printf ("\\t"); 1956 break; 1957 } 1958 1959 case '\n': 1960 { 1961 printf ("\\n"); 1962 break; 1963 } 1964 1965 case '\r': 1966 { 1967 printf ("\\r"); 1968 break; 1969 } 1970 1971 default: 1972 { 1973 printf ("[%X]", (unsigned) c); 1974 } 1975 1976 } 1977 1978 } 1979 1980 uint32 extra = (uint32) strlen (ss); 1981 1982 if (extra > 0) 1983 { 1984 printf ("...\" (%u more bytes)", (unsigned) extra); 1985 } 1986 1987 else 1988 { 1989 printf ("\""); 1990 } 1991 1992 } 1993 1994 /*****************************************************************************/ 1995 1996 void DumpTagValues (dng_stream &stream, 1997 const char *entry_name, 1998 uint32 parentCode, 1999 uint32 tagCode, 2000 uint32 tagType, 2001 uint32 tagCount, 2002 const char *tag_name) 2003 { 2004 2005 const uint32 kMaxDumpSingleLine = 4; 2006 2007 const uint32 kMaxDumpArray = Max_uint32 (gDumpLineLimit, kMaxDumpSingleLine); 2008 2009 printf ("%s:", tag_name ? tag_name 2010 : LookupTagCode (parentCode, tagCode)); 2011 2012 switch (tagType) 2013 { 2014 2015 case ttShort: 2016 case ttLong: 2017 case ttIFD: 2018 case ttSByte: 2019 case ttSShort: 2020 case ttSLong: 2021 case ttRational: 2022 case ttSRational: 2023 case ttFloat: 2024 case ttDouble: 2025 { 2026 2027 if (tagCount > kMaxDumpSingleLine) 2028 { 2029 2030 printf (" %u entries", (unsigned) tagCount); 2031 2032 } 2033 2034 for (uint32 j = 0; j < tagCount && j < kMaxDumpArray; j++) 2035 { 2036 2037 if (tagCount <= kMaxDumpSingleLine) 2038 { 2039 2040 if (j == 0) 2041 { 2042 2043 printf (" %s =", entry_name); 2044 2045 } 2046 2047 printf (" "); 2048 2049 } 2050 2051 else 2052 { 2053 2054 printf ("\n %s [%u] = ", entry_name, (unsigned) j); 2055 2056 } 2057 2058 switch (tagType) 2059 { 2060 2061 case ttByte: 2062 case ttShort: 2063 case ttLong: 2064 case ttIFD: 2065 { 2066 2067 uint32 x = stream.TagValue_uint32 (tagType); 2068 2069 printf ("%u", (unsigned) x); 2070 2071 break; 2072 2073 } 2074 2075 case ttSByte: 2076 case ttSShort: 2077 case ttSLong: 2078 { 2079 2080 int32 x = stream.TagValue_int32 (tagType); 2081 2082 printf ("%d", (int) x); 2083 2084 break; 2085 2086 } 2087 2088 case ttRational: 2089 { 2090 2091 dng_urational x = stream.TagValue_urational (tagType); 2092 2093 printf ("%u/%u", (unsigned) x.n, (unsigned) x.d); 2094 2095 break; 2096 2097 } 2098 2099 case ttSRational: 2100 { 2101 2102 dng_srational x = stream.TagValue_srational (tagType); 2103 2104 printf ("%d/%d", (int) x.n, (int) x.d); 2105 2106 break; 2107 2108 } 2109 2110 default: 2111 { 2112 2113 real64 x = stream.TagValue_real64 (tagType); 2114 2115 printf ("%f", x); 2116 2117 } 2118 2119 } 2120 2121 } 2122 2123 printf ("\n"); 2124 2125 if (tagCount > kMaxDumpArray) 2126 { 2127 2128 printf (" ... %u more entries\n", (unsigned) (tagCount - kMaxDumpArray)); 2129 2130 } 2131 2132 break; 2133 2134 } 2135 2136 case ttAscii: 2137 { 2138 2139 dng_string s; 2140 2141 ParseStringTag (stream, 2142 parentCode, 2143 tagCode, 2144 tagCount, 2145 s, 2146 false); 2147 2148 printf (" "); 2149 2150 DumpString (s); 2151 2152 printf ("\n"); 2153 2154 break; 2155 2156 } 2157 2158 default: 2159 { 2160 2161 uint32 tagSize = tagCount * TagTypeSize (tagType); 2162 2163 if (tagCount == 1 && (tagType == ttByte || 2164 tagType == ttUndefined)) 2165 { 2166 2167 uint8 x = stream.Get_uint8 (); 2168 2169 printf (" %s = %u\n", LookupTagType (tagType), x); 2170 2171 } 2172 2173 else 2174 { 2175 2176 printf (" %s, size = %u\n", LookupTagType (tagType), (unsigned) tagSize); 2177 2178 DumpHexAscii (stream, tagSize); 2179 2180 } 2181 2182 } 2183 2184 } 2185 2186 } 2187 2188 /*****************************************************************************/ 2189 2190 void DumpMatrix (const dng_matrix &m) 2191 { 2192 2193 for (uint32 row = 0; row < m.Rows (); row++) 2194 { 2195 2196 for (uint32 col = 0; col < m.Cols (); col++) 2197 { 2198 2199 if (col == 0) 2200 printf (" "); 2201 else 2202 printf (" "); 2203 2204 printf ("%8.4f", m [row] [col]); 2205 2206 } 2207 2208 printf ("\n"); 2209 2210 } 2211 2212 } 2213 2214 /*****************************************************************************/ 2215 2216 void DumpVector (const dng_vector &v) 2217 { 2218 2219 for (uint32 index = 0; index < v.Count (); index++) 2220 { 2221 2222 printf (" %0.4f", v [index]); 2223 2224 } 2225 2226 printf ("\n"); 2227 2228 } 2229 2230 /*****************************************************************************/ 2231 2232 void DumpDateTime (const dng_date_time &dt) 2233 { 2234 2235 printf ("%04d:%02d:%02d %02d:%02d:%02d", 2236 (int) dt.fYear, 2237 (int) dt.fMonth, 2238 (int) dt.fDay, 2239 (int) dt.fHour, 2240 (int) dt.fMinute, 2241 (int) dt.fSecond); 2242 2243 } 2244 2245 /*****************************************************************************/ 2246 2247 void DumpExposureTime (real64 x) 2248 { 2249 2250 if (x > 0.0) 2251 { 2252 2253 if (x >= 0.25) 2254 { 2255 printf ("%0.2f sec", x); 2256 } 2257 2258 else if (x >= 0.01) 2259 { 2260 printf ("1/%0.1f sec", 1.0 / x); 2261 } 2262 2263 else 2264 { 2265 printf ("1/%0.0f sec", 1.0 / x); 2266 } 2267 2268 } 2269 2270 else 2271 { 2272 2273 printf ("<invalid>"); 2274 2275 } 2276 2277 } 2278 2279 /*****************************************************************************/ 2280 2281 void DumpFingerprint (const dng_fingerprint &p) 2282 { 2283 2284 printf ("<"); 2285 2286 for (uint32 j = 0; j < 16; j++) 2287 { 2288 printf ("%02x", p.data [j]); 2289 } 2290 2291 printf (">"); 2292 2293 } 2294 2295 /*****************************************************************************/ 2296 2297 void DumpHueSatMap (dng_stream &stream, 2298 uint32 hues, 2299 uint32 sats, 2300 uint32 vals, 2301 bool skipSat0) 2302 { 2303 2304 uint32 doneLines = 0; 2305 uint32 skipLines = 0; 2306 2307 for (uint32 v = 0; v < vals; v++) 2308 { 2309 2310 for (uint32 h = 0; h < hues; h++) 2311 { 2312 2313 for (uint32 s = skipSat0 ? 1 : 0; s < sats; s++) 2314 { 2315 2316 real32 dh = stream.Get_real32 (); 2317 real32 ds = stream.Get_real32 (); 2318 real32 dv = stream.Get_real32 (); 2319 2320 if (gDumpLineLimit == 0 || 2321 gDumpLineLimit > doneLines) 2322 { 2323 2324 doneLines++; 2325 2326 if (vals == 1) 2327 { 2328 2329 printf (" h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n", 2330 (unsigned) h, 2331 (unsigned) s, 2332 (double) dh, 2333 (double) ds, 2334 (double) dv); 2335 2336 } 2337 2338 else 2339 { 2340 2341 printf (" v [%2u] h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n", 2342 (unsigned) v, 2343 (unsigned) h, 2344 (unsigned) s, 2345 (double) dh, 2346 (double) ds, 2347 (double) dv); 2348 2349 } 2350 2351 } 2352 2353 else 2354 { 2355 2356 skipLines++; 2357 2358 } 2359 2360 } 2361 2362 } 2363 2364 } 2365 2366 if (skipLines > 0) 2367 { 2368 2369 printf (" ... %u more entries\n", (unsigned) skipLines); 2370 2371 } 2372 2373 } 2374 2375 /*****************************************************************************/ 2376 2377 #endif 2378 2379 /*****************************************************************************/ 2380 2381 bool CheckTagType (uint32 parentCode, 2382 uint32 tagCode, 2383 uint32 tagType, 2384 uint16 validType0, 2385 uint16 validType1, 2386 uint16 validType2, 2387 uint16 validType3) 2388 { 2389 2390 if (tagType != validType0 && 2391 tagType != validType1 && 2392 tagType != validType2 && 2393 tagType != validType3) 2394 { 2395 2396 #if qDNGValidate 2397 2398 { 2399 2400 char message [256]; 2401 2402 sprintf (message, 2403 "%s %s has unexpected type (%s)", 2404 LookupParentCode (parentCode), 2405 LookupTagCode (parentCode, tagCode), 2406 LookupTagType (tagType)); 2407 2408 ReportWarning (message); 2409 2410 } 2411 2412 #else 2413 2414 (void) parentCode; // Unused 2415 (void) tagCode; // Unused 2416 2417 #endif 2418 2419 return false; 2420 2421 } 2422 2423 return true; 2424 2425 } 2426 2427 /*****************************************************************************/ 2428 2429 bool CheckTagCount (uint32 parentCode, 2430 uint32 tagCode, 2431 uint32 tagCount, 2432 uint32 minCount, 2433 uint32 maxCount) 2434 { 2435 2436 if (maxCount < minCount) 2437 maxCount = minCount; 2438 2439 if (tagCount < minCount || 2440 tagCount > maxCount) 2441 { 2442 2443 #if qDNGValidate 2444 2445 { 2446 2447 char message [256]; 2448 2449 sprintf (message, 2450 "%s %s has unexpected count (%u)", 2451 LookupParentCode (parentCode), 2452 LookupTagCode (parentCode, tagCode), 2453 (unsigned) tagCount); 2454 2455 ReportWarning (message); 2456 2457 } 2458 2459 #else 2460 2461 (void) parentCode; // Unused 2462 (void) tagCode; // Unused 2463 2464 #endif 2465 2466 return false; 2467 2468 } 2469 2470 return true; 2471 2472 } 2473 2474 /*****************************************************************************/ 2475 2476 bool CheckColorImage (uint32 parentCode, 2477 uint32 tagCode, 2478 uint32 colorPlanes) 2479 { 2480 2481 if (colorPlanes == 0) 2482 { 2483 2484 #if qDNGValidate 2485 2486 { 2487 2488 char message [256]; 2489 2490 sprintf (message, 2491 "%s %s is not allowed with unknown color plane count " 2492 " (missing ColorMatrix1 tag?)", 2493 LookupParentCode (parentCode), 2494 LookupTagCode (parentCode, tagCode)); 2495 2496 ReportWarning (message); 2497 2498 } 2499 2500 #else 2501 2502 (void) parentCode; // Unused 2503 (void) tagCode; // Unused 2504 2505 #endif 2506 2507 return false; 2508 2509 } 2510 2511 if (colorPlanes == 1) 2512 { 2513 2514 #if qDNGValidate 2515 2516 { 2517 2518 char message [256]; 2519 2520 sprintf (message, 2521 "%s %s is not allowed with monochrome images", 2522 LookupParentCode (parentCode), 2523 LookupTagCode (parentCode, tagCode)); 2524 2525 ReportWarning (message); 2526 2527 } 2528 2529 #endif 2530 2531 return false; 2532 2533 } 2534 2535 return true; 2536 2537 } 2538 2539 /*****************************************************************************/ 2540 2541 bool CheckMainIFD (uint32 parentCode, 2542 uint32 tagCode, 2543 uint32 newSubFileType) 2544 { 2545 2546 if (newSubFileType != sfMainImage) 2547 { 2548 2549 #if qDNGValidate 2550 2551 { 2552 2553 char message [256]; 2554 2555 sprintf (message, 2556 "%s %s is not allowed IFDs with NewSubFileType != 0", 2557 LookupParentCode (parentCode), 2558 LookupTagCode (parentCode, tagCode)); 2559 2560 ReportWarning (message); 2561 2562 } 2563 2564 #else 2565 2566 (void) parentCode; // Unused 2567 (void) tagCode; // Unused 2568 2569 #endif 2570 2571 return false; 2572 2573 } 2574 2575 return true; 2576 2577 } 2578 2579 /*****************************************************************************/ 2580 2581 bool CheckRawIFD (uint32 parentCode, 2582 uint32 tagCode, 2583 uint32 photometricInterpretation) 2584 { 2585 2586 if (photometricInterpretation != piCFA && 2587 photometricInterpretation != piLinearRaw) 2588 { 2589 2590 #if qDNGValidate 2591 2592 { 2593 2594 char message [256]; 2595 2596 sprintf (message, 2597 "%s %s is not allowed in IFDs with a non-raw PhotometricInterpretation", 2598 LookupParentCode (parentCode), 2599 LookupTagCode (parentCode, tagCode)); 2600 2601 ReportWarning (message); 2602 2603 } 2604 2605 #else 2606 2607 (void) parentCode; // Unused 2608 (void) tagCode; // Unused 2609 2610 #endif 2611 2612 return false; 2613 2614 } 2615 2616 return true; 2617 2618 } 2619 2620 /*****************************************************************************/ 2621 2622 bool CheckCFA (uint32 parentCode, 2623 uint32 tagCode, 2624 uint32 photometricInterpretation) 2625 { 2626 2627 if (photometricInterpretation != piCFA) 2628 { 2629 2630 #if qDNGValidate 2631 2632 { 2633 2634 char message [256]; 2635 2636 sprintf (message, 2637 "%s %s is not allowed in IFDs with a non-CFA PhotometricInterpretation", 2638 LookupParentCode (parentCode), 2639 LookupTagCode (parentCode, tagCode)); 2640 2641 ReportWarning (message); 2642 2643 } 2644 2645 #else 2646 2647 (void) parentCode; // Unused 2648 (void) tagCode; // Unused 2649 2650 #endif 2651 2652 return false; 2653 2654 } 2655 2656 return true; 2657 2658 } 2659 2660 /*****************************************************************************/ 2661 2662 void ParseStringTag (dng_stream &stream, 2663 uint32 parentCode, 2664 uint32 tagCode, 2665 uint32 tagCount, 2666 dng_string &s, 2667 bool trimBlanks) 2668 { 2669 2670 if (tagCount == 0 || 2671 tagCount == 0xFFFFFFFF) 2672 { 2673 2674 s.Clear (); 2675 2676 return; 2677 2678 } 2679 2680 dng_memory_data temp_buffer (tagCount + 1); 2681 2682 char *buffer = temp_buffer.Buffer_char (); 2683 2684 stream.Get (buffer, tagCount); 2685 2686 // Make sure the string is null terminated. 2687 2688 if (buffer [tagCount - 1] != 0) 2689 { 2690 2691 buffer [tagCount] = 0; 2692 2693 #if qDNGValidate 2694 2695 { 2696 2697 bool hasNull = false; 2698 2699 for (uint32 j = 0; j < tagCount; j++) 2700 { 2701 2702 if (buffer [j] == 0) 2703 { 2704 2705 hasNull = true; 2706 2707 break; 2708 2709 } 2710 2711 } 2712 2713 if (!hasNull && parentCode < tcFirstMakerNoteIFD) 2714 { 2715 2716 char message [256]; 2717 2718 sprintf (message, 2719 "%s %s is not NULL terminated", 2720 LookupParentCode (parentCode), 2721 LookupTagCode (parentCode, tagCode)); 2722 2723 ReportWarning (message); 2724 2725 } 2726 2727 } 2728 2729 #else 2730 2731 (void) parentCode; // Unused 2732 (void) tagCode; // Unused 2733 2734 #endif 2735 2736 } 2737 2738 // Medata working group - Allow UTF-8 2739 2740 s.Set_UTF8_or_System (buffer); 2741 2742 if (trimBlanks) 2743 { 2744 2745 s.TrimTrailingBlanks (); 2746 2747 } 2748 2749 } 2750 2751 /*****************************************************************************/ 2752 2753 void ParseDualStringTag (dng_stream &stream, 2754 uint32 parentCode, 2755 uint32 tagCode, 2756 uint32 tagCount, 2757 dng_string &s1, 2758 dng_string &s2) 2759 { 2760 2761 if (tagCount == 0 || 2762 tagCount == 0xFFFFFFFF) 2763 { 2764 2765 s1.Clear (); 2766 s2.Clear (); 2767 2768 return; 2769 2770 } 2771 2772 dng_memory_data temp_buffer (tagCount + 1); 2773 2774 char *buffer = temp_buffer.Buffer_char (); 2775 2776 stream.Get (buffer, tagCount); 2777 2778 // Make sure the string is null terminated. 2779 2780 if (buffer [tagCount - 1] != 0) 2781 { 2782 2783 buffer [tagCount] = 0; 2784 2785 #if qDNGValidate 2786 2787 { 2788 2789 uint32 nullCount = 0; 2790 2791 for (uint32 j = 0; j < tagCount; j++) 2792 { 2793 2794 if (buffer [j] == 0) 2795 { 2796 2797 nullCount++; 2798 2799 } 2800 2801 } 2802 2803 if (nullCount < 2 && parentCode < tcFirstMakerNoteIFD) 2804 { 2805 2806 char message [256]; 2807 2808 sprintf (message, 2809 "%s %s is not NULL terminated", 2810 LookupParentCode (parentCode), 2811 LookupTagCode (parentCode, tagCode)); 2812 2813 ReportWarning (message); 2814 2815 } 2816 2817 } 2818 2819 #else 2820 2821 (void) parentCode; // Unused 2822 (void) tagCode; // Unused 2823 2824 #endif 2825 2826 } 2827 2828 // Medata working group - Allow UTF-8 2829 2830 s1.Set_UTF8_or_System (buffer); 2831 2832 s2.Set_ASCII (NULL); 2833 2834 for (uint32 j = 1; j < tagCount - 1; j++) 2835 { 2836 2837 if (buffer [j - 1] != 0 && 2838 buffer [j ] == 0) 2839 { 2840 2841 // Medata working group - Allow UTF-8 2842 2843 s2.Set_UTF8_or_System (buffer + j + 1); 2844 2845 break; 2846 2847 } 2848 2849 } 2850 2851 s1.TrimTrailingBlanks (); 2852 s2.TrimTrailingBlanks (); 2853 2854 } 2855 2856 /*****************************************************************************/ 2857 2858 void ParseEncodedStringTag (dng_stream &stream, 2859 uint32 parentCode, 2860 uint32 tagCode, 2861 uint32 tagCount, 2862 dng_string &s) 2863 { 2864 2865 if (tagCount < 8) 2866 { 2867 2868 #if qDNGValidate 2869 2870 { 2871 2872 char message [256]; 2873 2874 sprintf (message, 2875 "%s %s has unexpected count (%u)", 2876 LookupParentCode (parentCode), 2877 LookupTagCode (parentCode, tagCode), 2878 (unsigned) tagCount); 2879 2880 ReportWarning (message); 2881 2882 } 2883 2884 #else 2885 2886 (void) parentCode; // Unused 2887 (void) tagCode; // Unused 2888 2889 #endif 2890 2891 s.Clear (); 2892 2893 return; 2894 2895 } 2896 2897 char label [8]; 2898 2899 stream.Get (label, 8); 2900 2901 // Sometimes lowercase is used by mistake. Accept this, but issue 2902 // warning. 2903 2904 { 2905 2906 bool hadLower = false; 2907 2908 for (uint32 j = 0; j < 8; j++) 2909 { 2910 2911 if (label [j] >= 'a' && label [j] <= 'z') 2912 { 2913 2914 label [j] = 'A' + (label [j] - 'a'); 2915 2916 hadLower = true; 2917 2918 } 2919 2920 } 2921 2922 #if qDNGValidate 2923 2924 if (hadLower) 2925 { 2926 2927 char message [256]; 2928 2929 sprintf (message, 2930 "%s %s text encoding label not all uppercase", 2931 LookupParentCode (parentCode), 2932 LookupTagCode (parentCode, tagCode)); 2933 2934 ReportWarning (message); 2935 2936 } 2937 2938 #endif 2939 2940 } 2941 2942 if (memcmp (label, "UNICODE\000", 8) == 0) 2943 { 2944 2945 uint32 uChars = (tagCount - 8) >> 1; 2946 2947 dng_memory_data temp_buffer ((uChars + 1) * 2); 2948 2949 uint16 *buffer = temp_buffer.Buffer_uint16 (); 2950 2951 for (uint32 j = 0; j < uChars; j++) 2952 { 2953 2954 buffer [j] = stream.Get_uint16 (); 2955 2956 } 2957 2958 buffer [uChars] = 0; 2959 2960 #if qDNGValidate 2961 2962 { 2963 2964 // If the writer used UTF-8 rather than UTF-16, and padded 2965 // the string with blanks, then there will be lots of 0x2020 2966 // (unicode dagger symbol) characters in the string. 2967 2968 uint32 count2020 = 0; 2969 2970 for (uint32 k = 0; buffer [k] != 0; k++) 2971 { 2972 2973 if (buffer [k] == 0x2020) 2974 { 2975 2976 count2020++; 2977 2978 } 2979 2980 } 2981 2982 if (count2020 > 1) 2983 { 2984 2985 char message [256]; 2986 2987 sprintf (message, 2988 "%s %s text appears to be UTF-8 rather than UTF-16", 2989 LookupParentCode (parentCode), 2990 LookupTagCode (parentCode, tagCode)); 2991 2992 ReportWarning (message); 2993 2994 } 2995 2996 } 2997 2998 #endif 2999 3000 s.Set_UTF16 (buffer); 3001 3002 } 3003 3004 else 3005 { 3006 3007 uint32 aChars = tagCount - 8; 3008 3009 dng_memory_data temp_buffer (aChars + 1); 3010 3011 char *buffer = temp_buffer.Buffer_char (); 3012 3013 stream.Get (buffer, aChars); 3014 3015 buffer [aChars] = 0; 3016 3017 enum dng_encoding 3018 { 3019 dng_encoding_ascii, 3020 dng_encoding_jis_x208_1990, 3021 dng_encoding_unknown 3022 }; 3023 3024 dng_encoding encoding = dng_encoding_unknown; 3025 3026 if (memcmp (label, "ASCII\000\000\000", 8) == 0) 3027 { 3028 3029 encoding = dng_encoding_ascii; 3030 3031 } 3032 3033 else if (memcmp (label, "JIS\000\000\000\000\000\000", 8) == 0) 3034 { 3035 3036 encoding = dng_encoding_jis_x208_1990; 3037 3038 } 3039 3040 else 3041 { 3042 3043 // Some Nikon D1 files have UserComment tags with zero encoding bits and 3044 // garbage text values. So don't try to parse tags with unknown text 3045 // encoding unless all the characters are printing ASCII. 3046 3047 #if qDNGValidate 3048 3049 if (memcmp (label, "\000\000\000\000\000\000\000\000\000", 8) == 0) 3050 { 3051 3052 // Many camera makes store null tags with all zero encoding, so 3053 // don't report a warning message for null strings. 3054 3055 if (buffer [0] != 0) 3056 { 3057 3058 char message [256]; 3059 3060 sprintf (message, 3061 "%s %s has unknown encoding", 3062 LookupParentCode (parentCode), 3063 LookupTagCode (parentCode, tagCode)); 3064 3065 ReportWarning (message); 3066 3067 } 3068 3069 } 3070 3071 else 3072 { 3073 3074 char message [256]; 3075 3076 sprintf (message, 3077 "%s %s has unexpected text encoding", 3078 LookupParentCode (parentCode), 3079 LookupTagCode (parentCode, tagCode)); 3080 3081 ReportWarning (message); 3082 3083 } 3084 3085 #endif 3086 3087 } 3088 3089 // If text encoding was unknown, and the text is anything 3090 // other than pure ASCII, then ignore it. 3091 3092 if (encoding == dng_encoding_unknown) 3093 { 3094 3095 encoding = dng_encoding_ascii; 3096 3097 for (uint32 i = 0; i < aChars && buffer [i] != 0; i++) 3098 { 3099 3100 if (buffer [i] < ' ' || 3101 buffer [i] > '~') 3102 { 3103 3104 buffer [0] = 0; 3105 3106 break; 3107 3108 } 3109 3110 } 3111 3112 } 3113 3114 switch (encoding) 3115 { 3116 3117 case dng_encoding_ascii: 3118 { 3119 3120 // Medata working group - allow UTF-8 for ASCII tags. 3121 3122 s.Set_UTF8_or_System (buffer); 3123 3124 break; 3125 3126 } 3127 3128 case dng_encoding_jis_x208_1990: 3129 { 3130 s.Set_JIS_X208_1990 (buffer); 3131 break; 3132 } 3133 3134 case dng_encoding_unknown: 3135 { 3136 s.Set_SystemEncoding (buffer); 3137 break; 3138 } 3139 3140 default: 3141 break; 3142 3143 } 3144 3145 #if qDNGValidate 3146 3147 { 3148 3149 if (encoding == dng_encoding_ascii && !s.IsASCII ()) 3150 { 3151 3152 char message [256]; 3153 3154 sprintf (message, 3155 "%s %s has non-ASCII characters", 3156 LookupParentCode (parentCode), 3157 LookupTagCode (parentCode, tagCode)); 3158 3159 ReportWarning (message); 3160 3161 } 3162 3163 } 3164 3165 #endif 3166 3167 } 3168 3169 s.TrimTrailingBlanks (); 3170 3171 } 3172 3173 /*****************************************************************************/ 3174 3175 bool ParseMatrixTag (dng_stream &stream, 3176 uint32 parentCode, 3177 uint32 tagCode, 3178 uint32 tagType, 3179 uint32 tagCount, 3180 uint32 rows, 3181 uint32 cols, 3182 dng_matrix &m) 3183 { 3184 3185 if (CheckTagCount (parentCode, tagCode, tagCount, rows * cols)) 3186 { 3187 3188 dng_matrix temp (rows, cols); 3189 3190 for (uint32 row = 0; row < rows; row++) 3191 for (uint32 col = 0; col < cols; col++) 3192 { 3193 3194 temp [row] [col] = stream.TagValue_real64 (tagType); 3195 3196 } 3197 3198 m = temp; 3199 3200 return true; 3201 3202 } 3203 3204 return false; 3205 3206 } 3207 3208 /*****************************************************************************/ 3209 3210 bool ParseVectorTag (dng_stream &stream, 3211 uint32 parentCode, 3212 uint32 tagCode, 3213 uint32 tagType, 3214 uint32 tagCount, 3215 uint32 count, 3216 dng_vector &v) 3217 { 3218 3219 if (CheckTagCount (parentCode, tagCode, tagCount, count)) 3220 { 3221 3222 dng_vector temp (count); 3223 3224 for (uint32 index = 0; index < count; index++) 3225 { 3226 3227 temp [index] = stream.TagValue_real64 (tagType); 3228 3229 } 3230 3231 v = temp; 3232 3233 return true; 3234 3235 } 3236 3237 return false; 3238 3239 } 3240 3241 /*****************************************************************************/ 3242 3243 bool ParseDateTimeTag (dng_stream &stream, 3244 uint32 parentCode, 3245 uint32 tagCode, 3246 uint32 tagType, 3247 uint32 tagCount, 3248 dng_date_time &dt) 3249 { 3250 3251 if (!CheckTagType (parentCode, tagCode, tagType, ttAscii)) 3252 { 3253 return false; 3254 } 3255 3256 // Kludge: Some versions of PaintShop Pro write these fields 3257 // with a length of 21 rather than 20. Otherwise they are 3258 // correctly formated. So relax this test and allow these 3259 // these longer than standard tags to be parsed. 3260 3261 (void) CheckTagCount (parentCode, tagCode, tagCount, 20); 3262 3263 if (tagCount < 20) 3264 { 3265 return false; 3266 } 3267 3268 char s [21]; 3269 3270 stream.Get (s, 20); 3271 3272 s [20] = 0; 3273 3274 // See if this is a valid date/time string. 3275 3276 if (dt.Parse (s)) 3277 { 3278 return true; 3279 } 3280 3281 // Accept strings that contain only blanks, colons, and zeros as 3282 // valid "null" dates. 3283 3284 dt = dng_date_time (); 3285 3286 for (uint32 index = 0; index < 21; index++) 3287 { 3288 3289 char c = s [index]; 3290 3291 if (c == 0) 3292 { 3293 return true; 3294 } 3295 3296 if (c != ' ' && c != ':' && c != '0') 3297 { 3298 3299 #if qDNGValidate 3300 3301 { 3302 3303 char message [256]; 3304 3305 sprintf (message, 3306 "%s %s is not a valid date/time", 3307 LookupParentCode (parentCode), 3308 LookupTagCode (parentCode, tagCode)); 3309 3310 ReportWarning (message); 3311 3312 } 3313 3314 #endif 3315 3316 return false; 3317 3318 } 3319 3320 } 3321 3322 return false; 3323 3324 } 3325 3326 /*****************************************************************************/ 3327