TiffIFD(ref FileMap f, UInt32 offset, UInt32 _depth) { TIFF_DEPTH(_depth); mFile = f; ushort[] entries; entries = *(ushort*)f.getData(offset, 2); // Directory entries in this IFD for (UInt32 i = 0; i < entries; i++) { int entry_offset = (int)(offset + 2 + i * 12); // If the space for the entry is no longer valid stop reading any more as // the file is broken or truncated if (!mFile.isValid(entry_offset, 12)) break; TiffEntry t = null; try { t = new TiffEntry(f, entry_offset, offset); } catch (IOException) { // Ignore unparsable entry continue; } switch (t.tag) { case DNGPRIVATEDATA: { try { TiffIFD* maker_ifd = parseDngPrivateData(t); mSubIFD.push_back(maker_ifd); delete(t); } catch (TiffParserException) { // Unparsable private data are added as entries mEntry[t.tag] = t; } catch (IOException) { // Unparsable private data are added as entries mEntry[t.tag] = t; } } break; case MAKERNOTE: case MAKERNOTE_ALT: { try { mSubIFD.push_back(parseMakerNote(f, t.getDataOffset(), endian)); delete(t); } catch (TiffParserException) { // Unparsable makernotes are added as entries mEntry[t.tag] = t; } catch (IOException) { // Unparsable makernotes are added as entries mEntry[t.tag] = t; } } break; case FUJI_RAW_IFD: if (t.type == 0xd) // FUJI - correct type t.type = TIFF_LONG; case SUBIFDS: case EXIFIFDPOINTER: try { for (UInt32 j = 0; j < t.count; j++) { mSubIFD.push_back(new TiffIFD(f, t.getInt(j), depth)); } delete(t); } catch (TiffParserException) { // Unparsable subifds are added as entries mEntry[t.tag] = t; } catch (IOException) { // Unparsable subifds are added as entries mEntry[t.tag] = t; } break; default: mEntry[t.tag] = t; } } nextIFD = *(align1_int*)f.getData(offset + 2 + entries * 12, 4); }
TiffIFD parseDngPrivateData(TiffEntry t) { /* 1. Six bytes containing the zero-terminated string "Adobe". (The DNG specification calls for the DNGPrivateData tag to start with an ASCII string identifying the creator/format). 2. 4 bytes: an ASCII string ("MakN" for a Makernote), indicating what sort of data is being stored here. Note that this is not zero-terminated. 3. A four-byte count (number of data bytes following); this is the length of the original MakerNote data. (This is always in "most significant byte first" format). 4. 2 bytes: the byte-order indicator from the original file (the usual 'MM'/4D4D or 'II'/4949). 5. 4 bytes: the original file offset for the MakerNote tag data (stored according to the byte order given above). 6. The contents of the MakerNote tag. This is a simple byte-for-byte copy, with no modification. */ UInt32 size = t.count; byte[] data = t.getData(); string id((char*) data); if (0 != id.compare("Adobe")) TiffParsingException.ThrowTPE("Not Adobe Private data"); data += 6; if (!(data[0] == 'M' && data[1] == 'a' && data[2] == 'k' && data[3] == 'N')) ThrowTPE("Not Makernote"); data += 4; UInt32 count; if (Endianness.big == Common.getHostEndianness()) count = *(UInt32*)data; else count = (unsigned int)data[0] << 24 | (unsigned int)data[1] << 16 | (unsigned int)data[2] << 8 | (unsigned int)data[3]; data += 4; if (count > size) ThrowTPE("Error reading TIFF structure (invalid size). File Corrupt"); Endianness makernote_endian = unknown; if (data[0] == 0x49 && data[1] == 0x49) makernote_endian = little; else if (data[0] == 0x4D && data[1] == 0x4D) makernote_endian = big; else ThrowTPE("Cannot determine endianess of DNG makernote"); data += 2; UInt32 org_offset; if (big == getHostEndianness()) org_offset = *(UInt32*)data; else org_offset = (unsigned int)data[0] << 24 | (unsigned int)data[1] << 16 | (unsigned int)data[2] << 8 | (unsigned int)data[3]; data += 4; /* We don't parse original makernotes that are placed after 300MB mark in the original file */ if (org_offset + count > 300 * 1024 * 1024) ThrowTPE("Adobe Private data: original offset of makernote is past 300MB offset"); /* Create fake tiff with original offsets */ byte[] maker_data = new byte8[org_offset + count]; memcpy(&maker_data[org_offset], data, count); FileMap* maker_map = new FileMap(maker_data, org_offset + count); TiffIFD* maker_ifd; try { maker_ifd = parseMakerNote(maker_map, org_offset, makernote_endian); } catch (TiffParserException &e) { delete[] maker_data; delete maker_map; throw e; } delete[] maker_data; delete maker_map; return maker_ifd; }