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