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