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