summaryrefslogtreecommitdiff
path: root/gpr/source/lib/dng_sdk/dng_parse_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gpr/source/lib/dng_sdk/dng_parse_utils.cpp')
-rw-r--r--gpr/source/lib/dng_sdk/dng_parse_utils.cpp3326
1 files changed, 3326 insertions, 0 deletions
diff --git a/gpr/source/lib/dng_sdk/dng_parse_utils.cpp b/gpr/source/lib/dng_sdk/dng_parse_utils.cpp
new file mode 100644
index 0000000..879efbc
--- /dev/null
+++ b/gpr/source/lib/dng_sdk/dng_parse_utils.cpp
@@ -0,0 +1,3326 @@
+/*****************************************************************************/
+// Copyright 2006-2008 Adobe Systems Incorporated
+// All Rights Reserved.
+//
+// NOTICE: Adobe permits you to use, modify, and distribute this file in
+// accordance with the terms of the Adobe license agreement accompanying it.
+/*****************************************************************************/
+
+/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_parse_utils.cpp#3 $ */
+/* $DateTime: 2012/06/06 12:08:58 $ */
+/* $Change: 833617 $ */
+/* $Author: tknoll $ */
+
+/*****************************************************************************/
+
+#include "dng_parse_utils.h"
+
+#include "dng_date_time.h"
+#include "dng_globals.h"
+#include "dng_ifd.h"
+#include "dng_tag_codes.h"
+#include "dng_tag_types.h"
+#include "dng_tag_values.h"
+#include "dng_types.h"
+#include "dng_stream.h"
+#include "dng_exceptions.h"
+#include "dng_utils.h"
+
+/*****************************************************************************/
+
+#if qDNGValidate
+
+/*****************************************************************************/
+
+struct dng_name_table
+ {
+ uint32 key;
+ const char *name;
+ };
+
+/*****************************************************************************/
+
+static const char * LookupName (uint32 key,
+ const dng_name_table *table,
+ uint32 table_entries)
+ {
+
+ for (uint32 index = 0; index < table_entries; index++)
+ {
+
+ if (key == table [index] . key)
+ {
+
+ return table [index] . name;
+
+ }
+
+ }
+
+ return NULL;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupParentCode (uint32 parentCode)
+ {
+
+ const dng_name_table kParentCodeNames [] =
+ {
+ { 0, "IFD 0" },
+ { tcExifIFD, "Exif IFD" },
+ { tcGPSInfo, "GPS IFD" },
+ { tcInteroperabilityIFD, "Interoperability IFD" },
+ { tcKodakDCRPrivateIFD, "Kodak DCR Private IFD" },
+ { tcKodakKDCPrivateIFD, "Kodak KDC Private IFD" },
+ { tcCanonMakerNote, "Canon MakerNote" },
+ { tcEpsonMakerNote, "Epson MakerNote" },
+ { tcFujiMakerNote, "Fuji MakerNote" },
+ { tcHasselbladMakerNote, "Hasselblad MakerNote" },
+ { tcKodakMakerNote, "Kodak MakerNote" },
+ { tcKodakMakerNote65280, "Kodak MakerNote 65280" },
+ { tcLeicaMakerNote, "Leica MakerNote" },
+ { tcMamiyaMakerNote, "Mamiya MakerNote" },
+ { tcMinoltaMakerNote, "Minolta MakerNote" },
+ { tcNikonMakerNote, "Nikon MakerNote" },
+ { tcOlympusMakerNote, "Olympus MakerNote" },
+ { tcOlympusMakerNote8208, "Olympus MakerNote 8208" },
+ { tcOlympusMakerNote8224, "Olympus MakerNote 8224" },
+ { tcOlympusMakerNote8240, "Olympus MakerNote 8240" },
+ { tcOlympusMakerNote8256, "Olympus MakerNote 8256" },
+ { tcOlympusMakerNote8272, "Olympus MakerNote 8272" },
+ { tcOlympusMakerNote12288, "Olympus MakerNote 12288" },
+ { tcPanasonicMakerNote, "Panasonic MakerNote" },
+ { tcPentaxMakerNote, "Pentax MakerNote" },
+ { tcPhaseOneMakerNote, "Phase One MakerNote" },
+ { tcRicohMakerNote, "Ricoh MakerNote" },
+ { tcRicohMakerNoteCameraInfo, "Ricoh MakerNote Camera Info" },
+ { tcSonyMakerNote, "Sony MakerNote" },
+ { tcSonyMakerNoteSubInfo, "Sony MakerNote SubInfo" },
+ { tcSonyPrivateIFD1, "Sony Private IFD 1" },
+ { tcSonyPrivateIFD2, "Sony Private IFD 2" },
+ { tcSonyPrivateIFD3A, "Sony Private IFD 3A" },
+ { tcSonyPrivateIFD3B, "Sony Private IFD 3B" },
+ { tcSonyPrivateIFD3C, "Sony Private IFD 3C" },
+ { tcCanonCRW, "Canon CRW" },
+ { tcContaxRAW, "Contax RAW" },
+ { tcFujiRAF, "Fuji RAF" },
+ { tcLeafMOS, "Leaf MOS" },
+ { tcMinoltaMRW, "Minolta MRW" },
+ { tcPanasonicRAW, "Panasonic RAW" },
+ { tcFoveonX3F, "Foveon X3F" },
+ { tcJPEG, "JPEG" },
+ { tcAdobePSD, "Adobe PSD" }
+ };
+
+ const char *name = LookupName (parentCode,
+ kParentCodeNames,
+ sizeof (kParentCodeNames ) /
+ sizeof (kParentCodeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ if (parentCode >= tcFirstSubIFD &&
+ parentCode <= tcLastSubIFD)
+ {
+
+ sprintf (s, "SubIFD %u", (unsigned) (parentCode - tcFirstSubIFD + 1));
+
+ }
+
+ else if (parentCode >= tcFirstChainedIFD &&
+ parentCode <= tcLastChainedIFD)
+ {
+
+ sprintf (s, "Chained IFD %u", (unsigned) (parentCode - tcFirstChainedIFD + 1));
+
+ }
+
+ else
+ {
+
+ sprintf (s, "ParentIFD %u", (unsigned) parentCode);
+
+ }
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupTagCode (uint32 parentCode,
+ uint32 tagCode)
+ {
+
+ const dng_name_table kTagNames [] =
+ {
+ { tcNewSubFileType, "NewSubFileType" },
+ { tcSubFileType, "SubFileType" },
+ { tcImageWidth, "ImageWidth" },
+ { tcImageLength, "ImageLength" },
+ { tcBitsPerSample, "BitsPerSample" },
+ { tcCompression, "Compression" },
+ { tcPhotometricInterpretation, "PhotometricInterpretation" },
+ { tcThresholding, "Thresholding" },
+ { tcCellWidth, "CellWidth" },
+ { tcCellLength, "CellLength" },
+ { tcFillOrder, "FillOrder" },
+ { tcImageDescription, "ImageDescription" },
+ { tcMake, "Make" },
+ { tcModel, "Model" },
+ { tcStripOffsets, "StripOffsets" },
+ { tcOrientation, "Orientation" },
+ { tcSamplesPerPixel, "SamplesPerPixel" },
+ { tcRowsPerStrip, "RowsPerStrip" },
+ { tcStripByteCounts, "StripByteCounts" },
+ { tcMinSampleValue, "MinSampleValue" },
+ { tcMaxSampleValue, "MaxSampleValue" },
+ { tcXResolution, "XResolution" },
+ { tcYResolution, "YResolution" },
+ { tcPlanarConfiguration, "PlanarConfiguration" },
+ { tcFreeOffsets, "FreeOffsets" },
+ { tcFreeByteCounts, "FreeByteCounts" },
+ { tcGrayResponseUnit, "GrayResponseUnit" },
+ { tcGrayResponseCurve, "GrayResponseCurve" },
+ { tcResolutionUnit, "ResolutionUnit" },
+ { tcTransferFunction, "TransferFunction" },
+ { tcSoftware, "Software" },
+ { tcDateTime, "DateTime" },
+ { tcArtist, "Artist" },
+ { tcHostComputer, "HostComputer" },
+ { tcWhitePoint, "WhitePoint" },
+ { tcPrimaryChromaticities, "PrimaryChromaticities" },
+ { tcColorMap, "ColorMap" },
+ { tcTileWidth, "TileWidth" },
+ { tcTileLength, "TileLength" },
+ { tcTileOffsets, "TileOffsets" },
+ { tcTileByteCounts, "TileByteCounts" },
+ { tcSubIFDs, "SubIFDs" },
+ { tcExtraSamples, "ExtraSamples" },
+ { tcSampleFormat, "SampleFormat" },
+ { tcJPEGTables, "JPEGTables" },
+ { tcJPEGProc, "JPEGProc" },
+ { tcJPEGInterchangeFormat, "JPEGInterchangeFormat" },
+ { tcJPEGInterchangeFormatLength, "JPEGInterchangeFormatLength" },
+ { tcYCbCrCoefficients, "YCbCrCoefficients" },
+ { tcYCbCrSubSampling, "YCbCrSubSampling" },
+ { tcYCbCrPositioning, "YCbCrPositioning" },
+ { tcReferenceBlackWhite, "ReferenceBlackWhite" },
+ { tcXMP, "XMP" },
+ { tcKodakCameraSerialNumber, "KodakCameraSerialNumber" },
+ { tcCFARepeatPatternDim, "CFARepeatPatternDim" },
+ { tcCFAPattern, "CFAPattern" },
+ { tcBatteryLevel, "BatteryLevel" },
+ { tcKodakDCRPrivateIFD, "KodakDCRPrivateIFD" },
+ { tcCopyright, "Copyright" },
+ { tcExposureTime, "ExposureTime" },
+ { tcFNumber, "FNumber" },
+ { tcIPTC_NAA, "IPTC/NAA" },
+ { tcLeafPKTS, "LeafPKTS" },
+ { tcAdobeData, "AdobeData" },
+ { tcExifIFD, "ExifIFD" },
+ { tcICCProfile, "ICCProfile" },
+ { tcExposureProgram, "ExposureProgram" },
+ { tcSpectralSensitivity, "SpectralSensitivity" },
+ { tcGPSInfo, "GPSInfo" },
+ { tcISOSpeedRatings, "ISOSpeedRatings" },
+ { tcOECF, "OECF" },
+ { tcInterlace, "Interlace" },
+ { tcTimeZoneOffset, "TimeZoneOffset" },
+ { tcSelfTimerMode, "SelfTimerMode" },
+ { tcSensitivityType, "SensitivityType" },
+ { tcStandardOutputSensitivity, "StandardOutputSensitivity" },
+ { tcRecommendedExposureIndex, "RecommendedExposureIndex" },
+ { tcISOSpeed, "ISOSpeed" },
+ { tcISOSpeedLatitudeyyy, "ISOSpeedLatitudeyyy" },
+ { tcISOSpeedLatitudezzz, "ISOSpeedLatitudezzz" },
+ { tcExifVersion, "ExifVersion" },
+ { tcDateTimeOriginal, "DateTimeOriginal" },
+ { tcDateTimeDigitized, "DateTimeDigitized" },
+ { tcComponentsConfiguration, "ComponentsConfiguration" },
+ { tcCompressedBitsPerPixel, "CompressedBitsPerPixel" },
+ { tcShutterSpeedValue, "ShutterSpeedValue" },
+ { tcApertureValue, "ApertureValue" },
+ { tcBrightnessValue, "BrightnessValue" },
+ { tcExposureBiasValue, "ExposureBiasValue" },
+ { tcMaxApertureValue, "MaxApertureValue" },
+ { tcSubjectDistance, "SubjectDistance" },
+ { tcMeteringMode, "MeteringMode" },
+ { tcLightSource, "LightSource" },
+ { tcFlash, "Flash" },
+ { tcFocalLength, "FocalLength" },
+ { tcFlashEnergy, "FlashEnergy" },
+ { tcSpatialFrequencyResponse, "SpatialFrequencyResponse" },
+ { tcNoise, "Noise" },
+ { tcFocalPlaneXResolution, "FocalPlaneXResolution" },
+ { tcFocalPlaneYResolution, "FocalPlaneYResolution" },
+ { tcFocalPlaneResolutionUnit, "FocalPlaneResolutionUnit" },
+ { tcImageNumber, "ImageNumber" },
+ { tcSecurityClassification, "SecurityClassification" },
+ { tcImageHistory, "ImageHistory" },
+ { tcSubjectArea, "SubjectArea" },
+ { tcExposureIndex, "ExposureIndex" },
+ { tcTIFF_EP_StandardID, "TIFF/EPStandardID" },
+ { tcSensingMethod, "SensingMethod" },
+ { tcMakerNote, "MakerNote" },
+ { tcUserComment, "UserComment" },
+ { tcSubsecTime, "SubsecTime" },
+ { tcSubsecTimeOriginal, "SubsecTimeOriginal" },
+ { tcSubsecTimeDigitized, "SubsecTimeDigitized" },
+ { tcAdobeLayerData, "AdobeLayerData" },
+ { tcFlashPixVersion, "FlashPixVersion" },
+ { tcColorSpace, "ColorSpace" },
+ { tcPixelXDimension, "PixelXDimension" },
+ { tcPixelYDimension, "PixelYDimension" },
+ { tcRelatedSoundFile, "RelatedSoundFile" },
+ { tcInteroperabilityIFD, "InteroperabilityIFD" },
+ { tcFlashEnergyExif, "FlashEnergyExif" },
+ { tcSpatialFrequencyResponseExif, "SpatialFrequencyResponseExif" },
+ { tcFocalPlaneXResolutionExif, "FocalPlaneXResolutionExif" },
+ { tcFocalPlaneYResolutionExif, "FocalPlaneYResolutionExif" },
+ { tcFocalPlaneResolutionUnitExif, "FocalPlaneResolutionUnitExif" },
+ { tcSubjectLocation, "SubjectLocation" },
+ { tcExposureIndexExif, "ExposureIndexExif" },
+ { tcSensingMethodExif, "SensingMethodExif" },
+ { tcFileSource, "FileSource" },
+ { tcSceneType, "SceneType" },
+ { tcCFAPatternExif, "CFAPatternExif" },
+ { tcCustomRendered, "CustomRendered" },
+ { tcExposureMode, "ExposureMode" },
+ { tcWhiteBalance, "WhiteBalance" },
+ { tcDigitalZoomRatio, "DigitalZoomRatio" },
+ { tcFocalLengthIn35mmFilm, "FocalLengthIn35mmFilm" },
+ { tcSceneCaptureType, "SceneCaptureType" },
+ { tcGainControl, "GainControl" },
+ { tcContrast, "Contrast" },
+ { tcSaturation, "Saturation" },
+ { tcSharpness, "Sharpness" },
+ { tcDeviceSettingDescription, "DeviceSettingDescription" },
+ { tcSubjectDistanceRange, "SubjectDistanceRange" },
+ { tcImageUniqueID, "ImageUniqueID" },
+ { tcCameraOwnerNameExif, "CameraOwnerNameExif" },
+ { tcCameraSerialNumberExif, "CameraSerialNumberExif" },
+ { tcLensSpecificationExif, "LensSpecificationExif" },
+ { tcLensMakeExif, "LensMakeExif" },
+ { tcLensModelExif, "LensModelExif" },
+ { tcLensSerialNumberExif, "LensSerialNumberExif" },
+ { tcGamma, "Gamma" },
+ { tcPrintImageMatchingInfo, "PrintImageMatchingInfo" },
+ { tcDNGVersion, "DNGVersion" },
+ { tcDNGBackwardVersion, "DNGBackwardVersion" },
+ { tcUniqueCameraModel, "UniqueCameraModel" },
+ { tcLocalizedCameraModel, "LocalizedCameraModel" },
+ { tcCFAPlaneColor, "CFAPlaneColor" },
+ { tcCFALayout, "CFALayout" },
+ { tcLinearizationTable, "LinearizationTable" },
+ { tcBlackLevelRepeatDim, "BlackLevelRepeatDim" },
+ { tcBlackLevel, "BlackLevel" },
+ { tcBlackLevelDeltaH, "BlackLevelDeltaH" },
+ { tcBlackLevelDeltaV, "BlackLevelDeltaV" },
+ { tcWhiteLevel, "WhiteLevel" },
+ { tcDefaultScale, "DefaultScale" },
+ { tcDefaultCropOrigin, "DefaultCropOrigin" },
+ { tcDefaultCropSize, "DefaultCropSize" },
+ { tcDefaultUserCrop, "DefaultUserCrop" },
+ { tcColorMatrix1, "ColorMatrix1" },
+ { tcColorMatrix2, "ColorMatrix2" },
+ { tcCameraCalibration1, "CameraCalibration1" },
+ { tcCameraCalibration2, "CameraCalibration2" },
+ { tcReductionMatrix1, "ReductionMatrix1" },
+ { tcReductionMatrix2, "ReductionMatrix2" },
+ { tcAnalogBalance, "AnalogBalance" },
+ { tcAsShotNeutral, "AsShotNeutral" },
+ { tcAsShotWhiteXY, "AsShotWhiteXY" },
+ { tcBaselineExposure, "BaselineExposure" },
+ { tcBaselineNoise, "BaselineNoise" },
+ { tcBaselineSharpness, "BaselineSharpness" },
+ { tcBayerGreenSplit, "BayerGreenSplit" },
+ { tcLinearResponseLimit, "LinearResponseLimit" },
+ { tcCameraSerialNumber, "CameraSerialNumber" },
+ { tcLensInfo, "LensInfo" },
+ { tcChromaBlurRadius, "ChromaBlurRadius" },
+ { tcAntiAliasStrength, "AntiAliasStrength" },
+ { tcShadowScale, "ShadowScale" },
+ { tcDNGPrivateData, "DNGPrivateData" },
+ { tcMakerNoteSafety, "MakerNoteSafety" },
+ { tcCalibrationIlluminant1, "CalibrationIlluminant1" },
+ { tcCalibrationIlluminant2, "CalibrationIlluminant2" },
+ { tcBestQualityScale, "BestQualityScale" },
+ { tcRawDataUniqueID, "RawDataUniqueID" },
+ { tcOriginalRawFileName, "OriginalRawFileName" },
+ { tcOriginalRawFileData, "OriginalRawFileData" },
+ { tcActiveArea, "ActiveArea" },
+ { tcMaskedAreas, "MaskedAreas" },
+ { tcAsShotICCProfile, "AsShotICCProfile" },
+ { tcAsShotPreProfileMatrix, "AsShotPreProfileMatrix" },
+ { tcCurrentICCProfile, "CurrentICCProfile" },
+ { tcCurrentPreProfileMatrix, "CurrentPreProfileMatrix" },
+ { tcColorimetricReference, "ColorimetricReference" },
+ { tcCameraCalibrationSignature, "CameraCalibrationSignature" },
+ { tcProfileCalibrationSignature, "ProfileCalibrationSignature" },
+ { tcExtraCameraProfiles, "ExtraCameraProfiles" },
+ { tcAsShotProfileName, "AsShotProfileName" },
+ { tcNoiseReductionApplied, "NoiseReductionApplied" },
+ { tcProfileName, "ProfileName" },
+ { tcProfileHueSatMapDims, "ProfileHueSatMapDims" },
+ { tcProfileHueSatMapData1, "ProfileHueSatMapData1" },
+ { tcProfileHueSatMapData2, "ProfileHueSatMapData2" },
+ { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" },
+ { tcProfileToneCurve, "ProfileToneCurve" },
+ { tcProfileEmbedPolicy, "ProfileEmbedPolicy" },
+ { tcProfileCopyright, "ProfileCopyright" },
+ { tcForwardMatrix1, "ForwardMatrix1" },
+ { tcForwardMatrix2, "ForwardMatrix2" },
+ { tcPreviewApplicationName, "PreviewApplicationName" },
+ { tcPreviewApplicationVersion, "PreviewApplicationVersion" },
+ { tcPreviewSettingsName, "PreviewSettingsName" },
+ { tcPreviewSettingsDigest, "PreviewSettingsDigest" },
+ { tcPreviewColorSpace, "PreviewColorSpace" },
+ { tcPreviewDateTime, "PreviewDateTime" },
+ { tcRawImageDigest, "RawImageDigest" },
+ { tcOriginalRawFileDigest, "OriginalRawFileDigest" },
+ { tcSubTileBlockSize, "SubTileBlockSize" },
+ { tcRowInterleaveFactor, "RowInterleaveFactor" },
+ { tcProfileLookTableDims, "ProfileLookTableDims" },
+ { tcProfileLookTableData, "ProfileLookTableData" },
+ { tcProfileLookTableEncoding, "ProfileLookTableEncoding" },
+ { tcBaselineExposureOffset, "BaselineExposureOffset" },
+ { tcDefaultBlackRender, "DefaultBlackRender" },
+ { tcOpcodeList1, "OpcodeList1" },
+ { tcOpcodeList2, "OpcodeList2" },
+ { tcOpcodeList3, "OpcodeList3" },
+ { tcNoiseProfile, "NoiseProfile" },
+ { tcOriginalDefaultFinalSize, "OriginalDefaultFinalSize" },
+ { tcOriginalBestQualityFinalSize, "OriginalBestQualityFinalSize" },
+ { tcOriginalDefaultCropSize, "OriginalDefaultCropSize" },
+ { tcProfileHueSatMapEncoding, "ProfileHueSatMapEncoding" },
+ { tcProfileLookTableEncoding, "ProfileLookTableEncoding" },
+ { tcBaselineExposureOffset, "BaselineExposureOffset" },
+ { tcDefaultBlackRender, "DefaultBlackRender" },
+ { tcNewRawImageDigest, "NewRawImageDigest" },
+ { tcRawToPreviewGain, "RawToPreviewGain" },
+ { tcCacheBlob, "CacheBlob" },
+ { tcKodakKDCPrivateIFD, "KodakKDCPrivateIFD" }
+ };
+
+ const dng_name_table kGPSTagNames [] =
+ {
+ { tcGPSVersionID, "GPSVersionID" },
+ { tcGPSLatitudeRef, "GPSLatitudeRef" },
+ { tcGPSLatitude, "GPSLatitude" },
+ { tcGPSLongitudeRef, "GPSLongitudeRef" },
+ { tcGPSLongitude, "GPSLongitude" },
+ { tcGPSAltitudeRef, "GPSAltitudeRef" },
+ { tcGPSAltitude, "GPSAltitude" },
+ { tcGPSTimeStamp, "GPSTimeStamp" },
+ { tcGPSSatellites, "GPSSatellites" },
+ { tcGPSStatus, "GPSStatus" },
+ { tcGPSMeasureMode, "GPSMeasureMode" },
+ { tcGPSDOP, "GPSDOP" },
+ { tcGPSSpeedRef, "GPSSpeedRef" },
+ { tcGPSSpeed, "GPSSpeed" },
+ { tcGPSTrackRef, "GPSTrackRef" },
+ { tcGPSTrack, "GPSTrack" },
+ { tcGPSImgDirectionRef, "GPSImgDirectionRef" },
+ { tcGPSImgDirection, "GPSImgDirection" },
+ { tcGPSMapDatum, "GPSMapDatum" },
+ { tcGPSDestLatitudeRef, "GPSDestLatitudeRef" },
+ { tcGPSDestLatitude, "GPSDestLatitude" },
+ { tcGPSDestLongitudeRef, "GPSDestLongitudeRef" },
+ { tcGPSDestLongitude, "GPSDestLongitude" },
+ { tcGPSDestBearingRef, "GPSDestBearingRef" },
+ { tcGPSDestBearing, "GPSDestBearing" },
+ { tcGPSDestDistanceRef, "GPSDestDistanceRef" },
+ { tcGPSDestDistance, "GPSDestDistance" },
+ { tcGPSProcessingMethod, "GPSProcessingMethod" },
+ { tcGPSAreaInformation, "GPSAreaInformation" },
+ { tcGPSDateStamp, "GPSDateStamp" },
+ { tcGPSDifferential, "GPSDifferential" },
+ { tcGPSHPositioningError, "GPSHPositioningError" },
+ };
+
+ const dng_name_table kInteroperabilityTagNames [] =
+ {
+ { tcInteroperabilityIndex, "InteroperabilityIndex" },
+ { tcInteroperabilityVersion, "InteroperabilityVersion" },
+ { tcRelatedImageFileFormat, "RelatedImageFileFormat" },
+ { tcRelatedImageWidth, "RelatedImageWidth" },
+ { tcRelatedImageLength, "RelatedImageLength" }
+ };
+
+ const dng_name_table kFujiTagNames [] =
+ {
+ { tcFujiHeader, "FujiHeader" },
+ { tcFujiRawInfo1, "FujiRawInfo1" },
+ { tcFujiRawInfo2, "FujiRawInfo2" }
+ };
+
+ const dng_name_table kContaxTagNames [] =
+ {
+ { tcContaxHeader, "ContaxHeader" }
+ };
+
+ const char *name = NULL;
+
+ if (parentCode == 0 ||
+ parentCode == tcExifIFD ||
+ parentCode == tcLeafMOS ||
+ (parentCode >= tcFirstSubIFD && parentCode <= tcLastSubIFD) ||
+ (parentCode >= tcFirstChainedIFD && parentCode <= tcLastChainedIFD))
+ {
+
+ name = LookupName (tagCode,
+ kTagNames,
+ sizeof (kTagNames ) /
+ sizeof (kTagNames [0]));
+
+ }
+
+ else if (parentCode == tcGPSInfo)
+ {
+
+ name = LookupName (tagCode,
+ kGPSTagNames,
+ sizeof (kGPSTagNames ) /
+ sizeof (kGPSTagNames [0]));
+
+ }
+
+ else if (parentCode == tcInteroperabilityIFD)
+ {
+
+ name = LookupName (tagCode,
+ kInteroperabilityTagNames,
+ sizeof (kInteroperabilityTagNames ) /
+ sizeof (kInteroperabilityTagNames [0]));
+
+ }
+
+ else if (parentCode == tcFujiRAF)
+ {
+
+ name = LookupName (tagCode,
+ kFujiTagNames,
+ sizeof (kFujiTagNames ) /
+ sizeof (kFujiTagNames [0]));
+
+ }
+
+ else if (parentCode == tcContaxRAW)
+ {
+
+ name = LookupName (tagCode,
+ kContaxTagNames,
+ sizeof (kContaxTagNames ) /
+ sizeof (kContaxTagNames [0]));
+
+ }
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ if (parentCode == tcCanonCRW)
+ {
+ sprintf (s, "CRW_%04X", (unsigned) tagCode);
+ }
+
+ else if (parentCode == tcMinoltaMRW)
+ {
+
+ char c1 = (char) ((tagCode >> 24) & 0xFF);
+ char c2 = (char) ((tagCode >> 16) & 0xFF);
+ char c3 = (char) ((tagCode >> 8) & 0xFF);
+ char c4 = (char) ((tagCode ) & 0xFF);
+
+ if (c1 < ' ') c1 = '_';
+ if (c2 < ' ') c2 = '_';
+ if (c3 < ' ') c3 = '_';
+ if (c4 < ' ') c4 = '_';
+
+ sprintf (s, "MRW%c%c%c%c", c1, c2, c3, c4);
+
+ }
+
+ else if (parentCode == tcFujiRawInfo1)
+ {
+ sprintf (s, "RAF1_%04X", (unsigned) tagCode);
+ }
+
+ else if (parentCode == tcFujiRawInfo2)
+ {
+ sprintf (s, "RAF2_%04X", (unsigned) tagCode);
+ }
+
+ else
+ {
+ sprintf (s, "Tag%u", (unsigned) tagCode);
+ }
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupTagType (uint32 tagType)
+ {
+
+ const dng_name_table kTagTypeNames [] =
+ {
+ { ttByte, "Byte" },
+ { ttAscii, "ASCII" },
+ { ttShort, "Short" },
+ { ttLong, "Long" },
+ { ttRational, "Rational" },
+ { ttSByte, "SByte" },
+ { ttUndefined, "Undefined" },
+ { ttSShort, "SShort" },
+ { ttSLong, "SLong" },
+ { ttSRational, "SRational" },
+ { ttFloat, "Float" },
+ { ttDouble, "Double" },
+ { ttIFD, "IFD" },
+ { ttUnicode, "Unicode" },
+ { ttComplex, "Complex" }
+ };
+
+ const char *name = LookupName (tagType,
+ kTagTypeNames,
+ sizeof (kTagTypeNames ) /
+ sizeof (kTagTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "Type%u", (unsigned) tagType);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupNewSubFileType (uint32 key)
+ {
+
+ const dng_name_table kNewSubFileTypeNames [] =
+ {
+ { sfMainImage , "Main Image" },
+ { sfPreviewImage , "Preview Image" },
+ { sfTransparencyMask , "Transparency Mask" },
+ { sfPreviewMask , "Preview Mask" },
+ { sfAltPreviewImage , "Alt Preview Image" }
+ };
+
+ const char *name = LookupName (key,
+ kNewSubFileTypeNames,
+ sizeof (kNewSubFileTypeNames ) /
+ sizeof (kNewSubFileTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCompression (uint32 key)
+ {
+
+ const dng_name_table kCompressionNames [] =
+ {
+ { ccUncompressed, "Uncompressed" },
+ { ccLZW, "LZW" },
+ { ccOldJPEG, "Old JPEG" },
+ { ccJPEG, "JPEG" },
+ { ccDeflate, "Deflate" },
+ { ccPackBits, "PackBits" },
+ { ccOldDeflate, "OldDeflate" },
+ { ccLossyJPEG, "Lossy JPEG" }
+ };
+
+ const char *name = LookupName (key,
+ kCompressionNames,
+ sizeof (kCompressionNames ) /
+ sizeof (kCompressionNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupPredictor (uint32 key)
+ {
+
+ const dng_name_table kPredictorNames [] =
+ {
+ { cpNullPredictor, "NullPredictor" },
+ { cpHorizontalDifference, "HorizontalDifference" },
+ { cpFloatingPoint, "FloatingPoint" },
+ { cpHorizontalDifferenceX2, "HorizontalDifferenceX2" },
+ { cpHorizontalDifferenceX4, "HorizontalDifferenceX4" },
+ { cpFloatingPointX2, "FloatingPointX2" },
+ { cpFloatingPointX4, "FloatingPointX4" }
+ };
+
+ const char *name = LookupName (key,
+ kPredictorNames,
+ sizeof (kPredictorNames ) /
+ sizeof (kPredictorNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSampleFormat (uint32 key)
+ {
+
+ const dng_name_table kSampleFormatNames [] =
+ {
+ { sfUnsignedInteger, "UnsignedInteger" },
+ { sfSignedInteger, "SignedInteger" },
+ { sfFloatingPoint, "FloatingPoint" },
+ { sfUndefined, "Undefined" }
+ };
+
+ const char *name = LookupName (key,
+ kSampleFormatNames,
+ sizeof (kSampleFormatNames ) /
+ sizeof (kSampleFormatNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupPhotometricInterpretation (uint32 key)
+ {
+
+ const dng_name_table kPhotometricInterpretationNames [] =
+ {
+ { piWhiteIsZero, "WhiteIsZero" },
+ { piBlackIsZero, "BlackIsZero" },
+ { piRGB, "RGB" },
+ { piRGBPalette, "RGBPalette" },
+ { piTransparencyMask, "TransparencyMask" },
+ { piCMYK, "CMYK" },
+ { piYCbCr, "YCbCr" },
+ { piCIELab, "CIELab" },
+ { piICCLab, "ICCLab" },
+ { piCFA, "CFA" },
+ { piLinearRaw, "LinearRaw" }
+ };
+
+ const char *name = LookupName (key,
+ kPhotometricInterpretationNames,
+ sizeof (kPhotometricInterpretationNames ) /
+ sizeof (kPhotometricInterpretationNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupOrientation (uint32 key)
+ {
+
+ const dng_name_table kOrientationNames [] =
+ {
+ { 1, "1 - 0th row is top, 0th column is left" },
+ { 2, "2 - 0th row is top, 0th column is right" },
+ { 3, "3 - 0th row is bottom, 0th column is right" },
+ { 4, "4 - 0th row is bottom, 0th column is left" },
+ { 5, "5 - 0th row is left, 0th column is top" },
+ { 6, "6 - 0th row is right, 0th column is top" },
+ { 7, "7 - 0th row is right, 0th column is bottom" },
+ { 8, "8 - 0th row is left, 0th column is bottom" },
+ { 9, "9 - unknown" }
+ };
+
+ const char *name = LookupName (key,
+ kOrientationNames,
+ sizeof (kOrientationNames ) /
+ sizeof (kOrientationNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupResolutionUnit (uint32 key)
+ {
+
+ const dng_name_table kResolutionUnitNames [] =
+ {
+ { ruNone, "None" },
+ { ruInch, "Inch" },
+ { ruCM, "cm" },
+ { ruMM, "mm" },
+ { ruMicroM, "Micrometer" }
+ };
+
+ const char *name = LookupName (key,
+ kResolutionUnitNames,
+ sizeof (kResolutionUnitNames ) /
+ sizeof (kResolutionUnitNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCFAColor (uint32 key)
+ {
+
+ const dng_name_table kCFAColorNames [] =
+ {
+ { 0, "Red" },
+ { 1, "Green" },
+ { 2, "Blue" },
+ { 3, "Cyan" },
+ { 4, "Magenta" },
+ { 5, "Yellow" },
+ { 6, "White" }
+ };
+
+ const char *name = LookupName (key,
+ kCFAColorNames,
+ sizeof (kCFAColorNames ) /
+ sizeof (kCFAColorNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "Color%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSensingMethod (uint32 key)
+ {
+
+ const dng_name_table kSensingMethodNames [] =
+ {
+ { 0, "Undefined" },
+ { 1, "MonochromeArea" },
+ { 2, "OneChipColorArea" },
+ { 3, "TwoChipColorArea" },
+ { 4, "ThreeChipColorArea" },
+ { 5, "ColorSequentialArea" },
+ { 6, "MonochromeLinear" },
+ { 7, "TriLinear" },
+ { 8, "ColorSequentialLinear" }
+ };
+
+ const char *name = LookupName (key,
+ kSensingMethodNames,
+ sizeof (kSensingMethodNames ) /
+ sizeof (kSensingMethodNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupExposureProgram (uint32 key)
+ {
+
+ const dng_name_table kExposureProgramNames [] =
+ {
+ { epUnidentified, "Unidentified" },
+ { epManual, "Manual" },
+ { epProgramNormal, "Program Normal" },
+ { epAperturePriority, "Aperture Priority" },
+ { epShutterPriority, "Shutter Priority" },
+ { epProgramCreative, "Program Creative" },
+ { epProgramAction, "Program Action" },
+ { epPortraitMode, "Portrait Mode" },
+ { epLandscapeMode, "Landscape Mode" }
+ };
+
+ const char *name = LookupName (key,
+ kExposureProgramNames,
+ sizeof (kExposureProgramNames ) /
+ sizeof (kExposureProgramNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupMeteringMode (uint32 key)
+ {
+
+ const dng_name_table kMeteringModeNames [] =
+ {
+ { mmUnidentified, "Unknown" },
+ { mmAverage, "Average" },
+ { mmCenterWeightedAverage, "CenterWeightedAverage" },
+ { mmSpot, "Spot" },
+ { mmMultiSpot, "MultiSpot" },
+ { mmPattern, "Pattern" },
+ { mmPartial, "Partial" },
+ { mmOther, "Other" }
+ };
+
+ const char *name = LookupName (key,
+ kMeteringModeNames,
+ sizeof (kMeteringModeNames ) /
+ sizeof (kMeteringModeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupLightSource (uint32 key)
+ {
+
+ const dng_name_table kLightSourceNames [] =
+ {
+ { lsUnknown, "Unknown" },
+ { lsDaylight, "Daylight" },
+ { lsFluorescent, "Fluorescent" },
+ { lsTungsten, "Tungsten (incandescent light)" },
+ { lsFlash, "Flash" },
+ { lsFineWeather, "Fine weather" },
+ { lsCloudyWeather, "Cloudy weather" },
+ { lsShade, "Shade" },
+ { lsDaylightFluorescent, "Daylight fluorescent (D 5700 - 7100K)" },
+ { lsDayWhiteFluorescent, "Day white fluorescent (N 4600 - 5500K)" },
+ { lsCoolWhiteFluorescent, "Cool white fluorescent (W 3800 - 4500K)" },
+ { lsWhiteFluorescent, "White fluorescent (WW 3250 - 3800K)" },
+ { lsWarmWhiteFluorescent, "Warm white fluorescent (L 2600 - 3250K)" },
+ { lsStandardLightA, "Standard light A" },
+ { lsStandardLightB, "Standard light B" },
+ { lsStandardLightC, "Standard light C" },
+ { lsD55, "D55" },
+ { lsD65, "D65" },
+ { lsD75, "D75" },
+ { lsD50, "D50" },
+ { lsISOStudioTungsten, "ISO studio tungsten" },
+ { lsOther, "Other" }
+ };
+
+ const char *name = LookupName (key,
+ kLightSourceNames,
+ sizeof (kLightSourceNames ) /
+ sizeof (kLightSourceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ if (key & 0x08000)
+ {
+
+ sprintf (s, "%uK", (unsigned) (key & 0x7FFF));
+
+ }
+
+ else
+ {
+
+ sprintf (s, "%u", (unsigned) key);
+
+ }
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupColorSpace (uint32 key)
+ {
+
+ const dng_name_table kColorSpaceNames [] =
+ {
+ { 1, "sRGB" },
+ { 0xFFFF, "Uncalibrated" }
+ };
+
+ const char *name = LookupName (key,
+ kColorSpaceNames,
+ sizeof (kColorSpaceNames ) /
+ sizeof (kColorSpaceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupFileSource (uint32 key)
+ {
+
+ const dng_name_table kFileSourceNames [] =
+ {
+ { 3, "DSC" }
+ };
+
+ const char *name = LookupName (key,
+ kFileSourceNames,
+ sizeof (kFileSourceNames ) /
+ sizeof (kFileSourceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSceneType (uint32 key)
+ {
+
+ const dng_name_table kSceneTypeNames [] =
+ {
+ { 1, "A directly photographed image" }
+ };
+
+ const char *name = LookupName (key,
+ kSceneTypeNames,
+ sizeof (kSceneTypeNames ) /
+ sizeof (kSceneTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCustomRendered (uint32 key)
+ {
+
+ const dng_name_table kCustomRenderedNames [] =
+ {
+ { 0, "Normal process" },
+ { 1, "Custom process" }
+ };
+
+ const char *name = LookupName (key,
+ kCustomRenderedNames,
+ sizeof (kCustomRenderedNames ) /
+ sizeof (kCustomRenderedNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupExposureMode (uint32 key)
+ {
+
+ const dng_name_table kExposureModeNames [] =
+ {
+ { 0, "Auto exposure" },
+ { 1, "Manual exposure" },
+ { 2, "Auto bracket" }
+ };
+
+ const char *name = LookupName (key,
+ kExposureModeNames,
+ sizeof (kExposureModeNames ) /
+ sizeof (kExposureModeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupWhiteBalance (uint32 key)
+ {
+
+ const dng_name_table kWhiteBalanceNames [] =
+ {
+ { 0, "Auto white balance" },
+ { 1, "Manual white balance" }
+ };
+
+ const char *name = LookupName (key,
+ kWhiteBalanceNames,
+ sizeof (kWhiteBalanceNames ) /
+ sizeof (kWhiteBalanceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSceneCaptureType (uint32 key)
+ {
+
+ const dng_name_table kSceneCaptureTypeNames [] =
+ {
+ { 0, "Standard" },
+ { 1, "Landscape" },
+ { 2, "Portrait" },
+ { 3, "Night scene" }
+ };
+
+ const char *name = LookupName (key,
+ kSceneCaptureTypeNames,
+ sizeof (kSceneCaptureTypeNames ) /
+ sizeof (kSceneCaptureTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupGainControl (uint32 key)
+ {
+
+ const dng_name_table kGainControlNames [] =
+ {
+ { 0, "None" },
+ { 1, "Low gain up" },
+ { 2, "High gain up" },
+ { 3, "Low gain down" },
+ { 4, "High gain down" }
+ };
+
+ const char *name = LookupName (key,
+ kGainControlNames,
+ sizeof (kGainControlNames ) /
+ sizeof (kGainControlNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupContrast (uint32 key)
+ {
+
+ const dng_name_table kContrastNames [] =
+ {
+ { 0, "Normal" },
+ { 1, "Soft" },
+ { 2, "Hard" }
+ };
+
+ const char *name = LookupName (key,
+ kContrastNames,
+ sizeof (kContrastNames ) /
+ sizeof (kContrastNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSaturation (uint32 key)
+ {
+
+ const dng_name_table kSaturationNames [] =
+ {
+ { 0, "Normal" },
+ { 1, "Low saturation" },
+ { 2, "High saturation" }
+ };
+
+ const char *name = LookupName (key,
+ kSaturationNames,
+ sizeof (kSaturationNames ) /
+ sizeof (kSaturationNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSharpness (uint32 key)
+ {
+
+ const dng_name_table kSharpnessNames [] =
+ {
+ { 0, "Normal" },
+ { 1, "Soft" },
+ { 2, "Hard" }
+ };
+
+ const char *name = LookupName (key,
+ kSharpnessNames,
+ sizeof (kSharpnessNames ) /
+ sizeof (kSharpnessNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSubjectDistanceRange (uint32 key)
+ {
+
+ const dng_name_table kSubjectDistanceRangeNames [] =
+ {
+ { 0, "Unknown" },
+ { 1, "Macro" },
+ { 2, "Close view" },
+ { 3, "Distant view" }
+ };
+
+ const char *name = LookupName (key,
+ kSubjectDistanceRangeNames,
+ sizeof (kSubjectDistanceRangeNames ) /
+ sizeof (kSubjectDistanceRangeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupComponent (uint32 key)
+ {
+
+ const dng_name_table kComponentNames [] =
+ {
+ { 0, "-" },
+ { 1, "Y" },
+ { 2, "Cb" },
+ { 3, "Cr" },
+ { 4, "R" },
+ { 5, "G" },
+ { 6, "B" }
+ };
+
+ const char *name = LookupName (key,
+ kComponentNames,
+ sizeof (kComponentNames ) /
+ sizeof (kComponentNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupCFALayout (uint32 key)
+ {
+
+ const dng_name_table kCFALayoutNames [] =
+ {
+ { 1, "Rectangular (or square) layout" },
+ { 2, "Staggered layout A: even columns are offset down by 1/2 row" },
+ { 3, "Staggered layout B: even columns are offset up by 1/2 row" },
+ { 4, "Staggered layout C: even rows are offset right by 1/2 column" },
+ { 5, "Staggered layout D: even rows are offset left by 1/2 column" },
+ { 6, "Staggered layout E: even rows are offset up by 1/2 row, even columns are offset left by 1/2 column" },
+ { 7, "Staggered layout F: even rows are offset up by 1/2 row, even columns are offset right by 1/2 column" },
+ { 8, "Staggered layout G: even rows are offset down by 1/2 row, even columns are offset left by 1/2 column" },
+ { 9, "Staggered layout H: even rows are offset down by 1/2 row, even columns are offset right by 1/2 column" }
+ };
+
+ const char *name = LookupName (key,
+ kCFALayoutNames,
+ sizeof (kCFALayoutNames ) /
+ sizeof (kCFALayoutNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupMakerNoteSafety (uint32 key)
+ {
+
+ const dng_name_table kMakerNoteSafetyNames [] =
+ {
+ { 0, "Unsafe" },
+ { 1, "Safe" }
+ };
+
+ const char *name = LookupName (key,
+ kMakerNoteSafetyNames,
+ sizeof (kMakerNoteSafetyNames ) /
+ sizeof (kMakerNoteSafetyNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupColorimetricReference (uint32 key)
+ {
+
+ const dng_name_table kColorimetricReferenceNames [] =
+ {
+ { crSceneReferred, "Scene Referred" },
+ { crICCProfilePCS, "ICC Profile PCS" }
+ };
+
+ const char *name = LookupName (key,
+ kColorimetricReferenceNames,
+ sizeof (kColorimetricReferenceNames ) /
+ sizeof (kColorimetricReferenceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupPreviewColorSpace (uint32 key)
+ {
+
+ const dng_name_table kPreviewColorSpaceNames [] =
+ {
+ { previewColorSpace_Unknown , "Unknown" },
+ { previewColorSpace_GrayGamma22, "Gray Gamma 2.2" },
+ { previewColorSpace_sRGB , "sRGB" },
+ { previewColorSpace_AdobeRGB , "Adobe RGB (1998)" },
+ { previewColorSpace_ProPhotoRGB, "Pro Photo RGB" }
+ };
+
+ const char *name = LookupName (key,
+ kPreviewColorSpaceNames,
+ sizeof (kPreviewColorSpaceNames ) /
+ sizeof (kPreviewColorSpaceNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupJPEGMarker (uint32 key)
+ {
+
+ const dng_name_table kJPEGMarkerNames [] =
+ {
+ { M_TEM, "TEM" },
+ { M_SOF0, "SOF0" },
+ { M_SOF1, "SOF1" },
+ { M_SOF2, "SOF2" },
+ { M_SOF3, "SOF3" },
+ { M_DHT, "DHT" },
+ { M_SOF5, "SOF5" },
+ { M_SOF6, "SOF6" },
+ { M_SOF7, "SOF7" },
+ { M_JPG, "JPG" },
+ { M_SOF9, "SOF9" },
+ { M_SOF10, "SOF10" },
+ { M_SOF11, "SOF11" },
+ { M_DAC, "DAC" },
+ { M_SOF13, "SOF13" },
+ { M_SOF14, "SOF14" },
+ { M_SOF15, "SOF15" },
+ { M_RST0, "RST0" },
+ { M_RST1, "RST1" },
+ { M_RST2, "RST2" },
+ { M_RST3, "RST3" },
+ { M_RST4, "RST4" },
+ { M_RST5, "RST5" },
+ { M_RST6, "RST6" },
+ { M_RST7, "RST7" },
+ { M_SOI, "SOI" },
+ { M_EOI, "EOI" },
+ { M_SOS, "SOS" },
+ { M_DQT, "DQT" },
+ { M_DNL, "DNL" },
+ { M_DRI, "DRI" },
+ { M_DHP, "DHP" },
+ { M_EXP, "EXP" },
+ { M_APP0, "APP0" },
+ { M_APP1, "APP1" },
+ { M_APP2, "APP2" },
+ { M_APP3, "APP3" },
+ { M_APP4, "APP4" },
+ { M_APP5, "APP5" },
+ { M_APP6, "APP6" },
+ { M_APP7, "APP7" },
+ { M_APP8, "APP8" },
+ { M_APP9, "APP9" },
+ { M_APP10, "APP10" },
+ { M_APP11, "APP11" },
+ { M_APP12, "APP12" },
+ { M_APP13, "APP13" },
+ { M_APP14, "APP14" },
+ { M_APP15, "APP15" },
+ { M_JPG0, "JPG0" },
+ { M_JPG1, "JPG1" },
+ { M_JPG2, "JPG2" },
+ { M_JPG3, "JPG3" },
+ { M_JPG4, "JPG4" },
+ { M_JPG5, "JPG5" },
+ { M_JPG6, "JPG6" },
+ { M_JPG7, "JPG7" },
+ { M_JPG8, "JPG8" },
+ { M_JPG9, "JPG9" },
+ { M_JPG10, "JPG10" },
+ { M_JPG11, "JPG11" },
+ { M_JPG12, "JPG12" },
+ { M_JPG13, "JPG13" },
+ { M_COM, "COM" },
+ { M_ERROR, "ERROR" }
+ };
+
+ const char *name = LookupName (key,
+ kJPEGMarkerNames,
+ sizeof (kJPEGMarkerNames ) /
+ sizeof (kJPEGMarkerNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "0x%02X", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+const char * LookupSensitivityType (uint32 key)
+ {
+
+ const dng_name_table kSensitivityTypeNames [] =
+ {
+ { stUnknown, "Unknown" },
+ { stStandardOutputSensitivity, "Standard Output Sensitivity (SOS)" },
+ { stRecommendedExposureIndex, "Recommended Exposure Index (REI)" },
+ { stISOSpeed, "ISO Speed" },
+ { stSOSandREI, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI)" },
+ { stSOSandISOSpeed, "Standard Output Sensitivity (SOS) and ISO Speed" },
+ { stREIandISOSpeed, "Recommended Exposure Index (REI) and ISO Speed" },
+ { stSOSandREIandISOSpeed, "Standard Output Sensitivity (SOS) and Recommended Exposure Index (REI) and ISO Speed" },
+ };
+
+ const char *name = LookupName (key,
+ kSensitivityTypeNames,
+ sizeof (kSensitivityTypeNames ) /
+ sizeof (kSensitivityTypeNames [0]));
+
+ if (name)
+ {
+ return name;
+ }
+
+ static char s [32];
+
+ sprintf (s, "%u", (unsigned) key);
+
+ return s;
+
+ }
+
+/*****************************************************************************/
+
+void DumpHexAscii (dng_stream &stream,
+ uint32 count)
+ {
+
+ uint32 rows = (count + 15) >> 4;
+
+ if (rows > gDumpLineLimit)
+ rows = gDumpLineLimit;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ printf (" ");
+
+ uint32 col;
+
+ uint32 cols = count - (row << 4);
+
+ if (cols > 16)
+ cols = 16;
+
+ uint8 x [16];
+
+ for (col = 0; col < 16; col++)
+ {
+
+ x [col] = ' ';
+
+ if (col < cols)
+ {
+
+ x [col] = stream.Get_uint8 ();
+
+ printf ("%02x ", x [col]);
+
+ }
+
+ else
+ {
+ printf (" ");
+ }
+
+ }
+
+ printf (" ");
+
+ for (col = 0; col < 16; col++)
+ {
+
+ if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~')
+ {
+ printf ("%c", x [col]);
+ }
+
+ else
+ {
+ printf (".");
+ }
+
+ }
+
+ printf ("\n");
+
+ }
+
+ if (count > rows * 16)
+ {
+ printf (" ... %u more bytes\n", (unsigned) (count - rows * 16));
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpHexAscii (const uint8 *buf,
+ uint32 count)
+ {
+
+ uint32 rows = (count + 15) >> 4;
+
+ if (rows > gDumpLineLimit)
+ rows = gDumpLineLimit;
+
+ for (uint32 row = 0; row < rows; row++)
+ {
+
+ printf (" ");
+
+ uint32 col;
+
+ uint32 cols = count - (row << 4);
+
+ if (cols > 16)
+ cols = 16;
+
+ uint8 x [16];
+
+ for (col = 0; col < 16; col++)
+ {
+
+ x [col] = ' ';
+
+ if (col < cols)
+ {
+
+ x [col] = *(buf++);
+
+ printf ("%02x ", x [col]);
+
+ }
+
+ else
+ {
+ printf (" ");
+ }
+
+ }
+
+ printf (" ");
+
+ for (col = 0; col < 16; col++)
+ {
+
+ if (x [col] >= (uint8) ' ' && x [col] <= (uint8) '~')
+ {
+ printf ("%c", x [col]);
+ }
+
+ else
+ {
+ printf (".");
+ }
+
+ }
+
+ printf ("\n");
+
+ }
+
+ if (count > rows * 16)
+ {
+ printf (" ... %u more bytes\n", (unsigned) (count - rows * 16));
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpXMP (dng_stream &stream,
+ uint32 count)
+ {
+
+ uint32 lineLength = 0;
+
+ while (count > 0)
+ {
+
+ uint32 x = stream.Get_uint8 ();
+
+ if (x == 0) break;
+
+ count--;
+
+ if (lineLength == 0)
+ {
+
+ printf ("XMP: ");
+
+ lineLength = 5;
+
+ }
+
+ if (x == '\n' ||
+ x == '\r')
+ {
+
+ printf ("\n");
+
+ lineLength = 0;
+
+ }
+
+ else
+ {
+
+ if (lineLength >= 128)
+ {
+
+ printf ("\nXMP: ");
+
+ lineLength = 5;
+
+ }
+
+ if (x >= ' ' && x <= '~')
+ {
+
+ printf ("%c", (char) x);
+
+ lineLength += 1;
+
+ }
+
+ else
+ {
+
+ printf ("\\%03o", (unsigned) x);
+
+ lineLength += 4;
+
+ }
+
+ }
+
+ }
+
+ if (lineLength != 0)
+ {
+
+ printf ("\n");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpString (const dng_string &s)
+ {
+
+ const uint32 kMaxDumpString = gDumpLineLimit * 64;
+
+ printf ("\"");
+
+ const char *ss = s.Get ();
+
+ uint32 total = 0;
+
+ while (*ss != 0 && total++ < kMaxDumpString)
+ {
+
+ uint32 c = dng_string::DecodeUTF8 (ss);
+
+ if (c >= ' ' && c <= '~')
+ {
+ printf ("%c", (char) c);
+ }
+
+ else switch (c)
+ {
+
+ case '\t':
+ {
+ printf ("\\t");
+ break;
+ }
+
+ case '\n':
+ {
+ printf ("\\n");
+ break;
+ }
+
+ case '\r':
+ {
+ printf ("\\r");
+ break;
+ }
+
+ default:
+ {
+ printf ("[%X]", (unsigned) c);
+ }
+
+ }
+
+ }
+
+ uint32 extra = (uint32) strlen (ss);
+
+ if (extra > 0)
+ {
+ printf ("...\" (%u more bytes)", (unsigned) extra);
+ }
+
+ else
+ {
+ printf ("\"");
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpTagValues (dng_stream &stream,
+ const char *entry_name,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ const char *tag_name)
+ {
+
+ const uint32 kMaxDumpSingleLine = 4;
+
+ const uint32 kMaxDumpArray = Max_uint32 (gDumpLineLimit, kMaxDumpSingleLine);
+
+ printf ("%s:", tag_name ? tag_name
+ : LookupTagCode (parentCode, tagCode));
+
+ switch (tagType)
+ {
+
+ case ttShort:
+ case ttLong:
+ case ttIFD:
+ case ttSByte:
+ case ttSShort:
+ case ttSLong:
+ case ttRational:
+ case ttSRational:
+ case ttFloat:
+ case ttDouble:
+ {
+
+ if (tagCount > kMaxDumpSingleLine)
+ {
+
+ printf (" %u entries", (unsigned) tagCount);
+
+ }
+
+ for (uint32 j = 0; j < tagCount && j < kMaxDumpArray; j++)
+ {
+
+ if (tagCount <= kMaxDumpSingleLine)
+ {
+
+ if (j == 0)
+ {
+
+ printf (" %s =", entry_name);
+
+ }
+
+ printf (" ");
+
+ }
+
+ else
+ {
+
+ printf ("\n %s [%u] = ", entry_name, (unsigned) j);
+
+ }
+
+ switch (tagType)
+ {
+
+ case ttByte:
+ case ttShort:
+ case ttLong:
+ case ttIFD:
+ {
+
+ uint32 x = stream.TagValue_uint32 (tagType);
+
+ printf ("%u", (unsigned) x);
+
+ break;
+
+ }
+
+ case ttSByte:
+ case ttSShort:
+ case ttSLong:
+ {
+
+ int32 x = stream.TagValue_int32 (tagType);
+
+ printf ("%d", (int) x);
+
+ break;
+
+ }
+
+ case ttRational:
+ {
+
+ dng_urational x = stream.TagValue_urational (tagType);
+
+ printf ("%u/%u", (unsigned) x.n, (unsigned) x.d);
+
+ break;
+
+ }
+
+ case ttSRational:
+ {
+
+ dng_srational x = stream.TagValue_srational (tagType);
+
+ printf ("%d/%d", (int) x.n, (int) x.d);
+
+ break;
+
+ }
+
+ default:
+ {
+
+ real64 x = stream.TagValue_real64 (tagType);
+
+ printf ("%f", x);
+
+ }
+
+ }
+
+ }
+
+ printf ("\n");
+
+ if (tagCount > kMaxDumpArray)
+ {
+
+ printf (" ... %u more entries\n", (unsigned) (tagCount - kMaxDumpArray));
+
+ }
+
+ break;
+
+ }
+
+ case ttAscii:
+ {
+
+ dng_string s;
+
+ ParseStringTag (stream,
+ parentCode,
+ tagCode,
+ tagCount,
+ s,
+ false);
+
+ printf (" ");
+
+ DumpString (s);
+
+ printf ("\n");
+
+ break;
+
+ }
+
+ default:
+ {
+
+ uint32 tagSize = tagCount * TagTypeSize (tagType);
+
+ if (tagCount == 1 && (tagType == ttByte ||
+ tagType == ttUndefined))
+ {
+
+ uint8 x = stream.Get_uint8 ();
+
+ printf (" %s = %u\n", LookupTagType (tagType), x);
+
+ }
+
+ else
+ {
+
+ printf (" %s, size = %u\n", LookupTagType (tagType), (unsigned) tagSize);
+
+ DumpHexAscii (stream, tagSize);
+
+ }
+
+ }
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpMatrix (const dng_matrix &m)
+ {
+
+ for (uint32 row = 0; row < m.Rows (); row++)
+ {
+
+ for (uint32 col = 0; col < m.Cols (); col++)
+ {
+
+ if (col == 0)
+ printf (" ");
+ else
+ printf (" ");
+
+ printf ("%8.4f", m [row] [col]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpVector (const dng_vector &v)
+ {
+
+ for (uint32 index = 0; index < v.Count (); index++)
+ {
+
+ printf (" %0.4f", v [index]);
+
+ }
+
+ printf ("\n");
+
+ }
+
+/*****************************************************************************/
+
+void DumpDateTime (const dng_date_time &dt)
+ {
+
+ printf ("%04d:%02d:%02d %02d:%02d:%02d",
+ (int) dt.fYear,
+ (int) dt.fMonth,
+ (int) dt.fDay,
+ (int) dt.fHour,
+ (int) dt.fMinute,
+ (int) dt.fSecond);
+
+ }
+
+/*****************************************************************************/
+
+void DumpExposureTime (real64 x)
+ {
+
+ if (x > 0.0)
+ {
+
+ if (x >= 0.25)
+ {
+ printf ("%0.2f sec", x);
+ }
+
+ else if (x >= 0.01)
+ {
+ printf ("1/%0.1f sec", 1.0 / x);
+ }
+
+ else
+ {
+ printf ("1/%0.0f sec", 1.0 / x);
+ }
+
+ }
+
+ else
+ {
+
+ printf ("<invalid>");
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void DumpFingerprint (const dng_fingerprint &p)
+ {
+
+ printf ("<");
+
+ for (uint32 j = 0; j < 16; j++)
+ {
+ printf ("%02x", p.data [j]);
+ }
+
+ printf (">");
+
+ }
+
+/*****************************************************************************/
+
+void DumpHueSatMap (dng_stream &stream,
+ uint32 hues,
+ uint32 sats,
+ uint32 vals,
+ bool skipSat0)
+ {
+
+ uint32 doneLines = 0;
+ uint32 skipLines = 0;
+
+ for (uint32 v = 0; v < vals; v++)
+ {
+
+ for (uint32 h = 0; h < hues; h++)
+ {
+
+ for (uint32 s = skipSat0 ? 1 : 0; s < sats; s++)
+ {
+
+ real32 dh = stream.Get_real32 ();
+ real32 ds = stream.Get_real32 ();
+ real32 dv = stream.Get_real32 ();
+
+ if (gDumpLineLimit == 0 ||
+ gDumpLineLimit > doneLines)
+ {
+
+ doneLines++;
+
+ if (vals == 1)
+ {
+
+ printf (" h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n",
+ (unsigned) h,
+ (unsigned) s,
+ (double) dh,
+ (double) ds,
+ (double) dv);
+
+ }
+
+ else
+ {
+
+ printf (" v [%2u] h [%2u] s [%2u]: h=%8.4f s=%6.4f v=%6.4f\n",
+ (unsigned) v,
+ (unsigned) h,
+ (unsigned) s,
+ (double) dh,
+ (double) ds,
+ (double) dv);
+
+ }
+
+ }
+
+ else
+ {
+
+ skipLines++;
+
+ }
+
+ }
+
+ }
+
+ }
+
+ if (skipLines > 0)
+ {
+
+ printf (" ... %u more entries\n", (unsigned) skipLines);
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+#endif
+
+/*****************************************************************************/
+
+bool CheckTagType (uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint16 validType0,
+ uint16 validType1,
+ uint16 validType2,
+ uint16 validType3)
+ {
+
+ if (tagType != validType0 &&
+ tagType != validType1 &&
+ tagType != validType2 &&
+ tagType != validType3)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected type (%s)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ LookupTagType (tagType));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckTagCount (uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ uint32 minCount,
+ uint32 maxCount)
+ {
+
+ if (maxCount < minCount)
+ maxCount = minCount;
+
+ if (tagCount < minCount ||
+ tagCount > maxCount)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected count (%u)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ (unsigned) tagCount);
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckColorImage (uint32 parentCode,
+ uint32 tagCode,
+ uint32 colorPlanes)
+ {
+
+ if (colorPlanes == 0)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed with unknown color plane count "
+ " (missing ColorMatrix1 tag?)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ if (colorPlanes == 1)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed with monochrome images",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckMainIFD (uint32 parentCode,
+ uint32 tagCode,
+ uint32 newSubFileType)
+ {
+
+ if (newSubFileType != sfMainImage)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed IFDs with NewSubFileType != 0",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckRawIFD (uint32 parentCode,
+ uint32 tagCode,
+ uint32 photometricInterpretation)
+ {
+
+ if (photometricInterpretation != piCFA &&
+ photometricInterpretation != piLinearRaw)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed in IFDs with a non-raw PhotometricInterpretation",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+bool CheckCFA (uint32 parentCode,
+ uint32 tagCode,
+ uint32 photometricInterpretation)
+ {
+
+ if (photometricInterpretation != piCFA)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not allowed in IFDs with a non-CFA PhotometricInterpretation",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ return false;
+
+ }
+
+ return true;
+
+ }
+
+/*****************************************************************************/
+
+void ParseStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s,
+ bool trimBlanks)
+ {
+
+ if (tagCount == 0 ||
+ tagCount == 0xFFFFFFFF)
+ {
+
+ s.Clear ();
+
+ return;
+
+ }
+
+ dng_memory_data temp_buffer (tagCount + 1);
+
+ char *buffer = temp_buffer.Buffer_char ();
+
+ stream.Get (buffer, tagCount);
+
+ // Make sure the string is null terminated.
+
+ if (buffer [tagCount - 1] != 0)
+ {
+
+ buffer [tagCount] = 0;
+
+ #if qDNGValidate
+
+ {
+
+ bool hasNull = false;
+
+ for (uint32 j = 0; j < tagCount; j++)
+ {
+
+ if (buffer [j] == 0)
+ {
+
+ hasNull = true;
+
+ break;
+
+ }
+
+ }
+
+ if (!hasNull && parentCode < tcFirstMakerNoteIFD)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not NULL terminated",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ }
+
+ // Medata working group - Allow UTF-8
+
+ s.Set_UTF8_or_System (buffer);
+
+ if (trimBlanks)
+ {
+
+ s.TrimTrailingBlanks ();
+
+ }
+
+ }
+
+/*****************************************************************************/
+
+void ParseDualStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s1,
+ dng_string &s2)
+ {
+
+ if (tagCount == 0 ||
+ tagCount == 0xFFFFFFFF)
+ {
+
+ s1.Clear ();
+ s2.Clear ();
+
+ return;
+
+ }
+
+ dng_memory_data temp_buffer (tagCount + 1);
+
+ char *buffer = temp_buffer.Buffer_char ();
+
+ stream.Get (buffer, tagCount);
+
+ // Make sure the string is null terminated.
+
+ if (buffer [tagCount - 1] != 0)
+ {
+
+ buffer [tagCount] = 0;
+
+ #if qDNGValidate
+
+ {
+
+ uint32 nullCount = 0;
+
+ for (uint32 j = 0; j < tagCount; j++)
+ {
+
+ if (buffer [j] == 0)
+ {
+
+ nullCount++;
+
+ }
+
+ }
+
+ if (nullCount < 2 && parentCode < tcFirstMakerNoteIFD)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not NULL terminated",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ }
+
+ // Medata working group - Allow UTF-8
+
+ s1.Set_UTF8_or_System (buffer);
+
+ s2.Set_ASCII (NULL);
+
+ for (uint32 j = 1; j < tagCount - 1; j++)
+ {
+
+ if (buffer [j - 1] != 0 &&
+ buffer [j ] == 0)
+ {
+
+ // Medata working group - Allow UTF-8
+
+ s2.Set_UTF8_or_System (buffer + j + 1);
+
+ break;
+
+ }
+
+ }
+
+ s1.TrimTrailingBlanks ();
+ s2.TrimTrailingBlanks ();
+
+ }
+
+/*****************************************************************************/
+
+void ParseEncodedStringTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagCount,
+ dng_string &s)
+ {
+
+ if (tagCount < 8)
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected count (%u)",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode),
+ (unsigned) tagCount);
+
+ ReportWarning (message);
+
+ }
+
+ #else
+
+ (void) parentCode; // Unused
+ (void) tagCode; // Unused
+
+ #endif
+
+ s.Clear ();
+
+ return;
+
+ }
+
+ char label [8];
+
+ stream.Get (label, 8);
+
+ // Sometimes lowercase is used by mistake. Accept this, but issue
+ // warning.
+
+ {
+
+ bool hadLower = false;
+
+ for (uint32 j = 0; j < 8; j++)
+ {
+
+ if (label [j] >= 'a' && label [j] <= 'z')
+ {
+
+ label [j] = 'A' + (label [j] - 'a');
+
+ hadLower = true;
+
+ }
+
+ }
+
+ #if qDNGValidate
+
+ if (hadLower)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s text encoding label not all uppercase",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ }
+
+ if (memcmp (label, "UNICODE\000", 8) == 0)
+ {
+
+ uint32 uChars = (tagCount - 8) >> 1;
+
+ dng_memory_data temp_buffer ((uChars + 1) * 2);
+
+ uint16 *buffer = temp_buffer.Buffer_uint16 ();
+
+ for (uint32 j = 0; j < uChars; j++)
+ {
+
+ buffer [j] = stream.Get_uint16 ();
+
+ }
+
+ buffer [uChars] = 0;
+
+ #if qDNGValidate
+
+ {
+
+ // If the writer used UTF-8 rather than UTF-16, and padded
+ // the string with blanks, then there will be lots of 0x2020
+ // (unicode dagger symbol) characters in the string.
+
+ uint32 count2020 = 0;
+
+ for (uint32 k = 0; buffer [k] != 0; k++)
+ {
+
+ if (buffer [k] == 0x2020)
+ {
+
+ count2020++;
+
+ }
+
+ }
+
+ if (count2020 > 1)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s text appears to be UTF-8 rather than UTF-16",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #endif
+
+ s.Set_UTF16 (buffer);
+
+ }
+
+ else
+ {
+
+ uint32 aChars = tagCount - 8;
+
+ dng_memory_data temp_buffer (aChars + 1);
+
+ char *buffer = temp_buffer.Buffer_char ();
+
+ stream.Get (buffer, aChars);
+
+ buffer [aChars] = 0;
+
+ enum dng_encoding
+ {
+ dng_encoding_ascii,
+ dng_encoding_jis_x208_1990,
+ dng_encoding_unknown
+ };
+
+ dng_encoding encoding = dng_encoding_unknown;
+
+ if (memcmp (label, "ASCII\000\000\000", 8) == 0)
+ {
+
+ encoding = dng_encoding_ascii;
+
+ }
+
+ else if (memcmp (label, "JIS\000\000\000\000\000\000", 8) == 0)
+ {
+
+ encoding = dng_encoding_jis_x208_1990;
+
+ }
+
+ else
+ {
+
+ // Some Nikon D1 files have UserComment tags with zero encoding bits and
+ // garbage text values. So don't try to parse tags with unknown text
+ // encoding unless all the characters are printing ASCII.
+
+ #if qDNGValidate
+
+ if (memcmp (label, "\000\000\000\000\000\000\000\000\000", 8) == 0)
+ {
+
+ // Many camera makes store null tags with all zero encoding, so
+ // don't report a warning message for null strings.
+
+ if (buffer [0] != 0)
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unknown encoding",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ else
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has unexpected text encoding",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ }
+
+ // If text encoding was unknown, and the text is anything
+ // other than pure ASCII, then ignore it.
+
+ if (encoding == dng_encoding_unknown)
+ {
+
+ encoding = dng_encoding_ascii;
+
+ for (uint32 i = 0; i < aChars && buffer [i] != 0; i++)
+ {
+
+ if (buffer [i] < ' ' ||
+ buffer [i] > '~')
+ {
+
+ buffer [0] = 0;
+
+ break;
+
+ }
+
+ }
+
+ }
+
+ switch (encoding)
+ {
+
+ case dng_encoding_ascii:
+ {
+
+ // Medata working group - allow UTF-8 for ASCII tags.
+
+ s.Set_UTF8_or_System (buffer);
+
+ break;
+
+ }
+
+ case dng_encoding_jis_x208_1990:
+ {
+ s.Set_JIS_X208_1990 (buffer);
+ break;
+ }
+
+ case dng_encoding_unknown:
+ {
+ s.Set_SystemEncoding (buffer);
+ break;
+ }
+
+ default:
+ break;
+
+ }
+
+ #if qDNGValidate
+
+ {
+
+ if (encoding == dng_encoding_ascii && !s.IsASCII ())
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s has non-ASCII characters",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ }
+
+ #endif
+
+ }
+
+ s.TrimTrailingBlanks ();
+
+ }
+
+/*****************************************************************************/
+
+bool ParseMatrixTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint32 rows,
+ uint32 cols,
+ dng_matrix &m)
+ {
+
+ if (CheckTagCount (parentCode, tagCode, tagCount, rows * cols))
+ {
+
+ dng_matrix temp (rows, cols);
+
+ for (uint32 row = 0; row < rows; row++)
+ for (uint32 col = 0; col < cols; col++)
+ {
+
+ temp [row] [col] = stream.TagValue_real64 (tagType);
+
+ }
+
+ m = temp;
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool ParseVectorTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ uint32 count,
+ dng_vector &v)
+ {
+
+ if (CheckTagCount (parentCode, tagCode, tagCount, count))
+ {
+
+ dng_vector temp (count);
+
+ for (uint32 index = 0; index < count; index++)
+ {
+
+ temp [index] = stream.TagValue_real64 (tagType);
+
+ }
+
+ v = temp;
+
+ return true;
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/
+
+bool ParseDateTimeTag (dng_stream &stream,
+ uint32 parentCode,
+ uint32 tagCode,
+ uint32 tagType,
+ uint32 tagCount,
+ dng_date_time &dt)
+ {
+
+ if (!CheckTagType (parentCode, tagCode, tagType, ttAscii))
+ {
+ return false;
+ }
+
+ // Kludge: Some versions of PaintShop Pro write these fields
+ // with a length of 21 rather than 20. Otherwise they are
+ // correctly formated. So relax this test and allow these
+ // these longer than standard tags to be parsed.
+
+ (void) CheckTagCount (parentCode, tagCode, tagCount, 20);
+
+ if (tagCount < 20)
+ {
+ return false;
+ }
+
+ char s [21];
+
+ stream.Get (s, 20);
+
+ s [20] = 0;
+
+ // See if this is a valid date/time string.
+
+ if (dt.Parse (s))
+ {
+ return true;
+ }
+
+ // Accept strings that contain only blanks, colons, and zeros as
+ // valid "null" dates.
+
+ dt = dng_date_time ();
+
+ for (uint32 index = 0; index < 21; index++)
+ {
+
+ char c = s [index];
+
+ if (c == 0)
+ {
+ return true;
+ }
+
+ if (c != ' ' && c != ':' && c != '0')
+ {
+
+ #if qDNGValidate
+
+ {
+
+ char message [256];
+
+ sprintf (message,
+ "%s %s is not a valid date/time",
+ LookupParentCode (parentCode),
+ LookupTagCode (parentCode, tagCode));
+
+ ReportWarning (message);
+
+ }
+
+ #endif
+
+ return false;
+
+ }
+
+ }
+
+ return false;
+
+ }
+
+/*****************************************************************************/