Coverage Report

Created: 2025-01-23 06:28

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