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