1 /*****************************************************************************/
2 // Copyright 2006-2019 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 #include "dng_ifd.h"
10 
11 #include "dng_exceptions.h"
12 #include "dng_flags.h"
13 #include "dng_globals.h"
14 #include "dng_ifd.h"
15 #include "dng_types.h"
16 #include "dng_parse_utils.h"
17 #include "dng_read_image.h"
18 #include "dng_stream.h"
19 #include "dng_tag_codes.h"
20 #include "dng_tag_types.h"
21 #include "dng_tag_values.h"
22 #include "dng_utils.h"
23 
24 /*****************************************************************************/
25 
dng_preview_info()26 dng_preview_info::dng_preview_info ()
27 
28 	:	fIsPrimary          (true)
29 	,	fApplicationName    ()
30 	,	fApplicationVersion ()
31 	,	fSettingsName       ()
32 	,	fSettingsDigest     ()
33 	,	fColorSpace			(previewColorSpace_MaxEnum)
34 	,	fDateTime			()
35 	,	fRawToPreviewGain   (1.0)
36 	,	fCacheVersion		(0)
37 
38 	{
39 
40 	}
41 
42 /*****************************************************************************/
43 
~dng_preview_info()44 dng_preview_info::~dng_preview_info ()
45 	{
46 
47 	}
48 
49 /*****************************************************************************/
50 
dng_ifd()51 dng_ifd::dng_ifd ()
52 
53 	:	fUsesNewSubFileType (false)
54 	,	fNewSubFileType     (0)
55 
56 	,	fImageWidth  (0)
57 	,	fImageLength (0)
58 
59 	,	fCompression (ccUncompressed)
60 	,	fPredictor   (cpNullPredictor)
61 
62 	,	fPhotometricInterpretation (0xFFFFFFFF)
63 
64 	,	fFillOrder (1)
65 
66 	,	fOrientation          (0)
67 	,	fOrientationType      (0)
68 	,	fOrientationOffset    (kDNGStreamInvalidOffset)
69 	,	fOrientationBigEndian (false)
70 
71 	,	fSamplesPerPixel (1)
72 
73 	,	fPlanarConfiguration (pcInterleaved)
74 
75 	,	fXResolution    (0.0)
76 	,	fYResolution    (0.0)
77 	,	fResolutionUnit (0)
78 
79 	,	fUsesStrips (false)
80 	,	fUsesTiles  (false)
81 
82 	,	fTileWidth  (0)
83 	,	fTileLength (0)
84 
85 	,	fTileOffsetsType   (0)
86 	,	fTileOffsetsCount  (0)
87 	,	fTileOffsetsOffset (0)
88 
89 	,	fTileByteCountsType   (0)
90 	,	fTileByteCountsCount  (0)
91 	,	fTileByteCountsOffset (0)
92 
93 	,	fSubIFDsCount  (0)
94 	,	fSubIFDsOffset (0)
95 
96 	,	fExtraSamplesCount (0)
97 
98 	,	fJPEGTablesCount  (0)
99 	,	fJPEGTablesOffset (0)
100 
101 	,	fJPEGInterchangeFormat		 (0)
102 	,	fJPEGInterchangeFormatLength (0)
103 
104 	,	fYCbCrCoefficientR (0.0)
105 	,	fYCbCrCoefficientG (0.0)
106 	,	fYCbCrCoefficientB (0.0)
107 
108 	,	fYCbCrSubSampleH (0)
109 	,	fYCbCrSubSampleV (0)
110 
111 	,	fYCbCrPositioning (0)
112 
113 	,	fCFARepeatPatternRows (0)
114 	,	fCFARepeatPatternCols (0)
115 
116 	,	fCFALayout (1)
117 
118 	,	fLinearizationTableType   (0)
119 	,	fLinearizationTableCount  (0)
120 	,	fLinearizationTableOffset (0)
121 
122 	,	fBlackLevelRepeatRows (1)
123 	,	fBlackLevelRepeatCols (1)
124 
125 	,	fBlackLevelDeltaHType   (0)
126 	,	fBlackLevelDeltaHCount  (0)
127 	,	fBlackLevelDeltaHOffset (0)
128 
129 	,	fBlackLevelDeltaVType   (0)
130 	,	fBlackLevelDeltaVCount  (0)
131 	,	fBlackLevelDeltaVOffset (0)
132 
133 	,	fDefaultScaleH (1, 1)
134 	,	fDefaultScaleV (1, 1)
135 
136 	,	fBestQualityScale (1, 1)
137 
138 	,	fDefaultCropOriginH (0, 1)
139 	,	fDefaultCropOriginV (0, 1)
140 
141 	,	fDefaultCropSizeH ()
142 	,	fDefaultCropSizeV ()
143 
144 	,	fDefaultUserCropT (0, 1)
145 	,	fDefaultUserCropL (0, 1)
146 	,	fDefaultUserCropB (1, 1)
147 	,	fDefaultUserCropR (1, 1)
148 
149 	,	fBayerGreenSplit (0)
150 
151 	,	fChromaBlurRadius ()
152 
153 	,	fAntiAliasStrength (1, 1)
154 
155 	,	fActiveArea ()
156 
157 	,	fMaskedAreaCount (0)
158 
159 	,	fRowInterleaveFactor (1)
160 
161 	,	fSubTileBlockRows (1)
162 	,	fSubTileBlockCols (1)
163 
164 	,	fPreviewInfo ()
165 
166 	,	fOpcodeList1Count  (0)
167 	,	fOpcodeList1Offset (0)
168 
169 	,	fOpcodeList2Count  (0)
170 	,	fOpcodeList2Offset (0)
171 
172 	,	fOpcodeList3Count  (0)
173 	,	fOpcodeList3Offset (0)
174 
175     ,   fNoiseProfile ()
176 
177     ,   fEnhanceParams ()
178 
179     ,   fBaselineSharpness (0, 0)
180 
181     ,   fNoiseReductionApplied (0, 0)
182 
183 	,	fLosslessJPEGBug16 (false)
184 
185 	,	fSampleBitShift (0)
186 
187 	,	fThisIFD (0)
188 	,	fNextIFD (0)
189 
190 	,	fCompressionQuality (-1)
191 
192 	,	fPatchFirstJPEGByte (false)
193 
194 	{
195 
196 	uint32 j;
197 	uint32 k;
198 	uint32 n;
199 
200 	for (j = 0; j < kMaxSamplesPerPixel; j++)
201 		{
202 		fBitsPerSample [j] = 0;
203 		}
204 
205 	for (j = 0; j < kMaxTileInfo; j++)
206 		{
207 		fTileOffset    [j] = 0;
208 		fTileByteCount [j] = 0;
209 		}
210 
211 	for (j = 0; j < kMaxSamplesPerPixel; j++)
212 		{
213 		fExtraSamples [j] = esUnspecified;
214 		}
215 
216 	for (j = 0; j < kMaxSamplesPerPixel; j++)
217 		{
218 		fSampleFormat [j] = sfUnsignedInteger;
219 		}
220 
221 	for (j = 0; j < 6; j++)
222 		{
223 		fReferenceBlackWhite [j] = 0.0;
224 		}
225 
226 	for (j = 0; j < kMaxCFAPattern; j++)
227 		for (k = 0; k < kMaxCFAPattern; k++)
228 			{
229 			fCFAPattern [j] [k] = 255;
230 			}
231 
232 	for (j = 0; j < kMaxColorPlanes; j++)
233 		{
234 		fCFAPlaneColor [j] = (uint8) (j < 3 ? j : 255);
235 		}
236 
237 	for (j = 0; j < kMaxBlackPattern; j++)
238 		for (k = 0; k < kMaxBlackPattern; k++)
239 			for (n = 0; n < kMaxSamplesPerPixel; n++)
240 				{
241 				fBlackLevel [j] [k] [n] = 0.0;
242 				}
243 
244 	for (j = 0; j < kMaxSamplesPerPixel; j++)
245 		{
246 		fWhiteLevel [j] = -1.0;		// Don't know real default yet.
247 		}
248 
249 	}
250 
251 /*****************************************************************************/
252 
~dng_ifd()253 dng_ifd::~dng_ifd ()
254 	{
255 
256 	}
257 
258 /*****************************************************************************/
259 
Clone() const260 dng_ifd * dng_ifd::Clone () const
261 	{
262 
263 	return new dng_ifd (*this);
264 
265 	}
266 
267 /*****************************************************************************/
268 
269 // Parses tags that should only appear in IFDs that contain images.
270 
ParseTag(dng_stream & stream,uint32 parentCode,uint32 tagCode,uint32 tagType,uint32 tagCount,uint64 tagOffset)271 bool dng_ifd::ParseTag (dng_stream &stream,
272 						uint32 parentCode,
273 						uint32 tagCode,
274 						uint32 tagType,
275 						uint32 tagCount,
276 						uint64 tagOffset)
277 	{
278 
279 	uint32 j;
280 	uint32 k;
281 	uint32 n;
282 
283 	switch (tagCode)
284 		{
285 
286 		case tcNewSubFileType:
287 			{
288 
289 			CheckTagType (parentCode, tagCode, tagType, ttLong);
290 
291 			CheckTagCount (parentCode, tagCode, tagCount, 1);
292 
293 			fUsesNewSubFileType = true;
294 
295 			fNewSubFileType = stream.TagValue_uint32 (tagType);
296 
297 			fPreviewInfo.fIsPrimary = (fNewSubFileType == sfPreviewImage);
298 
299 			#if qDNGValidate
300 
301 			if (gVerbose)
302 				{
303 
304 				printf ("NewSubFileType: %s\n",
305 						LookupNewSubFileType (fNewSubFileType));
306 
307 				}
308 
309 			#endif
310 
311 			break;
312 
313 			}
314 
315 		case tcImageWidth:
316 			{
317 
318 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
319 
320 			CheckTagCount (parentCode, tagCode, tagCount, 1);
321 
322 			fImageWidth = stream.TagValue_uint32 (tagType);
323 
324 			#if qDNGValidate
325 
326 			if (gVerbose)
327 				{
328 				printf ("ImageWidth: %u\n", (unsigned) fImageWidth);
329 				}
330 
331 			#endif
332 
333 			break;
334 
335 			}
336 
337 		case tcImageLength:
338 			{
339 
340 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
341 
342 			CheckTagCount (parentCode, tagCode, tagCount, 1);
343 
344 			fImageLength = stream.TagValue_uint32 (tagType);
345 
346 			#if qDNGValidate
347 
348 			if (gVerbose)
349 				{
350 				printf ("ImageLength: %u\n", (unsigned) fImageLength);
351 				}
352 
353 			#endif
354 
355 			break;
356 
357 			}
358 
359 		case tcBitsPerSample:
360 			{
361 
362 			CheckTagType (parentCode, tagCode, tagType, ttShort);
363 
364 			CheckTagCount (parentCode, tagCode, tagCount, 1, 0x0FFFF);
365 
366 			#if qDNGValidate
367 
368 			if (gVerbose)
369 				{
370 				printf ("BitsPerSample:");
371 				}
372 
373 			#endif
374 
375 			bool extrasMatch = true;
376 
377 			for (j = 0; j < tagCount; j++)
378 				{
379 
380 				uint32 x = stream.TagValue_uint32 (tagType);
381 
382 				const uint32 maxBitsPerSample = 32;
383 
384 				if (j < kMaxSamplesPerPixel)
385 					{
386 
387 					if (x > maxBitsPerSample)
388 						{
389 						//ThrowBadFormat ("BitsPerSample out of bounds");
390 						DNG_REPORT ("BitsPerSample > 32");
391 						x = maxBitsPerSample;
392 						}
393 
394 					fBitsPerSample [j] = x;
395 
396 					}
397 
398 				else if (x != fBitsPerSample [kMaxSamplesPerPixel - 1])
399 					{
400 					extrasMatch = false;
401 					}
402 
403 				#if qDNGValidate
404 
405 				if (gVerbose)
406 					{
407 					printf (" %u", (unsigned) x);
408 					}
409 
410 				#endif
411 
412 				}
413 
414 			#if qDNGValidate
415 
416 			if (gVerbose)
417 				{
418 				printf ("\n");
419 				}
420 
421 			#endif
422 
423 			if (!extrasMatch)
424 				{
425 
426 				#if qDNGValidate
427 
428 				ReportError ("BitsPerSample not constant");
429 
430 				#endif
431 
432 				ThrowBadFormat ();
433 
434 				}
435 
436 			break;
437 
438 			}
439 
440 		case tcCompression:
441 			{
442 
443 			CheckTagType (parentCode, tagCode, tagType, ttShort);
444 
445 			CheckTagCount (parentCode, tagCode, tagCount, 1);
446 
447 			fCompression = stream.TagValue_uint32 (tagType);
448 
449 			#if qDNGValidate
450 
451 			if (gVerbose)
452 				{
453 
454 				printf ("Compression: %s\n",
455 					    LookupCompression (fCompression));
456 
457 				}
458 
459 			#endif
460 
461 			// Correct a common TIFF writer mistake.
462 
463 			if (fCompression == 0)
464 				{
465 
466 				#if qDNGValidate
467 
468 					{
469 
470 					char message [256];
471 
472 					sprintf (message,
473 							 "%s has invalid zero compression code",
474 							 LookupParentCode (parentCode));
475 
476 					ReportWarning (message);
477 
478 					}
479 
480 				#endif
481 
482 				fCompression = ccUncompressed;
483 
484 				}
485 
486 			break;
487 
488 			}
489 
490 		case tcPhotometricInterpretation:
491 			{
492 
493 			CheckTagType (parentCode, tagCode, tagType, ttShort);
494 
495 			CheckTagCount (parentCode, tagCode, tagCount, 1);
496 
497 			fPhotometricInterpretation = stream.TagValue_uint32 (tagType);
498 
499 			#if qDNGValidate
500 
501 			if (gVerbose)
502 				{
503 
504 				printf ("PhotometricInterpretation: %s\n",
505 						LookupPhotometricInterpretation (fPhotometricInterpretation));
506 
507 				}
508 
509 			#endif
510 
511 			break;
512 
513 			}
514 
515 		case tcFillOrder:
516 			{
517 
518 			CheckTagType (parentCode, tagCode, tagType, ttShort);
519 
520 			CheckTagCount (parentCode, tagCode, tagCount, 1);
521 
522 			fFillOrder = stream.TagValue_uint32 (tagType);
523 
524 			#if qDNGValidate
525 
526 			if (gVerbose)
527 				{
528 				printf ("FillOrder: %u\n", (unsigned) fFillOrder);
529 				}
530 
531 			#endif
532 
533 			break;
534 
535 			}
536 
537 		case tcStripOffsets:
538 			{
539 
540 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
541 
542 			fUsesStrips = true;
543 
544 			fTileOffsetsType   = tagType;
545 			fTileOffsetsCount  = tagCount;
546 			fTileOffsetsOffset = tagOffset;
547 
548 			if (tagCount <= kMaxTileInfo)
549 				{
550 
551 				for (j = 0; j < tagCount; j++)
552 					{
553 
554 					fTileOffset [j] = stream.TagValue_uint32 (tagType);
555 
556 					}
557 
558 				}
559 
560 			#if qDNGValidate
561 
562 			if (gVerbose)
563 				{
564 
565 				stream.SetReadPosition (tagOffset);
566 
567 				DumpTagValues (stream,
568 							   "Offset",
569 							   parentCode,
570 							   tagCode,
571 							   tagType,
572 							   tagCount);
573 
574 				}
575 
576 			#endif
577 
578 			break;
579 
580 			}
581 
582 		case tcOrientation:
583 			{
584 
585 			CheckTagType (parentCode, tagCode, tagType, ttShort);
586 
587 			CheckTagCount (parentCode, tagCode, tagCount, 1);
588 
589 			fOrientationType      = tagType;
590 			fOrientationOffset    = stream.PositionInOriginalFile ();
591 			fOrientationBigEndian = stream.BigEndian ();
592 
593 			fOrientation = stream.TagValue_uint32 (tagType);
594 
595 			#if qDNGValidate
596 
597 			if (gVerbose)
598 				{
599 
600 				printf ("Orientation: %s\n",
601 					    LookupOrientation (fOrientation));
602 
603 				}
604 
605 			#endif
606 
607 			break;
608 
609 			}
610 
611 		case tcSamplesPerPixel:
612 			{
613 
614 			CheckTagType (parentCode, tagCode, tagType, ttShort);
615 
616 			CheckTagCount (parentCode, tagCode, tagCount, 1);
617 
618 			fSamplesPerPixel = stream.TagValue_uint32 (tagType);
619 
620 			#if qDNGValidate
621 
622 			if (gVerbose)
623 				{
624 				printf ("SamplesPerPixel: %u\n", (unsigned) fSamplesPerPixel);
625 				}
626 
627 			#endif
628 
629 			break;
630 
631 			}
632 
633 		case tcRowsPerStrip:
634 			{
635 
636 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
637 
638 			CheckTagCount (parentCode, tagCode, tagCount, 1);
639 
640 			fUsesStrips = true;
641 
642 			fTileLength = stream.TagValue_uint32 (tagType);
643 
644 			#if qDNGValidate
645 
646 			if (gVerbose)
647 				{
648 				printf ("RowsPerStrip: %u\n", (unsigned) fTileLength);
649 				}
650 
651 			#endif
652 
653 			break;
654 
655 			}
656 
657 		case tcStripByteCounts:
658 			{
659 
660 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
661 
662 			fUsesStrips = true;
663 
664 			fTileByteCountsType   = tagType;
665 			fTileByteCountsCount  = tagCount;
666 			fTileByteCountsOffset = tagOffset;
667 
668 			if (tagCount <= kMaxTileInfo)
669 				{
670 
671 				for (j = 0; j < tagCount; j++)
672 					{
673 
674 					fTileByteCount [j] = stream.TagValue_uint32 (tagType);
675 
676 					}
677 
678 				}
679 
680 			#if qDNGValidate
681 
682 			if (gVerbose)
683 				{
684 
685 				stream.SetReadPosition (tagOffset);
686 
687 				DumpTagValues (stream,
688 							   "Count",
689 							   parentCode,
690 							   tagCode,
691 							   tagType,
692 							   tagCount);
693 
694 				}
695 
696 			#endif
697 
698 			break;
699 
700 			}
701 
702 		case tcXResolution:
703 			{
704 
705 			CheckTagType (parentCode, tagCode, tagType, ttRational);
706 
707 			CheckTagCount (parentCode, tagCode, tagCount, 1);
708 
709 			fXResolution = stream.TagValue_real64 (tagType);
710 
711 			#if qDNGValidate
712 
713 			if (gVerbose)
714 				{
715 				printf ("XResolution: %0.2f\n", fXResolution);
716 				}
717 
718 			#endif
719 
720 			break;
721 
722 			}
723 
724 		case tcYResolution:
725 			{
726 
727 			CheckTagType (parentCode, tagCode, tagType, ttRational);
728 
729 			CheckTagCount (parentCode, tagCode, tagCount, 1);
730 
731 			fYResolution = stream.TagValue_real64 (tagType);
732 
733 			#if qDNGValidate
734 
735 			if (gVerbose)
736 				{
737 				printf ("YResolution: %0.2f\n", fYResolution);
738 				}
739 
740 			#endif
741 
742 			break;
743 
744 			}
745 
746 		case tcPlanarConfiguration:
747 			{
748 
749 			CheckTagType (parentCode, tagCode, tagType, ttShort);
750 
751 			CheckTagCount (parentCode, tagCode, tagCount, 1);
752 
753 			fPlanarConfiguration = stream.TagValue_uint32 (tagType);
754 
755 			#if qDNGValidate
756 
757 			if (gVerbose)
758 				{
759 				printf ("PlanarConfiguration: %u\n", (unsigned) fPlanarConfiguration);
760 				}
761 
762 			#endif
763 
764 			break;
765 
766 			}
767 
768 		case tcResolutionUnit:
769 			{
770 
771 			CheckTagType (parentCode, tagCode, tagType, ttShort);
772 
773 			CheckTagCount (parentCode, tagCode, tagCount, 1);
774 
775 			fResolutionUnit = stream.TagValue_uint32 (tagType);
776 
777 			#if qDNGValidate
778 
779 			if (gVerbose)
780 				{
781 
782 				printf ("ResolutionUnit: %s\n",
783 					    LookupResolutionUnit (fResolutionUnit));
784 
785 				}
786 
787 			#endif
788 
789 			break;
790 
791 			}
792 
793 		case tcPredictor:
794 			{
795 
796 			CheckTagType (parentCode, tagCode, tagType, ttShort);
797 
798 			CheckTagCount (parentCode, tagCode, tagCount, 1);
799 
800 			fPredictor = stream.TagValue_uint32 (tagType);
801 
802 			#if qDNGValidate
803 
804 			if (gVerbose)
805 				{
806 
807 				printf ("Predictor: %s\n",
808 						LookupPredictor (fPredictor));
809 
810 				}
811 
812 			#endif
813 
814 			break;
815 
816 			}
817 
818 		case tcTileWidth:
819 			{
820 
821 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
822 
823 			CheckTagCount (parentCode, tagCode, tagCount, 1);
824 
825 			fUsesTiles = true;
826 
827 			fTileWidth = stream.TagValue_uint32 (tagType);
828 
829 			#if qDNGValidate
830 
831 			if (gVerbose)
832 				{
833 				printf ("TileWidth: %u\n", (unsigned) fTileWidth);
834 				}
835 
836 			#endif
837 
838 			break;
839 
840 			}
841 
842 		case tcTileLength:
843 			{
844 
845 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
846 
847 			CheckTagCount (parentCode, tagCode, tagCount, 1);
848 
849 			fUsesTiles = true;
850 
851 			fTileLength = stream.TagValue_uint32 (tagType);
852 
853 			#if qDNGValidate
854 
855 			if (gVerbose)
856 				{
857 				printf ("TileLength: %u\n", (unsigned) fTileLength);
858 				}
859 
860 			#endif
861 
862 			break;
863 
864 			}
865 
866 		case tcTileOffsets:
867 			{
868 
869 			CheckTagType (parentCode, tagCode, tagType, ttLong);
870 
871 			fUsesTiles = true;
872 
873 			fTileOffsetsType   = tagType;
874 			fTileOffsetsCount  = tagCount;
875 			fTileOffsetsOffset = tagOffset;
876 
877 			if (tagCount <= kMaxTileInfo)
878 				{
879 
880 				for (j = 0; j < tagCount; j++)
881 					{
882 
883 					fTileOffset [j] = stream.TagValue_uint32 (tagType);
884 
885 					}
886 
887 				}
888 
889 			#if qDNGValidate
890 
891 			if (gVerbose)
892 				{
893 
894 				stream.SetReadPosition (tagOffset);
895 
896 				DumpTagValues (stream,
897 							   "Offset",
898 							   parentCode,
899 							   tagCode,
900 							   tagType,
901 							   tagCount);
902 
903 				}
904 
905 			#endif
906 
907 			break;
908 
909 			}
910 
911 		case tcTileByteCounts:
912 			{
913 
914 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
915 
916 			fUsesTiles = true;
917 
918 			fTileByteCountsType   = tagType;
919 			fTileByteCountsCount  = tagCount;
920 			fTileByteCountsOffset = tagOffset;
921 
922 			if (tagCount <= kMaxTileInfo)
923 				{
924 
925 				for (j = 0; j < tagCount; j++)
926 					{
927 
928 					fTileByteCount [j] = stream.TagValue_uint32 (tagType);
929 
930 					}
931 
932 				}
933 
934 			#if qDNGValidate
935 
936 			if (gVerbose)
937 				{
938 
939 				stream.SetReadPosition (tagOffset);
940 
941 				DumpTagValues (stream,
942 							   "Count",
943 							   parentCode,
944 							   tagCode,
945 							   tagType,
946 							   tagCount);
947 
948 				}
949 
950 			#endif
951 
952 			break;
953 
954 			}
955 
956 		case tcSubIFDs:
957 			{
958 
959 			CheckTagType (parentCode, tagCode, tagType, ttLong, ttIFD);
960 
961 			fSubIFDsCount  = tagCount;
962 			fSubIFDsOffset = tagOffset;
963 
964 			#if qDNGValidate
965 
966 			if (gVerbose)
967 				{
968 
969 				DumpTagValues (stream,
970 							   "IFD",
971 							   parentCode,
972 							   tagCode,
973 							   ttLong,
974 							   tagCount);
975 
976 				}
977 
978 			#endif
979 
980 			break;
981 
982 			}
983 
984 		case tcExtraSamples:
985 			{
986 
987 			CheckTagType (parentCode, tagCode, tagType, ttShort);
988 
989 			CheckTagCount (parentCode, tagCode, tagCount, 1, fSamplesPerPixel);
990 
991 			#if qDNGValidate
992 
993 			if (gVerbose)
994 				{
995 				printf ("ExtraSamples:");
996 				}
997 
998 			#endif
999 
1000 			fExtraSamplesCount = tagCount;
1001 
1002 			for (j = 0; j < tagCount; j++)
1003 				{
1004 
1005 				uint32 x = stream.TagValue_uint32 (tagType);
1006 
1007 				if (j < kMaxSamplesPerPixel)
1008 					{
1009 					fExtraSamples [j] = x;
1010 					}
1011 
1012 				#if qDNGValidate
1013 
1014 				if (gVerbose)
1015 					{
1016 					printf (" %u", (unsigned) x);
1017 					}
1018 
1019 				#endif
1020 
1021 				}
1022 
1023 			#if qDNGValidate
1024 
1025 			if (gVerbose)
1026 				{
1027 				printf ("\n");
1028 				}
1029 
1030 			#endif
1031 
1032 			break;
1033 
1034 			}
1035 
1036 		case tcSampleFormat:
1037 			{
1038 
1039 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1040 
1041 			CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel);
1042 
1043 			#if qDNGValidate
1044 
1045 			if (gVerbose)
1046 				{
1047 				printf ("SampleFormat:");
1048 				}
1049 
1050 			#endif
1051 
1052 			bool extrasMatch = true;
1053 
1054 			for (j = 0; j < tagCount; j++)
1055 				{
1056 
1057 				uint32 x = stream.TagValue_uint32 (tagType);
1058 
1059 				if (j < kMaxSamplesPerPixel)
1060 					{
1061 					fSampleFormat [j] = x;
1062 					}
1063 
1064 				else if (x != fSampleFormat [kMaxSamplesPerPixel - 1])
1065 					{
1066 					extrasMatch = false;
1067 					}
1068 
1069 				#if qDNGValidate
1070 
1071 				if (gVerbose)
1072 					{
1073 					printf (" %s", LookupSampleFormat (x));
1074 					}
1075 
1076 				#endif
1077 
1078 				}
1079 
1080 			#if qDNGValidate
1081 
1082 			if (gVerbose)
1083 				{
1084 				printf ("\n");
1085 				}
1086 
1087 			#endif
1088 
1089 			if (!extrasMatch)
1090 				{
1091 
1092 				#if qDNGValidate
1093 
1094 				ReportError ("SampleFormat not constant");
1095 
1096 				#endif
1097 
1098 				ThrowBadFormat ();
1099 
1100 				}
1101 
1102 			break;
1103 
1104 			}
1105 
1106 		case tcJPEGTables:
1107 			{
1108 
1109 			CheckTagType (parentCode, tagCode, tagType, ttUndefined);
1110 
1111 			fJPEGTablesCount  = tagCount;
1112 			fJPEGTablesOffset = tagOffset;
1113 
1114 			#if qDNGValidate
1115 
1116 			if (gVerbose)
1117 				{
1118 
1119 				printf ("JPEGTables: count = %u, offset = %u\n",
1120 						(unsigned) fJPEGTablesCount,
1121 						(unsigned) fJPEGTablesOffset);
1122 
1123 				}
1124 
1125 			#endif
1126 
1127 			break;
1128 
1129 			}
1130 
1131 		case tcJPEGInterchangeFormat:
1132 			{
1133 
1134 			CheckTagType (parentCode, tagCode, tagType, ttLong);
1135 
1136 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1137 
1138 			fJPEGInterchangeFormat = stream.TagValue_uint32 (tagType);
1139 
1140 			#if qDNGValidate
1141 
1142 			if (gVerbose)
1143 				{
1144 				printf ("JPEGInterchangeFormat: %u\n",
1145 						(unsigned) fJPEGInterchangeFormat);
1146 				}
1147 
1148 			#endif
1149 
1150 			break;
1151 
1152 			}
1153 
1154 		case tcJPEGInterchangeFormatLength:
1155 			{
1156 
1157 			CheckTagType (parentCode, tagCode, tagType, ttLong);
1158 
1159 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1160 
1161 			fJPEGInterchangeFormatLength = stream.TagValue_uint32 (tagType);
1162 
1163 			#if qDNGValidate
1164 
1165 			if (gVerbose)
1166 				{
1167 				printf ("JPEGInterchangeFormatLength: %u\n",
1168 						(unsigned) fJPEGInterchangeFormatLength);
1169 				}
1170 
1171 			#endif
1172 
1173 			break;
1174 
1175 			}
1176 
1177 		case tcYCbCrCoefficients:
1178 			{
1179 
1180 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1181 
1182 			if (!CheckTagCount (parentCode, tagCode, tagCount, 3))
1183 				{
1184 				return false;
1185 				}
1186 
1187 			fYCbCrCoefficientR = stream.TagValue_real64 (tagType);
1188 			fYCbCrCoefficientG = stream.TagValue_real64 (tagType);
1189 			fYCbCrCoefficientB = stream.TagValue_real64 (tagType);
1190 
1191 			#if qDNGValidate
1192 
1193 			if (gVerbose)
1194 				{
1195 
1196 				printf ("YCbCrCoefficients: R = %0.3f, G = %0.3f, B = %0.3f\n",
1197 						fYCbCrCoefficientR,
1198 						fYCbCrCoefficientG,
1199 						fYCbCrCoefficientB);
1200 
1201 				}
1202 
1203 			#endif
1204 
1205 			break;
1206 
1207 			}
1208 
1209 		case tcYCbCrSubSampling:
1210 			{
1211 
1212 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1213 
1214 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1215 				{
1216 				return false;
1217 				}
1218 
1219 			fYCbCrSubSampleH = stream.TagValue_uint32 (tagType);
1220 			fYCbCrSubSampleV = stream.TagValue_uint32 (tagType);
1221 
1222 			#if qDNGValidate
1223 
1224 			if (gVerbose)
1225 				{
1226 
1227 				printf ("YCbCrSubSampling: H = %u, V = %u\n",
1228 						(unsigned) fYCbCrSubSampleH,
1229 						(unsigned) fYCbCrSubSampleV);
1230 
1231 				}
1232 
1233 			#endif
1234 
1235 			break;
1236 
1237 			}
1238 
1239 		case tcYCbCrPositioning:
1240 			{
1241 
1242 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1243 
1244 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1245 
1246 			fYCbCrPositioning = stream.TagValue_uint32 (tagType);
1247 
1248 			#if qDNGValidate
1249 
1250 			if (gVerbose)
1251 				{
1252 
1253 				printf ("YCbCrPositioning: %u\n",
1254 						(unsigned) fYCbCrPositioning);
1255 
1256 				}
1257 
1258 			#endif
1259 
1260 			break;
1261 
1262 			}
1263 
1264 		case tcReferenceBlackWhite:
1265 			{
1266 
1267 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1268 
1269 			if (!CheckTagCount (parentCode, tagCode, tagCount, 6))
1270 				{
1271 				return false;
1272 				}
1273 
1274 			for (j = 0; j < 6; j++)
1275 				{
1276 				fReferenceBlackWhite [j] = stream.TagValue_real64 (tagType);
1277 				}
1278 
1279 			#if qDNGValidate
1280 
1281 			if (gVerbose)
1282 				{
1283 
1284 				printf ("ReferenceBlackWhite: %0.1f %0.1f %0.1f %0.1f %0.1f %0.1f\n",
1285 						fReferenceBlackWhite [0],
1286 						fReferenceBlackWhite [1],
1287 						fReferenceBlackWhite [2],
1288 						fReferenceBlackWhite [3],
1289 						fReferenceBlackWhite [4],
1290 						fReferenceBlackWhite [5]);
1291 
1292 				}
1293 
1294 			#endif
1295 
1296 			break;
1297 
1298 			}
1299 
1300 		case tcCFARepeatPatternDim:
1301 			{
1302 
1303 			CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1304 
1305 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1306 
1307 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1308 				{
1309 				return false;
1310 				}
1311 
1312 			fCFARepeatPatternRows = stream.TagValue_uint32 (tagType);
1313 			fCFARepeatPatternCols = stream.TagValue_uint32 (tagType);
1314 
1315 			#if qDNGValidate
1316 
1317 			if (gVerbose)
1318 				{
1319 
1320 				printf ("CFARepeatPatternDim: Rows = %u, Cols = %u\n",
1321 						(unsigned) fCFARepeatPatternRows,
1322 						(unsigned) fCFARepeatPatternCols);
1323 
1324 				}
1325 
1326 			#endif
1327 
1328 			break;
1329 
1330 			}
1331 
1332 		case tcCFAPattern:
1333 			{
1334 
1335 			CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1336 
1337 			if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
1338 				{
1339 				return false;
1340 				}
1341 
1342 			if (!CheckTagCount (parentCode, tagCode, tagCount, fCFARepeatPatternRows *
1343 															   fCFARepeatPatternCols))
1344 				{
1345 				return false;
1346 				}
1347 
1348 			if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
1349 				fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
1350 				{
1351 				return false;
1352 				}
1353 
1354 			// Note that the Exif spec stores this array in a different
1355 			// scan order than the TIFF-EP spec.
1356 
1357 			for (j = 0; j < fCFARepeatPatternRows; j++)
1358 				for (k = 0; k < fCFARepeatPatternCols; k++)
1359 					{
1360 
1361 					fCFAPattern [j] [k] = stream.Get_uint8 ();
1362 
1363 					}
1364 
1365 			#if qDNGValidate
1366 
1367 			if (gVerbose)
1368 				{
1369 
1370 				printf ("CFAPattern:\n");
1371 
1372 				for (j = 0; j < fCFARepeatPatternRows; j++)
1373 					{
1374 
1375 					int32 spaces = 4;
1376 
1377 					for (k = 0; k < fCFARepeatPatternCols; k++)
1378 						{
1379 
1380 						while (spaces-- > 0)
1381 							{
1382 							printf (" ");
1383 							}
1384 
1385 						const char *name = LookupCFAColor (fCFAPattern [j] [k]);
1386 
1387 						spaces = 9 - (int32) strlen (name);
1388 
1389 						printf ("%s", name);
1390 
1391 						}
1392 
1393 					printf ("\n");
1394 
1395 					}
1396 
1397 				}
1398 
1399 			#endif
1400 
1401 			break;
1402 
1403 			}
1404 
1405 		case tcCFAPlaneColor:
1406 			{
1407 
1408 			CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1409 
1410 			if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
1411 				{
1412 				return false;
1413 				}
1414 
1415 			if (!CheckTagCount (parentCode, tagCode, tagCount, 3, kMaxColorPlanes))
1416 				{
1417 				return false;
1418 				}
1419 
1420 			for (j = 0; j < kMaxColorPlanes; j++)
1421 				{
1422 
1423 				if (j < tagCount)
1424 					fCFAPlaneColor [j] = stream.Get_uint8 ();
1425 
1426 				else
1427 					fCFAPlaneColor [j] = 255;
1428 
1429 				}
1430 
1431 			#if qDNGValidate
1432 
1433 			if (gVerbose)
1434 				{
1435 
1436 				printf ("CFAPlaneColor:");
1437 
1438 				for (j = 0; j < tagCount; j++)
1439 					{
1440 
1441 					printf (" %s", LookupCFAColor (fCFAPlaneColor [j]));
1442 
1443 					}
1444 
1445 				printf ("\n");
1446 
1447 				}
1448 
1449 			#endif
1450 
1451 			break;
1452 
1453 			}
1454 
1455 		case tcCFALayout:
1456 			{
1457 
1458 			CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1459 
1460 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1461 
1462 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1463 
1464 			fCFALayout = stream.TagValue_uint32 (tagType);
1465 
1466 			#if qDNGValidate
1467 
1468 			if (gVerbose)
1469 				{
1470 
1471 				printf ("CFALayout: %s\n",
1472 						LookupCFALayout (fCFALayout));
1473 
1474 				}
1475 
1476 			#endif
1477 
1478 			break;
1479 
1480 			}
1481 
1482 		case tcLinearizationTable:
1483 			{
1484 
1485 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1486 
1487 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1488 
1489 			fLinearizationTableType   = tagType;
1490 			fLinearizationTableCount  = tagCount;
1491 			fLinearizationTableOffset = tagOffset;
1492 
1493 			#if qDNGValidate
1494 
1495 			if (gVerbose)
1496 				{
1497 
1498 				DumpTagValues (stream,
1499 							   "Table",
1500 							   parentCode,
1501 							   tagCode,
1502 							   tagType,
1503 							   tagCount);
1504 
1505 				}
1506 
1507 			#endif
1508 
1509 			break;
1510 
1511 			}
1512 
1513 		case tcBlackLevelRepeatDim:
1514 			{
1515 
1516 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1517 
1518 			CheckTagType (parentCode, tagCode, tagType, ttShort);
1519 
1520 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1521 				{
1522 				return false;
1523 				}
1524 
1525 			fBlackLevelRepeatRows = stream.TagValue_uint32 (tagType);
1526 			fBlackLevelRepeatCols = stream.TagValue_uint32 (tagType);
1527 
1528 			#if qDNGValidate
1529 
1530 			if (gVerbose)
1531 				{
1532 
1533 				printf ("BlackLevelRepeatDim: Rows = %u, Cols = %u\n",
1534 						(unsigned) fBlackLevelRepeatRows,
1535 						(unsigned) fBlackLevelRepeatCols);
1536 
1537 				}
1538 
1539 			#endif
1540 
1541 			break;
1542 
1543 			}
1544 
1545 		case tcBlackLevel:
1546 			{
1547 
1548 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1549 
1550 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1551 
1552 			if (!CheckTagCount (parentCode, tagCode, tagCount, fBlackLevelRepeatRows *
1553 															   fBlackLevelRepeatCols *
1554 															   fSamplesPerPixel))
1555 				{
1556 				return false;
1557 				}
1558 
1559 			if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern   ||
1560 				fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern   ||
1561 				fSamplesPerPixel      < 1 || fSamplesPerPixel      > kMaxSamplesPerPixel)
1562 				{
1563 				return false;
1564 				}
1565 
1566 			for (j = 0; j < fBlackLevelRepeatRows; j++)
1567 				for (k = 0; k < fBlackLevelRepeatCols; k++)
1568 					for (n = 0; n < fSamplesPerPixel; n++)
1569 						{
1570 
1571 						fBlackLevel [j] [k] [n] = stream.TagValue_real64 (tagType);
1572 
1573 						}
1574 
1575 			#if qDNGValidate
1576 
1577 			if (gVerbose)
1578 				{
1579 
1580 				printf ("BlackLevel:");
1581 
1582 				if (fBlackLevelRepeatRows == 1 &&
1583 					fBlackLevelRepeatCols == 1)
1584 					{
1585 
1586 					for (n = 0; n < fSamplesPerPixel; n++)
1587 						{
1588 						printf (" %0.2f", fBlackLevel [0] [0] [n]);
1589 						}
1590 
1591 					printf ("\n");
1592 
1593 					}
1594 
1595 				else
1596 					{
1597 
1598 					printf ("\n");
1599 
1600 					for (n = 0; n < fSamplesPerPixel; n++)
1601 						{
1602 
1603 						if (fSamplesPerPixel > 1)
1604 							{
1605 							printf ("    Sample: %u\n", (unsigned) n);
1606 							}
1607 
1608 						for (j = 0; j < fBlackLevelRepeatRows; j++)
1609 							{
1610 
1611 							printf ("   ");
1612 
1613 							for (k = 0; k < fBlackLevelRepeatCols; k++)
1614 								{
1615 
1616 								printf (" %8.2f", fBlackLevel [j] [k] [n]);
1617 
1618 								}
1619 
1620 							printf ("\n");
1621 
1622 							}
1623 
1624 						}
1625 
1626 					}
1627 
1628 				}
1629 
1630 			#endif
1631 
1632 			break;
1633 
1634 			}
1635 
1636 		case tcBlackLevelDeltaH:
1637 			{
1638 
1639 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1640 
1641 			CheckTagType (parentCode, tagCode, tagType, ttSRational);
1642 
1643 			fBlackLevelDeltaHType   = tagType;
1644 			fBlackLevelDeltaHCount  = tagCount;
1645 			fBlackLevelDeltaHOffset = tagOffset;
1646 
1647 			#if qDNGValidate
1648 
1649 			if (gVerbose)
1650 				{
1651 
1652 				DumpTagValues (stream,
1653 							   "Delta",
1654 							   parentCode,
1655 							   tagCode,
1656 							   tagType,
1657 							   tagCount);
1658 
1659 				}
1660 
1661 			#endif
1662 
1663 			break;
1664 
1665 			}
1666 
1667 		case tcBlackLevelDeltaV:
1668 			{
1669 
1670 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1671 
1672 			CheckTagType (parentCode, tagCode, tagType, ttSRational);
1673 
1674 			fBlackLevelDeltaVType   = tagType;
1675 			fBlackLevelDeltaVCount  = tagCount;
1676 			fBlackLevelDeltaVOffset = tagOffset;
1677 
1678 			#if qDNGValidate
1679 
1680 			if (gVerbose)
1681 				{
1682 
1683 				DumpTagValues (stream,
1684 							   "Delta",
1685 							   parentCode,
1686 							   tagCode,
1687 							   tagType,
1688 							   tagCount);
1689 
1690 				}
1691 
1692 			#endif
1693 
1694 			break;
1695 
1696 			}
1697 
1698 		case tcWhiteLevel:
1699 			{
1700 
1701 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
1702 
1703 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1704 
1705 			if (!CheckTagCount (parentCode, tagCode, tagCount, fSamplesPerPixel))
1706 				return false;
1707 
1708 			for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
1709 				{
1710 
1711 				fWhiteLevel [j] = stream.TagValue_real64 (tagType);
1712 
1713 				}
1714 
1715 			#if qDNGValidate
1716 
1717 			if (gVerbose)
1718 				{
1719 
1720 				printf ("WhiteLevel:");
1721 
1722 				for (j = 0; j < tagCount && j < kMaxSamplesPerPixel; j++)
1723 					{
1724 
1725 					printf (" %0.0f", fWhiteLevel [j]);
1726 
1727 					}
1728 
1729 				printf ("\n");
1730 
1731 				}
1732 
1733 			#endif
1734 
1735 			break;
1736 
1737 			}
1738 
1739 		case tcDefaultScale:
1740 			{
1741 
1742 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1743 
1744 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1745 
1746 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1747 				return false;
1748 
1749 			fDefaultScaleH = stream.TagValue_urational (tagType);
1750 			fDefaultScaleV = stream.TagValue_urational (tagType);
1751 
1752 			#if qDNGValidate
1753 
1754 			if (gVerbose)
1755 				{
1756 
1757 				printf ("DefaultScale: H = %0.4f V = %0.4f\n",
1758 						fDefaultScaleH.As_real64 (),
1759 						fDefaultScaleV.As_real64 ());
1760 
1761 				}
1762 
1763 			#endif
1764 
1765 			break;
1766 
1767 			}
1768 
1769 		case tcDefaultCropOrigin:
1770 			{
1771 
1772 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1773 
1774 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1775 
1776 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1777 				return false;
1778 
1779 			fDefaultCropOriginH = stream.TagValue_urational (tagType);
1780 			fDefaultCropOriginV = stream.TagValue_urational (tagType);
1781 
1782 			#if qDNGValidate
1783 
1784 			if (gVerbose)
1785 				{
1786 
1787 				printf ("DefaultCropOrigin: H = %0.2f V = %0.2f\n",
1788 						fDefaultCropOriginH.As_real64 (),
1789 						fDefaultCropOriginV.As_real64 ());
1790 
1791 				}
1792 
1793 			#endif
1794 
1795 			break;
1796 
1797 			}
1798 
1799 		case tcDefaultCropSize:
1800 			{
1801 
1802 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1803 
1804 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong, ttRational);
1805 
1806 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
1807 				return false;
1808 
1809 			fDefaultCropSizeH = stream.TagValue_urational (tagType);
1810 			fDefaultCropSizeV = stream.TagValue_urational (tagType);
1811 
1812 			#if qDNGValidate
1813 
1814 			if (gVerbose)
1815 				{
1816 
1817 				printf ("DefaultCropSize: H = %0.2f V = %0.2f\n",
1818 						fDefaultCropSizeH.As_real64 (),
1819 						fDefaultCropSizeV.As_real64 ());
1820 
1821 				}
1822 
1823 			#endif
1824 
1825 			break;
1826 
1827 			}
1828 
1829 		case tcDefaultUserCrop:
1830 			{
1831 
1832 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1833 
1834 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1835 
1836 			if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
1837 				return false;
1838 
1839 			fDefaultUserCropT = stream.TagValue_urational (tagType);
1840 			fDefaultUserCropL = stream.TagValue_urational (tagType);
1841 			fDefaultUserCropB = stream.TagValue_urational (tagType);
1842 			fDefaultUserCropR = stream.TagValue_urational (tagType);
1843 
1844 			#if qDNGValidate
1845 
1846 			if (gVerbose)
1847 				{
1848 
1849 				printf ("DefaultUserCrop: T = %0.2lf L = %0.2lf B = %0.2lf R = %0.2lf\n",
1850 						(double) fDefaultUserCropT.As_real64 (),
1851 						(double) fDefaultUserCropL.As_real64 (),
1852 						(double) fDefaultUserCropB.As_real64 (),
1853 						(double) fDefaultUserCropR.As_real64 ());
1854 
1855 
1856 				}
1857 
1858 			#endif	// qDNGValidate
1859 
1860 			break;
1861 
1862 			}
1863 
1864 		case tcBayerGreenSplit:
1865 			{
1866 
1867 			CheckCFA (parentCode, tagCode, fPhotometricInterpretation);
1868 
1869 			CheckTagType (parentCode, tagCode, tagType, ttLong);
1870 
1871 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1872 
1873 			fBayerGreenSplit = stream.TagValue_uint32 (tagType);
1874 
1875 			#if qDNGValidate
1876 
1877 			if (gVerbose)
1878 				{
1879 				printf ("BayerGreenSplit: %u\n", (unsigned) fBayerGreenSplit);
1880 				}
1881 
1882 			#endif
1883 
1884 			break;
1885 
1886 			}
1887 
1888 		case tcChromaBlurRadius:
1889 			{
1890 
1891 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1892 
1893 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1894 
1895 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1896 
1897 			fChromaBlurRadius = stream.TagValue_urational (tagType);
1898 
1899 			#if qDNGValidate
1900 
1901 			if (gVerbose)
1902 				{
1903 
1904 				printf ("ChromaBlurRadius: %0.2f\n",
1905 						fChromaBlurRadius.As_real64 ());
1906 
1907 				}
1908 
1909 			#endif
1910 
1911 			break;
1912 
1913 			}
1914 
1915 		case tcAntiAliasStrength:
1916 			{
1917 
1918 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1919 
1920 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1921 
1922 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1923 
1924 			fAntiAliasStrength = stream.TagValue_urational (tagType);
1925 
1926 			#if qDNGValidate
1927 
1928 			if (gVerbose)
1929 				{
1930 
1931 				printf ("AntiAliasStrength: %0.2f\n",
1932 						fAntiAliasStrength.As_real64 ());
1933 
1934 				}
1935 
1936 			#endif
1937 
1938 			break;
1939 
1940 			}
1941 
1942 		case tcBestQualityScale:
1943 			{
1944 
1945 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1946 
1947 			CheckTagType (parentCode, tagCode, tagType, ttRational);
1948 
1949 			CheckTagCount (parentCode, tagCode, tagCount, 1);
1950 
1951 			fBestQualityScale = stream.TagValue_urational (tagType);
1952 
1953 			#if qDNGValidate
1954 
1955 			if (gVerbose)
1956 				{
1957 
1958 				printf ("BestQualityScale: %0.4f\n",
1959 						fBestQualityScale.As_real64 ());
1960 
1961 				}
1962 
1963 			#endif
1964 
1965 			break;
1966 
1967 			}
1968 
1969 		case tcActiveArea:
1970 			{
1971 
1972 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
1973 
1974 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
1975 
1976 			if (!CheckTagCount (parentCode, tagCode, tagCount, 4))
1977 				return false;
1978 
1979 			fActiveArea.t = stream.TagValue_int32 (tagType);
1980 			fActiveArea.l = stream.TagValue_int32 (tagType);
1981 			fActiveArea.b = stream.TagValue_int32 (tagType);
1982 			fActiveArea.r = stream.TagValue_int32 (tagType);
1983 
1984 			#if qDNGValidate
1985 
1986 			if (gVerbose)
1987 				{
1988 
1989 				printf ("ActiveArea: T = %d L = %d B = %d R = %d\n",
1990 						(int) fActiveArea.t,
1991 						(int) fActiveArea.l,
1992 						(int) fActiveArea.b,
1993 						(int) fActiveArea.r);
1994 
1995 				}
1996 
1997 			#endif
1998 
1999 			break;
2000 
2001 			}
2002 
2003 		case tcMaskedAreas:
2004 			{
2005 
2006 			CheckMainIFD (parentCode, tagCode, fNewSubFileType);
2007 
2008 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2009 
2010 			uint32 rect_count = tagCount / 4;
2011 
2012 			if (!CheckTagCount (parentCode, tagCode, tagCount, rect_count * 4))
2013 				return false;
2014 
2015 			fMaskedAreaCount = rect_count;
2016 
2017 			if (fMaskedAreaCount > kMaxMaskedAreas)
2018 				fMaskedAreaCount = kMaxMaskedAreas;
2019 
2020 			for (j = 0; j < fMaskedAreaCount; j++)
2021 				{
2022 
2023 				fMaskedArea [j].t = stream.TagValue_int32 (tagType);
2024 				fMaskedArea [j].l = stream.TagValue_int32 (tagType);
2025 				fMaskedArea [j].b = stream.TagValue_int32 (tagType);
2026 				fMaskedArea [j].r = stream.TagValue_int32 (tagType);
2027 
2028 				}
2029 
2030 			#if qDNGValidate
2031 
2032 			if (gVerbose)
2033 				{
2034 
2035 				printf ("MaskedAreas: %u\n", (unsigned) fMaskedAreaCount);
2036 
2037 				for (j = 0; j < fMaskedAreaCount; j++)
2038 					{
2039 
2040 					printf ("    Area [%u]: T = %d L = %d B = %d R = %d\n",
2041 							(unsigned) j,
2042 							(int) fMaskedArea [j].t,
2043 							(int) fMaskedArea [j].l,
2044 							(int) fMaskedArea [j].b,
2045 							(int) fMaskedArea [j].r);
2046 
2047 					}
2048 
2049 				}
2050 
2051 			#endif
2052 
2053 			break;
2054 
2055 			}
2056 
2057 		case tcPreviewApplicationName:
2058 			{
2059 
2060 			CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2061 
2062 			ParseStringTag (stream,
2063 							parentCode,
2064 							tagCode,
2065 							tagCount,
2066 							fPreviewInfo.fApplicationName,
2067 							false);
2068 
2069 			#if qDNGValidate
2070 
2071 			if (gVerbose)
2072 				{
2073 
2074 				printf ("PreviewApplicationName: ");
2075 
2076 				DumpString (fPreviewInfo.fApplicationName);
2077 
2078 				printf ("\n");
2079 
2080 				}
2081 
2082 			#endif
2083 
2084 			break;
2085 
2086 			}
2087 
2088 		case tcPreviewApplicationVersion:
2089 			{
2090 
2091 			CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2092 
2093 			ParseStringTag (stream,
2094 							parentCode,
2095 							tagCode,
2096 							tagCount,
2097 							fPreviewInfo.fApplicationVersion,
2098 							false);
2099 
2100 			#if qDNGValidate
2101 
2102 			if (gVerbose)
2103 				{
2104 
2105 				printf ("PreviewApplicationVersion: ");
2106 
2107 				DumpString (fPreviewInfo.fApplicationVersion);
2108 
2109 				printf ("\n");
2110 
2111 				}
2112 
2113 			#endif
2114 
2115 			break;
2116 
2117 			}
2118 
2119 		case tcPreviewSettingsName:
2120 			{
2121 
2122 			CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2123 
2124 			ParseStringTag (stream,
2125 							parentCode,
2126 							tagCode,
2127 							tagCount,
2128 							fPreviewInfo.fSettingsName,
2129 							false);
2130 
2131 			#if qDNGValidate
2132 
2133 			if (gVerbose)
2134 				{
2135 
2136 				printf ("PreviewSettingsName: ");
2137 
2138 				DumpString (fPreviewInfo.fSettingsName);
2139 
2140 				printf ("\n");
2141 
2142 				}
2143 
2144 			#endif
2145 
2146 			break;
2147 
2148 			}
2149 
2150 		case tcPreviewSettingsDigest:
2151 			{
2152 
2153 			if (!CheckTagType (parentCode, tagCode, tagType, ttByte))
2154 				return false;
2155 
2156 			if (!CheckTagCount (parentCode, tagCode, tagCount, 16))
2157 				return false;
2158 
2159 			stream.Get (fPreviewInfo.fSettingsDigest.data, 16);
2160 
2161 			#if qDNGValidate
2162 
2163 			if (gVerbose)
2164 				{
2165 
2166 				printf ("PreviewSettingsDigest: ");
2167 
2168 				DumpFingerprint (fPreviewInfo.fSettingsDigest);
2169 
2170 				printf ("\n");
2171 
2172 				}
2173 
2174 			#endif
2175 
2176 			break;
2177 
2178 			}
2179 
2180 		case tcPreviewColorSpace:
2181 			{
2182 
2183 			CheckTagType (parentCode, tagCode, tagType, ttLong);
2184 
2185 			CheckTagCount (parentCode, tagCode, tagCount, 1);
2186 
2187 			fPreviewInfo.fColorSpace = (PreviewColorSpaceEnum)
2188 									   stream.TagValue_uint32 (tagType);
2189 
2190 			#if qDNGValidate
2191 
2192 			if (gVerbose)
2193 				{
2194 
2195 				printf ("PreviewColorSpace: %s\n",
2196 						LookupPreviewColorSpace ((uint32) fPreviewInfo.fColorSpace));
2197 
2198 				}
2199 
2200 			#endif
2201 
2202 			break;
2203 
2204 			}
2205 
2206 		case tcPreviewDateTime:
2207 			{
2208 
2209 			CheckTagType (parentCode, tagCode, tagType, ttAscii);
2210 
2211 			ParseStringTag (stream,
2212 							parentCode,
2213 							tagCode,
2214 							tagCount,
2215 							fPreviewInfo.fDateTime,
2216 							false);
2217 
2218 			#if qDNGValidate
2219 
2220 			if (gVerbose)
2221 				{
2222 
2223 				printf ("PreviewDateTime: ");
2224 
2225 				DumpString (fPreviewInfo.fDateTime);
2226 
2227 				printf ("\n");
2228 
2229 				}
2230 
2231 			#endif
2232 
2233 			break;
2234 
2235 			}
2236 
2237 		case tcRowInterleaveFactor:
2238 			{
2239 
2240 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2241 
2242 			if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2243 				return false;
2244 
2245 			fRowInterleaveFactor = stream.TagValue_uint32 (tagType);
2246 
2247 			#if qDNGValidate
2248 
2249 			if (gVerbose)
2250 				{
2251 
2252 				printf ("RowInterleaveFactor: %u\n",
2253 						(unsigned) fRowInterleaveFactor);
2254 
2255 				}
2256 
2257 			#endif
2258 
2259 			break;
2260 
2261 			}
2262 
2263 		case tcSubTileBlockSize:
2264 			{
2265 
2266 			CheckTagType (parentCode, tagCode, tagType, ttShort, ttLong);
2267 
2268 			if (!CheckTagCount (parentCode, tagCode, tagCount, 2))
2269 				return false;
2270 
2271 			fSubTileBlockRows = stream.TagValue_uint32 (tagType);
2272 			fSubTileBlockCols = stream.TagValue_uint32 (tagType);
2273 
2274 			#if qDNGValidate
2275 
2276 			if (gVerbose)
2277 				{
2278 
2279 				printf ("SubTileBlockSize: rows = %u, cols = %u\n",
2280 						(unsigned) fSubTileBlockRows,
2281 						(unsigned) fSubTileBlockCols);
2282 
2283 				}
2284 
2285 			#endif
2286 
2287 			break;
2288 
2289 			}
2290 
2291 		case tcOpcodeList1:
2292 			{
2293 
2294 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2295 
2296 			CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2297 
2298 			fOpcodeList1Count  = tagCount;
2299 			fOpcodeList1Offset = tagOffset;
2300 
2301 			#if qDNGValidate
2302 
2303 			if (gVerbose)
2304 				{
2305 
2306 				printf ("OpcodeList1: count = %u, offset = %u\n",
2307 						(unsigned) fOpcodeList1Count,
2308 						(unsigned) fOpcodeList1Offset);
2309 
2310 				}
2311 
2312 			#endif
2313 
2314 			break;
2315 
2316 			}
2317 
2318 		case tcOpcodeList2:
2319 			{
2320 
2321 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2322 
2323 			CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2324 
2325 			fOpcodeList2Count  = tagCount;
2326 			fOpcodeList2Offset = tagOffset;
2327 
2328 			#if qDNGValidate
2329 
2330 			if (gVerbose)
2331 				{
2332 
2333 				printf ("OpcodeList2: count = %u, offset = %u\n",
2334 						(unsigned) fOpcodeList2Count,
2335 						(unsigned) fOpcodeList2Offset);
2336 
2337 				}
2338 
2339 			#endif
2340 
2341 			break;
2342 
2343 			}
2344 
2345 		case tcOpcodeList3:
2346 			{
2347 
2348 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2349 
2350 			CheckTagType (parentCode, tagCode, tagType, ttUndefined);
2351 
2352 			fOpcodeList3Count  = tagCount;
2353 			fOpcodeList3Offset = tagOffset;
2354 
2355 			#if qDNGValidate
2356 
2357 			if (gVerbose)
2358 				{
2359 
2360 				printf ("OpcodeList3: count = %u, offset = %u\n",
2361 						(unsigned) fOpcodeList3Count,
2362 						(unsigned) fOpcodeList3Offset);
2363 
2364 				}
2365 
2366 			#endif
2367 
2368 			break;
2369 
2370 			}
2371 
2372 		case tcRawToPreviewGain:
2373 			{
2374 
2375 			#if qDNGValidate
2376 
2377 			if (fNewSubFileType != sfPreviewImage)
2378 				{
2379 
2380 				char message [256];
2381 
2382 				sprintf (message,
2383 						 "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
2384 						 LookupParentCode (parentCode),
2385 						 LookupTagCode (parentCode, tagCode));
2386 
2387 				ReportWarning (message);
2388 
2389 				}
2390 
2391 			#endif
2392 
2393 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2394 
2395 			CheckTagType (parentCode, tagCode, tagType, ttDouble);
2396 
2397 			if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2398 				return false;
2399 
2400 			fPreviewInfo.fRawToPreviewGain = stream.TagValue_real64 (tagType);
2401 
2402 			#if qDNGValidate
2403 
2404 			if (gVerbose)
2405 				{
2406 
2407 				printf ("RawToPreviewGain = %f\n",
2408 						fPreviewInfo.fRawToPreviewGain);
2409 
2410 				}
2411 
2412 			#endif
2413 
2414 			break;
2415 
2416 			}
2417 
2418 		case tcNoiseProfile:
2419 			{
2420 
2421 			if (!CheckTagType (parentCode, tagCode, tagType, ttDouble))
2422 				return false;
2423 
2424 			// This tag will be parsed even in non-raw IFDs (such as
2425 			// thumbnails, previews, etc.) to support legacy DNGs that have
2426 			// the tag in the wrong IFD, but we'll now issue a warning.
2427             // (Turn off the warning for IFD0 since we are writing it
2428             // there for backward compatiblity).
2429 
2430             if (parentCode != 0)
2431                 {
2432 
2433 			    CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2434 
2435                 }
2436 
2437 			// Must be an even, positive number of doubles in a noise profile.
2438 
2439 			if (!tagCount || (tagCount & 1))
2440 				return false;
2441 
2442 			// Determine number of planes (i.e., half the number of doubles).
2443 
2444 			const uint32 numPlanes = Pin_uint32 (0,
2445 												 tagCount >> 1,
2446 												 kMaxColorPlanes);
2447 
2448 			// Parse the noise function parameters.
2449 
2450 			dng_std_vector<dng_noise_function> noiseFunctions;
2451 
2452 			for (uint32 i = 0; i < numPlanes; i++)
2453 				{
2454 
2455 				const real64 scale	= stream.TagValue_real64 (tagType);
2456 				const real64 offset = stream.TagValue_real64 (tagType);
2457 
2458 				noiseFunctions.push_back (dng_noise_function (scale, offset));
2459 
2460 				}
2461 
2462 			// Store the noise profile.
2463 
2464 			fNoiseProfile = dng_noise_profile (noiseFunctions);
2465 
2466 			// Debug.
2467 
2468 			#if qDNGValidate
2469 
2470 			if (gVerbose)
2471 				{
2472 
2473 				printf ("NoiseProfile:\n");
2474 
2475 				printf ("  Planes: %u\n", (unsigned) numPlanes);
2476 
2477 				for (uint32 plane = 0; plane < numPlanes; plane++)
2478 					{
2479 
2480 					printf ("  Noise function for plane %u: scale = %.20lf, offset = %.20lf\n",
2481 							(unsigned) plane,
2482 							noiseFunctions [plane].Scale  (),
2483 							noiseFunctions [plane].Offset ());
2484 
2485 					}
2486 
2487 				}
2488 
2489 			#endif
2490 
2491 			break;
2492 
2493 			}
2494 
2495 		case tcCacheVersion:
2496 			{
2497 
2498 			#if qDNGValidate
2499 
2500 			if (fNewSubFileType != sfPreviewImage)
2501 				{
2502 
2503 				char message [256];
2504 
2505 				sprintf (message,
2506 						 "%s %s is not allowed IFDs with NewSubFileType != PreviewImage",
2507 						 LookupParentCode (parentCode),
2508 						 LookupTagCode (parentCode, tagCode));
2509 
2510 				ReportWarning (message);
2511 
2512 				}
2513 
2514 			#endif
2515 
2516 			CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2517 
2518 			CheckTagType (parentCode, tagCode, tagType, ttLong);
2519 
2520 			if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2521 				return false;
2522 
2523 			fPreviewInfo.fCacheVersion = stream.TagValue_uint32 (tagType);
2524 
2525 			#if qDNGValidate
2526 
2527 			if (gVerbose)
2528 				{
2529 
2530 				printf ("CacheVersion = 0x%x\n",
2531 						(unsigned) fPreviewInfo.fCacheVersion);
2532 
2533 				}
2534 
2535 			#endif
2536 
2537 			break;
2538 
2539 			}
2540 
2541         case tcEnhanceParams:
2542             {
2543 
2544             #if qDNGValidate
2545 
2546             if (fNewSubFileType != sfEnhancedImage)
2547                 {
2548 
2549                 char message [256];
2550 
2551                 sprintf (message,
2552                          "%s %s is not allowed IFDs with NewSubFileType != EnhancedImage",
2553                          LookupParentCode (parentCode),
2554                          LookupTagCode (parentCode, tagCode));
2555 
2556                 ReportWarning (message);
2557 
2558                 }
2559 
2560             #endif
2561 
2562             CheckTagType (parentCode, tagCode, tagType, ttAscii, ttByte);
2563 
2564             ParseStringTag (stream,
2565                             parentCode,
2566                             tagCode,
2567                             tagCount,
2568                             fEnhanceParams,
2569                             false);
2570 
2571             #if qDNGValidate
2572 
2573             if (gVerbose)
2574                 {
2575 
2576                 printf ("EnhanceParams: ");
2577 
2578                 DumpString (fEnhanceParams);
2579 
2580                 printf ("\n");
2581 
2582                 }
2583 
2584             #endif
2585 
2586             break;
2587 
2588             }
2589 
2590         case tcBaselineSharpness:
2591             {
2592 
2593             if (fNewSubFileType != sfEnhancedImage)
2594                 {
2595                 return false;
2596                 }
2597 
2598             CheckTagType (parentCode, tagCode, tagType, ttRational);
2599 
2600             CheckTagCount (parentCode, tagCode, tagCount, 1);
2601 
2602             fBaselineSharpness = stream.TagValue_urational (tagType);
2603 
2604             #if qDNGValidate
2605 
2606             if (gVerbose)
2607                 {
2608 
2609                 printf ("BaselineSharpness (EnhancedImage): %0.2f\n",
2610                         fBaselineSharpness.As_real64 ());
2611 
2612                 }
2613 
2614             #endif
2615 
2616             break;
2617 
2618             }
2619 
2620         case tcNoiseReductionApplied:
2621             {
2622 
2623             if (!CheckTagType (parentCode, tagCode, tagType, ttRational))
2624                 return false;
2625 
2626             if (!CheckTagCount (parentCode, tagCode, tagCount, 1))
2627                 return false;
2628 
2629             // This tag will be parsed even in non-raw IFDs (such as
2630             // thumbnails, previews, etc.) to support legacy DNGs that have
2631             // the tag in the wrong IFD, but we'll now issue a warning.
2632             // (Turn off the warning for IFD0 since we are writing it
2633             // there for backward compatiblity).
2634 
2635             if (parentCode != 0)
2636                 {
2637 
2638                 CheckRawIFD (parentCode, tagCode, fPhotometricInterpretation);
2639 
2640                 }
2641 
2642             fNoiseReductionApplied = stream.TagValue_urational (tagType);
2643 
2644             #if qDNGValidate
2645 
2646             if (gVerbose)
2647                 {
2648 
2649                 printf ("NoiseReductionApplied: %u/%u\n",
2650                         (unsigned) fNoiseReductionApplied.n,
2651                         (unsigned) fNoiseReductionApplied.d);
2652 
2653                 }
2654 
2655             #endif
2656 
2657             break;
2658 
2659             }
2660 
2661 		default:
2662 			{
2663 
2664 			return false;
2665 
2666 			}
2667 
2668 		}
2669 
2670 	return true;
2671 
2672 	}
2673 
2674 /*****************************************************************************/
2675 
PostParse()2676 void dng_ifd::PostParse ()
2677 	{
2678 
2679 	uint32 j;
2680 	uint32 k;
2681 
2682 	// There is only one PlanarConfiguration for single sample imaages.
2683 
2684 	if (fSamplesPerPixel == 1)
2685 		{
2686 		fPlanarConfiguration = pcInterleaved;
2687 		}
2688 
2689 	// Default tile size.
2690 
2691 	if (fTileWidth == 0)
2692 		{
2693 		fTileWidth = fImageWidth;
2694 		}
2695 
2696 	if (fTileLength == 0)
2697 		{
2698 		fTileLength = fImageLength;
2699 		}
2700 
2701 	// Default ActiveArea.
2702 
2703 	dng_rect imageArea (0, 0, fImageLength, fImageWidth);
2704 
2705 	if (fActiveArea.IsZero ())
2706 		{
2707 		fActiveArea = imageArea;
2708 		}
2709 
2710 	// Default crop size.
2711 
2712 	if (fDefaultCropSizeH.d == 0)
2713 		{
2714 		fDefaultCropSizeH = dng_urational (fActiveArea.W (), 1);
2715 		}
2716 
2717 	if (fDefaultCropSizeV.d == 0)
2718 		{
2719 		fDefaultCropSizeV = dng_urational (fActiveArea.H (), 1);
2720 		}
2721 
2722 	// Default white level.
2723 
2724 	uint32 defaultWhite = (fSampleFormat [0] == sfFloatingPoint) ?
2725 						  1 :
2726 						  (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
2727 
2728 	for (j = 0; j < kMaxSamplesPerPixel; j++)
2729 		{
2730 
2731 		if (fWhiteLevel [j] < 0.0)
2732 			{
2733 			fWhiteLevel [j] = (real64) defaultWhite;
2734 			}
2735 
2736 		}
2737 
2738 	// Check AntiAliasStrength.
2739 
2740 	if (fAntiAliasStrength.As_real64 () < 0.0 ||
2741 		fAntiAliasStrength.As_real64 () > 1.0)
2742 		{
2743 
2744 		#if qDNGValidate
2745 
2746 		ReportWarning ("Invalid AntiAliasStrength");
2747 
2748 		#endif
2749 
2750 		fAntiAliasStrength = dng_urational (1, 1);
2751 
2752 		}
2753 
2754 	// Check MaskedAreas.
2755 
2756 	for (j = 0; j < fMaskedAreaCount; j++)
2757 		{
2758 
2759 		const dng_rect &r = fMaskedArea [j];
2760 
2761 		if (r.IsEmpty () || ((r & imageArea) != r))
2762 			{
2763 
2764 			#if qDNGValidate
2765 
2766 			ReportWarning ("Invalid MaskedArea");
2767 
2768 			#endif
2769 
2770 			fMaskedAreaCount = 0;
2771 
2772 			break;
2773 
2774 			}
2775 
2776 		if ((r & fActiveArea).NotEmpty ())
2777 			{
2778 
2779 			#if qDNGValidate
2780 
2781 			ReportWarning ("MaskedArea overlaps ActiveArea");
2782 
2783 			#endif
2784 
2785 			fMaskedAreaCount = 0;
2786 
2787 			break;
2788 
2789 			}
2790 
2791 		for (k = 0; k < j; k++)
2792 			{
2793 
2794 			if ((r & fMaskedArea [k]).NotEmpty ())
2795 				{
2796 
2797 				#if qDNGValidate
2798 
2799 				ReportWarning ("MaskedAreas overlap each other");
2800 
2801 				#endif
2802 
2803 				fMaskedAreaCount = 0;
2804 
2805 				break;
2806 
2807 				}
2808 
2809 			}
2810 
2811 		}
2812 
2813 	// Check NoiseProfile.
2814 
2815 	if (!fNoiseProfile.IsValid () && fNoiseProfile.NumFunctions () != 0)
2816 		{
2817 
2818 		#if qDNGValidate
2819 
2820 		ReportWarning ("Invalid NoiseProfile");
2821 
2822 		#endif
2823 
2824 		fNoiseProfile = dng_noise_profile ();
2825 
2826 		}
2827 
2828 	}
2829 
2830 /*****************************************************************************/
2831 
IsValidCFA(dng_shared & shared,uint32 parentCode)2832 bool dng_ifd::IsValidCFA (dng_shared &shared,
2833 						  uint32 parentCode)
2834 	{
2835 
2836 	uint32 j;
2837 	uint32 k;
2838 	uint32 n;
2839 
2840 	#if !qDNGValidate
2841 
2842 	(void) parentCode;			// Unused
2843 
2844 	#endif
2845 
2846 	if (fCFARepeatPatternRows < 1 || fCFARepeatPatternRows > kMaxCFAPattern ||
2847 		fCFARepeatPatternCols < 1 || fCFARepeatPatternCols > kMaxCFAPattern)
2848 		{
2849 
2850 		#if qDNGValidate
2851 
2852 		ReportError ("Missing or invalid CFAPatternRepeatDim",
2853 					 LookupParentCode (parentCode));
2854 
2855 		#endif
2856 
2857 		return false;
2858 
2859 		}
2860 
2861 	uint32 count [kMaxColorPlanes];
2862 
2863 	for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2864 		{
2865 		count [n] = 0;
2866 		}
2867 
2868 	for (j = 0; j < fCFARepeatPatternRows; j++)
2869 		{
2870 
2871 		for (k = 0; k < fCFARepeatPatternCols; k++)
2872 			{
2873 
2874 			bool found = false;
2875 
2876 			for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2877 				{
2878 
2879 				if (fCFAPattern [j] [k] == fCFAPlaneColor [n])
2880 					{
2881 					found = true;
2882 					count [n] ++;
2883 					break;
2884 					}
2885 
2886 				}
2887 
2888 			if (!found)
2889 				{
2890 
2891 				#if qDNGValidate
2892 
2893 				ReportError ("CFAPattern contains colors not included in the CFAPlaneColor tag",
2894 							 LookupParentCode (parentCode));
2895 
2896 				#endif
2897 
2898 				return false;
2899 
2900 				}
2901 
2902 			}
2903 
2904 		}
2905 
2906 	for (n = 0; n < shared.fCameraProfile.fColorPlanes; n++)
2907 		{
2908 
2909 		if (count [n] == 0)
2910 			{
2911 
2912 			#if qDNGValidate
2913 
2914 			ReportError ("CFAPattern does not contain all the colors in the CFAPlaneColor tag",
2915 						 LookupParentCode (parentCode));
2916 
2917 			#endif
2918 
2919 			return false;
2920 
2921 			}
2922 
2923 		}
2924 
2925 	if (fCFALayout < 1 || fCFALayout > 9)
2926 		{
2927 
2928 		#if qDNGValidate
2929 
2930 		ReportError ("Invalid CFALayout",
2931 					 LookupParentCode (parentCode));
2932 
2933 		#endif
2934 
2935 		return false;
2936 
2937 		}
2938 
2939 	return true;
2940 
2941 	}
2942 
2943 /*****************************************************************************/
2944 
IsValidDNG(dng_shared & shared,uint32 parentCode)2945 bool dng_ifd::IsValidDNG (dng_shared &shared,
2946 					      uint32 parentCode)
2947 	{
2948 
2949 	uint32 j;
2950 
2951 	bool isFloatingPoint = (fSampleFormat [0] == sfFloatingPoint);
2952 
2953 	dng_rect imageArea (0, 0, fImageLength, fImageWidth);
2954 
2955 	uint32 defaultWhite = isFloatingPoint ?
2956 						  1 :
2957 						  (uint32) ((((uint64) 1) << fBitsPerSample [0]) - 1);
2958 
2959 	bool isMonochrome = (shared.fCameraProfile.fColorPlanes == 1);
2960 	bool isColor      = !isMonochrome;
2961 
2962 	bool isMainIFD = (fNewSubFileType == sfMainImage);
2963 
2964 	// Check NewSubFileType.
2965 
2966 	if (!fUsesNewSubFileType)
2967 		{
2968 
2969 		#if qDNGValidate
2970 
2971 		ReportError ("Missing NewSubFileType",
2972 					 LookupParentCode (parentCode));
2973 
2974 		#endif
2975 
2976 		return false;
2977 
2978 		}
2979 
2980 	if (fNewSubFileType != sfMainImage		  &&
2981 		fNewSubFileType != sfPreviewImage	  &&
2982 		fNewSubFileType != sfTransparencyMask &&
2983 		fNewSubFileType != sfPreviewMask      &&
2984         fNewSubFileType != sfDepthMap         &&
2985         fNewSubFileType != sfPreviewDepthMap  &&
2986         fNewSubFileType != sfEnhancedImage    &&
2987 		fNewSubFileType != sfAltPreviewImage)
2988 		{
2989 
2990 		#if qDNGValidate
2991 
2992 		ReportError ("Unexpected NewSubFileType",
2993 					 LookupParentCode (parentCode));
2994 
2995 		#endif
2996 
2997 		return false;
2998 
2999 		}
3000 
3001 	// Check ImageWidth and ImageLength.
3002 
3003 	if (fImageWidth < 1)
3004 		{
3005 
3006 		#if qDNGValidate
3007 
3008 		ReportError ("Missing or invalid ImageWidth",
3009 					 LookupParentCode (parentCode));
3010 
3011 		#endif
3012 
3013 		return false;
3014 
3015 		}
3016 
3017 	if (fImageLength < 1)
3018 		{
3019 
3020 		#if qDNGValidate
3021 
3022 		ReportError ("Missing or invalid ImageLength",
3023 					 LookupParentCode (parentCode));
3024 
3025 		#endif
3026 
3027 		return false;
3028 
3029 		}
3030 
3031 	if (fImageWidth  > kMaxImageSide ||
3032 		fImageLength > kMaxImageSide)
3033 		{
3034 
3035 		#if qDNGValidate
3036 
3037 		ReportWarning ("Image size is larger than supported");
3038 
3039 		#endif
3040 
3041 		return false;
3042 
3043 		}
3044 
3045 	// Check PhotometricInterpretation.
3046 
3047 	if (fNewSubFileType == sfTransparencyMask ||
3048 		fNewSubFileType == sfPreviewMask)
3049 		{
3050 
3051 		if (fPhotometricInterpretation != piTransparencyMask)
3052 			{
3053 
3054 			#if qDNGValidate
3055 
3056 			ReportError ("NewSubFileType requires PhotometricInterpretation = TransparencyMask",
3057 						 LookupParentCode (parentCode));
3058 
3059 			#endif
3060 
3061 			return false;
3062 
3063 			}
3064 
3065 		}
3066 
3067     else if (fNewSubFileType == sfDepthMap ||
3068              fNewSubFileType == sfPreviewDepthMap)
3069         {
3070 
3071         if (fPhotometricInterpretation != piDepth)
3072             {
3073 
3074             #if qDNGValidate
3075 
3076             ReportError ("NewSubFileType requires PhotometricInterpretation = Depth",
3077                          LookupParentCode (parentCode));
3078 
3079             #endif
3080 
3081             return false;
3082 
3083             }
3084 
3085         }
3086 
3087 	else
3088 		{
3089 
3090 		switch (fPhotometricInterpretation)
3091 			{
3092 
3093 			case piBlackIsZero:
3094 			case piRGB:
3095 			case piYCbCr:
3096 				{
3097 
3098 				if (isMainIFD)
3099 					{
3100 
3101 					#if qDNGValidate
3102 
3103 					ReportError ("PhotometricInterpretation requires NewSubFileType = 1",
3104 								 LookupParentCode (parentCode));
3105 
3106 					#endif
3107 
3108 					return false;
3109 
3110 					}
3111 
3112 				break;
3113 
3114 				}
3115 
3116 			case piCFA:
3117 				{
3118 
3119 				if (!isMainIFD)
3120 					{
3121 
3122 					#if qDNGValidate
3123 
3124 					ReportError ("PhotometricInterpretation requires NewSubFileType = 0",
3125 								 LookupParentCode (parentCode));
3126 
3127 					#endif
3128 
3129 					return false;
3130 
3131 					}
3132 
3133 				break;
3134 
3135 				}
3136 
3137 			case piLinearRaw:
3138 				break;
3139 
3140 			default:
3141 				{
3142 
3143 				#if qDNGValidate
3144 
3145 				ReportError ("Missing or invalid PhotometricInterpretation",
3146 							 LookupParentCode (parentCode));
3147 
3148 				#endif
3149 
3150 				return false;
3151 
3152 				}
3153 
3154 			}
3155 
3156 		}
3157 
3158 	switch (fPhotometricInterpretation)
3159 		{
3160 
3161 		case piBlackIsZero:
3162 			{
3163 
3164 			// Allow black in white previews even in color images since the
3165 			// raw processing software may be converting to grayscale.
3166 
3167 			if (isColor && isMainIFD)
3168 				{
3169 
3170 				#if qDNGValidate
3171 
3172 				ReportError ("PhotometricInterpretation forbids use of ColorMatrix1 tag",
3173 							 LookupParentCode (parentCode));
3174 
3175 				#endif
3176 
3177 				return false;
3178 
3179 				}
3180 
3181 			break;
3182 
3183 			}
3184 
3185 		case piRGB:
3186 		case piYCbCr:
3187 			{
3188 
3189 			// Allow color previews even in monochrome DNG files, since the
3190 			// raw procesing software may be adding color effects.
3191 
3192 			break;
3193 
3194 			}
3195 
3196 		case piCFA:
3197 			{
3198 
3199 			if (isMonochrome)
3200 				{
3201 
3202 				#if qDNGValidate
3203 
3204 				ReportError ("PhotometricInterpretation requires use of ColorMatrix1 tag",
3205 							 LookupParentCode (parentCode));
3206 
3207 				#endif
3208 
3209 				return false;
3210 
3211 				}
3212 
3213 			break;
3214 
3215 			}
3216 
3217 		}
3218 
3219 	if (isFloatingPoint)
3220 		{
3221 
3222 		if (fPhotometricInterpretation != piCFA &&
3223 			fPhotometricInterpretation != piLinearRaw &&
3224 			fPhotometricInterpretation != piTransparencyMask)
3225 			{
3226 
3227 			#if qDNGValidate
3228 
3229 			ReportError ("Floating point data requires PhotometricInterpretation CFA or LinearRaw or TransparencyMask",
3230 						 LookupParentCode (parentCode));
3231 
3232 			#endif
3233 
3234 			return false;
3235 
3236 			}
3237 
3238 		}
3239 
3240 	// Check SamplesPerPixel and BitsPerSample.
3241 
3242 	uint32 minSamplesPerPixel = 1;
3243 	uint32 maxSamplesPerPixel = 1;
3244 
3245 	uint32 minBitsPerSample = 8;
3246 	uint32 maxBitsPerSample = 16;
3247 
3248 	switch (fPhotometricInterpretation)
3249 		{
3250 
3251 		case piBlackIsZero:
3252 			break;
3253 
3254 		case piRGB:
3255 		case piYCbCr:
3256 			{
3257 			minSamplesPerPixel = 3;
3258 			maxSamplesPerPixel = 3;
3259 			break;
3260 			}
3261 
3262 		case piCFA:
3263 			{
3264 			maxSamplesPerPixel = kMaxSamplesPerPixel;
3265 			maxBitsPerSample   = 32;
3266 			break;
3267 			}
3268 
3269 		case piLinearRaw:
3270 			{
3271 			minSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
3272 			maxSamplesPerPixel = shared.fCameraProfile.fColorPlanes;
3273 			maxBitsPerSample   = 32;
3274 			break;
3275 			}
3276 
3277 		case piTransparencyMask:
3278 			{
3279 			minBitsPerSample = 8;
3280 			maxBitsPerSample = 16;
3281 			break;
3282 			}
3283 
3284         case piDepth:
3285             {
3286             minBitsPerSample = 8;
3287             maxBitsPerSample = 16;
3288             break;
3289             }
3290 
3291 		}
3292 
3293 	if (isFloatingPoint)
3294 		{
3295 		minBitsPerSample = 16;
3296 		maxBitsPerSample = 32;
3297 		}
3298 
3299 	if (fSamplesPerPixel < minSamplesPerPixel ||
3300 		fSamplesPerPixel > maxSamplesPerPixel)
3301 		{
3302 
3303 		#if qDNGValidate
3304 
3305 		ReportError ("Missing or invalid SamplesPerPixel",
3306 					 LookupParentCode (parentCode));
3307 
3308 		#endif
3309 
3310 		return false;
3311 
3312 		}
3313 
3314 	for (j = 0; j < kMaxSamplesPerPixel; j++)
3315 		{
3316 
3317 		if (j < fSamplesPerPixel)
3318 			{
3319 
3320 			if (fBitsPerSample [j] < minBitsPerSample ||
3321 				fBitsPerSample [j] > maxBitsPerSample)
3322 				{
3323 
3324 				#if qDNGValidate
3325 
3326 				ReportError ("Missing or invalid BitsPerSample",
3327 							 LookupParentCode (parentCode));
3328 
3329 				#endif
3330 
3331 				return false;
3332 
3333 				}
3334 
3335 			if (isFloatingPoint &&
3336 				fBitsPerSample [j] != 16 &&
3337 				fBitsPerSample [j] != 24 &&
3338 				fBitsPerSample [j] != 32)
3339 				{
3340 
3341 				#if qDNGValidate
3342 
3343 				ReportError ("Invalid BitsPerSample for floating point",
3344 							 LookupParentCode (parentCode));
3345 
3346 				#endif
3347 
3348 				return false;
3349 
3350 				}
3351 
3352 			if (minBitsPerSample   ==  8 &&
3353 				maxBitsPerSample   == 16 &&
3354 				fBitsPerSample [j] !=  8 &&
3355 				fBitsPerSample [j] != 16)
3356 				{
3357 
3358 				#if qDNGValidate
3359 
3360 				ReportError ("Rendered previews and integer masks require 8 or 16 bits per sample",
3361 							 LookupParentCode (parentCode));
3362 
3363 				#endif
3364 
3365 				return false;
3366 
3367 				}
3368 
3369 			if (j > 0 && fBitsPerSample [j] != fBitsPerSample [0])
3370 				{
3371 
3372 				#if qDNGValidate
3373 
3374 				ReportError ("BitsPerSample not equal for all samples",
3375 							 LookupParentCode (parentCode));
3376 
3377 				#endif
3378 
3379 				return false;
3380 
3381 				}
3382 
3383 			}
3384 
3385 		else
3386 			{
3387 
3388 			if (fBitsPerSample [j] != 0)
3389 				{
3390 
3391 				#if qDNGValidate
3392 
3393 				ReportError ("Too many values specified in BitsPerSample",
3394 							 LookupParentCode (parentCode));
3395 
3396 				#endif
3397 
3398 				return false;
3399 
3400 				}
3401 
3402 			}
3403 
3404 		}
3405 
3406 	// Check Compression.
3407 
3408 	switch (fCompression)
3409 		{
3410 
3411 		case ccUncompressed:
3412 			break;
3413 
3414 		#if qDNGSupportVC5
3415 
3416 		case ccVc5:
3417 			break;
3418 
3419 		#endif	// qDNGSupportVC5
3420 
3421 		case ccJPEG:
3422 			{
3423 
3424 			if (fPhotometricInterpretation == piRGB)
3425 				{
3426 
3427 				#if qDNGValidate
3428 
3429 				ReportError ("JPEG previews should use PhotometricInterpretation = YCbYb",
3430 							 LookupParentCode (parentCode));
3431 
3432 				#endif
3433 
3434 				return false;
3435 
3436 				}
3437 
3438 			if (fBitsPerSample [0] > 16)
3439 				{
3440 
3441 				#if qDNGValidate
3442 
3443 				ReportError ("JPEG compression is limited to 16 bits/sample",
3444 							 LookupParentCode (parentCode));
3445 
3446 				#endif
3447 
3448 				return false;
3449 
3450 				}
3451 
3452 			break;
3453 
3454 			}
3455 
3456 		case ccLossyJPEG:
3457 			{
3458 
3459 			if (fPhotometricInterpretation != piLinearRaw)
3460 				{
3461 
3462 				#if qDNGValidate
3463 
3464 				ReportError ("Lossy JPEG compression code requires PhotometricInterpretation = LinearRaw",
3465 							 LookupParentCode (parentCode));
3466 
3467 				#endif
3468 
3469 				return false;
3470 
3471 				}
3472 
3473 			if (fBitsPerSample [0] != 8)
3474 				{
3475 
3476 				#if qDNGValidate
3477 
3478 				ReportError ("Lossy JPEG compression is limited to 8 bits/sample",
3479 							 LookupParentCode (parentCode));
3480 
3481 				#endif
3482 
3483 				return false;
3484 
3485 				}
3486 
3487 			break;
3488 
3489 			}
3490 
3491 		case ccDeflate:
3492 			{
3493 
3494 			if (!isFloatingPoint &&
3495 				fBitsPerSample [0] != 32 &&
3496 				fPhotometricInterpretation != piTransparencyMask &&
3497                 fPhotometricInterpretation != piDepth)
3498 				{
3499 
3500 				#if qDNGValidate
3501 
3502 				ReportError ("ZIP compression is limited to floating point, 32-bit integer,"
3503                              " transparency masks, and depth maps",
3504 							 LookupParentCode (parentCode));
3505 
3506 				#endif
3507 
3508 				}
3509 
3510 			break;
3511 
3512 			}
3513 
3514 		default:
3515 			{
3516 
3517 			#if qDNGValidate
3518 
3519 			ReportError ("Unsupported Compression",
3520 						 LookupParentCode (parentCode));
3521 
3522 			#endif
3523 
3524 			return false;
3525 
3526 			}
3527 
3528 		}
3529 
3530 	// Check Predictor.
3531 
3532 	if (isFloatingPoint && fCompression == ccDeflate &&
3533 				(fPredictor == cpFloatingPoint   ||
3534 				 fPredictor == cpFloatingPointX2 ||
3535 				 fPredictor == cpFloatingPointX4))
3536 		{
3537 
3538 		// These combinations are supported.
3539 
3540 		}
3541 
3542 	else if (!isFloatingPoint && fCompression == ccDeflate &&
3543 				(fPredictor == cpHorizontalDifference   ||
3544 				 fPredictor == cpHorizontalDifferenceX2 ||
3545 				 fPredictor == cpHorizontalDifferenceX4))
3546 		{
3547 
3548 		// These combinations are supported.
3549 
3550 		}
3551 
3552 	else if (fPredictor != cpNullPredictor)
3553 		{
3554 
3555 		#if qDNGValidate
3556 
3557 		ReportError ("Unsupported Predictor",
3558 					 LookupParentCode (parentCode));
3559 
3560 		#endif
3561 
3562 		return false;
3563 
3564 		}
3565 
3566 	// Check FillOrder.
3567 
3568 	if (fFillOrder != 1)
3569 		{
3570 
3571 		#if qDNGValidate
3572 
3573 		ReportError ("Unsupported FillOrder",
3574 					 LookupParentCode (parentCode));
3575 
3576 		#endif
3577 
3578 		return false;
3579 
3580 		}
3581 
3582 	// Check PlanarConfiguration.
3583 
3584 	if (fPlanarConfiguration != pcInterleaved)
3585 		{
3586 
3587 		#if qDNGValidate
3588 
3589 		ReportError ("Unsupported PlanarConfiguration",
3590 					 LookupParentCode (parentCode));
3591 
3592 		#endif
3593 
3594 		return false;
3595 
3596 		}
3597 
3598 	// Check ExtraSamples.
3599 
3600 	if (fExtraSamplesCount != 0)
3601 		{
3602 
3603 		#if qDNGValidate
3604 
3605 		ReportError ("Unsupported ExtraSamples",
3606 					 LookupParentCode (parentCode));
3607 
3608 		#endif
3609 
3610 		return false;
3611 
3612 		}
3613 
3614 	// Check SampleFormat.
3615 
3616 	for (j = 0; j < fSamplesPerPixel; j++)
3617 		{
3618 
3619 		if (fSampleFormat [j] != (isFloatingPoint ? sfFloatingPoint : sfUnsignedInteger))
3620 			{
3621 
3622 			#if qDNGValidate
3623 
3624 			ReportError ("Unsupported SampleFormat",
3625 						 LookupParentCode (parentCode));
3626 
3627 			#endif
3628 
3629 			return false;
3630 
3631 			}
3632 
3633 		}
3634 
3635 	// Check Orientation.
3636 
3637 	if (fOrientation > 9)
3638 		{
3639 
3640 		#if qDNGValidate
3641 
3642 		ReportError ("Unknown Orientation",
3643 					 LookupParentCode (parentCode));
3644 
3645 		#endif
3646 
3647 		return false;
3648 
3649 		}
3650 
3651 	#if qDNGValidate
3652 
3653 	if (fOrientation != 0 && parentCode != 0)
3654 		{
3655 
3656 		ReportWarning ("Unexpected Orientation tag",
3657 					   LookupParentCode (parentCode));
3658 
3659 		}
3660 
3661 	if (fOrientation == 0 && parentCode == 0)
3662 		{
3663 
3664 		ReportWarning ("Missing Orientation tag",
3665 					   LookupParentCode (parentCode));
3666 
3667 		}
3668 
3669 	#endif
3670 
3671 	// Check Strips vs. Tiles.
3672 
3673 	if (!fUsesStrips && !fUsesTiles)
3674 		{
3675 
3676 		#if qDNGValidate
3677 
3678 		ReportError ("IFD uses neither strips nor tiles",
3679 					 LookupParentCode (parentCode));
3680 
3681 		#endif
3682 
3683 		return false;
3684 
3685 		}
3686 
3687 	if (fUsesStrips && fUsesTiles)
3688 		{
3689 
3690 		#if qDNGValidate
3691 
3692 		ReportError ("IFD uses both strips and tiles",
3693 					 LookupParentCode (parentCode));
3694 
3695 		#endif
3696 
3697 		return false;
3698 
3699 		}
3700 
3701 	// Check tile info.
3702 
3703 	uint32 tilesWide = (fImageWidth  + fTileWidth  - 1) / fTileWidth;
3704 	uint32 tilesHigh = (fImageLength + fTileLength - 1) / fTileLength;
3705 
3706 	uint32 tileCount = tilesWide * tilesHigh;
3707 
3708 	if (fTileOffsetsCount != tileCount)
3709 		{
3710 
3711 		#if qDNGValidate
3712 
3713 		ReportError ("Missing or invalid Strip/TileOffsets",
3714 					 LookupParentCode (parentCode));
3715 
3716 		#endif
3717 
3718 		return false;
3719 
3720 		}
3721 
3722 	if (fTileByteCountsCount != tileCount)
3723 		{
3724 
3725 		#if qDNGValidate
3726 
3727 		ReportError ("Missing or invalid Strip/TileByteCounts",
3728 					 LookupParentCode (parentCode));
3729 
3730 		#endif
3731 
3732 		return false;
3733 
3734 		}
3735 
3736 	// Check CFA pattern.
3737 
3738 	if (fPhotometricInterpretation == piCFA)
3739 		{
3740 
3741 		if (!IsValidCFA (shared, parentCode))
3742 			{
3743 
3744 			return false;
3745 
3746 			}
3747 
3748 		}
3749 
3750 	// Check ActiveArea.
3751 
3752 	if (((fActiveArea & imageArea) != fActiveArea) || fActiveArea.IsEmpty ())
3753 		{
3754 
3755 		#if qDNGValidate
3756 
3757 		ReportError ("Invalid ActiveArea",
3758 					 LookupParentCode (parentCode));
3759 
3760 		#endif
3761 
3762 		return false;
3763 
3764 		}
3765 
3766 	if (fActiveArea != imageArea)
3767 		{
3768 
3769 		if (shared.fDNGBackwardVersion < dngVersion_1_1_0_0)
3770 			{
3771 
3772 			#if qDNGValidate
3773 
3774 			ReportError ("Non-default ActiveArea tag not allowed in this DNG version",
3775 						 LookupParentCode (parentCode));
3776 
3777 			#endif
3778 
3779 			return false;
3780 
3781 			}
3782 
3783 		}
3784 
3785 	// Check LinearizationTable.
3786 
3787 	if (fLinearizationTableCount)
3788 		{
3789 
3790 		if (fLinearizationTableType != ttShort)
3791 			{
3792 
3793 			#if qDNGValidate
3794 
3795 			ReportError ("Invalidate LinearizationTable type",
3796 						 LookupParentCode (parentCode));
3797 
3798 			#endif
3799 
3800 			return false;
3801 
3802 			}
3803 
3804 		if (fLinearizationTableCount < 2 ||
3805 			fLinearizationTableCount > 65536)
3806 			{
3807 
3808 			#if qDNGValidate
3809 
3810 			ReportError ("Invalidate LinearizationTable count",
3811 						 LookupParentCode (parentCode));
3812 
3813 			#endif
3814 
3815 			return false;
3816 
3817 			}
3818 
3819 		if (isFloatingPoint || fBitsPerSample [0] > 16)
3820 			{
3821 
3822 			#if qDNGValidate
3823 
3824 			ReportError ("Linearization table not allowed for this data type",
3825 						 LookupParentCode (parentCode));
3826 
3827 			#endif
3828 
3829 			return false;
3830 
3831 			}
3832 
3833 		}
3834 
3835 	// Check BlackLevelRepeatDim.
3836 
3837 	if (fBlackLevelRepeatRows < 1 || fBlackLevelRepeatRows > kMaxBlackPattern ||
3838 		fBlackLevelRepeatCols < 1 || fBlackLevelRepeatCols > kMaxBlackPattern)
3839 		{
3840 
3841 		#if qDNGValidate
3842 
3843 		ReportError ("Invalid BlackLevelRepeatDim",
3844 					 LookupParentCode (parentCode));
3845 
3846 		#endif
3847 
3848 		return false;
3849 
3850 		}
3851 
3852 	// Check BlackLevelDeltaH.
3853 
3854 	if (fBlackLevelDeltaHCount != 0 &&
3855 		fBlackLevelDeltaHCount != fActiveArea.W ())
3856 		{
3857 
3858 		#if qDNGValidate
3859 
3860 		ReportError ("Invalid BlackLevelDeltaH count",
3861 					 LookupParentCode (parentCode));
3862 
3863 		#endif
3864 
3865 		return false;
3866 
3867 		}
3868 
3869 	// Check BlackLevelDeltaV.
3870 
3871 	if (fBlackLevelDeltaVCount != 0 &&
3872 		fBlackLevelDeltaVCount != fActiveArea.H ())
3873 		{
3874 
3875 		#if qDNGValidate
3876 
3877 		ReportError ("Invalid BlackLevelDeltaV count",
3878 					 LookupParentCode (parentCode));
3879 
3880 		#endif
3881 
3882 		return false;
3883 
3884 		}
3885 
3886 	// Check WhiteLevel.
3887 
3888 	real64 maxWhite = fLinearizationTableCount ? 65535.0
3889 											   : (real64) defaultWhite;
3890 
3891 	for (j = 0; j < fSamplesPerPixel; j++)
3892 		{
3893 
3894 		if (fWhiteLevel [j] < 1.0 || (fWhiteLevel [j] > maxWhite && !isFloatingPoint))
3895 			{
3896 
3897 			#if qDNGValidate
3898 
3899 			ReportError ("Invalid WhiteLevel",
3900 						 LookupParentCode (parentCode));
3901 
3902 			#endif
3903 
3904 			return false;
3905 
3906 			}
3907 
3908 		}
3909 
3910 	// Check BlackLevel.
3911 
3912 	for (j = 0; j < kMaxBlackPattern; j++)
3913 		{
3914 
3915 		for (uint32 k = 0; k < kMaxBlackPattern; k++)
3916 			{
3917 
3918 			for (uint32 s = 0; s < kMaxSamplesPerPixel; s++)
3919 				{
3920 
3921 				const real64 black = fBlackLevel [j][k][s];
3922 
3923 				if (black >= fWhiteLevel [s])
3924 					{
3925 
3926 					#if qDNGValidate
3927 
3928 					ReportError ("Invalid BlackLevel",
3929 								 LookupParentCode (parentCode));
3930 
3931 					#endif
3932 
3933 					return false;
3934 
3935 					}
3936 
3937 				}
3938 
3939 			}
3940 
3941 		}
3942 
3943 	// Check DefaultScale.
3944 
3945 	if (fDefaultScaleH.As_real64 () <= 0.0 ||
3946 		fDefaultScaleV.As_real64 () <= 0.0)
3947 		{
3948 
3949 		#if qDNGValidate
3950 
3951 		ReportError ("Invalid DefaultScale");
3952 
3953 		#endif
3954 
3955 		return false;
3956 
3957 		}
3958 
3959 	// Check BestQualityScale.
3960 
3961 	if (fBestQualityScale.As_real64 () < 1.0)
3962 		{
3963 
3964 		#if qDNGValidate
3965 
3966 		ReportError ("Invalid BestQualityScale");
3967 
3968 		#endif
3969 
3970 		return false;
3971 
3972 		}
3973 
3974 	// Check DefaultCropOrigin.
3975 
3976 	if (fDefaultCropOriginH.As_real64 () < 0.0 ||
3977 		fDefaultCropOriginV.As_real64 () < 0.0 ||
3978 		fDefaultCropOriginH.As_real64 () >= (real64) fActiveArea.W () ||
3979 		fDefaultCropOriginV.As_real64 () >= (real64) fActiveArea.H ())
3980 		{
3981 
3982 		#if qDNGValidate
3983 
3984 		ReportError ("Invalid DefaultCropOrigin");
3985 
3986 		#endif
3987 
3988 		return false;
3989 
3990 		}
3991 
3992 	// Check DefaultCropSize.
3993 
3994 	if (fDefaultCropSizeH.As_real64 () <= 0.0 					   ||
3995 		fDefaultCropSizeV.As_real64 () <= 0.0 					   ||
3996 		fDefaultCropSizeH.As_real64 () > (real64) fActiveArea.W () ||
3997 		fDefaultCropSizeV.As_real64 () > (real64) fActiveArea.H ())
3998 		{
3999 
4000 		#if qDNGValidate
4001 
4002 		ReportError ("Invalid DefaultCropSize");
4003 
4004 		#endif
4005 
4006 		return false;
4007 
4008 		}
4009 
4010 	// Check DefaultCrop area.
4011 
4012 	if (fDefaultCropOriginH.As_real64 () +
4013 		fDefaultCropSizeH  .As_real64 () > (real64) fActiveArea.W () ||
4014 		fDefaultCropOriginV.As_real64 () +
4015 		fDefaultCropSizeV  .As_real64 () > (real64) fActiveArea.H ())
4016 		{
4017 
4018 		#if qDNGValidate
4019 
4020 		ReportError ("Default crop extends outside ActiveArea");
4021 
4022 		#endif
4023 
4024 		return false;
4025 
4026 		}
4027 
4028 	// Check DefaultUserCrop.
4029 
4030 	if (fDefaultUserCropT.As_real64 () < 0.0 ||
4031 		fDefaultUserCropL.As_real64 () < 0.0 ||
4032 		fDefaultUserCropB.As_real64 () > 1.0 ||
4033 		fDefaultUserCropR.As_real64 () > 1.0 ||
4034 		fDefaultUserCropT.As_real64 () >= fDefaultUserCropB.As_real64 () ||
4035 		fDefaultUserCropL.As_real64 () >= fDefaultUserCropR.As_real64 ())
4036 		{
4037 
4038 		#if qDNGValidate
4039 
4040 		ReportError ("Invalid DefaultUserCrop");
4041 
4042 		#endif	// qDNGValidate
4043 
4044 		return false;
4045 
4046 		}
4047 
4048 	// The default crop and default user crop tags are not allowed for the
4049 	// non-main image. If they are there, at least require that they be NOPs.
4050 
4051 	if (!isMainIFD)
4052 		{
4053 
4054 		if (Round_int32 (fDefaultCropOriginH.As_real64 ()) != 0 ||
4055 			Round_int32 (fDefaultCropOriginV.As_real64 ()) != 0)
4056 			{
4057 
4058 			#if qDNGValidate
4059 
4060 			ReportError ("non-default DefaultCropOrigin on non-main image");
4061 
4062 			#endif
4063 
4064 			return false;
4065 
4066 			}
4067 
4068 		if (Round_int32 (fDefaultCropSizeH.As_real64 ()) != (int32) fImageWidth ||
4069 			Round_int32 (fDefaultCropSizeV.As_real64 ()) != (int32) fImageLength)
4070 			{
4071 
4072 			#if qDNGValidate
4073 
4074 			ReportError ("non-default DefaultCropSize on non-main image");
4075 
4076 			#endif
4077 
4078 			return false;
4079 
4080 			}
4081 
4082 		if (fDefaultUserCropT.As_real64 () != 0.0 ||
4083 			fDefaultUserCropL.As_real64 () != 0.0 ||
4084 			fDefaultUserCropB.As_real64 () != 1.0 ||
4085 			fDefaultUserCropR.As_real64 () != 1.0)
4086 			{
4087 
4088 			#if qDNGValidate
4089 
4090 			ReportError ("non-default DefaultCUserCrop on non-main image");
4091 
4092 			#endif	// qDNGValidate
4093 
4094 			return false;
4095 
4096 			}
4097 
4098 		}
4099 
4100 	// Warning if too little padding on CFA image.
4101 
4102 	#if qDNGValidate
4103 
4104 	if (fPhotometricInterpretation == piCFA)
4105 		{
4106 
4107 		const real64 kMinPad = 1.9;
4108 
4109 		if (fDefaultCropOriginH.As_real64 () < kMinPad)
4110 			{
4111 
4112 			ReportWarning ("Too little padding on left edge of CFA image",
4113 						   "possible interpolation artifacts");
4114 
4115 			}
4116 
4117 		if (fDefaultCropOriginV.As_real64 () < kMinPad)
4118 			{
4119 
4120 			ReportWarning ("Too little padding on top edge of CFA image",
4121 						   "possible interpolation artifacts");
4122 
4123 			}
4124 
4125 		if (fDefaultCropOriginH.As_real64 () +
4126 			fDefaultCropSizeH  .As_real64 () > (real64) fActiveArea.W () - kMinPad)
4127 			{
4128 
4129 			ReportWarning ("Too little padding on right edge of CFA image",
4130 						   "possible interpolation artifacts");
4131 
4132 			}
4133 
4134 		if (fDefaultCropOriginV.As_real64 () +
4135 			fDefaultCropSizeV  .As_real64 () > (real64) fActiveArea.H () - kMinPad)
4136 			{
4137 
4138 			ReportWarning ("Too little padding on bottom edge of CFA image",
4139 						   "possible interpolation artifacts");
4140 
4141 			}
4142 
4143 		}
4144 
4145 	#endif
4146 
4147 	// Check RowInterleaveFactor
4148 
4149 	if (fRowInterleaveFactor != 1)
4150 		{
4151 
4152 		if (fRowInterleaveFactor < 1 ||
4153 			fRowInterleaveFactor > fImageLength)
4154 			{
4155 
4156 			#if qDNGValidate
4157 
4158 			ReportError ("RowInterleaveFactor out of valid range",
4159 						 LookupParentCode (parentCode));
4160 
4161 			#endif
4162 
4163 			return false;
4164 
4165 			}
4166 
4167 		if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
4168 			{
4169 
4170 			#if qDNGValidate
4171 
4172 			ReportError ("Non-default RowInterleaveFactor tag not allowed in this DNG version",
4173 						 LookupParentCode (parentCode));
4174 
4175 			#endif
4176 
4177 			return false;
4178 
4179 			}
4180 
4181 		}
4182 
4183 	// Check SubTileBlockSize
4184 
4185 	if (fSubTileBlockRows != 1 || fSubTileBlockCols != 1)
4186 		{
4187 
4188 		if (fSubTileBlockRows < 2 || fSubTileBlockRows > fTileLength ||
4189 			fSubTileBlockCols < 1 || fSubTileBlockCols > fTileWidth)
4190 			{
4191 
4192 			#if qDNGValidate
4193 
4194 			ReportError ("SubTileBlockSize out of valid range",
4195 						 LookupParentCode (parentCode));
4196 
4197 			#endif
4198 
4199 			return false;
4200 
4201 			}
4202 
4203 		if ((fTileLength % fSubTileBlockRows) != 0 ||
4204 			(fTileWidth  % fSubTileBlockCols) != 0)
4205 			{
4206 
4207 			#if qDNGValidate
4208 
4209 			ReportError ("TileSize not exact multiple of SubTileBlockSize",
4210 						 LookupParentCode (parentCode));
4211 
4212 			#endif
4213 
4214 			return false;
4215 
4216 			}
4217 
4218 		if (shared.fDNGBackwardVersion < dngVersion_1_2_0_0)
4219 			{
4220 
4221 			#if qDNGValidate
4222 
4223 			ReportError ("Non-default SubTileBlockSize tag not allowed in this DNG version",
4224 						 LookupParentCode (parentCode));
4225 
4226 			#endif
4227 
4228 			return false;
4229 
4230 			}
4231 
4232 		}
4233 
4234 	return true;
4235 
4236 	}
4237 
4238 /*****************************************************************************/
4239 
TilesAcross() const4240 uint32 dng_ifd::TilesAcross () const
4241 	{
4242 
4243 	if (fTileWidth)
4244 		{
4245 
4246 		uint64 width64 = (uint64) fTileWidth;
4247 
4248 		return (uint32) (((fImageWidth + width64) - 1) / width64);
4249 
4250 		}
4251 
4252 	return 0;
4253 
4254 	}
4255 
4256 /*****************************************************************************/
4257 
TilesDown() const4258 uint32 dng_ifd::TilesDown () const
4259 	{
4260 
4261 	if (fTileLength)
4262 		{
4263 
4264 		// Use 64-bit math to prevent overflow. RowsPerStrip (assigned to
4265 		// fImageLength during parsing) may be 2^32 - 1, indicating a single
4266 		// strip.
4267 
4268 		uint64 length64 = (uint64) fTileLength;
4269 
4270 		return (uint32) (((fImageLength + length64) - 1) / length64);
4271 
4272 		}
4273 
4274 	return 0;
4275 
4276 	}
4277 
4278 /*****************************************************************************/
4279 
TilesPerImage() const4280 uint32 dng_ifd::TilesPerImage () const
4281 	{
4282 
4283 	uint32 total = TilesAcross () * TilesDown ();
4284 
4285 	if (fPlanarConfiguration == pcPlanar)
4286 		{
4287 
4288 		total *= fSamplesPerPixel;
4289 
4290 		}
4291 
4292 	return total;
4293 
4294 	}
4295 
4296 /*****************************************************************************/
4297 
TileArea(uint32 rowIndex,uint32 colIndex) const4298 dng_rect dng_ifd::TileArea (uint32 rowIndex,
4299 						    uint32 colIndex) const
4300 	{
4301 
4302 	dng_rect r;
4303 
4304 	r.t = rowIndex * fTileLength;
4305 	r.b = r.t      + fTileLength;
4306 
4307 	r.l = colIndex * fTileWidth;
4308 	r.r = r.l      + fTileWidth;
4309 
4310 	// If this IFD is using strips rather than tiles, the last strip
4311 	// is trimmed so it does not extend beyond the end of the image.
4312 
4313 	if (fUsesStrips)
4314 		{
4315 
4316 		r.b = Min_uint32 (r.b, fImageLength);
4317 
4318 		}
4319 
4320 	return r;
4321 
4322 	}
4323 
4324 /*****************************************************************************/
4325 
TileByteCount(const dng_rect & tile) const4326 uint32 dng_ifd::TileByteCount (const dng_rect &tile) const
4327 	{
4328 
4329 	if (fCompression == ccUncompressed)
4330 		{
4331 
4332 		uint32 bitsPerRow = tile.W () *
4333 							fBitsPerSample [0];
4334 
4335 		if (fPlanarConfiguration == pcInterleaved)
4336 			{
4337 
4338 			bitsPerRow *= fSamplesPerPixel;
4339 
4340 			}
4341 
4342 		uint32 bytesPerRow = (bitsPerRow + 7) >> 3;
4343 
4344 		if (fPlanarConfiguration == pcRowInterleaved)
4345 			{
4346 
4347 			bytesPerRow *= fSamplesPerPixel;
4348 
4349 			}
4350 
4351 		return bytesPerRow * tile.H ();
4352 
4353 		}
4354 
4355 	return 0;
4356 
4357 	}
4358 
4359 /*****************************************************************************/
4360 
SetSingleStrip()4361 void dng_ifd::SetSingleStrip ()
4362 	{
4363 
4364 	fTileWidth  = fImageWidth;
4365 	fTileLength = fImageLength;
4366 
4367 	fUsesTiles  = false;
4368 	fUsesStrips = true;
4369 
4370 	}
4371 
4372 /*****************************************************************************/
4373 
FindTileSize(uint32 bytesPerTile,uint32 cellH,uint32 cellV)4374 void dng_ifd::FindTileSize (uint32 bytesPerTile,
4375 						    uint32 cellH,
4376 						    uint32 cellV)
4377 	{
4378 
4379 	uint32 bytesPerSample = fSamplesPerPixel *
4380 							((fBitsPerSample [0] + 7) >> 3);
4381 
4382 	uint32 samplesPerTile = bytesPerTile / bytesPerSample;
4383 
4384 	uint32 tileSide = Round_uint32 (sqrt ((real64) samplesPerTile));
4385 
4386 	fTileWidth = Min_uint32 (fImageWidth, tileSide);
4387 
4388 	uint32 across = TilesAcross ();
4389 
4390 	DNG_REQUIRE (across > 0, "Bad number of tiles across in dng_ifd::FindTileSize");
4391 
4392 	fTileWidth = (fImageWidth + across - 1) / across;
4393 
4394 	fTileWidth = ((fTileWidth + cellH - 1) / cellH) * cellH;
4395 
4396 	fTileLength = Pin_uint32 (1,
4397 						      samplesPerTile / fTileWidth,
4398 						      fImageLength);
4399 
4400 	uint32 down = TilesDown ();
4401 
4402 	fTileLength = (fImageLength + down - 1) / down;
4403 
4404 	fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
4405 
4406 	fUsesTiles  = true;
4407 	fUsesStrips = false;
4408 
4409 	}
4410 
4411 /*****************************************************************************/
4412 
FindStripSize(uint32 bytesPerStrip,uint32 cellV)4413 void dng_ifd::FindStripSize (uint32 bytesPerStrip,
4414 						     uint32 cellV)
4415 	{
4416 
4417 	uint32 bytesPerSample = fSamplesPerPixel *
4418 							((fBitsPerSample [0] + 7) >> 3);
4419 
4420 	uint32 samplesPerStrip = bytesPerStrip / bytesPerSample;
4421 
4422 	fTileWidth = fImageWidth;
4423 
4424 	fTileLength = Pin_uint32 (1,
4425 						      samplesPerStrip / fTileWidth,
4426 						      fImageLength);
4427 
4428 	uint32 down = TilesDown ();
4429 
4430 	fTileLength = (fImageLength + down - 1) / down;
4431 
4432 	fTileLength = ((fTileLength + cellV - 1) / cellV) * cellV;
4433 
4434 	fUsesTiles  = false;
4435 	fUsesStrips = true;
4436 
4437 	}
4438 
4439 /*****************************************************************************/
4440 
PixelType() const4441 uint32 dng_ifd::PixelType () const
4442 	{
4443 
4444 	if (fSampleFormat [0] == sfFloatingPoint)
4445 		{
4446 		return ttFloat;
4447 		}
4448 
4449 	if (fBitsPerSample [0] <= 8)
4450 		{
4451 		return ttByte;
4452 		}
4453 
4454 	else if (fBitsPerSample [0] <= 16)
4455 		{
4456 		return ttShort;
4457 		}
4458 
4459 	return ttLong;
4460 
4461 	}
4462 
4463 /*****************************************************************************/
4464 
IsBaselineJPEG() const4465 bool dng_ifd::IsBaselineJPEG () const
4466 	{
4467 
4468 	if (fBitsPerSample [0] != 8)
4469 		{
4470 		return false;
4471 		}
4472 
4473 	if (fSampleFormat [0] != sfUnsignedInteger)
4474 		{
4475 		return false;
4476 		}
4477 
4478 	if (fCompression == ccLossyJPEG)
4479 		{
4480 		return true;
4481 		}
4482 
4483 	if (fCompression != ccJPEG)
4484 		{
4485 		return false;
4486 		}
4487 
4488 	switch (fPhotometricInterpretation)
4489 		{
4490 
4491 		case piBlackIsZero:
4492 			{
4493 			return (fSamplesPerPixel == 1);
4494 			}
4495 
4496 		case piYCbCr:
4497 			{
4498 			return (fSamplesPerPixel     == 3            ) &&
4499 				   (fPlanarConfiguration == pcInterleaved);
4500 			}
4501 
4502 		default:
4503 			break;
4504 
4505 		}
4506 
4507 	return false;
4508 
4509 	}
4510 
4511 /*****************************************************************************/
4512 
CanRead() const4513 bool dng_ifd::CanRead () const
4514 	{
4515 
4516 	dng_read_image reader;
4517 
4518 	return reader.CanRead (*this);
4519 
4520 	}
4521 
4522 /*****************************************************************************/
4523 
ReadImage(dng_host & host,dng_stream & stream,dng_image & image,dng_jpeg_image * jpegImage,dng_fingerprint * jpegDigest) const4524 void dng_ifd::ReadImage (dng_host &host,
4525 						 dng_stream &stream,
4526 						 dng_image &image,
4527 						 dng_jpeg_image *jpegImage,
4528 						 dng_fingerprint *jpegDigest) const
4529 	{
4530 
4531 	dng_read_image reader;
4532 
4533 	reader.Read (host,
4534 				 *this,
4535 				 stream,
4536 				 image,
4537 				 jpegImage,
4538 				 jpegDigest);
4539 
4540 	}
4541 
4542 /*****************************************************************************/
4543