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 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 51 dng_preview_info::~dng_preview_info () 52 { 53 54 } 55 56 /*****************************************************************************/ 57 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 252 dng_ifd::~dng_ifd () 253 { 254 255 } 256 257 /*****************************************************************************/ 258 259 // Parses tags that should only appear in IFDs that contain images. 260 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 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 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 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 3976 uint32 dng_ifd::TilesAcross () const 3977 { 3978 3979 if (fTileWidth) 3980 { 3981 3982 return (SafeUint32Sub(SafeUint32Add(fImageWidth, fTileWidth), 1)) / fTileWidth; 3983 3984 } 3985 3986 return 0; 3987 3988 } 3989 3990 /*****************************************************************************/ 3991 3992 uint32 dng_ifd::TilesDown () const 3993 { 3994 3995 if (fTileLength) 3996 { 3997 3998 return (SafeUint32Sub(SafeUint32Add(fImageLength, fTileLength), 1)) / fTileLength; 3999 4000 } 4001 4002 return 0; 4003 4004 } 4005 4006 /*****************************************************************************/ 4007 4008 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 4026 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 4054 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 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 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 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 4166 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 4190 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 4238 bool dng_ifd::CanRead () const 4239 { 4240 4241 dng_read_image reader; 4242 4243 return reader.CanRead (*this); 4244 4245 } 4246 4247 /*****************************************************************************/ 4248 4249 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