public TiffEntry(ref FileMap f, UInt32 offset, UInt32 up_offset) { parent_offset = up_offset; own_data = null; empty_data = 0; file = f; type = TiffDataType.TIFF_UNDEFINED; // We set type to undefined to avoid debug assertion errors. byte[] temp_data = f.getData(offset, 8); tag = (TiffTag)Common.get4LEget2LE(temp_data, 0); type = (TiffDataType)Common.get4LEget2LE(temp_data, 2); count = Common.get4LE(temp_data, 4); bytesize = (UInt64)count << (int)Data.datashifts[(int)type]; if (bytesize > UInt32.MaxValue) { TiffParserException.ThrowTPE("TIFF entry is supposedly " + bytesize + " bytes"); } if (bytesize == 0) // Better return empty than null-dereference later { data = (byte8 *)&empty_data; } else if (bytesize <= 4) { data = fgetDataWrt(offset + 8, bytesize); } else { // offset data_offset = get4LE(f.getData(offset + 8, 4), 0); fetchData(); } }
/* Construct decoder instance - FileMap is a filemap of the file to be decoded */ /* The FileMap is not owned by this class, will not be deleted, and must remain */ /* valid while this object exists */ RawDecoder(ref FileMap file) { mRaw = RawImage.create(); mFile = file; decoderVersion = 0; failOnUnknown = false; interpolateBadPixels = true; applyStage1DngOpcodes = true; applyCrop = true; uncorrectedRawValues = false; fujiRotate = true; }
AriDecoder(FileMap file):base(file) { if (mFile.getSize() < 4096) { ThrowRDE("ARRI: File too small (no header)"); } try { ByteStream s; if (getHostEndianness() == Endianness.little) { s = new ByteStream(ref mFile, 8); } else { s = new ByteStreamSwap(ref mFile, 8); } mDataOffset = s.getInt(); UInt32 sompublicber = s.getInt(); // Value: 3? UInt32 segmentLength = s.getInt(); // Value: 0x3c = length if (sompublicber != 3 || segmentLength != 0x3c) { ThrowRDE("Unknown values in ARRIRAW header, %d, %d", sompublicber, segmentLength); } mWidth = s.getInt(); mHeight = s.getInt(); s.setAbsoluteOffset(0x40); mDataSize = s.getInt(); // Smells like whitebalance s.setAbsoluteOffset(0x5c); mWB[0] = s.getFloat(); // 1.3667001 in sample mWB[1] = s.getFloat(); // 1.0000000 in sample mWB[2] = s.getFloat(); // 1.6450000 in sample // Smells like iso s.setAbsoluteOffset(0xb8); mIso = s.getInt(); // 100 in sample s.setAbsoluteOffset(0x29c - 8); mModel = s.getString(); s.setAbsoluteOffset(0x2a4 - 8); mEncoder = s.getString(); } catch (IOException &e) { ThrowRDE("ARRI: IO Exception:%s", e.what()); } }
public TiffEntry(TiffTag _tag, TiffDataType _type, UInt32 _count, byte[] _data) { file = null; parent_offset = 0; tag = _tag; type = _type; count = _count; data_offset = 0; // Set nonsense value in case someone tries to use it bytesize = (ulong)_count << (int)Data.datashifts[(int)_type]; if (null == _data) { own_data = new byte[bytesize]; memset(own_data, 0, bytesize); data = own_data; } else { data = _data; own_data = null; } }
TiffEntryBE(ref FileMap f, UInt32 offset, UInt32 up_offset) { parent_offset = up_offset; own_data = null; empty_data = 0; file = f; type = TiffDataType.TIFF_UNDEFINED; // We set type to undefined to avoid debug assertion errors. byte[] temp_data = f.getData(offset, 8); tag = (TiffTag)get2BE(temp_data, 0); type = (TiffDataType)get2BE(temp_data, 2); count = get4BE(temp_data, 4); if ((int)type > 13) { TiffParserException.ThrowTPE("Error reading TIFF structure. Unknown Type " + type + " encountered."); } bytesize = (UInt64)count << (int)Data.datashifts[(int)type]; if (bytesize > UInt32.MaxValue) { TiffParserException.ThrowTPE("TIFF entry is supposedly " + bytesize + " bytes"); } if (bytesize == 0) // Better return empty than null-dereference later { data = empty_data; } else if (bytesize <= 4) { data = f.getDataWrt(offset + 8, bytesize); } else { // offset data_offset = get4BE(f.getData(offset + 8, 4), 0); data = f.getDataWrt(data_offset, bytesize); } }
public TiffEntry() { own_data = null; parent_offset = 0; file = null; }
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(ref FileMap f) { TIFF_DEPTH(0); mFile = f; }
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; }