You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3327 lines
69 KiB

/*****************************************************************************/
// 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;
}
/*****************************************************************************/