TiffEntry::TiffEntry(FileMap* f, uint32 offset, uint32 up_offset) { parent_offset = up_offset; own_data = NULL; empty_data = 0; file = f; unsigned short* p = (unsigned short*)f->getData(offset, 2); tag = (TiffTag)p[0]; type = (TiffDataType)p[1]; count = *(align1_int*)f->getData(offset + 4, 4); if (type > 13) ThrowTPE("Error reading TIFF structure. Unknown Type 0x%x encountered.", type); uint64 bytesize = (uint64)count << datashifts[type]; if (bytesize > UINT32_MAX) ThrowTPE("TIFF entry is supposedly %llu bytes", bytesize); if (bytesize == 0) // Better return empty than NULL-dereference later data = (uchar8 *) &empty_data; else if (bytesize <= 4) data = f->getDataWrt(offset + 8, bytesize); else { // offset data_offset = *(align1_uint*)f->getData(offset + 8, 4); fetchData(); } #ifdef _DEBUG debug_intVal = 0xC0CAC01A; debug_floatVal = sqrtf(-1); if (type == TIFF_LONG || type == TIFF_SHORT) debug_intVal = getInt(); if (type == TIFF_FLOAT || type == TIFF_DOUBLE) debug_floatVal = getFloat(); #endif }
unsigned int TiffEntryBE::getInt() { if (!(type == TIFF_LONG || type == TIFF_SHORT || type == TIFF_UNDEFINED)) ThrowTPE("TIFF, getInt: Wrong type 0x%x encountered. Expected Int", type); if (type == TIFF_SHORT) return getShort(); return (unsigned int)data[0] << 24 | (unsigned int)data[1] << 16 | (unsigned int)data[2] << 8 | (unsigned int)data[3]; }
TiffEntryBE::TiffEntryBE(FileMap* f, uint32 offset) : mDataSwapped(false) { type = TIFF_UNDEFINED; // We set type to undefined to avoid debug assertion errors. data = f->getDataWrt(offset); tag = (TiffTag)getShort(); data += 2; TiffDataType _type = (TiffDataType)getShort(); data += 2; count = getInt(); type = _type; //Now we can set it to the proper type if (type > 13) ThrowTPE("Error reading TIFF structure. Unknown Type 0x%x encountered.", type); uint32 bytesize = count << datashifts[type]; if (bytesize <= 4) { data = f->getDataWrt(offset + 8); } else { // offset data = f->getDataWrt(offset + 8); data_offset = (unsigned int)data[0] << 24 | (unsigned int)data[1] << 16 | (unsigned int)data[2] << 8 | (unsigned int)data[3]; CHECKSIZE(data_offset + bytesize); data = f->getDataWrt(data_offset); } #ifdef _DEBUG debug_intVal = 0xC0CAC01A; debug_floatVal = sqrtf(-1); if (type == TIFF_LONG || type == TIFF_SHORT) debug_intVal = getInt(); if (type == TIFF_FLOAT || type == TIFF_DOUBLE) debug_floatVal = getFloat(); #endif }
TiffEntry::TiffEntry(FileMap* f, uint32 offset, uint32 up_offset) { parent_offset = up_offset; own_data = NULL; file = f; unsigned short* p = (unsigned short*)f->getData(offset); tag = (TiffTag)p[0]; type = (TiffDataType)p[1]; count = *(int*)f->getData(offset + 4); if (type > 13) ThrowTPE("Error reading TIFF structure. Unknown Type 0x%x encountered.", type); uint32 bytesize = count << datashifts[type]; if (bytesize <= 4) { data = f->getDataWrt(offset + 8); } else { // offset data_offset = *(uint32*)f->getData(offset + 8); fetchData(); } #ifdef _DEBUG debug_intVal = 0xC0CAC01A; debug_floatVal = sqrtf(-1); if (type == TIFF_LONG || type == TIFF_SHORT) debug_intVal = getInt(); if (type == TIFF_FLOAT || type == TIFF_DOUBLE) debug_floatVal = getFloat(); #endif }
unsigned int TiffEntry::getInt() { if (!(type == TIFF_LONG || type == TIFF_SHORT || type == TIFF_BYTE || type == TIFF_OFFSET)) ThrowTPE("TIFF, getInt: Wrong type 0x%x encountered. Expected Long, Short or Byte", type); if (type == TIFF_BYTE) return getByte(); if (type == TIFF_SHORT) return getShort(); return (uint32)data[3] << 24 | (uint32)data[2] << 16 | (uint32)data[1] << 8 | (uint32)data[0]; }
string TiffEntry::getString() { if (type != TIFF_ASCII) ThrowTPE("TIFF, getString: Wrong type 0x%x encountered. Expected Ascii", type); if (!own_data) { own_data = new uchar8[count]; memcpy(own_data, data, count); own_data[count-1] = 0; // Ensure string is not larger than count defines } return string((const char*)&own_data[0]); }
void TiffEntry::setData( const void *in_data, uint32 byte_count ) { uint32 bytesize = count << datashifts[type]; if (byte_count > bytesize) ThrowTPE("TIFF, data set larger than entry size given"); if (!own_data) { own_data = new uchar8[bytesize]; memcpy(own_data, data, bytesize); } memcpy(own_data, in_data, byte_count); }
TiffEntryBE::TiffEntryBE(FileMap* f, uint32 offset, uint32 up_offset) { own_data = NULL; empty_data = 0; file = f; parent_offset = up_offset; type = TIFF_UNDEFINED; // We set type to undefined to avoid debug assertion errors. data = f->getDataWrt(offset, 8); tag = (TiffTag)getShort(); data += 2; TiffDataType _type = (TiffDataType)getShort(); data += 2; count = getInt(); type = _type; //Now we can set it to the proper type if (type > 13) ThrowTPE("Error reading TIFF structure. Unknown Type 0x%x encountered.", type); uint64 bytesize = (uint64)count << datashifts[type]; if (bytesize > UINT32_MAX) ThrowTPE("TIFF entry is supposedly %llu bytes", bytesize); if (bytesize == 0) // Better return empty than NULL-dereference later data = (uchar8 *) &empty_data; else if (bytesize <= 4) data = f->getDataWrt(offset + 8, bytesize); else { // it's an offset data = f->getDataWrt(offset + 8, 4); data_offset = (unsigned int)data[0] << 24 | (unsigned int)data[1] << 16 | (unsigned int)data[2] << 8 | (unsigned int)data[3]; data = f->getDataWrt(data_offset, bytesize); } #ifdef _DEBUG debug_intVal = 0xC0CAC01A; debug_floatVal = sqrtf(-1); if (type == TIFF_LONG || type == TIFF_SHORT) debug_intVal = getInt(); if (type == TIFF_FLOAT || type == TIFF_DOUBLE) debug_floatVal = getFloat(); #endif }
/* It is a simpler form of Tiff IFD, so we add them as TiffEntries */ void RawParser::ParseFuji(uint32 offset, TiffIFD *target_ifd) { try { ByteStreamSwap bytes(mInput->getData(offset), mInput->getSize()-offset); uint32 entries = bytes.getUInt(); if (entries > 255) ThrowTPE("ParseFuji: Too many entries"); for (uint32 i = 0; i < entries; i++) { ushort16 tag = bytes.getShort(); ushort16 length = bytes.getShort(); TiffEntry *t; // Set types of known tags switch (tag) { case 0x100: case 0x121: case 0x2ff0: t = new TiffEntryBE((TiffTag)tag, TIFF_SHORT, length/2, bytes.getData()); break; case 0xc000: // This entry seem to have swapped endianness: t = new TiffEntry((TiffTag)tag, TIFF_LONG, length/4, bytes.getData()); break; default: t = new TiffEntry((TiffTag)tag, TIFF_UNDEFINED, length, bytes.getData()); } target_ifd->mEntry[t->tag] = t; bytes.skipBytes(length); } } catch (IOException e) { ThrowTPE("ParseFuji: IO error occurred during parsing. Skipping the rest"); } }
std::unique_ptr<RawDecoder> TiffParser::makeDecoder(TiffRootIFDOwner root, const Buffer& data) { const Buffer* mInput = &data; if (!root) ThrowTPE("TiffIFD is null."); for (const auto& decoder : Map) { checker_t dChecker = nullptr; constructor_t dConstructor = nullptr; std::tie(dChecker, dConstructor) = decoder; assert(dChecker); assert(dConstructor); if (!dChecker(root.get(), mInput)) continue; return dConstructor(move(root), mInput); } ThrowTPE("No decoder found. Sorry."); }
const short16* TiffEntryBE::getSignedShortArray() { if (!(type == TIFF_SSHORT)) ThrowTPE("TIFF, getShortArray: Wrong type 0x%x encountered. Expected SShort", type); if (own_data) return (short16 *)own_data; own_data = new uchar8[count*2]; ushort16* d = (ushort16*)own_data; for (uint32 i = 0; i < count; i++) { d[i] = (ushort16)data[i*2+0] << 8 | (ushort16)data[i*2+1]; } return (short16 *)d; }
const unsigned int* TiffEntryBE::getIntArray() { //TODO: Make critical section to avoid clashes. if (!(type == TIFF_LONG || type == TIFF_UNDEFINED || type == TIFF_RATIONAL || type == TIFF_SRATIONAL)) ThrowTPE("TIFF, getIntArray: Wrong type 0x%x encountered. Expected Int", type); if (mDataSwapped) return (unsigned int*)&data[0]; unsigned int* d = (unsigned int*) & data[0]; for (uint32 i = 0; i < count; i++) { d[i] = (unsigned int)data[i*4+0] << 24 | (unsigned int)data[i*4+1] << 16 | (unsigned int)data[i*4+2] << 8 | (unsigned int)data[i*4+3]; } mDataSwapped = true; return d; }
const unsigned short* TiffEntryBE::getShortArray() { //TODO: Make critical section to avoid clashes. if (!(type == TIFF_SHORT || type == TIFF_UNDEFINED)) ThrowTPE("TIFF, getShortArray: Wrong type 0x%x encountered. Expected Short", type); if (mDataSwapped) return (unsigned short*)&data[0]; unsigned short* d = (unsigned short*) & data[0]; for (uint32 i = 0; i < count; i++) { d[i] = (unsigned short)data[i*2+0] << 8 | (unsigned short)data[i*2+1]; } mDataSwapped = true; return d; }
const uint32* TiffEntryBE::getIntArray() { if (!(type == TIFF_LONG || type == TIFF_SLONG || type == TIFF_UNDEFINED || type == TIFF_RATIONAL || type == TIFF_SRATIONAL)) ThrowTPE("TIFF, getIntArray: Wrong type 0x%x encountered. Expected Int", type); if (own_data) return (uint32*)own_data; uint32 ncount = count * ((type == TIFF_RATIONAL || type == TIFF_SRATIONAL) ? 2 : 1); own_data = new uchar8[ncount*4]; uint32* d = (uint32*)own_data; for (uint32 i = 0; i < ncount; i++) { #ifdef LE_PLATFORM_HAS_BSWAP d[i] = PLATFORM_BSWAP32(*(uint32*)&data[i*4]); #else d[i] = (unsigned int)data[i*4+0] << 24 | (unsigned int)data[i*4+1] << 16 | (unsigned int)data[i*4+2] << 8 | (unsigned int)data[i*4+3]; #endif } return (uint32*)own_data; }
float TiffEntry::getFloat() { if (!(type == TIFF_FLOAT || type == TIFF_DOUBLE || type == TIFF_RATIONAL || type == TIFF_SRATIONAL || type == TIFF_LONG || type == TIFF_SHORT)) ThrowTPE("TIFF, getFloat: Wrong type 0x%x encountered. Expected Float", type); if (type == TIFF_DOUBLE) { return (float)*(double*)&data[0]; } else if (type == TIFF_FLOAT) { return *(float*)&data[0]; } else if (type == TIFF_LONG || type == TIFF_SHORT) { return (float)getInt(); } else if (type == TIFF_RATIONAL) { const unsigned int* t = getIntArray(); if (t[1]) return (float)t[0]/t[1]; } else if (type == TIFF_SRATIONAL) { const int* t = (const int*)getIntArray(); if (t[1]) return (float)t[0]/t[1]; } return 0.0f; }
TiffRootIFDOwner TiffParser::parse(const Buffer& data) { ByteStream bs(data, 0); bs.setByteOrder(getTiffByteOrder(bs, 0, "TIFF header")); bs.skipBytes(2); ushort16 magic = bs.getU16(); if (magic != 42 && magic != 0x4f52 && magic != 0x5352 && magic != 0x55) // ORF has 0x4f52/0x5352, RW2 0x55 - Brillant! ThrowTPE("Not a TIFF file (magic 42)"); TiffRootIFDOwner root = std::make_unique<TiffRootIFD>( nullptr, nullptr, bs, UINT32_MAX); // tell TiffIFD constructur not to parse bs as IFD NORangesSet<Buffer> ifds; for (uint32 IFDOffset = bs.getU32(); IFDOffset; IFDOffset = root->getSubIFDs().back()->getNextIFD()) { root->add(std::make_unique<TiffIFD>(root.get(), &ifds, bs, IFDOffset)); } return root; }
void TiffEntryBE::setData( const void *in_data, uint32 byte_count ) { if (datashifts[type] != 0) ThrowTPE("TIFF, Unable to set data on byteswapped platforms (unsupported)"); TiffEntry::setData(in_data, byte_count); }
uchar8 TiffEntry::getByte() { if (type != TIFF_BYTE) ThrowTPE("TIFF, getByte: Wrong type 0x%x encountered. Expected Byte", type); return data[0]; }
const short16* TiffEntry::getSignedShortArray() { if (!(type == TIFF_SSHORT)) ThrowTPE("TIFF, getShortArray: Wrong type 0x%x encountered. Expected Signed Short", type); return (short16*)&data[0]; }
const ushort16* TiffEntry::getShortArray() { if (!(type == TIFF_SHORT || type == TIFF_UNDEFINED)) ThrowTPE("TIFF, getShortArray: Wrong type 0x%x encountered. Expected Short", type); return (ushort16*)&data[0]; }
const uint32* TiffEntry::getIntArray() { if (type != TIFF_LONG && type != TIFF_SLONG && type != TIFF_RATIONAL && type != TIFF_SRATIONAL && type != TIFF_UNDEFINED && type != TIFF_OFFSET) ThrowTPE("TIFF, getIntArray: Wrong type 0x%x encountered. Expected Long", type); return (uint32*)&data[0]; }
unsigned short TiffEntry::getShort() { if (type != TIFF_SHORT) ThrowTPE("TIFF, getShort: Wrong type 0x%x encountered. Expected Short", type); return ((ushort16)data[1] << 8) | (ushort16)data[0]; }
unsigned short TiffEntryBE::getShort() { if (!(type == TIFF_SHORT || type == TIFF_UNDEFINED)) ThrowTPE("TIFF, getShort: Wrong type 0x%x encountered. Expected Short", type); return (unsigned short)data[0] << 8 | (unsigned short)data[1]; }