1/*****************************************************************************/ 2// Copyright 2006-2007 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_info.cpp#1 $ */ 10/* $DateTime: 2012/05/30 13:28:51 $ */ 11/* $Change: 832332 $ */ 12/* $Author: tknoll $ */ 13 14/*****************************************************************************/ 15 16#include "dng_info.h" 17 18#include "dng_camera_profile.h" 19#include "dng_exceptions.h" 20#include "dng_globals.h" 21#include "dng_host.h" 22#include "dng_tag_codes.h" 23#include "dng_parse_utils.h" 24#include "dng_safe_arithmetic.h" 25#include "dng_tag_types.h" 26#include "dng_tag_values.h" 27#include "dng_utils.h" 28 29/*****************************************************************************/ 30 31dng_info::dng_info () 32 33 : fTIFFBlockOffset (0) 34 , fTIFFBlockOriginalOffset (kDNGStreamInvalidOffset) 35 , fBigEndian (false) 36 , fMagic (0) 37 , fExif () 38 , fShared () 39 , fMainIndex (-1) 40 , fMaskIndex (-1) 41 , fIFDCount (0) 42 , fChainedIFDCount (0) 43 , fMakerNoteNextIFD (0) 44 45 { 46 47 } 48 49/*****************************************************************************/ 50 51dng_info::~dng_info () 52 { 53 54 } 55 56/*****************************************************************************/ 57 58void dng_info::ValidateMagic () 59 { 60 61 switch (fMagic) 62 { 63 64 case magicTIFF: 65 case magicExtendedProfile: 66 case magicRawCache: 67 case magicPanasonic: 68 case magicOlympusA: 69 case magicOlympusB: 70 { 71 72 return; 73 74 } 75 76 default: 77 { 78 79 #if qDNGValidate 80 81 ReportError ("Invalid TIFF magic number"); 82 83 #endif 84 85 ThrowBadFormat (); 86 87 } 88 89 } 90 91 } 92 93/*****************************************************************************/ 94 95void dng_info::ParseTag (dng_host &host, 96 dng_stream &stream, 97 dng_exif *exif, 98 dng_shared *shared, 99 dng_ifd *ifd, 100 uint32 parentCode, 101 uint32 tagCode, 102 uint32 tagType, 103 uint32 tagCount, 104 uint64 tagOffset, 105 int64 offsetDelta) 106 { 107 108 bool isSubIFD = parentCode >= tcFirstSubIFD && 109 parentCode <= tcLastSubIFD; 110 111 bool isMainIFD = (parentCode == 0 || isSubIFD) && 112 ifd && 113 ifd->fUsesNewSubFileType && 114 ifd->fNewSubFileType == sfMainImage; 115 116 // Panasonic RAW format stores private tags using tag codes < 254 in 117 // IFD 0. Redirect the parsing of these tags into a logical 118 // "PanasonicRAW" IFD. 119 120 // Panasonic is starting to use some higher numbers also (280..283). 121 122 if (fMagic == 85 && parentCode == 0 && (tagCode < tcNewSubFileType || 123 (tagCode >= 280 && tagCode <= 283))) 124 { 125 126 parentCode = tcPanasonicRAW; 127 128 ifd = NULL; 129 130 } 131 132 stream.SetReadPosition (tagOffset); 133 134 if (ifd && ifd->ParseTag (stream, 135 parentCode, 136 tagCode, 137 tagType, 138 tagCount, 139 tagOffset)) 140 { 141 142 return; 143 144 } 145 146 stream.SetReadPosition (tagOffset); 147 148 if (exif && shared && exif->ParseTag (stream, 149 *shared, 150 parentCode, 151 isMainIFD, 152 tagCode, 153 tagType, 154 tagCount, 155 tagOffset)) 156 { 157 158 return; 159 160 } 161 162 stream.SetReadPosition (tagOffset); 163 164 if (shared && exif && shared->ParseTag (stream, 165 *exif, 166 parentCode, 167 isMainIFD, 168 tagCode, 169 tagType, 170 tagCount, 171 tagOffset, 172 offsetDelta)) 173 { 174 175 return; 176 177 } 178 179 if (parentCode == tcLeicaMakerNote && 180 tagType == ttUndefined && 181 tagCount >= 14) 182 { 183 184 if (ParseMakerNoteIFD (host, 185 stream, 186 tagCount, 187 tagOffset, 188 offsetDelta, 189 tagOffset, 190 stream.Length (), 191 tcLeicaMakerNote)) 192 { 193 194 return; 195 196 } 197 198 } 199 200 if (parentCode == tcOlympusMakerNote && 201 tagType == ttUndefined && 202 tagCount >= 14) 203 { 204 205 uint32 olympusMakerParent = 0; 206 207 switch (tagCode) 208 { 209 210 case 8208: 211 olympusMakerParent = tcOlympusMakerNote8208; 212 break; 213 214 case 8224: 215 olympusMakerParent = tcOlympusMakerNote8224; 216 break; 217 218 case 8240: 219 olympusMakerParent = tcOlympusMakerNote8240; 220 break; 221 222 case 8256: 223 olympusMakerParent = tcOlympusMakerNote8256; 224 break; 225 226 case 8272: 227 olympusMakerParent = tcOlympusMakerNote8272; 228 break; 229 230 case 12288: 231 olympusMakerParent = tcOlympusMakerNote12288; 232 break; 233 234 default: 235 break; 236 237 } 238 239 if (olympusMakerParent) 240 { 241 242 // Olympus made a mistake in some camera models in computing 243 // the size of these sub-tags, so we fudge the count. 244 245 if (ParseMakerNoteIFD (host, 246 stream, 247 stream.Length () - tagOffset, 248 tagOffset, 249 offsetDelta, 250 tagOffset, 251 stream.Length (), 252 olympusMakerParent)) 253 { 254 255 return; 256 257 } 258 259 } 260 261 } 262 263 if (parentCode == tcRicohMakerNote && 264 tagCode == 0x2001 && 265 tagType == ttUndefined && 266 tagCount > 22) 267 { 268 269 char header [20]; 270 271 stream.SetReadPosition (tagOffset); 272 273 stream.Get (header, sizeof (header)); 274 275 if (memcmp (header, "[Ricoh Camera Info]", 19) == 0) 276 { 277 278 ParseMakerNoteIFD (host, 279 stream, 280 tagCount - 20, 281 tagOffset + 20, 282 offsetDelta, 283 tagOffset + 20, 284 tagOffset + tagCount, 285 tcRicohMakerNoteCameraInfo); 286 287 return; 288 289 } 290 291 } 292 293 #if qDNGValidate 294 295 { 296 297 stream.SetReadPosition (tagOffset); 298 299 if (gVerbose) 300 { 301 302 printf ("*"); 303 304 DumpTagValues (stream, 305 LookupTagType (tagType), 306 parentCode, 307 tagCode, 308 tagType, 309 tagCount); 310 311 } 312 313 // If type is ASCII, then parse anyway so we report any ASCII 314 // NULL termination or character set errors. 315 316 else if (tagType == ttAscii) 317 { 318 319 dng_string s; 320 321 ParseStringTag (stream, 322 parentCode, 323 tagCode, 324 tagCount, 325 s, 326 false); 327 328 } 329 330 } 331 332 #endif 333 334 } 335 336/*****************************************************************************/ 337 338bool dng_info::ValidateIFD (dng_stream &stream, 339 uint64 ifdOffset, 340 int64 offsetDelta) 341 { 342 343 // Make sure we have a count. 344 345 if (ifdOffset + 2 > stream.Length ()) 346 { 347 return false; 348 } 349 350 // Get entry count. 351 352 stream.SetReadPosition (ifdOffset); 353 354 uint32 ifdEntries = stream.Get_uint16 (); 355 356 if (ifdEntries < 1) 357 { 358 return false; 359 } 360 361 // Make sure we have room for all entries and next IFD link. 362 363 if (ifdOffset + 2 + ifdEntries * 12 + 4 > stream.Length ()) 364 { 365 return false; 366 } 367 368 // Check each entry. 369 370 for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++) 371 { 372 373 stream.SetReadPosition (ifdOffset + 2 + tag_index * 12); 374 375 stream.Skip (2); // Ignore tag code. 376 377 uint32 tagType = stream.Get_uint16 (); 378 uint32 tagCount = stream.Get_uint32 (); 379 380 uint32 tag_type_size = TagTypeSize (tagType); 381 382 if (tag_type_size == 0) 383 { 384 return false; 385 } 386 387 uint32 tag_data_size = SafeUint32Mult(tagCount, tag_type_size); 388 389 if (tag_data_size > 4) 390 { 391 392 uint64 tagOffset = stream.Get_uint32 (); 393 394 tagOffset += offsetDelta; 395 396 if (SafeUint64Add(tagOffset, tag_data_size) > stream.Length()) 397 { 398 return false; 399 } 400 401 } 402 403 } 404 405 return true; 406 407 } 408 409/*****************************************************************************/ 410 411void dng_info::ParseIFD (dng_host &host, 412 dng_stream &stream, 413 dng_exif *exif, 414 dng_shared *shared, 415 dng_ifd *ifd, 416 uint64 ifdOffset, 417 int64 offsetDelta, 418 uint32 parentCode) 419 { 420 421 #if qDNGValidate 422 423 bool isMakerNote = (parentCode >= tcFirstMakerNoteIFD && 424 parentCode <= tcLastMakerNoteIFD); 425 426 #endif 427 428 stream.SetReadPosition (ifdOffset); 429 430 if (ifd) 431 { 432 ifd->fThisIFD = ifdOffset; 433 } 434 435 uint32 ifdEntries = stream.Get_uint16 (); 436 437 #if qDNGValidate 438 439 if (gVerbose) 440 { 441 442 printf ("%s: Offset = %u, Entries = %u\n\n", 443 LookupParentCode (parentCode), 444 (unsigned) ifdOffset, 445 (unsigned) ifdEntries); 446 447 } 448 449 if ((ifdOffset & 1) && !isMakerNote) 450 { 451 452 char message [256]; 453 454 sprintf (message, 455 "%s has odd offset (%u)", 456 LookupParentCode (parentCode), 457 (unsigned) ifdOffset); 458 459 ReportWarning (message); 460 461 } 462 463 #endif 464 465 uint32 prev_tag_code = 0; 466 467 for (uint32 tag_index = 0; tag_index < ifdEntries; tag_index++) 468 { 469 470 stream.SetReadPosition (ifdOffset + 2 + tag_index * 12); 471 472 uint32 tagCode = stream.Get_uint16 (); 473 uint32 tagType = stream.Get_uint16 (); 474 475 // Minolta 7D files have a bug in the EXIF block where the count 476 // is wrong, and we run off into next IFD link. So if abort parsing 477 // if we get a zero code/type combinations. 478 479 if (tagCode == 0 && tagType == 0) 480 { 481 482 #if qDNGValidate 483 484 char message [256]; 485 486 sprintf (message, 487 "%s had zero/zero tag code/type entry", 488 LookupParentCode (parentCode)); 489 490 ReportWarning (message); 491 492 #endif 493 494 return; 495 496 } 497 498 uint32 tagCount = stream.Get_uint32 (); 499 500 #if qDNGValidate 501 502 { 503 504 if (tag_index > 0 && tagCode <= prev_tag_code && !isMakerNote) 505 { 506 507 char message [256]; 508 509 sprintf (message, 510 "%s tags are not sorted in ascending numerical order", 511 LookupParentCode (parentCode)); 512 513 ReportWarning (message); 514 515 } 516 517 } 518 519 #endif 520 521 prev_tag_code = tagCode; 522 523 uint32 tag_type_size = TagTypeSize (tagType); 524 525 if (tag_type_size == 0) 526 { 527 528 #if qDNGValidate 529 530 { 531 532 char message [256]; 533 534 sprintf (message, 535 "%s %s has unknown type (%u)", 536 LookupParentCode (parentCode), 537 LookupTagCode (parentCode, tagCode), 538 (unsigned) tagType); 539 540 ReportWarning (message); 541 542 } 543 544 #endif 545 546 continue; 547 548 } 549 550 uint64 tagOffset = ifdOffset + 2 + tag_index * 12 + 8; 551 552 if (SafeUint32Mult(tagCount, tag_type_size) > 4) 553 { 554 555 tagOffset = stream.Get_uint32 (); 556 557 #if qDNGValidate 558 559 { 560 561 if (!(ifdOffset & 1) && 562 (tagOffset & 1) && 563 !isMakerNote && 564 parentCode != tcKodakDCRPrivateIFD && 565 parentCode != tcKodakKDCPrivateIFD) 566 { 567 568 char message [256]; 569 570 sprintf (message, 571 "%s %s has odd data offset (%u)", 572 LookupParentCode (parentCode), 573 LookupTagCode (parentCode, tagCode), 574 (unsigned) tagOffset); 575 576 ReportWarning (message); 577 578 } 579 580 } 581 582 #endif 583 584 tagOffset += offsetDelta; 585 586 stream.SetReadPosition (tagOffset); 587 588 } 589 590 ParseTag (host, 591 stream, 592 exif, 593 shared, 594 ifd, 595 parentCode, 596 tagCode, 597 tagType, 598 tagCount, 599 tagOffset, 600 offsetDelta); 601 602 } 603 604 stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12); 605 606 uint32 nextIFD = stream.Get_uint32 (); 607 608 #if qDNGValidate 609 610 if (gVerbose) 611 { 612 printf ("NextIFD = %u\n", (unsigned) nextIFD); 613 } 614 615 #endif 616 617 if (ifd) 618 { 619 ifd->fNextIFD = nextIFD; 620 } 621 622 #if qDNGValidate 623 624 if (nextIFD) 625 { 626 627 if (parentCode != 0 && 628 (parentCode < tcFirstChainedIFD || 629 parentCode > tcLastChainedIFD )) 630 { 631 632 char message [256]; 633 634 sprintf (message, 635 "%s has an unexpected non-zero NextIFD (%u)", 636 LookupParentCode (parentCode), 637 (unsigned) nextIFD); 638 639 ReportWarning (message); 640 641 } 642 643 } 644 645 if (gVerbose) 646 { 647 printf ("\n"); 648 } 649 650 #endif 651 652 } 653 654/*****************************************************************************/ 655 656bool dng_info::ParseMakerNoteIFD (dng_host &host, 657 dng_stream &stream, 658 uint64 ifdSize, 659 uint64 ifdOffset, 660 int64 offsetDelta, 661 uint64 minOffset, 662 uint64 maxOffset, 663 uint32 parentCode) 664 { 665 666 uint32 tagIndex; 667 uint32 tagCode; 668 uint32 tagType; 669 uint32 tagCount; 670 671 // Assume there is no next IFD pointer. 672 673 fMakerNoteNextIFD = 0; 674 675 // If size is too small to hold a single entry IFD, abort. 676 677 if (ifdSize < 14) 678 { 679 return false; 680 } 681 682 // Get entry count. 683 684 stream.SetReadPosition (ifdOffset); 685 686 uint32 ifdEntries = stream.Get_uint16 (); 687 688 // Make the entry count if reasonable for the MakerNote size. 689 690 if (ifdEntries < 1 || 2 + ifdEntries * 12 > ifdSize) 691 { 692 return false; 693 } 694 695 // Scan IFD to verify all the tag types are all valid. 696 697 for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++) 698 { 699 700 stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12 + 2); 701 702 tagType = stream.Get_uint16 (); 703 704 // Kludge: Some Canon MakerNotes contain tagType = 0 tags, so we 705 // need to ignore them. This was a "firmware 1.0.4" Canon 40D raw file. 706 707 if (parentCode == tcCanonMakerNote && tagType == 0) 708 { 709 continue; 710 } 711 712 if (TagTypeSize (tagType) == 0) 713 { 714 return false; 715 } 716 717 } 718 719 // OK, the IFD looks reasonable enough to parse. 720 721 #if qDNGValidate 722 723 if (gVerbose) 724 { 725 726 printf ("%s: Offset = %u, Entries = %u\n\n", 727 LookupParentCode (parentCode), 728 (unsigned) ifdOffset, 729 (unsigned) ifdEntries); 730 731 } 732 733 #endif 734 735 for (tagIndex = 0; tagIndex < ifdEntries; tagIndex++) 736 { 737 738 stream.SetReadPosition (ifdOffset + 2 + tagIndex * 12); 739 740 tagCode = stream.Get_uint16 (); 741 tagType = stream.Get_uint16 (); 742 tagCount = stream.Get_uint32 (); 743 744 if (tagType == 0) 745 { 746 continue; 747 } 748 749 uint32 tagSize = SafeUint32Mult(tagCount, TagTypeSize (tagType)); 750 751 uint64 tagOffset = ifdOffset + 2 + tagIndex * 12 + 8; 752 753 if (tagSize > 4) 754 { 755 756 tagOffset = stream.Get_uint32 () + offsetDelta; 757 758 if (tagOffset < minOffset || 759 SafeUint64Add(tagOffset, tagSize) > maxOffset) 760 { 761 762 // Tag data is outside the valid offset range, 763 // so ignore this tag. 764 765 continue; 766 767 } 768 769 stream.SetReadPosition (tagOffset); 770 771 } 772 773 // Olympus switched to using IFDs in version 3 makernotes. 774 775 if (parentCode == tcOlympusMakerNote && 776 tagType == ttIFD && 777 tagCount == 1) 778 { 779 780 uint32 olympusMakerParent = 0; 781 782 switch (tagCode) 783 { 784 785 case 8208: 786 olympusMakerParent = tcOlympusMakerNote8208; 787 break; 788 789 case 8224: 790 olympusMakerParent = tcOlympusMakerNote8224; 791 break; 792 793 case 8240: 794 olympusMakerParent = tcOlympusMakerNote8240; 795 break; 796 797 case 8256: 798 olympusMakerParent = tcOlympusMakerNote8256; 799 break; 800 801 case 8272: 802 olympusMakerParent = tcOlympusMakerNote8272; 803 break; 804 805 case 12288: 806 olympusMakerParent = tcOlympusMakerNote12288; 807 break; 808 809 default: 810 break; 811 812 } 813 814 if (olympusMakerParent) 815 { 816 817 stream.SetReadPosition (tagOffset); 818 819 uint64 subMakerNoteOffset = stream.Get_uint32 () + offsetDelta; 820 821 if (subMakerNoteOffset >= minOffset && 822 subMakerNoteOffset < maxOffset) 823 { 824 825 if (ParseMakerNoteIFD (host, 826 stream, 827 maxOffset - subMakerNoteOffset, 828 subMakerNoteOffset, 829 offsetDelta, 830 minOffset, 831 maxOffset, 832 olympusMakerParent)) 833 { 834 835 continue; 836 837 } 838 839 } 840 841 } 842 843 stream.SetReadPosition (tagOffset); 844 845 } 846 847 ParseTag (host, 848 stream, 849 fExif.Get (), 850 fShared.Get (), 851 NULL, 852 parentCode, 853 tagCode, 854 tagType, 855 tagCount, 856 tagOffset, 857 offsetDelta); 858 859 } 860 861 // Grab next IFD pointer, for possible use. 862 863 if (ifdSize >= 2 + ifdEntries * 12 + 4) 864 { 865 866 stream.SetReadPosition (ifdOffset + 2 + ifdEntries * 12); 867 868 fMakerNoteNextIFD = stream.Get_uint32 (); 869 870 } 871 872 #if qDNGValidate 873 874 if (gVerbose) 875 { 876 printf ("\n"); 877 } 878 879 #endif 880 881 return true; 882 883 } 884 885/*****************************************************************************/ 886 887void dng_info::ParseMakerNote (dng_host &host, 888 dng_stream &stream, 889 uint32 makerNoteCount, 890 uint64 makerNoteOffset, 891 int64 offsetDelta, 892 uint64 minOffset, 893 uint64 maxOffset) 894 { 895 896 uint8 firstBytes [16]; 897 898 memset (firstBytes, 0, sizeof (firstBytes)); 899 900 stream.SetReadPosition (makerNoteOffset); 901 902 stream.Get (firstBytes, (uint32) Min_uint64 (sizeof (firstBytes), 903 makerNoteCount)); 904 905 // Epson MakerNote with header. 906 907 if (memcmp (firstBytes, "EPSON\000\001\000", 8) == 0) 908 { 909 910 if (makerNoteCount > 8) 911 { 912 913 ParseMakerNoteIFD (host, 914 stream, 915 makerNoteCount - 8, 916 makerNoteOffset + 8, 917 offsetDelta, 918 minOffset, 919 maxOffset, 920 tcEpsonMakerNote); 921 922 } 923 924 return; 925 926 } 927 928 // Fujifilm MakerNote. 929 930 if (memcmp (firstBytes, "FUJIFILM", 8) == 0) 931 { 932 933 stream.SetReadPosition (makerNoteOffset + 8); 934 935 TempLittleEndian tempEndian (stream); 936 937 uint32 ifd_offset = stream.Get_uint32 (); 938 939 if (ifd_offset >= 12 && ifd_offset < makerNoteCount) 940 { 941 942 ParseMakerNoteIFD (host, 943 stream, 944 makerNoteCount - ifd_offset, 945 makerNoteOffset + ifd_offset, 946 makerNoteOffset, 947 minOffset, 948 maxOffset, 949 tcFujiMakerNote); 950 951 } 952 953 return; 954 955 } 956 957 // Leica MakerNote for models that store entry offsets relative to the start of 958 // the MakerNote (e.g., M9). 959 960 if ((memcmp (firstBytes, "LEICA\000\000\000", 8) == 0) || 961 (memcmp (firstBytes, "LEICA0\003\000", 8) == 0) || 962 (memcmp (firstBytes, "LEICA\000\001\000", 8) == 0) || 963 (memcmp (firstBytes, "LEICA\000\005\000", 8) == 0)) 964 { 965 966 if (makerNoteCount > 8) 967 { 968 969 ParseMakerNoteIFD (host, 970 stream, 971 makerNoteCount - 8, 972 makerNoteOffset + 8, 973 makerNoteOffset, 974 minOffset, 975 maxOffset, 976 tcLeicaMakerNote); 977 978 } 979 980 return; 981 982 } 983 984 // Leica MakerNote for models that store absolute entry offsets (i.e., relative 985 // to the start of the file, e.g., S2). 986 987 if (memcmp (firstBytes, "LEICA\000\002\377", 8) == 0) 988 { 989 990 if (makerNoteCount > 8) 991 { 992 993 ParseMakerNoteIFD (host, 994 stream, 995 makerNoteCount - 8, 996 makerNoteOffset + 8, 997 offsetDelta, 998 minOffset, 999 maxOffset, 1000 tcLeicaMakerNote); 1001 1002 } 1003 1004 return; 1005 1006 } 1007 1008 // Nikon version 2 MakerNote with header. 1009 1010 if (memcmp (firstBytes, "Nikon\000\002", 7) == 0) 1011 { 1012 1013 stream.SetReadPosition (makerNoteOffset + 10); 1014 1015 bool bigEndian = false; 1016 1017 uint16 endianMark = stream.Get_uint16 (); 1018 1019 if (endianMark == byteOrderMM) 1020 { 1021 bigEndian = true; 1022 } 1023 1024 else if (endianMark != byteOrderII) 1025 { 1026 return; 1027 } 1028 1029 TempBigEndian temp_endian (stream, bigEndian); 1030 1031 uint16 magic = stream.Get_uint16 (); 1032 1033 if (magic != 42) 1034 { 1035 return; 1036 } 1037 1038 uint32 ifd_offset = stream.Get_uint32 (); 1039 1040 if (ifd_offset >= 8 && ifd_offset < makerNoteCount - 10) 1041 { 1042 1043 ParseMakerNoteIFD (host, 1044 stream, 1045 makerNoteCount - 10 - ifd_offset, 1046 makerNoteOffset + 10 + ifd_offset, 1047 makerNoteOffset + 10, 1048 minOffset, 1049 maxOffset, 1050 tcNikonMakerNote); 1051 1052 } 1053 1054 return; 1055 1056 } 1057 1058 // Newer version of Olympus MakerNote with byte order mark. 1059 1060 if (memcmp (firstBytes, "OLYMPUS\000", 8) == 0) 1061 { 1062 1063 stream.SetReadPosition (makerNoteOffset + 8); 1064 1065 bool bigEndian = false; 1066 1067 uint16 endianMark = stream.Get_uint16 (); 1068 1069 if (endianMark == byteOrderMM) 1070 { 1071 bigEndian = true; 1072 } 1073 1074 else if (endianMark != byteOrderII) 1075 { 1076 return; 1077 } 1078 1079 TempBigEndian temp_endian (stream, bigEndian); 1080 1081 uint16 version = stream.Get_uint16 (); 1082 1083 if (version != 3) 1084 { 1085 return; 1086 } 1087 1088 if (makerNoteCount > 12) 1089 { 1090 1091 ParseMakerNoteIFD (host, 1092 stream, 1093 makerNoteCount - 12, 1094 makerNoteOffset + 12, 1095 makerNoteOffset, 1096 minOffset, 1097 maxOffset, 1098 tcOlympusMakerNote); 1099 1100 } 1101 1102 return; 1103 1104 } 1105 1106 // Olympus MakerNote with header. 1107 1108 if (memcmp (firstBytes, "OLYMP", 5) == 0) 1109 { 1110 1111 if (makerNoteCount > 8) 1112 { 1113 1114 ParseMakerNoteIFD (host, 1115 stream, 1116 makerNoteCount - 8, 1117 makerNoteOffset + 8, 1118 offsetDelta, 1119 minOffset, 1120 maxOffset, 1121 tcOlympusMakerNote); 1122 1123 } 1124 1125 return; 1126 1127 } 1128 1129 // Panasonic MakerNote. 1130 1131 if (memcmp (firstBytes, "Panasonic\000\000\000", 12) == 0) 1132 { 1133 1134 if (makerNoteCount > 12) 1135 { 1136 1137 ParseMakerNoteIFD (host, 1138 stream, 1139 makerNoteCount - 12, 1140 makerNoteOffset + 12, 1141 offsetDelta, 1142 minOffset, 1143 maxOffset, 1144 tcPanasonicMakerNote); 1145 1146 } 1147 1148 return; 1149 1150 } 1151 1152 // Pentax MakerNote. 1153 1154 if (memcmp (firstBytes, "AOC", 4) == 0) 1155 { 1156 1157 if (makerNoteCount > 6) 1158 { 1159 1160 stream.SetReadPosition (makerNoteOffset + 4); 1161 1162 bool bigEndian = stream.BigEndian (); 1163 1164 uint16 endianMark = stream.Get_uint16 (); 1165 1166 if (endianMark == byteOrderMM) 1167 { 1168 bigEndian = true; 1169 } 1170 1171 else if (endianMark == byteOrderII) 1172 { 1173 bigEndian = false; 1174 } 1175 1176 TempBigEndian temp_endian (stream, bigEndian); 1177 1178 ParseMakerNoteIFD (host, 1179 stream, 1180 makerNoteCount - 6, 1181 makerNoteOffset + 6, 1182 offsetDelta, 1183 minOffset, 1184 maxOffset, 1185 tcPentaxMakerNote); 1186 1187 } 1188 1189 return; 1190 1191 } 1192 1193 // Ricoh MakerNote. 1194 1195 if (memcmp (firstBytes, "RICOH", 5) == 0 || 1196 memcmp (firstBytes, "Ricoh", 5) == 0) 1197 { 1198 1199 if (makerNoteCount > 8) 1200 { 1201 1202 TempBigEndian tempEndian (stream); 1203 1204 ParseMakerNoteIFD (host, 1205 stream, 1206 makerNoteCount - 8, 1207 makerNoteOffset + 8, 1208 offsetDelta, 1209 minOffset, 1210 maxOffset, 1211 tcRicohMakerNote); 1212 1213 } 1214 1215 return; 1216 1217 } 1218 1219 // Nikon MakerNote without header. 1220 1221 if (fExif->fMake.StartsWith ("NIKON")) 1222 { 1223 1224 ParseMakerNoteIFD (host, 1225 stream, 1226 makerNoteCount, 1227 makerNoteOffset, 1228 offsetDelta, 1229 minOffset, 1230 maxOffset, 1231 tcNikonMakerNote); 1232 1233 return; 1234 1235 } 1236 1237 // Canon MakerNote. 1238 1239 if (fExif->fMake.StartsWith ("CANON")) 1240 { 1241 1242 ParseMakerNoteIFD (host, 1243 stream, 1244 makerNoteCount, 1245 makerNoteOffset, 1246 offsetDelta, 1247 minOffset, 1248 maxOffset, 1249 tcCanonMakerNote); 1250 1251 return; 1252 1253 } 1254 1255 // Minolta MakerNote. 1256 1257 if (fExif->fMake.StartsWith ("MINOLTA" ) || 1258 fExif->fMake.StartsWith ("KONICA MINOLTA")) 1259 { 1260 1261 ParseMakerNoteIFD (host, 1262 stream, 1263 makerNoteCount, 1264 makerNoteOffset, 1265 offsetDelta, 1266 minOffset, 1267 maxOffset, 1268 tcMinoltaMakerNote); 1269 1270 return; 1271 1272 } 1273 1274 // Sony MakerNote. 1275 1276 if (fExif->fMake.StartsWith ("SONY")) 1277 { 1278 1279 ParseMakerNoteIFD (host, 1280 stream, 1281 makerNoteCount, 1282 makerNoteOffset, 1283 offsetDelta, 1284 minOffset, 1285 maxOffset, 1286 tcSonyMakerNote); 1287 1288 return; 1289 1290 } 1291 1292 // Kodak MakerNote. 1293 1294 if (fExif->fMake.StartsWith ("EASTMAN KODAK")) 1295 { 1296 1297 ParseMakerNoteIFD (host, 1298 stream, 1299 makerNoteCount, 1300 makerNoteOffset, 1301 offsetDelta, 1302 minOffset, 1303 maxOffset, 1304 tcKodakMakerNote); 1305 1306 return; 1307 1308 } 1309 1310 // Mamiya MakerNote. 1311 1312 if (fExif->fMake.StartsWith ("Mamiya")) 1313 { 1314 1315 ParseMakerNoteIFD (host, 1316 stream, 1317 makerNoteCount, 1318 makerNoteOffset, 1319 offsetDelta, 1320 minOffset, 1321 maxOffset, 1322 tcMamiyaMakerNote); 1323 1324 // Mamiya uses a MakerNote chain. 1325 1326 while (fMakerNoteNextIFD) 1327 { 1328 1329 ParseMakerNoteIFD (host, 1330 stream, 1331 makerNoteCount, 1332 offsetDelta + fMakerNoteNextIFD, 1333 offsetDelta, 1334 minOffset, 1335 maxOffset, 1336 tcMamiyaMakerNote); 1337 1338 } 1339 1340 return; 1341 1342 } 1343 1344 // Nikon MakerNote without header. 1345 1346 if (fExif->fMake.StartsWith ("Hasselblad")) 1347 { 1348 1349 ParseMakerNoteIFD (host, 1350 stream, 1351 makerNoteCount, 1352 makerNoteOffset, 1353 offsetDelta, 1354 minOffset, 1355 maxOffset, 1356 tcHasselbladMakerNote); 1357 1358 return; 1359 1360 } 1361 1362 // Samsung MakerNote. 1363 1364 if (fExif->fMake.StartsWith ("Samsung")) 1365 { 1366 1367 ParseMakerNoteIFD (host, 1368 stream, 1369 makerNoteCount, 1370 makerNoteOffset, 1371 makerNoteOffset, 1372 minOffset, 1373 maxOffset, 1374 tcSamsungMakerNote); 1375 1376 return; 1377 1378 } 1379 1380 // Casio MakerNote. 1381 1382 if (fExif->fMake.StartsWith ("CASIO COMPUTER") && 1383 memcmp (firstBytes, "QVC\000\000\000", 6) == 0) 1384 { 1385 1386 ParseMakerNoteIFD (host, 1387 stream, 1388 makerNoteCount - 6, 1389 makerNoteOffset + 6, 1390 makerNoteOffset, 1391 minOffset, 1392 maxOffset, 1393 tcCasioMakerNote); 1394 1395 return; 1396 1397 } 1398 1399 } 1400 1401/*****************************************************************************/ 1402 1403void dng_info::ParseSonyPrivateData (dng_host & /* host */, 1404 dng_stream & /* stream */, 1405 uint64 /* count */, 1406 uint64 /* oldOffset */, 1407 uint64 /* newOffset */) 1408 { 1409 1410 // Sony private data is encrypted, sorry. 1411 1412 } 1413 1414/*****************************************************************************/ 1415 1416void dng_info::ParseDNGPrivateData (dng_host &host, 1417 dng_stream &stream) 1418 { 1419 1420 if (fShared->fDNGPrivateDataCount < 2) 1421 { 1422 return; 1423 } 1424 1425 // DNG private data should always start with a null-terminated 1426 // company name, to define the format of the private data. 1427 1428 dng_string privateName; 1429 1430 { 1431 1432 char buffer [64]; 1433 1434 stream.SetReadPosition (fShared->fDNGPrivateDataOffset); 1435 1436 uint32 readLength = Min_uint32 (fShared->fDNGPrivateDataCount, 1437 sizeof (buffer) - 1); 1438 1439 stream.Get (buffer, readLength); 1440 1441 buffer [readLength] = 0; 1442 1443 privateName.Set (buffer); 1444 1445 } 1446 1447 // Pentax is storing their MakerNote in the DNGPrivateData data. 1448 1449 if (privateName.StartsWith ("PENTAX" ) || 1450 privateName.StartsWith ("SAMSUNG")) 1451 { 1452 1453 #if qDNGValidate 1454 1455 if (gVerbose) 1456 { 1457 printf ("Parsing Pentax/Samsung DNGPrivateData\n\n"); 1458 } 1459 1460 #endif 1461 1462 stream.SetReadPosition (fShared->fDNGPrivateDataOffset + 8); 1463 1464 bool bigEndian = stream.BigEndian (); 1465 1466 uint16 endianMark = stream.Get_uint16 (); 1467 1468 if (endianMark == byteOrderMM) 1469 { 1470 bigEndian = true; 1471 } 1472 1473 else if (endianMark == byteOrderII) 1474 { 1475 bigEndian = false; 1476 } 1477 1478 TempBigEndian temp_endian (stream, bigEndian); 1479 1480 ParseMakerNoteIFD (host, 1481 stream, 1482 fShared->fDNGPrivateDataCount - 10, 1483 fShared->fDNGPrivateDataOffset + 10, 1484 fShared->fDNGPrivateDataOffset, 1485 fShared->fDNGPrivateDataOffset, 1486 fShared->fDNGPrivateDataOffset + fShared->fDNGPrivateDataCount, 1487 tcPentaxMakerNote); 1488 1489 return; 1490 1491 } 1492 1493 // Stop parsing if this is not an Adobe format block. 1494 1495 if (!privateName.Matches ("Adobe")) 1496 { 1497 return; 1498 } 1499 1500 TempBigEndian temp_order (stream); 1501 1502 uint32 section_offset = 6; 1503 1504 while (SafeUint32Add(section_offset, 8) < fShared->fDNGPrivateDataCount) 1505 { 1506 1507 stream.SetReadPosition (SafeUint64Add(fShared->fDNGPrivateDataOffset, 1508 section_offset)); 1509 1510 uint32 section_key = stream.Get_uint32 (); 1511 uint32 section_count = stream.Get_uint32 (); 1512 1513 if (section_key == DNG_CHAR4 ('M','a','k','N') && section_count > 6) 1514 { 1515 1516 #if qDNGValidate 1517 1518 if (gVerbose) 1519 { 1520 printf ("Found MakerNote inside DNGPrivateData\n\n"); 1521 } 1522 1523 #endif 1524 1525 uint16 order_mark = stream.Get_uint16 (); 1526 int64 old_offset = stream.Get_uint32 (); 1527 1528 uint32 tempSize = SafeUint32Sub(section_count, 6); 1529 1530 AutoPtr<dng_memory_block> tempBlock (host.Allocate (tempSize)); 1531 1532 uint64 positionInOriginalFile = stream.PositionInOriginalFile(); 1533 1534 stream.Get (tempBlock->Buffer (), tempSize); 1535 1536 dng_stream tempStream (tempBlock->Buffer (), 1537 tempSize, 1538 positionInOriginalFile); 1539 1540 tempStream.SetBigEndian (order_mark == byteOrderMM); 1541 1542 ParseMakerNote (host, 1543 tempStream, 1544 tempSize, 1545 0, 1546 0 - old_offset, 1547 0, 1548 tempSize); 1549 1550 } 1551 1552 else if (section_key == DNG_CHAR4 ('S','R','2',' ') && section_count > 6) 1553 { 1554 1555 #if qDNGValidate 1556 1557 if (gVerbose) 1558 { 1559 printf ("Found Sony private data inside DNGPrivateData\n\n"); 1560 } 1561 1562 #endif 1563 1564 uint16 order_mark = stream.Get_uint16 (); 1565 uint64 old_offset = stream.Get_uint32 (); 1566 1567 uint64 new_offset = fShared->fDNGPrivateDataOffset + section_offset + 14; 1568 1569 TempBigEndian sr2_order (stream, order_mark == byteOrderMM); 1570 1571 ParseSonyPrivateData (host, 1572 stream, 1573 section_count - 6, 1574 old_offset, 1575 new_offset); 1576 1577 } 1578 1579 else if (section_key == DNG_CHAR4 ('R','A','F',' ') && section_count > 4) 1580 { 1581 1582 #if qDNGValidate 1583 1584 if (gVerbose) 1585 { 1586 printf ("Found Fuji RAF tags inside DNGPrivateData\n\n"); 1587 } 1588 1589 #endif 1590 1591 uint16 order_mark = stream.Get_uint16 (); 1592 1593 uint32 tagCount = stream.Get_uint32 (); 1594 1595 uint64 tagOffset = stream.Position (); 1596 1597 if (tagCount) 1598 { 1599 1600 TempBigEndian raf_order (stream, order_mark == byteOrderMM); 1601 1602 ParseTag (host, 1603 stream, 1604 fExif.Get (), 1605 fShared.Get (), 1606 NULL, 1607 tcFujiRAF, 1608 tcFujiHeader, 1609 ttUndefined, 1610 tagCount, 1611 tagOffset, 1612 0); 1613 1614 stream.SetReadPosition (SafeUint64Add(tagOffset, tagCount)); 1615 1616 } 1617 1618 tagCount = stream.Get_uint32 (); 1619 1620 tagOffset = stream.Position (); 1621 1622 if (tagCount) 1623 { 1624 1625 TempBigEndian raf_order (stream, order_mark == byteOrderMM); 1626 1627 ParseTag (host, 1628 stream, 1629 fExif.Get (), 1630 fShared.Get (), 1631 NULL, 1632 tcFujiRAF, 1633 tcFujiRawInfo1, 1634 ttUndefined, 1635 tagCount, 1636 tagOffset, 1637 0); 1638 1639 stream.SetReadPosition (SafeUint64Add(tagOffset, tagCount)); 1640 1641 } 1642 1643 tagCount = stream.Get_uint32 (); 1644 1645 tagOffset = stream.Position (); 1646 1647 if (tagCount) 1648 { 1649 1650 TempBigEndian raf_order (stream, order_mark == byteOrderMM); 1651 1652 ParseTag (host, 1653 stream, 1654 fExif.Get (), 1655 fShared.Get (), 1656 NULL, 1657 tcFujiRAF, 1658 tcFujiRawInfo2, 1659 ttUndefined, 1660 tagCount, 1661 tagOffset, 1662 0); 1663 1664 stream.SetReadPosition (SafeUint64Add(tagOffset, tagCount)); 1665 1666 } 1667 1668 } 1669 1670 else if (section_key == DNG_CHAR4 ('C','n','t','x') && section_count > 4) 1671 { 1672 1673 #if qDNGValidate 1674 1675 if (gVerbose) 1676 { 1677 printf ("Found Contax Raw header inside DNGPrivateData\n\n"); 1678 } 1679 1680 #endif 1681 1682 uint16 order_mark = stream.Get_uint16 (); 1683 1684 uint32 tagCount = stream.Get_uint32 (); 1685 1686 uint64 tagOffset = stream.Position (); 1687 1688 if (tagCount) 1689 { 1690 1691 TempBigEndian contax_order (stream, order_mark == byteOrderMM); 1692 1693 ParseTag (host, 1694 stream, 1695 fExif.Get (), 1696 fShared.Get (), 1697 NULL, 1698 tcContaxRAW, 1699 tcContaxHeader, 1700 ttUndefined, 1701 tagCount, 1702 tagOffset, 1703 0); 1704 1705 } 1706 1707 } 1708 1709 else if (section_key == DNG_CHAR4 ('C','R','W',' ') && section_count > 4) 1710 { 1711 1712 #if qDNGValidate 1713 1714 if (gVerbose) 1715 { 1716 printf ("Found Canon CRW tags inside DNGPrivateData\n\n"); 1717 } 1718 1719 #endif 1720 1721 uint16 order_mark = stream.Get_uint16 (); 1722 uint32 entries = stream.Get_uint16 (); 1723 1724 uint64 crwTagStart = stream.Position (); 1725 1726 for (uint32 parsePass = 1; parsePass <= 2; parsePass++) 1727 { 1728 1729 stream.SetReadPosition (crwTagStart); 1730 1731 for (uint32 index = 0; index < entries; index++) 1732 { 1733 1734 uint32 tagCode = stream.Get_uint16 (); 1735 1736 uint32 tagCount = stream.Get_uint32 (); 1737 1738 uint64 tagOffset = stream.Position (); 1739 1740 // We need to grab the model id tag first, and then all the 1741 // other tags. 1742 1743 if ((parsePass == 1) == (tagCode == 0x5834)) 1744 { 1745 1746 TempBigEndian tag_order (stream, order_mark == byteOrderMM); 1747 1748 ParseTag (host, 1749 stream, 1750 fExif.Get (), 1751 fShared.Get (), 1752 NULL, 1753 tcCanonCRW, 1754 tagCode, 1755 ttUndefined, 1756 tagCount, 1757 tagOffset, 1758 0); 1759 1760 } 1761 1762 stream.SetReadPosition (tagOffset + tagCount); 1763 1764 } 1765 1766 } 1767 1768 } 1769 1770 else if (section_count > 4) 1771 { 1772 1773 uint32 parentCode = 0; 1774 1775 bool code32 = false; 1776 bool hasType = true; 1777 1778 switch (section_key) 1779 { 1780 1781 case DNG_CHAR4 ('M','R','W',' '): 1782 { 1783 parentCode = tcMinoltaMRW; 1784 code32 = true; 1785 hasType = false; 1786 break; 1787 } 1788 1789 case DNG_CHAR4 ('P','a','n','o'): 1790 { 1791 parentCode = tcPanasonicRAW; 1792 break; 1793 } 1794 1795 case DNG_CHAR4 ('L','e','a','f'): 1796 { 1797 parentCode = tcLeafMOS; 1798 break; 1799 } 1800 1801 case DNG_CHAR4 ('K','o','d','a'): 1802 { 1803 parentCode = tcKodakDCRPrivateIFD; 1804 break; 1805 } 1806 1807 case DNG_CHAR4 ('K','D','C',' '): 1808 { 1809 parentCode = tcKodakKDCPrivateIFD; 1810 break; 1811 } 1812 1813 default: 1814 break; 1815 1816 } 1817 1818 if (parentCode) 1819 { 1820 1821 #if qDNGValidate 1822 1823 if (gVerbose) 1824 { 1825 printf ("Found %s tags inside DNGPrivateData\n\n", 1826 LookupParentCode (parentCode)); 1827 } 1828 1829 #endif 1830 1831 uint16 order_mark = stream.Get_uint16 (); 1832 uint32 entries = stream.Get_uint16 (); 1833 1834 for (uint32 index = 0; index < entries; index++) 1835 { 1836 1837 uint32 tagCode = code32 ? stream.Get_uint32 () 1838 : stream.Get_uint16 (); 1839 1840 uint32 tagType = hasType ? stream.Get_uint16 () 1841 : ttUndefined; 1842 1843 uint32 tagCount = stream.Get_uint32 (); 1844 1845 uint32 tagSize = SafeUint32Mult(tagCount, TagTypeSize (tagType)); 1846 1847 uint64 tagOffset = stream.Position (); 1848 1849 TempBigEndian tag_order (stream, order_mark == byteOrderMM); 1850 1851 ParseTag (host, 1852 stream, 1853 fExif.Get (), 1854 fShared.Get (), 1855 NULL, 1856 parentCode, 1857 tagCode, 1858 tagType, 1859 tagCount, 1860 tagOffset, 1861 0); 1862 1863 stream.SetReadPosition (SafeUint64Add(tagOffset, tagSize)); 1864 1865 } 1866 1867 } 1868 1869 } 1870 1871 section_offset = SafeUint32Add(section_offset, 8); 1872 section_offset = SafeUint32Add(section_offset, section_count); 1873 1874 if (section_offset & 1) 1875 { 1876 section_offset = SafeUint32Add(section_offset, 1); 1877 } 1878 1879 } 1880 1881 } 1882 1883/*****************************************************************************/ 1884 1885void dng_info::Parse (dng_host &host, 1886 dng_stream &stream) 1887 { 1888 1889 fTIFFBlockOffset = stream.Position (); 1890 1891 fTIFFBlockOriginalOffset = stream.PositionInOriginalFile (); 1892 1893 // Check byte order indicator. 1894 1895 uint16 byteOrder = stream.Get_uint16 (); 1896 1897 if (byteOrder == byteOrderII) 1898 { 1899 1900 fBigEndian = false; 1901 1902 #if qDNGValidate 1903 1904 if (gVerbose) 1905 { 1906 printf ("\nUses little-endian byte order\n"); 1907 } 1908 1909 #endif 1910 1911 stream.SetLittleEndian (); 1912 1913 } 1914 1915 else if (byteOrder == byteOrderMM) 1916 { 1917 1918 fBigEndian = true; 1919 1920 #if qDNGValidate 1921 1922 if (gVerbose) 1923 { 1924 printf ("\nUses big-endian byte order\n"); 1925 } 1926 1927 #endif 1928 1929 stream.SetBigEndian (); 1930 1931 } 1932 1933 else 1934 { 1935 1936 #if qDNGValidate 1937 1938 ReportError ("Unknown byte order"); 1939 1940 #endif 1941 1942 ThrowBadFormat (); 1943 1944 } 1945 1946 // Check "magic number" indicator. 1947 1948 fMagic = stream.Get_uint16 (); 1949 1950 #if qDNGValidate 1951 1952 if (gVerbose) 1953 { 1954 printf ("Magic number = %u\n\n", (unsigned) fMagic); 1955 } 1956 1957 #endif 1958 1959 ValidateMagic (); 1960 1961 // Parse IFD 0. 1962 1963 uint64 next_offset = stream.Get_uint32 (); 1964 1965 fExif.Reset (host.Make_dng_exif ()); 1966 1967 fShared.Reset (host.Make_dng_shared ()); 1968 1969 fIFD [0].Reset (host.Make_dng_ifd ()); 1970 1971 ParseIFD (host, 1972 stream, 1973 fExif.Get (), 1974 fShared.Get (), 1975 fIFD [0].Get (), 1976 fTIFFBlockOffset + next_offset, 1977 fTIFFBlockOffset, 1978 0); 1979 1980 next_offset = fIFD [0]->fNextIFD; 1981 1982 fIFDCount = 1; 1983 1984 // Parse chained IFDs. 1985 1986 while (next_offset) 1987 { 1988 1989 if (next_offset >= stream.Length ()) 1990 { 1991 1992 #if qDNGValidate 1993 1994 { 1995 1996 ReportWarning ("Chained IFD offset past end of stream"); 1997 1998 } 1999 2000 #endif 2001 2002 break; 2003 2004 } 2005 2006 // Some TIFF file writers forget about the next IFD offset, so 2007 // validate the IFD at that offset before parsing it. 2008 2009 if (!ValidateIFD (stream, 2010 fTIFFBlockOffset + next_offset, 2011 fTIFFBlockOffset)) 2012 { 2013 2014 #if qDNGValidate 2015 2016 { 2017 2018 ReportWarning ("Chained IFD is not valid"); 2019 2020 } 2021 2022 #endif 2023 2024 break; 2025 2026 } 2027 2028 if (fChainedIFDCount == kMaxChainedIFDs) 2029 { 2030 2031 #if qDNGValidate 2032 2033 { 2034 2035 ReportWarning ("Chained IFD count exceeds DNG SDK parsing limit"); 2036 2037 } 2038 2039 #endif 2040 2041 break; 2042 2043 } 2044 2045 fChainedIFD [fChainedIFDCount].Reset (host.Make_dng_ifd ()); 2046 2047 ParseIFD (host, 2048 stream, 2049 NULL, 2050 NULL, 2051 fChainedIFD [fChainedIFDCount].Get (), 2052 fTIFFBlockOffset + next_offset, 2053 fTIFFBlockOffset, 2054 tcFirstChainedIFD + fChainedIFDCount); 2055 2056 next_offset = fChainedIFD [fChainedIFDCount]->fNextIFD; 2057 2058 fChainedIFDCount++; 2059 2060 } 2061 2062 // Parse SubIFDs. 2063 2064 uint32 searchedIFDs = 0; 2065 2066 bool tooManySubIFDs = false; 2067 2068 while (searchedIFDs < fIFDCount && !tooManySubIFDs) 2069 { 2070 2071 uint32 searchLimit = fIFDCount; 2072 2073 for (uint32 searchIndex = searchedIFDs; 2074 searchIndex < searchLimit && !tooManySubIFDs; 2075 searchIndex++) 2076 { 2077 2078 for (uint32 subIndex = 0; 2079 subIndex < fIFD [searchIndex]->fSubIFDsCount; 2080 subIndex++) 2081 { 2082 2083 if (fIFDCount == kMaxSubIFDs + 1) 2084 { 2085 2086 tooManySubIFDs = true; 2087 2088 break; 2089 2090 } 2091 2092 stream.SetReadPosition (fIFD [searchIndex]->fSubIFDsOffset + 2093 subIndex * 4); 2094 2095 uint32 sub_ifd_offset = stream.Get_uint32 (); 2096 2097 fIFD [fIFDCount].Reset (host.Make_dng_ifd ()); 2098 2099 ParseIFD (host, 2100 stream, 2101 fExif.Get (), 2102 fShared.Get (), 2103 fIFD [fIFDCount].Get (), 2104 fTIFFBlockOffset + sub_ifd_offset, 2105 fTIFFBlockOffset, 2106 tcFirstSubIFD + fIFDCount - 1); 2107 2108 fIFDCount++; 2109 2110 } 2111 2112 searchedIFDs = searchLimit; 2113 2114 } 2115 2116 } 2117 2118 #if qDNGValidate 2119 2120 { 2121 2122 if (tooManySubIFDs) 2123 { 2124 2125 ReportWarning ("SubIFD count exceeds DNG SDK parsing limit"); 2126 2127 } 2128 2129 } 2130 2131 #endif 2132 2133 // Parse EXIF IFD. 2134 2135 if (fShared->fExifIFD) 2136 { 2137 2138 ParseIFD (host, 2139 stream, 2140 fExif.Get (), 2141 fShared.Get (), 2142 NULL, 2143 fTIFFBlockOffset + fShared->fExifIFD, 2144 fTIFFBlockOffset, 2145 tcExifIFD); 2146 2147 } 2148 2149 // Parse GPS IFD. 2150 2151 if (fShared->fGPSInfo) 2152 { 2153 2154 ParseIFD (host, 2155 stream, 2156 fExif.Get (), 2157 fShared.Get (), 2158 NULL, 2159 fTIFFBlockOffset + fShared->fGPSInfo, 2160 fTIFFBlockOffset, 2161 tcGPSInfo); 2162 2163 } 2164 2165 // Parse Interoperability IFD. 2166 2167 if (fShared->fInteroperabilityIFD) 2168 { 2169 2170 // Some Kodak KDC files have bogus Interoperability IFDs, so 2171 // validate the IFD before trying to parse it. 2172 2173 if (ValidateIFD (stream, 2174 fTIFFBlockOffset + fShared->fInteroperabilityIFD, 2175 fTIFFBlockOffset)) 2176 { 2177 2178 ParseIFD (host, 2179 stream, 2180 fExif.Get (), 2181 fShared.Get (), 2182 NULL, 2183 fTIFFBlockOffset + fShared->fInteroperabilityIFD, 2184 fTIFFBlockOffset, 2185 tcInteroperabilityIFD); 2186 2187 } 2188 2189 #if qDNGValidate 2190 2191 else 2192 { 2193 2194 ReportWarning ("The Interoperability IFD is not a valid IFD"); 2195 2196 } 2197 2198 #endif 2199 2200 } 2201 2202 // Parse Kodak DCR Private IFD. 2203 2204 if (fShared->fKodakDCRPrivateIFD) 2205 { 2206 2207 ParseIFD (host, 2208 stream, 2209 fExif.Get (), 2210 fShared.Get (), 2211 NULL, 2212 fTIFFBlockOffset + fShared->fKodakDCRPrivateIFD, 2213 fTIFFBlockOffset, 2214 tcKodakDCRPrivateIFD); 2215 2216 } 2217 2218 // Parse Kodak KDC Private IFD. 2219 2220 if (fShared->fKodakKDCPrivateIFD) 2221 { 2222 2223 ParseIFD (host, 2224 stream, 2225 fExif.Get (), 2226 fShared.Get (), 2227 NULL, 2228 fTIFFBlockOffset + fShared->fKodakKDCPrivateIFD, 2229 fTIFFBlockOffset, 2230 tcKodakKDCPrivateIFD); 2231 2232 } 2233 2234 // Parse MakerNote tag. 2235 2236 if (fShared->fMakerNoteCount) 2237 { 2238 2239 ParseMakerNote (host, 2240 stream, 2241 (uint32) (fTIFFBlockOffset + fShared->fMakerNoteCount), 2242 fShared->fMakerNoteOffset, 2243 fTIFFBlockOffset, 2244 0, 2245 stream.Length ()); 2246 2247 } 2248 2249 // Parse DNGPrivateData tag. 2250 2251 if (fShared->fDNGPrivateDataCount && 2252 fShared->fDNGVersion) 2253 { 2254 2255 ParseDNGPrivateData (host, stream); 2256 2257 } 2258 2259 #if qDNGValidate 2260 2261 // If we are running dng_validate on stand-alone camera profile file, 2262 // complete the validation of the profile. 2263 2264 if (fMagic == magicExtendedProfile) 2265 { 2266 2267 dng_camera_profile_info &profileInfo = fShared->fCameraProfile; 2268 2269 dng_camera_profile profile; 2270 2271 profile.Parse (stream, profileInfo); 2272 2273 if (profileInfo.fColorPlanes < 3 || !profile.IsValid (profileInfo.fColorPlanes)) 2274 { 2275 2276 ReportError ("Invalid camera profile file"); 2277 2278 } 2279 2280 } 2281 2282 #endif 2283 2284 } 2285 2286/*****************************************************************************/ 2287 2288void dng_info::PostParse (dng_host &host) 2289 { 2290 2291 uint32 index; 2292 2293 fExif->PostParse (host, *fShared.Get ()); 2294 2295 fShared->PostParse (host, *fExif.Get ()); 2296 2297 for (index = 0; index < fIFDCount; index++) 2298 { 2299 2300 fIFD [index]->PostParse (); 2301 2302 } 2303 2304 for (index = 0; index < fChainedIFDCount; index++) 2305 { 2306 2307 fChainedIFD [index]->PostParse (); 2308 2309 } 2310 2311 if (fShared->fDNGVersion != 0) 2312 { 2313 2314 // Find main IFD. 2315 2316 fMainIndex = -1; 2317 2318 for (index = 0; index < fIFDCount; index++) 2319 { 2320 2321 if (fIFD [index]->fUsesNewSubFileType && 2322 fIFD [index]->fNewSubFileType == sfMainImage) 2323 { 2324 2325 if (fMainIndex == -1) 2326 { 2327 2328 fMainIndex = index; 2329 2330 } 2331 2332 #if qDNGValidate 2333 2334 else 2335 { 2336 2337 ReportError ("Multiple IFDs marked as main image"); 2338 2339 } 2340 2341 #endif 2342 2343 } 2344 2345 else if (fIFD [index]->fNewSubFileType == sfPreviewImage || 2346 fIFD [index]->fNewSubFileType == sfAltPreviewImage) 2347 { 2348 2349 // Fill in default color space for DNG previews if not included. 2350 2351 if (fIFD [index]->fPreviewInfo.fColorSpace == previewColorSpace_MaxEnum) 2352 { 2353 2354 if (fIFD [index]->fSamplesPerPixel == 1) 2355 { 2356 2357 fIFD [index]->fPreviewInfo.fColorSpace = previewColorSpace_GrayGamma22; 2358 2359 } 2360 2361 else 2362 { 2363 2364 fIFD [index]->fPreviewInfo.fColorSpace = previewColorSpace_sRGB; 2365 2366 } 2367 2368 } 2369 2370 } 2371 2372 } 2373 2374 // Deal with lossless JPEG bug in early DNG versions. 2375 2376 if (fShared->fDNGVersion < dngVersion_1_1_0_0) 2377 { 2378 2379 if (fMainIndex != -1) 2380 { 2381 2382 fIFD [fMainIndex]->fLosslessJPEGBug16 = true; 2383 2384 } 2385 2386 } 2387 2388 // Find mask index. 2389 2390 for (index = 0; index < fIFDCount; index++) 2391 { 2392 2393 if (fIFD [index]->fNewSubFileType == sfTransparencyMask) 2394 { 2395 2396 if (fMaskIndex == -1) 2397 { 2398 2399 fMaskIndex = index; 2400 2401 } 2402 2403 #if qDNGValidate 2404 2405 else 2406 { 2407 2408 ReportError ("Multiple IFDs marked as transparency mask image"); 2409 2410 } 2411 2412 #endif 2413 2414 } 2415 2416 } 2417 2418 // Warn about Chained IFDs. 2419 2420 #if qDNGValidate 2421 2422 if (fChainedIFDCount > 0) 2423 { 2424 2425 ReportWarning ("This file has Chained IFDs, which will be ignored by DNG readers"); 2426 2427 } 2428 2429 #endif 2430 2431 } 2432 2433 } 2434 2435/*****************************************************************************/ 2436 2437bool dng_info::IsValidDNG () 2438 { 2439 2440 // Check shared info. 2441 2442 if (!fShared->IsValidDNG ()) 2443 { 2444 2445 return false; 2446 2447 } 2448 2449 // Check TIFF magic number. 2450 2451 if (fMagic != 42) 2452 { 2453 2454 #if qDNGValidate 2455 2456 ReportError ("Invalid TIFF magic number"); 2457 2458 #endif 2459 2460 return false; 2461 2462 } 2463 2464 // Make sure we have a main image IFD. 2465 2466 if (fMainIndex == -1) 2467 { 2468 2469 #if qDNGValidate 2470 2471 ReportError ("Unable to find main image IFD"); 2472 2473 #endif 2474 2475 return false; 2476 2477 } 2478 2479 // Make sure is each IFD is valid. 2480 2481 for (uint32 index = 0; index < fIFDCount; index++) 2482 { 2483 2484 uint32 parentCode = (index == 0 ? 0 : tcFirstSubIFD + index - 1); 2485 2486 if (!fIFD [index]->IsValidDNG (*fShared.Get (), 2487 parentCode)) 2488 { 2489 2490 // Only errors in the main and transparency mask IFDs are fatal to parsing. 2491 2492 if (index == (uint32) fMainIndex || 2493 index == (uint32) fMaskIndex) 2494 { 2495 2496 return false; 2497 2498 } 2499 2500 } 2501 2502 } 2503 2504 return true; 2505 2506 } 2507 2508/*****************************************************************************/ 2509