From cd7d9dd8236f37975ed2f4d111acde89d1683849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Mon, 4 Sep 2017 22:49:23 +0200 Subject: [PATCH 01/71] Importing Robin Mills' bigtiff draft + basic cmake stuff --- CMakeLists.txt | 2 + bigtiff/CMakeLists.txt | 2 + bigtiff/parse.cpp | 396 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 400 insertions(+) create mode 100644 bigtiff/CMakeLists.txt create mode 100644 bigtiff/parse.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 570e5742..3f7deff6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,8 @@ if( EXIV2_ENABLE_BUILD_PO ) add_subdirectory( po ) endif() +add_subdirectory( bigtiff ) + ## # tests add_custom_target(tests COMMAND env EXIV2_BINDIR="${CMAKE_BINARY_DIR}"/bin make tests WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ) diff --git a/bigtiff/CMakeLists.txt b/bigtiff/CMakeLists.txt new file mode 100644 index 00000000..fb580ab6 --- /dev/null +++ b/bigtiff/CMakeLists.txt @@ -0,0 +1,2 @@ + +add_executable(big_tiff_parser parse.cpp) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp new file mode 100644 index 00000000..59dba031 --- /dev/null +++ b/bigtiff/parse.cpp @@ -0,0 +1,396 @@ +#include + +#define WIDTH 32 + +enum TypeId { + unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. + asciiString = 2, //!< Exif ASCII type, 8-bit byte. + unsignedShort = 3, //!< Exif SHORT type, 16-bit (2-byte) unsigned integer. + unsignedLong = 4, //!< Exif LONG type, 32-bit (4-byte) unsigned integer. + unsignedRational = 5, //!< Exif RATIONAL type, two LONGs: numerator and denumerator of a fraction. + signedByte = 6, //!< Exif SBYTE type, an 8-bit signed (twos-complement) integer. + undefined = 7, //!< Exif UNDEFINED type, an 8-bit byte that may contain anything. + signedShort = 8, //!< Exif SSHORT type, a 16-bit (2-byte) signed (twos-complement) integer. + signedLong = 9, //!< Exif SLONG type, a 32-bit (4-byte) signed (twos-complement) integer. + signedRational = 10, //!< Exif SRATIONAL type, two SLONGs: numerator and denumerator of a fraction. + tiffFloat = 11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. + tiffDouble = 12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. + tiffIfd = 13, //!< TIFF IFD type, 32-bit (4-byte) unsigned integer. + iptcString = 0x10000, //!< IPTC string type. + iptcDate = 0x10001, //!< IPTC date type. + iptcTime = 0x10002, //!< IPTC time type. + comment = 0x10003, //!< %Exiv2 type for the Exif user comment. + directory = 0x10004, //!< %Exiv2 type for a CIFF directory. + xmpText = 0x10005, //!< XMP text type. + xmpAlt = 0x10006, //!< XMP alternative type. + xmpBag = 0x10007, //!< XMP bag type. + xmpSeq = 0x10008, //!< XMP sequence type. + langAlt = 0x10009, //!< XMP language alternative type. + invalidTypeId = 0x1fffe, //!< Invalid type id. + lastTypeId = 0x1ffff //!< Last type id. +}; + +bool isStringType(uint16_t type) +{ + return type == asciiString + || type == unsignedByte + || type == signedByte + || type == undefined + ; +} + +bool isShortType(uint16_t type) { + return type == unsignedShort + || type == signedShort + ; +} + +bool isLongType(uint16_t type) { + return type == unsignedLong + || type == signedLong + ; +} + +bool isRationalType(uint16_t type) { + return type == unsignedRational + || type == signedRational + ; +} + +bool is2ByteType(uint16_t type) +{ + return isShortType(type); +} + +bool is4ByteType(uint16_t type) +{ + return isLongType(type) + || type == tiffFloat + || type == tiffIfd + ; +} + +bool is8ByteType(uint16_t type) +{ + return isRationalType(type) + || type == tiffDouble + ; +} + +bool isBigEndianPlatform() +{ + union { + uint32_t i; + char c[4]; + } e = { 0x01000000 }; + + return e.c[0]?true:false; +} + +bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } + +uint32_t byteSwap(uint32_t value,bool bSwap) +{ + uint32_t result = 0; + result |= (value & 0x000000FF) << 24; + result |= (value & 0x0000FF00) << 8; + result |= (value & 0x00FF0000) >> 8; + result |= (value & 0xFF000000) >> 24; + return bSwap ? result : value; +} + +uint16_t byteSwap(uint16_t value,bool bSwap) +{ + uint16_t result = 0; + result |= (value & 0x00FF) << 8; + result |= (value & 0xFF00) >> 8; + return bSwap ? result : value; +} + +uint16_t byteSwap2(void* buf,size_t offset,bool bSwap) +{ + uint16_t v; + char* p = (char*) &v; + char* b = (char*) buf; + p[0] = b[offset]; + p[1] = b[offset+1]; + return byteSwap(v,bSwap); +} + +uint32_t byteSwap4(void* buf,size_t offset,bool bSwap) +{ + uint32_t v; + char* p = (char*) &v; + char* b = (char*) buf; + p[0] = b[offset]; + p[1] = b[offset+1]; + p[2] = b[offset+2]; + p[3] = b[offset+3]; + return byteSwap(v,bSwap); +} + +std::string indent(int32_t d) +{ + std::string result ; + if ( d > 0 ) + while ( d--) + result += " "; + return result; +} + +static const char* tagName(uint16_t tag,size_t nMaxLength) +{ + const char* result = NULL; +/* + // build a static map of tags for fast search + static std::map tags; + static bool init = true; + static char buffer[80]; + + if ( init ) { + int idx; + const TagInfo* ti ; + for (ti = mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = mpfTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = Nikon1MakerNote::tagList(), idx = 0 + ; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + } + init = false; + + try { + result = tags[tag].c_str(); + if ( nMaxLength > sizeof(buffer) -2 ) + nMaxLength = sizeof(buffer) -2; + strncpy(buffer,result,nMaxLength); + result = buffer; + } catch ( ... ) {} +*/ + return result ; +} + +static const char* typeName(uint16_t tag) +{ + //! List of TIFF image tags + const char* result = NULL; + switch (tag ) { + case unsignedByte : result = "BYTE" ; break; + case asciiString : result = "ASCII" ; break; + case unsignedShort : result = "SHORT" ; break; + case unsignedLong : result = "LONG" ; break; + case unsignedRational : result = "RATIONAL" ; break; + case signedByte : result = "SBYTE" ; break; + case undefined : result = "UNDEFINED" ; break; + case signedShort : result = "SSHORT" ; break; + case signedLong : result = "SLONG" ; break; + case signedRational : result = "SRATIONAL" ; break; + case tiffFloat : result = "FLOAT" ; break; + case tiffDouble : result = "DOUBLE" ; break; + case tiffIfd : result = "IFD" ; break; + default : result = "unknown" ; break; + } + return result; +} + +typedef struct { + uint16_t tagID; + uint16_t tagType ; + uint32_t count; + uint32_t offset; +} field_t; + +void printIFD(FILE* f, std::ostream& out, uint32_t offset,bool bSwap,int depth) +{ + depth++; + bool bFirst = true; + + // buffer + bool bPrint = true; + + do { + // Read top of directory + fseek(f,offset,beg); + uint16_t dir; + fread(&dir,1,2,f); + uint16_t dirLength = byteSwap2(dir,0,bSwap); + + bool tooBig = dirLength > 500; + + if ( bFirst && bPrint ) { + out << indent(depth) << stringFormat("STRUCTURE OF TIFF FILE << path << std::endl; + if ( tooBig ) out << indent(depth) << "dirLength = " << dirLength << std::endl; + } + if (tooBig) break; + + // Read the dictionary + for ( int i = 0 ; i < dirLength ; i ++ ) { + if ( bFirst && bPrint ) { + out << indent(depth) + << " address | tag | " + << " type | count | offset | value\n"; + } + bFirst = false; + field_t field; + + fread(&field,sizeof(field_t),1,f); + uint16_t tag = byteSwap2(&field.tagID ,0,bSwap); + uint16_t type = byteSwap2(&field.tagType,2,bSwap); + uint32_t count = byteSwap4(&field.count ,4,bSwap); + uint32_t offset = byteSwap4(&field.offset ,8,bSwap); + + std::string sp = "" ; // output spacer + + //prepare to print the value + uint32_t kount = isStringType(type) ? (count > 32 ? 32 : count) // restrict long arrays + : count > 5 ? 5 + : count + ; + uint32_t pad = isStringType(type) ? 1 : 0; + uint32_t size = isStringType(type) ? 1 + : is2ByteType(type) ? 2 + : is4ByteType(type) ? 4 + : is8ByteType(type) ? 8 + : 1 + ; + + DataBuf buf(size*count + pad); // allocate a buffer + std::memcpy(buf.pData_,dir.pData_+8,4); // copy dir[8:11] into buffer (short strings) + if ( count*size > 4 ) { // read into buffer + size_t restore = io.tell(); // save + io.seek(offset,BasicIo::beg); // position + io.read(buf.pData_,count*size);// read + io.seek(restore,BasicIo::beg); // restore + } + + if ( bPrint ) { + uint32_t address = start + 2 + i*12 ; + out << indent(depth) + << stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " + ,address,tag,tagName(tag,25),typeName(type),count,offset); + if ( isShortType(type) ){ + for ( size_t k = 0 ; k < kount ; k++ ) { + out << sp << byteSwap2(buf,k*size,bSwap); + sp = " "; + } + } else if ( isLongType(type) ){ + for ( size_t k = 0 ; k < kount ; k++ ) { + out << sp << byteSwap4(buf,k*size,bSwap); + sp = " "; + } + + } else if ( isRationalType(type) ){ + for ( size_t k = 0 ; k < kount ; k++ ) { + uint32_t a = byteSwap4(buf,k*size+0,bSwap); + uint32_t b = byteSwap4(buf,k*size+4,bSwap); + out << sp << a << "/" << b; + sp = " "; + } + } else if ( isStringType(type) ) { + out << sp << binaryToString(buf, kount); + } + + sp = kount == count ? "" : " ..."; + out << sp << std::endl; + + if ( option == kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) { + for ( size_t k = 0 ; k < count ; k++ ) { + size_t restore = io.tell(); + uint32_t offset = byteSwap4(buf,k*size,bSwap); + std::cerr << "tag = " << stringFormat("%#x",tag) << std::endl; + printIFDStructure(io,out,option,offset,bSwap,c,depth); + io.seek(restore,BasicIo::beg); + } + } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { + size_t restore = io.tell(); // save + io.seek(offset,BasicIo::beg); // position + byte* bytes=new byte[count] ; // allocate memory + io.read(bytes,count) ; // read + io.seek(restore,BasicIo::beg); // restore + IptcData::printStructure(out,bytes,count,depth); + delete[] bytes; // free + } else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { + size_t restore = io.tell(); // save + + uint32_t jump= 10 ; + byte bytes[20] ; + const char* chars = (const char*) &bytes[0] ; + io.seek(offset,BasicIo::beg); // position + io.read(bytes,jump ) ; // read + bytes[jump]=0 ; + if ( ::strcmp("Nikon",chars) == 0 ) { + // tag is an embedded tiff + byte* bytes=new byte[count-jump] ; // allocate memory + io.read(bytes,count-jump) ; // read + MemIo memIo(bytes,count-jump) ; // create a file + std::cerr << "Nikon makernote" << std::endl; + printTiffStructure(memIo,out,option,depth); + delete[] bytes ; // free + } else { + // tag is an IFD + io.seek(0,BasicIo::beg); // position + std::cerr << "makernote" << std::endl; + printIFDStructure(io,out,option,offset,bSwap,c,depth); + } + + io.seek(restore,BasicIo::beg); // restore + } + } + } + io.read(dir.pData_, 4); + start = tooBig ? 0 : byteSwap4(dir,0,bSwap); + out.flush(); + } while (start) ; + + if ( bPrint ) { + out << indent(depth) << "END " << io.path() << std::endl; + } + depth--; +} + +int main(int argc,const char* argv[]) +{ + int result = 0; + int bSwap = false; + uint32_t offset = 0; + + if ( argc > 0 ) { + FILE* f = fopen(argv[1],"rb"); + if ( f ) { + char buff[2*WIDTH]; + fread(buff,1,sizeof buff,f); + bSwap = (isLittleEndianPlatform() && buff[0] == 'M') + || (isBigEndianPlatform() && buff[0] == 'I') + ; + uint16_t magic = byteSwap2(buff,2,bSwap); + offset = byteSwap4(buff,4,bSwap); + if ( buff[0] != buff[1] || (buff[0] != 'I' && buff[0] != 'M') || magic != 42 ) { + std::cerr << "bSwap = " << bSwap << std::endl; + std::cerr << "magic = " << magic << std::endl; + std::cerr << "offset = " << offset << std::endl; + std::cerr << argv[1] << " is not a TIFF file" << std::endl; + result = 3 ; + } + fclose(f); + } else { + std::cerr << argv[0] << " unable to open " << argv[1] << std::endl; + result = 2 ; + } + + } else { + std::cerr << argv[0] << " path" << std::endl; + result = 1 ; + } + + if ( result == 0 ) { + std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; + int depth = 0 ; + FILE* f = fopen(path,"rb"); + printIFD(f,std::cout,offset,bSwap,depth); + fclose(f); + } + + return result; +} From 8516f402cf8660704199e8ff65e719b00cbed8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Mon, 4 Sep 2017 23:31:15 +0200 Subject: [PATCH 02/71] first set of build fixes --- bigtiff/CMakeLists.txt | 14 ++++++++++- bigtiff/parse.cpp | 57 +++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/bigtiff/CMakeLists.txt b/bigtiff/CMakeLists.txt index fb580ab6..fd9c5eb0 100644 --- a/bigtiff/CMakeLists.txt +++ b/bigtiff/CMakeLists.txt @@ -1,2 +1,14 @@ -add_executable(big_tiff_parser parse.cpp) +add_executable(big_tiff_parser + parse.cpp + + # + ${CMAKE_SOURCE_DIR}/src/basicio.cpp + ${CMAKE_SOURCE_DIR}/src/image.cpp + ${CMAKE_SOURCE_DIR}/src/types.cpp +) + +target_include_directories(big_tiff_parser PRIVATE + ${CMAKE_SOURCE_DIR}/include/exiv2 + ${CMAKE_SOURCE_DIR}/src +) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 59dba031..f5ace122 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -1,5 +1,16 @@ + +#include +#include +#include +#include #include +#include "basicio.hpp" +#include "image_int.hpp" +#include "image.hpp" +#include "riffvideo.hpp" +#include "types.hpp" + #define WIDTH 32 enum TypeId { @@ -202,25 +213,30 @@ typedef struct { uint32_t offset; } field_t; -void printIFD(FILE* f, std::ostream& out, uint32_t offset,bool bSwap,int depth) +void printIFD(FILE* f, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset,bool bSwap,int depth) { + std::string path; // TODO: just a compilation fix. It should probably come instead of FILE* f. + Exiv2::FileIo io(path); // TODO: should come as argument? + depth++; bool bFirst = true; // buffer bool bPrint = true; + int start = 0; // TODO: just a buld fix + do { // Read top of directory - fseek(f,offset,beg); + fseek(f,offset,SEEK_SET); uint16_t dir; fread(&dir,1,2,f); - uint16_t dirLength = byteSwap2(dir,0,bSwap); + uint16_t dirLength = byteSwap2(&dir,0,bSwap); bool tooBig = dirLength > 500; if ( bFirst && bPrint ) { - out << indent(depth) << stringFormat("STRUCTURE OF TIFF FILE << path << std::endl; + out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << path << std::endl; if ( tooBig ) out << indent(depth) << "dirLength = " << dirLength << std::endl; } if (tooBig) break; @@ -256,51 +272,52 @@ void printIFD(FILE* f, std::ostream& out, uint32_t offset,bool bSwap,int depth) : 1 ; - DataBuf buf(size*count + pad); // allocate a buffer + Exiv2::DataBuf buf(size*count + pad); // allocate a buffer + Exiv2::DataBuf dir(size*count + pad); // TODO: fix me, I'm object out of nowhere std::memcpy(buf.pData_,dir.pData_+8,4); // copy dir[8:11] into buffer (short strings) if ( count*size > 4 ) { // read into buffer size_t restore = io.tell(); // save - io.seek(offset,BasicIo::beg); // position + io.seek(offset, Exiv2::BasicIo::beg); // position io.read(buf.pData_,count*size);// read - io.seek(restore,BasicIo::beg); // restore + io.seek(restore, Exiv2::BasicIo::beg); // restore } if ( bPrint ) { uint32_t address = start + 2 + i*12 ; out << indent(depth) - << stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " + << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " ,address,tag,tagName(tag,25),typeName(type),count,offset); if ( isShortType(type) ){ for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << byteSwap2(buf,k*size,bSwap); + out << sp << byteSwap2(&buf,k*size,bSwap); sp = " "; } } else if ( isLongType(type) ){ for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << byteSwap4(buf,k*size,bSwap); + out << sp << byteSwap4(&buf,k*size,bSwap); sp = " "; } } else if ( isRationalType(type) ){ for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = byteSwap4(buf,k*size+0,bSwap); - uint32_t b = byteSwap4(buf,k*size+4,bSwap); + uint32_t a = byteSwap4(&buf,k*size+0,bSwap); + uint32_t b = byteSwap4(&buf,k*size+4,bSwap); out << sp << a << "/" << b; sp = " "; } } else if ( isStringType(type) ) { - out << sp << binaryToString(buf, kount); + out << sp << Exiv2::Internal::binaryToString(buf, kount); } sp = kount == count ? "" : " ..."; out << sp << std::endl; - if ( option == kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) { + if ( option == Exiv2::kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) { for ( size_t k = 0 ; k < count ; k++ ) { size_t restore = io.tell(); - uint32_t offset = byteSwap4(buf,k*size,bSwap); - std::cerr << "tag = " << stringFormat("%#x",tag) << std::endl; - printIFDStructure(io,out,option,offset,bSwap,c,depth); + uint32_t offset = byteSwap4(&buf,k*size,bSwap); + std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; + Exiv2::RiffVideo(io).printIFDStructure(io,out,option,offset,bSwap,k,depth); // TODO: blind fix io.seek(restore,BasicIo::beg); } } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { @@ -340,7 +357,7 @@ void printIFD(FILE* f, std::ostream& out, uint32_t offset,bool bSwap,int depth) } } io.read(dir.pData_, 4); - start = tooBig ? 0 : byteSwap4(dir,0,bSwap); + start = tooBig ? 0 : byteSwap4(&dir,0,bSwap); out.flush(); } while (start) ; @@ -387,8 +404,8 @@ int main(int argc,const char* argv[]) if ( result == 0 ) { std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; int depth = 0 ; - FILE* f = fopen(path,"rb"); - printIFD(f,std::cout,offset,bSwap,depth); + FILE* f = fopen(argv[1],"rb"); + printIFD(f,std::cout, Exiv2::kpsRecursive, offset,bSwap,depth); fclose(f); } From 8933bd9c3b769570add89e5620b01855684c818e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 5 Sep 2017 22:38:18 +0200 Subject: [PATCH 03/71] making code to build (linking still broken) --- bigtiff/parse.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index f5ace122..1cfea2dd 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -6,9 +6,9 @@ #include #include "basicio.hpp" +#include "iptc.hpp" #include "image_int.hpp" #include "image.hpp" -#include "riffvideo.hpp" #include "types.hpp" #define WIDTH 32 @@ -317,46 +317,46 @@ void printIFD(FILE* f, std::ostream& out, Exiv2::PrintStructureOption option, ui size_t restore = io.tell(); uint32_t offset = byteSwap4(&buf,k*size,bSwap); std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; - Exiv2::RiffVideo(io).printIFDStructure(io,out,option,offset,bSwap,k,depth); // TODO: blind fix - io.seek(restore,BasicIo::beg); + //Exiv2::RiffVideo(io).printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: blind fix + io.seek(restore, Exiv2::BasicIo::beg); } - } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { + } else if ( option == Exiv2::kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { size_t restore = io.tell(); // save - io.seek(offset,BasicIo::beg); // position - byte* bytes=new byte[count] ; // allocate memory + io.seek(offset, Exiv2::BasicIo::beg); // position + Exiv2::byte* bytes=new Exiv2::byte[count] ; // allocate memory io.read(bytes,count) ; // read - io.seek(restore,BasicIo::beg); // restore - IptcData::printStructure(out,bytes,count,depth); + io.seek(restore, Exiv2::BasicIo::beg); // restore + Exiv2::IptcData::printStructure(out,bytes,count,depth); delete[] bytes; // free - } else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { + } else if ( option == Exiv2::kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { size_t restore = io.tell(); // save uint32_t jump= 10 ; - byte bytes[20] ; + Exiv2::byte bytes[20] ; const char* chars = (const char*) &bytes[0] ; - io.seek(offset,BasicIo::beg); // position + io.seek(offset, Exiv2::BasicIo::beg); // position io.read(bytes,jump ) ; // read bytes[jump]=0 ; if ( ::strcmp("Nikon",chars) == 0 ) { // tag is an embedded tiff - byte* bytes=new byte[count-jump] ; // allocate memory + Exiv2::byte* bytes=new Exiv2::byte[count-jump] ; // allocate memory io.read(bytes,count-jump) ; // read - MemIo memIo(bytes,count-jump) ; // create a file + Exiv2::MemIo memIo(bytes,count-jump) ; // create a file std::cerr << "Nikon makernote" << std::endl; - printTiffStructure(memIo,out,option,depth); + // printTiffStructure(memIo,out,option,depth); TODO: fix it delete[] bytes ; // free } else { // tag is an IFD - io.seek(0,BasicIo::beg); // position + io.seek(0, Exiv2::BasicIo::beg); // position std::cerr << "makernote" << std::endl; - printIFDStructure(io,out,option,offset,bSwap,c,depth); + //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me } - io.seek(restore,BasicIo::beg); // restore + io.seek(restore,Exiv2::BasicIo::beg); // restore } } } - io.read(dir.pData_, 4); + //io.read(&dir.pData_, 4); TODO: fix me start = tooBig ? 0 : byteSwap4(&dir,0,bSwap); out.flush(); } while (start) ; From 87f0152fbe8495c3d53cdf3a2989b97bf1ec4613 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 19:34:41 +0200 Subject: [PATCH 04/71] linking against exiv2lib to fix link problems --- bigtiff/CMakeLists.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bigtiff/CMakeLists.txt b/bigtiff/CMakeLists.txt index fd9c5eb0..44f5798f 100644 --- a/bigtiff/CMakeLists.txt +++ b/bigtiff/CMakeLists.txt @@ -1,14 +1,11 @@ add_executable(big_tiff_parser parse.cpp - - # - ${CMAKE_SOURCE_DIR}/src/basicio.cpp - ${CMAKE_SOURCE_DIR}/src/image.cpp - ${CMAKE_SOURCE_DIR}/src/types.cpp ) target_include_directories(big_tiff_parser PRIVATE ${CMAKE_SOURCE_DIR}/include/exiv2 ${CMAKE_SOURCE_DIR}/src ) + +target_link_libraries(big_tiff_parser PRIVATE exiv2lib) From fc29e0a90c02abe0321a8b11939d0feef236db48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 20:08:34 +0200 Subject: [PATCH 05/71] adding first link --- bigtiff/parse.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 1cfea2dd..05271b87 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -13,6 +13,9 @@ #define WIDTH 32 +// helpful links: +// http://www.awaresystems.be/imaging/tiff/bigtiff.html + enum TypeId { unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. asciiString = 2, //!< Exif ASCII type, 8-bit byte. From b668cf335eb37f0467e4ecba377bb927a9855142 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 20:19:07 +0200 Subject: [PATCH 06/71] fixing BigTIFF's header expectations As defined in http://www.awaresystems.be/imaging/tiff/bigtiff.html --- bigtiff/parse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 05271b87..8ceb2a05 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -386,7 +386,7 @@ int main(int argc,const char* argv[]) ; uint16_t magic = byteSwap2(buff,2,bSwap); offset = byteSwap4(buff,4,bSwap); - if ( buff[0] != buff[1] || (buff[0] != 'I' && buff[0] != 'M') || magic != 42 ) { + if ( buff[0] != buff[1] || (buff[0] != 'I' && buff[0] != 'M') || magic != 43 ) { std::cerr << "bSwap = " << bSwap << std::endl; std::cerr << "magic = " << magic << std::endl; std::cerr << "offset = " << offset << std::endl; From 2fd287bc0c522eed2b25f2a19a3b272fa65c68be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 20:55:07 +0200 Subject: [PATCH 07/71] printIFD uses BasicIo now --- bigtiff/parse.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 8ceb2a05..506c7255 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -216,11 +216,8 @@ typedef struct { uint32_t offset; } field_t; -void printIFD(FILE* f, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset,bool bSwap,int depth) +void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset, bool bSwap, int depth) { - std::string path; // TODO: just a compilation fix. It should probably come instead of FILE* f. - Exiv2::FileIo io(path); // TODO: should come as argument? - depth++; bool bFirst = true; @@ -231,15 +228,17 @@ void printIFD(FILE* f, std::ostream& out, Exiv2::PrintStructureOption option, ui do { // Read top of directory - fseek(f,offset,SEEK_SET); + io.seek(offset, Exiv2::BasicIo::beg); + uint16_t dir; - fread(&dir,1,2,f); + io.read(reinterpret_cast(&dir), 2); + uint16_t dirLength = byteSwap2(&dir,0,bSwap); bool tooBig = dirLength > 500; if ( bFirst && bPrint ) { - out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << path << std::endl; + out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << io.path() << std::endl; if ( tooBig ) out << indent(depth) << "dirLength = " << dirLength << std::endl; } if (tooBig) break; @@ -254,7 +253,7 @@ void printIFD(FILE* f, std::ostream& out, Exiv2::PrintStructureOption option, ui bFirst = false; field_t field; - fread(&field,sizeof(field_t),1,f); + io.read(reinterpret_cast(&field), sizeof(field)); uint16_t tag = byteSwap2(&field.tagID ,0,bSwap); uint16_t type = byteSwap2(&field.tagType,2,bSwap); uint32_t count = byteSwap4(&field.count ,4,bSwap); @@ -407,9 +406,8 @@ int main(int argc,const char* argv[]) if ( result == 0 ) { std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; int depth = 0 ; - FILE* f = fopen(argv[1],"rb"); - printIFD(f,std::cout, Exiv2::kpsRecursive, offset,bSwap,depth); - fclose(f); + Exiv2::FileIo file(argv[1]); + printIFD(file, std::cout, Exiv2::kpsRecursive, offset, bSwap, depth); } return result; From 37e4bd6661f47bd571790794e079a622d4a76eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 21:50:10 +0200 Subject: [PATCH 08/71] opening file in proper mode --- bigtiff/parse.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 506c7255..fa96f87a 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -407,6 +407,7 @@ int main(int argc,const char* argv[]) std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; int depth = 0 ; Exiv2::FileIo file(argv[1]); + file.open("rb"); printIFD(file, std::cout, Exiv2::kpsRecursive, offset, bSwap, depth); } From 5d5234db1d82c46e023940d9e08113008dc2cc31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 21:50:57 +0200 Subject: [PATCH 09/71] adopting code to BigTIFF header format --- bigtiff/parse.cpp | 134 ++++++++++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 51 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index fa96f87a..cf2bc939 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -15,6 +15,7 @@ // helpful links: // http://www.awaresystems.be/imaging/tiff/bigtiff.html +// https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c enum TypeId { unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. @@ -91,7 +92,7 @@ bool is8ByteType(uint16_t type) ; } -bool isBigEndianPlatform() +constexpr bool isBigEndianPlatform() { union { uint32_t i; @@ -101,47 +102,65 @@ bool isBigEndianPlatform() return e.c[0]?true:false; } -bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } +constexpr bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } -uint32_t byteSwap(uint32_t value,bool bSwap) +template +struct TypeForSize {}; + +template<> +struct TypeForSize<16> { - uint32_t result = 0; - result |= (value & 0x000000FF) << 24; - result |= (value & 0x0000FF00) << 8; - result |= (value & 0x00FF0000) >> 8; - result |= (value & 0xFF000000) >> 24; - return bSwap ? result : value; + typedef int16_t Type; +}; + +template<> +struct TypeForSize<32> +{ + typedef int32_t Type; +}; + +template<> +struct TypeForSize<64> +{ + typedef int64_t Type; +}; + +template +typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) +{ + static_assert(size == 16 || size == 32 || size == 64); + + typename TypeForSize::Type result = 0; + if (size == 16) + result = __builtin_bswap16(v); + else if (size == 32) + result = __builtin_bswap32(v); + else if (size == 64) + result = __builtin_bswap64(v); + + return result; } -uint16_t byteSwap(uint16_t value,bool bSwap) +template +typename TypeForSize::Type conditional_byte_swap(const typename TypeForSize::Type& v, bool swap) { - uint16_t result = 0; - result |= (value & 0x00FF) << 8; - result |= (value & 0xFF00) >> 8; - return bSwap ? result : value; + const typename TypeForSize::Type result = swap? byte_swap(v): v; + + return result; } -uint16_t byteSwap2(void* buf,size_t offset,bool bSwap) + +template +typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, int offset, bool swap) { - uint16_t v; - char* p = (char*) &v; - char* b = (char*) buf; - p[0] = b[offset]; - p[1] = b[offset+1]; - return byteSwap(v,bSwap); + typedef typename TypeForSize::Type Type; + + const uint8_t* bytes_buf = static_cast(buf); + const Type* value = reinterpret_cast(&bytes_buf[offset]); + + return conditional_byte_swap(*value, swap); } -uint32_t byteSwap4(void* buf,size_t offset,bool bSwap) -{ - uint32_t v; - char* p = (char*) &v; - char* b = (char*) buf; - p[0] = b[offset]; - p[1] = b[offset+1]; - p[2] = b[offset+2]; - p[3] = b[offset+3]; - return byteSwap(v,bSwap); -} std::string indent(int32_t d) { @@ -233,7 +252,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption uint16_t dir; io.read(reinterpret_cast(&dir), 2); - uint16_t dirLength = byteSwap2(&dir,0,bSwap); + uint16_t dirLength = conditional_byte_swap_4_array<16>(&dir, 0, bSwap); bool tooBig = dirLength > 500; @@ -254,10 +273,10 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption field_t field; io.read(reinterpret_cast(&field), sizeof(field)); - uint16_t tag = byteSwap2(&field.tagID ,0,bSwap); - uint16_t type = byteSwap2(&field.tagType,2,bSwap); - uint32_t count = byteSwap4(&field.count ,4,bSwap); - uint32_t offset = byteSwap4(&field.offset ,8,bSwap); + uint16_t tag = conditional_byte_swap_4_array<16>(&field.tagID, 0, bSwap); + uint16_t type = conditional_byte_swap_4_array<16>(&field.tagType, 2, bSwap); + uint32_t count = conditional_byte_swap_4_array<32>(&field.count, 4, bSwap); + uint32_t offset = conditional_byte_swap_4_array<32>(&field.offset, 8, bSwap); std::string sp = "" ; // output spacer @@ -291,19 +310,19 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption ,address,tag,tagName(tag,25),typeName(type),count,offset); if ( isShortType(type) ){ for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << byteSwap2(&buf,k*size,bSwap); + out << sp << conditional_byte_swap_4_array<16>(&buf, k*size, bSwap); sp = " "; } } else if ( isLongType(type) ){ for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << byteSwap4(&buf,k*size,bSwap); + out << sp << conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); sp = " "; } } else if ( isRationalType(type) ){ for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = byteSwap4(&buf,k*size+0,bSwap); - uint32_t b = byteSwap4(&buf,k*size+4,bSwap); + uint32_t a = conditional_byte_swap_4_array<32>(&buf, k*size+0, bSwap); + uint32_t b = conditional_byte_swap_4_array<32>(&buf, k*size+4, bSwap); out << sp << a << "/" << b; sp = " "; } @@ -317,7 +336,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption if ( option == Exiv2::kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) { for ( size_t k = 0 ; k < count ; k++ ) { size_t restore = io.tell(); - uint32_t offset = byteSwap4(&buf,k*size,bSwap); + uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; //Exiv2::RiffVideo(io).printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: blind fix io.seek(restore, Exiv2::BasicIo::beg); @@ -359,7 +378,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption } } //io.read(&dir.pData_, 4); TODO: fix me - start = tooBig ? 0 : byteSwap4(&dir,0,bSwap); + start = tooBig ? 0 : conditional_byte_swap_4_array<32>(&dir, 0, bSwap); out.flush(); } while (start) ; @@ -372,7 +391,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption int main(int argc,const char* argv[]) { int result = 0; - int bSwap = false; + bool bSwap = false; uint32_t offset = 0; if ( argc > 0 ) { @@ -380,16 +399,29 @@ int main(int argc,const char* argv[]) if ( f ) { char buff[2*WIDTH]; fread(buff,1,sizeof buff,f); + bSwap = (isLittleEndianPlatform() && buff[0] == 'M') || (isBigEndianPlatform() && buff[0] == 'I') ; - uint16_t magic = byteSwap2(buff,2,bSwap); - offset = byteSwap4(buff,4,bSwap); - if ( buff[0] != buff[1] || (buff[0] != 'I' && buff[0] != 'M') || magic != 43 ) { - std::cerr << "bSwap = " << bSwap << std::endl; - std::cerr << "magic = " << magic << std::endl; - std::cerr << "offset = " << offset << std::endl; - std::cerr << argv[1] << " is not a TIFF file" << std::endl; + + uint16_t magic = conditional_byte_swap_4_array<16>(buff, 2, bSwap); + uint16_t byteSize = conditional_byte_swap_4_array<16>(buff, 4, bSwap); + uint16_t zeroByte = conditional_byte_swap_4_array<16>(buff, 6, bSwap); + offset = conditional_byte_swap_4_array<64>(buff, 8, bSwap); + + if ( buff[0] != buff[1] || + (buff[0] != 'I' && buff[0] != 'M') || + magic != 43 || + byteSize != 8 || + zeroByte != 0 + ) + { + std::cerr << "bSwap = " << bSwap << std::endl; + std::cerr << "magic = " << magic << std::endl; + std::cerr << "byteSize = " << byteSize << std::endl; + std::cerr << "zeroByte = " << zeroByte << std::endl; + std::cerr << "offset = " << offset << std::endl; + std::cerr << argv[1] << " is not a BigTIFF file" << std::endl; result = 3 ; } fclose(f); From d7ce238441a498918a674c6cdca91d56bdd7000b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 6 Sep 2017 21:52:43 +0200 Subject: [PATCH 10/71] code format --- bigtiff/parse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index cf2bc939..3e9a534e 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -391,7 +391,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption int main(int argc,const char* argv[]) { int result = 0; - bool bSwap = false; + bool bSwap = false; uint32_t offset = 0; if ( argc > 0 ) { From 7d0009d6bd44fe7181e37bfc9cd9eb45772a8a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 7 Sep 2017 18:49:44 +0200 Subject: [PATCH 11/71] yet another link --- bigtiff/parse.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 3e9a534e..eb0178ab 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -15,6 +15,7 @@ // helpful links: // http://www.awaresystems.be/imaging/tiff/bigtiff.html +// http://bigtiff.org/ // https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c enum TypeId { From 018eced12d26e55f3f71fbd1bc8b93a15067931d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 7 Sep 2017 21:43:32 +0200 Subject: [PATCH 12/71] Making field_t to match BigTIFF's specification and reading it properly. There are also adjustments for IFD to match BigTIFF --- bigtiff/parse.cpp | 114 +++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index eb0178ab..9e3f63c7 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -48,49 +48,46 @@ enum TypeId { bool isStringType(uint16_t type) { - return type == asciiString - || type == unsignedByte - || type == signedByte - || type == undefined - ; + return type == asciiString + || type == unsignedByte + || type == signedByte + || type == undefined; } -bool isShortType(uint16_t type) { - return type == unsignedShort - || type == signedShort - ; +bool isShortType(uint16_t type) +{ + return type == unsignedShort + || type == signedShort; } -bool isLongType(uint16_t type) { - return type == unsignedLong - || type == signedLong - ; +bool isLongType(uint16_t type) +{ + return type == unsignedLong + || type == signedLong; } -bool isRationalType(uint16_t type) { - return type == unsignedRational - || type == signedRational - ; +bool isRationalType(uint16_t type) +{ + return type == unsignedRational + || type == signedRational; } bool is2ByteType(uint16_t type) { - return isShortType(type); + return isShortType(type); } bool is4ByteType(uint16_t type) { - return isLongType(type) - || type == tiffFloat - || type == tiffIfd - ; + return isLongType(type) + || type == tiffFloat + || type == tiffIfd; } bool is8ByteType(uint16_t type) { - return isRationalType(type) - || type == tiffDouble - ; + return isRationalType(type) + || type == tiffDouble; } constexpr bool isBigEndianPlatform() @@ -231,9 +228,9 @@ static const char* typeName(uint16_t tag) typedef struct { uint16_t tagID; - uint16_t tagType ; - uint32_t count; - uint32_t offset; + uint16_t tagType; + uint64_t count; + uint64_t offset; } field_t; void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset, bool bSwap, int depth) @@ -250,49 +247,53 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption // Read top of directory io.seek(offset, Exiv2::BasicIo::beg); - uint16_t dir; - io.read(reinterpret_cast(&dir), 2); + uint64_t entries_raw; + io.read(reinterpret_cast(&entries_raw), 8); - uint16_t dirLength = conditional_byte_swap_4_array<16>(&dir, 0, bSwap); + const uint16_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); - bool tooBig = dirLength > 500; + const bool tooBig = entries > 500; - if ( bFirst && bPrint ) { + if ( bFirst && bPrint ) + { out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << io.path() << std::endl; - if ( tooBig ) out << indent(depth) << "dirLength = " << dirLength << std::endl; + if (tooBig) + out << indent(depth) << "entries = " << entries << std::endl; } - if (tooBig) break; + + if (tooBig) + break; // Read the dictionary - for ( int i = 0 ; i < dirLength ; i ++ ) { - if ( bFirst && bPrint ) { - out << indent(depth) - << " address | tag | " - << " type | count | offset | value\n"; - } + for ( int i = 0; i < entries; i ++ ) + { + if ( bFirst && bPrint ) + out << indent(depth) + << " address | tag | " + << " type | count | offset | value\n"; + bFirst = false; field_t field; io.read(reinterpret_cast(&field), sizeof(field)); - uint16_t tag = conditional_byte_swap_4_array<16>(&field.tagID, 0, bSwap); - uint16_t type = conditional_byte_swap_4_array<16>(&field.tagType, 2, bSwap); - uint32_t count = conditional_byte_swap_4_array<32>(&field.count, 4, bSwap); - uint32_t offset = conditional_byte_swap_4_array<32>(&field.offset, 8, bSwap); + const uint16_t tag = conditional_byte_swap_4_array<16>(&field.tagID, 0, bSwap); + const uint16_t type = conditional_byte_swap_4_array<16>(&field.tagType, 2, bSwap); + const uint32_t count = conditional_byte_swap_4_array<64>(&field.count, 4, bSwap); + const uint32_t offset = conditional_byte_swap_4_array<64>(&field.offset, 12, bSwap); - std::string sp = "" ; // output spacer + std::string sp = "" ; // output spacer //prepare to print the value - uint32_t kount = isStringType(type) ? (count > 32 ? 32 : count) // restrict long arrays + const uint32_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays : count > 5 ? 5 : count ; - uint32_t pad = isStringType(type) ? 1 : 0; - uint32_t size = isStringType(type) ? 1 - : is2ByteType(type) ? 2 - : is4ByteType(type) ? 4 - : is8ByteType(type) ? 8 - : 1 - ; + const uint32_t pad = isStringType(type) ? 1 : 0; + const uint32_t size = isStringType(type) ? 1 + : is2ByteType(type) ? 2 + : is4ByteType(type) ? 4 + : is8ByteType(type) ? 8 + : 1; Exiv2::DataBuf buf(size*count + pad); // allocate a buffer Exiv2::DataBuf dir(size*count + pad); // TODO: fix me, I'm object out of nowhere @@ -378,8 +379,9 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption } } } - //io.read(&dir.pData_, 4); TODO: fix me - start = tooBig ? 0 : conditional_byte_swap_4_array<32>(&dir, 0, bSwap); + uint64_t next_dir_offset_raw; + io.read(reinterpret_cast(&next_dir_offset_raw), 8); + start = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); out.flush(); } while (start) ; From 0ad4d43003ee708aeb8472ec11d3964114921d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 7 Sep 2017 21:45:21 +0200 Subject: [PATCH 13/71] dropping formerly unknown variable --- bigtiff/parse.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 9e3f63c7..f7124a1b 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -241,8 +241,6 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption // buffer bool bPrint = true; - int start = 0; // TODO: just a buld fix - do { // Read top of directory io.seek(offset, Exiv2::BasicIo::beg); @@ -306,7 +304,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption } if ( bPrint ) { - uint32_t address = start + 2 + i*12 ; + uint32_t address = offset + 2 + i*12 ; out << indent(depth) << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " ,address,tag,tagName(tag,25),typeName(type),count,offset); @@ -381,9 +379,9 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption } uint64_t next_dir_offset_raw; io.read(reinterpret_cast(&next_dir_offset_raw), 8); - start = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); + offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); out.flush(); - } while (start) ; + } while (offset) ; if ( bPrint ) { out << indent(depth) << "END " << io.path() << std::endl; From 542941a06239d28a345a366a5ee2a0823de0f6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 22:50:29 +0200 Subject: [PATCH 14/71] extending TypeId enum by BigTIFF's values --- bigtiff/parse.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index f7124a1b..ba54eddb 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -16,6 +16,7 @@ // helpful links: // http://www.awaresystems.be/imaging/tiff/bigtiff.html // http://bigtiff.org/ +// http://bigtiff.org/libtiff-4.1.zip // https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c enum TypeId { @@ -32,6 +33,9 @@ enum TypeId { tiffFloat = 11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. tiffDouble = 12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. tiffIfd = 13, //!< TIFF IFD type, 32-bit (4-byte) unsigned integer. + unsigned64 = 16, //!< 64-bit unsigned value + signed64 = 17, //!< 64-bit signed value + tiffIfd8 = 18, //!< 64-bit IFD offset iptcString = 0x10000, //!< IPTC string type. iptcDate = 0x10001, //!< IPTC date type. iptcTime = 0x10002, //!< IPTC time type. From 77b6af4024cced90f74804a5aee67cc4315e7e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 22:53:09 +0200 Subject: [PATCH 15/71] adding some TODO --- bigtiff/parse.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index ba54eddb..247147f9 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -286,6 +286,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption std::string sp = "" ; // output spacer //prepare to print the value + // TODO: figure out what's going on with kount const uint32_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays : count > 5 ? 5 : count From 0828db2e4fc9805c238a70c06f2cf516109fc6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 22:57:02 +0200 Subject: [PATCH 16/71] fixing TODO, copy data from entry (short string) --- bigtiff/parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 247147f9..5535146a 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -299,8 +299,8 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption : 1; Exiv2::DataBuf buf(size*count + pad); // allocate a buffer - Exiv2::DataBuf dir(size*count + pad); // TODO: fix me, I'm object out of nowhere - std::memcpy(buf.pData_,dir.pData_+8,4); // copy dir[8:11] into buffer (short strings) + + std::memcpy(buf.pData_, &offset, 8); // copy data into buffer (short strings) if ( count*size > 4 ) { // read into buffer size_t restore = io.tell(); // save io.seek(offset, Exiv2::BasicIo::beg); // position From 0349e5b06251c9307b39352583f2f5afd18403b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 23:00:05 +0200 Subject: [PATCH 17/71] fix for field sizes --- bigtiff/parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 5535146a..9e4b22f0 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -280,8 +280,8 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption io.read(reinterpret_cast(&field), sizeof(field)); const uint16_t tag = conditional_byte_swap_4_array<16>(&field.tagID, 0, bSwap); const uint16_t type = conditional_byte_swap_4_array<16>(&field.tagType, 2, bSwap); - const uint32_t count = conditional_byte_swap_4_array<64>(&field.count, 4, bSwap); - const uint32_t offset = conditional_byte_swap_4_array<64>(&field.offset, 12, bSwap); + const uint64_t count = conditional_byte_swap_4_array<64>(&field.count, 4, bSwap); + const uint64_t offset = conditional_byte_swap_4_array<64>(&field.offset, 12, bSwap); std::string sp = "" ; // output spacer From ebc735439191496a263c44c6bd7ca2ec9f564803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 23:01:21 +0200 Subject: [PATCH 18/71] renaming variables to more accurate --- bigtiff/parse.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 9e4b22f0..f8e8b21d 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -234,7 +234,7 @@ typedef struct { uint16_t tagID; uint16_t tagType; uint64_t count; - uint64_t offset; + uint64_t data; } field_t; void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset, bool bSwap, int depth) @@ -281,7 +281,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption const uint16_t tag = conditional_byte_swap_4_array<16>(&field.tagID, 0, bSwap); const uint16_t type = conditional_byte_swap_4_array<16>(&field.tagType, 2, bSwap); const uint64_t count = conditional_byte_swap_4_array<64>(&field.count, 4, bSwap); - const uint64_t offset = conditional_byte_swap_4_array<64>(&field.offset, 12, bSwap); + const uint64_t data = conditional_byte_swap_4_array<64>(&field.data, 12, bSwap); std::string sp = "" ; // output spacer @@ -300,7 +300,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption Exiv2::DataBuf buf(size*count + pad); // allocate a buffer - std::memcpy(buf.pData_, &offset, 8); // copy data into buffer (short strings) + std::memcpy(buf.pData_, &data, 8); // copy data into buffer (short strings) if ( count*size > 4 ) { // read into buffer size_t restore = io.tell(); // save io.seek(offset, Exiv2::BasicIo::beg); // position From 79f0953967bf7bf8b246199c20759e1f781684c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 23:01:47 +0200 Subject: [PATCH 19/71] cleanups --- bigtiff/parse.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index f8e8b21d..60960eb6 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -301,10 +301,10 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption Exiv2::DataBuf buf(size*count + pad); // allocate a buffer std::memcpy(buf.pData_, &data, 8); // copy data into buffer (short strings) - if ( count*size > 4 ) { // read into buffer - size_t restore = io.tell(); // save + if ( count*size > 4 ) { // read into buffer + size_t restore = io.tell(); // save io.seek(offset, Exiv2::BasicIo::beg); // position - io.read(buf.pData_,count*size);// read + io.read(buf.pData_,count*size); // read io.seek(restore, Exiv2::BasicIo::beg); // restore } From 2f3940246652a34f45b021a5ffa99d41e406134a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 8 Sep 2017 23:05:15 +0200 Subject: [PATCH 20/71] switching short strings from 4 to 8 bytes; fixing recursive tags --- bigtiff/parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 60960eb6..8a948f43 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -301,7 +301,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption Exiv2::DataBuf buf(size*count + pad); // allocate a buffer std::memcpy(buf.pData_, &data, 8); // copy data into buffer (short strings) - if ( count*size > 4 ) { // read into buffer + if ( count*size > 8 ) { // read into buffer size_t restore = io.tell(); // save io.seek(offset, Exiv2::BasicIo::beg); // position io.read(buf.pData_,count*size); // read @@ -343,7 +343,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption size_t restore = io.tell(); uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; - //Exiv2::RiffVideo(io).printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: blind fix + printIFD(io, out, option, offset, bSwap, depth); io.seek(restore, Exiv2::BasicIo::beg); } } else if ( option == Exiv2::kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { From 388fd9b0f8da1ca962bb00aca6f053e7c7bfbb9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 10:16:47 +0200 Subject: [PATCH 21/71] fix for interpretation of dir's entry data --- bigtiff/parse.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 8a948f43..8a62b076 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -230,12 +230,12 @@ static const char* typeName(uint16_t tag) return result; } -typedef struct { +struct field_t { uint16_t tagID; uint16_t tagType; uint64_t count; uint64_t data; -} field_t; +} __attribute__((packed)); void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset, bool bSwap, int depth) { @@ -278,10 +278,10 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption field_t field; io.read(reinterpret_cast(&field), sizeof(field)); - const uint16_t tag = conditional_byte_swap_4_array<16>(&field.tagID, 0, bSwap); - const uint16_t type = conditional_byte_swap_4_array<16>(&field.tagType, 2, bSwap); - const uint64_t count = conditional_byte_swap_4_array<64>(&field.count, 4, bSwap); - const uint64_t data = conditional_byte_swap_4_array<64>(&field.data, 12, bSwap); + const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); + const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); + const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); + const uint64_t data = conditional_byte_swap<64>(field.data, bSwap); std::string sp = "" ; // output spacer From 41c245963b139b31987eab5dd5e52f4f81e3ac73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 10:17:38 +0200 Subject: [PATCH 22/71] fixing offset's size --- bigtiff/parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 8a62b076..7b884778 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -237,7 +237,7 @@ struct field_t { uint64_t data; } __attribute__((packed)); -void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint32_t offset, bool bSwap, int depth) +void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint64_t offset, bool bSwap, int depth) { depth++; bool bFirst = true; @@ -398,7 +398,7 @@ int main(int argc,const char* argv[]) { int result = 0; bool bSwap = false; - uint32_t offset = 0; + uint64_t offset = 0; if ( argc > 0 ) { FILE* f = fopen(argv[1],"rb"); From 1c4026fd56a0613aca399d6c29e80081a3b471cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 13:16:19 +0200 Subject: [PATCH 23/71] fixing some warnings --- bigtiff/parse.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 7b884778..71ab66c3 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -130,7 +130,7 @@ struct TypeForSize<64> template typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) { - static_assert(size == 16 || size == 32 || size == 64); + static_assert(size == 16 || size == 32 || size == 64, "unsupported data size"); typename TypeForSize::Type result = 0; if (size == 16) @@ -153,7 +153,7 @@ typename TypeForSize::Type conditional_byte_swap(const typename TypeForSiz template -typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, int offset, bool swap) +typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, uint64_t offset, bool swap) { typedef typename TypeForSize::Type Type; @@ -252,7 +252,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption uint64_t entries_raw; io.read(reinterpret_cast(&entries_raw), 8); - const uint16_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); + const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); const bool tooBig = entries > 500; @@ -267,7 +267,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption break; // Read the dictionary - for ( int i = 0; i < entries; i ++ ) + for ( uint64_t i = 0; i < entries; i ++ ) { if ( bFirst && bPrint ) out << indent(depth) @@ -287,7 +287,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption //prepare to print the value // TODO: figure out what's going on with kount - const uint32_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays + const uint64_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays : count > 5 ? 5 : count ; @@ -309,7 +309,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption } if ( bPrint ) { - uint32_t address = offset + 2 + i*12 ; + uint64_t address = offset + 2 + i*12 ; out << indent(depth) << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " ,address,tag,tagName(tag,25),typeName(type),count,offset); From 63403ac0bb8af095278a078634fe56be417472b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:04:29 +0200 Subject: [PATCH 24/71] code cleanup --- bigtiff/parse.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 71ab66c3..ba2328d8 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -300,13 +300,16 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption Exiv2::DataBuf buf(size*count + pad); // allocate a buffer - std::memcpy(buf.pData_, &data, 8); // copy data into buffer (short strings) - if ( count*size > 8 ) { // read into buffer - size_t restore = io.tell(); // save - io.seek(offset, Exiv2::BasicIo::beg); // position - io.read(buf.pData_,count*size); // read - io.seek(restore, Exiv2::BasicIo::beg); // restore + // big data? Use 'data' as pointer to real data + if ( count*size > 8 ) // read into buffer + { + size_t restore = io.tell(); // save + io.seek(data, Exiv2::BasicIo::beg); // position + io.read(buf.pData_,count*size); // read + io.seek(restore, Exiv2::BasicIo::beg); // restore } + else // use 'data' as data :) + std::memcpy(buf.pData_, &data, 8); // copy data if ( bPrint ) { uint64_t address = offset + 2 + i*12 ; From 26ab6805f5010f6a4ff9b9e546232fabffa89aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:09:45 +0200 Subject: [PATCH 25/71] code format (indentations) --- bigtiff/parse.cpp | 574 ++++++++++++++++++++++++---------------------- 1 file changed, 297 insertions(+), 277 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index ba2328d8..56585c01 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -20,34 +20,34 @@ // https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c enum TypeId { - unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. - asciiString = 2, //!< Exif ASCII type, 8-bit byte. - unsignedShort = 3, //!< Exif SHORT type, 16-bit (2-byte) unsigned integer. - unsignedLong = 4, //!< Exif LONG type, 32-bit (4-byte) unsigned integer. - unsignedRational = 5, //!< Exif RATIONAL type, two LONGs: numerator and denumerator of a fraction. - signedByte = 6, //!< Exif SBYTE type, an 8-bit signed (twos-complement) integer. - undefined = 7, //!< Exif UNDEFINED type, an 8-bit byte that may contain anything. - signedShort = 8, //!< Exif SSHORT type, a 16-bit (2-byte) signed (twos-complement) integer. - signedLong = 9, //!< Exif SLONG type, a 32-bit (4-byte) signed (twos-complement) integer. - signedRational = 10, //!< Exif SRATIONAL type, two SLONGs: numerator and denumerator of a fraction. - tiffFloat = 11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. - tiffDouble = 12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. - tiffIfd = 13, //!< TIFF IFD type, 32-bit (4-byte) unsigned integer. - unsigned64 = 16, //!< 64-bit unsigned value - signed64 = 17, //!< 64-bit signed value - tiffIfd8 = 18, //!< 64-bit IFD offset - iptcString = 0x10000, //!< IPTC string type. - iptcDate = 0x10001, //!< IPTC date type. - iptcTime = 0x10002, //!< IPTC time type. - comment = 0x10003, //!< %Exiv2 type for the Exif user comment. - directory = 0x10004, //!< %Exiv2 type for a CIFF directory. - xmpText = 0x10005, //!< XMP text type. - xmpAlt = 0x10006, //!< XMP alternative type. - xmpBag = 0x10007, //!< XMP bag type. - xmpSeq = 0x10008, //!< XMP sequence type. - langAlt = 0x10009, //!< XMP language alternative type. - invalidTypeId = 0x1fffe, //!< Invalid type id. - lastTypeId = 0x1ffff //!< Last type id. + unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. + asciiString = 2, //!< Exif ASCII type, 8-bit byte. + unsignedShort = 3, //!< Exif SHORT type, 16-bit (2-byte) unsigned integer. + unsignedLong = 4, //!< Exif LONG type, 32-bit (4-byte) unsigned integer. + unsignedRational = 5, //!< Exif RATIONAL type, two LONGs: numerator and denumerator of a fraction. + signedByte = 6, //!< Exif SBYTE type, an 8-bit signed (twos-complement) integer. + undefined = 7, //!< Exif UNDEFINED type, an 8-bit byte that may contain anything. + signedShort = 8, //!< Exif SSHORT type, a 16-bit (2-byte) signed (twos-complement) integer. + signedLong = 9, //!< Exif SLONG type, a 32-bit (4-byte) signed (twos-complement) integer. + signedRational = 10, //!< Exif SRATIONAL type, two SLONGs: numerator and denumerator of a fraction. + tiffFloat = 11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. + tiffDouble = 12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. + tiffIfd = 13, //!< TIFF IFD type, 32-bit (4-byte) unsigned integer. + unsigned64 = 16, //!< 64-bit unsigned value + signed64 = 17, //!< 64-bit signed value + tiffIfd8 = 18, //!< 64-bit IFD offset + iptcString = 0x10000, //!< IPTC string type. + iptcDate = 0x10001, //!< IPTC date type. + iptcTime = 0x10002, //!< IPTC time type. + comment = 0x10003, //!< %Exiv2 type for the Exif user comment. + directory = 0x10004, //!< %Exiv2 type for a CIFF directory. + xmpText = 0x10005, //!< XMP text type. + xmpAlt = 0x10006, //!< XMP alternative type. + xmpBag = 0x10007, //!< XMP bag type. + xmpSeq = 0x10008, //!< XMP sequence type. + langAlt = 0x10009, //!< XMP language alternative type. + invalidTypeId = 0x1fffe, //!< Invalid type id. + lastTypeId = 0x1ffff //!< Last type id. }; bool isStringType(uint16_t type) @@ -96,12 +96,13 @@ bool is8ByteType(uint16_t type) constexpr bool isBigEndianPlatform() { - union { - uint32_t i; - char c[4]; - } e = { 0x01000000 }; + union + { + uint32_t i; + char c[4]; + } e = { 0x01000000 }; - return e.c[0]?true:false; + return e.c[0]?true:false; } constexpr bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } @@ -166,291 +167,310 @@ typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, uint64 std::string indent(int32_t d) { - std::string result ; - if ( d > 0 ) - while ( d--) - result += " "; - return result; + std::string result ; + if ( d > 0 ) + while ( d--) + result += " "; + + return result; } static const char* tagName(uint16_t tag,size_t nMaxLength) { - const char* result = NULL; + const char* result = NULL; /* - // build a static map of tags for fast search - static std::map tags; - static bool init = true; - static char buffer[80]; + // build a static map of tags for fast search + static std::map tags; + static bool init = true; + static char buffer[80]; - if ( init ) { - int idx; - const TagInfo* ti ; - for (ti = mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = mpfTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = Nikon1MakerNote::tagList(), idx = 0 - ; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - } - init = false; + if ( init ) { + int idx; + const TagInfo* ti ; + for (ti = mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = mpfTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + for (ti = Nikon1MakerNote::tagList(), idx = 0 + ; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; + } + init = false; - try { - result = tags[tag].c_str(); - if ( nMaxLength > sizeof(buffer) -2 ) - nMaxLength = sizeof(buffer) -2; - strncpy(buffer,result,nMaxLength); - result = buffer; - } catch ( ... ) {} + try { + result = tags[tag].c_str(); + if ( nMaxLength > sizeof(buffer) -2 ) + nMaxLength = sizeof(buffer) -2; + strncpy(buffer,result,nMaxLength); + result = buffer; + } catch ( ... ) {} */ - return result ; + return result ; } static const char* typeName(uint16_t tag) { - //! List of TIFF image tags - const char* result = NULL; - switch (tag ) { - case unsignedByte : result = "BYTE" ; break; - case asciiString : result = "ASCII" ; break; - case unsignedShort : result = "SHORT" ; break; - case unsignedLong : result = "LONG" ; break; - case unsignedRational : result = "RATIONAL" ; break; - case signedByte : result = "SBYTE" ; break; - case undefined : result = "UNDEFINED" ; break; - case signedShort : result = "SSHORT" ; break; - case signedLong : result = "SLONG" ; break; - case signedRational : result = "SRATIONAL" ; break; - case tiffFloat : result = "FLOAT" ; break; - case tiffDouble : result = "DOUBLE" ; break; - case tiffIfd : result = "IFD" ; break; - default : result = "unknown" ; break; - } - return result; + //! List of TIFF image tags + const char* result = NULL; + switch (tag ) { + case unsignedByte : result = "BYTE" ; break; + case asciiString : result = "ASCII" ; break; + case unsignedShort : result = "SHORT" ; break; + case unsignedLong : result = "LONG" ; break; + case unsignedRational : result = "RATIONAL" ; break; + case signedByte : result = "SBYTE" ; break; + case undefined : result = "UNDEFINED" ; break; + case signedShort : result = "SSHORT" ; break; + case signedLong : result = "SLONG" ; break; + case signedRational : result = "SRATIONAL" ; break; + case tiffFloat : result = "FLOAT" ; break; + case tiffDouble : result = "DOUBLE" ; break; + case tiffIfd : result = "IFD" ; break; + default : result = "unknown" ; break; + } + return result; } struct field_t { - uint16_t tagID; - uint16_t tagType; - uint64_t count; - uint64_t data; + uint16_t tagID; + uint16_t tagType; + uint64_t count; + uint64_t data; } __attribute__((packed)); void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint64_t offset, bool bSwap, int depth) { - depth++; - bool bFirst = true; + depth++; + bool bFirst = true; - // buffer - bool bPrint = true; + // buffer + bool bPrint = true; - do { - // Read top of directory - io.seek(offset, Exiv2::BasicIo::beg); + do { + // Read top of directory + io.seek(offset, Exiv2::BasicIo::beg); - uint64_t entries_raw; - io.read(reinterpret_cast(&entries_raw), 8); + uint64_t entries_raw; + io.read(reinterpret_cast(&entries_raw), 8); - const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); + const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); - const bool tooBig = entries > 500; + const bool tooBig = entries > 500; - if ( bFirst && bPrint ) + if ( bFirst && bPrint ) + { + out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << io.path() << std::endl; + if (tooBig) + out << indent(depth) << "entries = " << entries << std::endl; + } + + if (tooBig) + break; + + // Read the dictionary + for ( uint64_t i = 0; i < entries; i ++ ) + { + if ( bFirst && bPrint ) + out << indent(depth) + << " address | tag | " + << " type | count | offset | value\n"; + + bFirst = false; + field_t field; + + io.read(reinterpret_cast(&field), sizeof(field)); + const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); + const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); + const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); + const uint64_t data = conditional_byte_swap<64>(field.data, bSwap); + + std::string sp = "" ; // output spacer + + //prepare to print the value + // TODO: figure out what's going on with kount + const uint64_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays + : count > 5 ? 5 + : count + ; + const uint32_t pad = isStringType(type) ? 1 : 0; + const uint32_t size = isStringType(type) ? 1 + : is2ByteType(type) ? 2 + : is4ByteType(type) ? 4 + : is8ByteType(type) ? 8 + : 1; + + Exiv2::DataBuf buf(size*count + pad); // allocate a buffer + + // big data? Use 'data' as pointer to real data + if ( count*size > 8 ) // read into buffer + { + size_t restore = io.tell(); // save + io.seek(data, Exiv2::BasicIo::beg); // position + io.read(buf.pData_,count*size); // read + io.seek(restore, Exiv2::BasicIo::beg); // restore + } + else // use 'data' as data :) + std::memcpy(buf.pData_, &data, 8); // copy data + + if ( bPrint ) + { + uint64_t address = offset + 2 + i*12 ; + out << indent(depth) + << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " + ,address,tag,tagName(tag,25),typeName(type),count,offset); + if ( isShortType(type) ) { - out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << io.path() << std::endl; - if (tooBig) - out << indent(depth) << "entries = " << entries << std::endl; - } - - if (tooBig) - break; - - // Read the dictionary - for ( uint64_t i = 0; i < entries; i ++ ) + for ( size_t k = 0 ; k < kount ; k++ ) + { + out << sp << conditional_byte_swap_4_array<16>(&buf, k*size, bSwap); + sp = " "; + } + } + else if ( isLongType(type) ) { - if ( bFirst && bPrint ) - out << indent(depth) - << " address | tag | " - << " type | count | offset | value\n"; + for ( size_t k = 0 ; k < kount ; k++ ) + { + out << sp << conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); + sp = " "; + } + } + else if ( isRationalType(type) ) + { + for ( size_t k = 0 ; k < kount ; k++ ) { + uint32_t a = conditional_byte_swap_4_array<32>(&buf, k*size+0, bSwap); + uint32_t b = conditional_byte_swap_4_array<32>(&buf, k*size+4, bSwap); + out << sp << a << "/" << b; + sp = " "; + } + } else if ( isStringType(type) ) { + out << sp << Exiv2::Internal::binaryToString(buf, kount); + } - bFirst = false; - field_t field; + sp = kount == count ? "" : " ..."; + out << sp << std::endl; - io.read(reinterpret_cast(&field), sizeof(field)); - const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); - const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); - const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); - const uint64_t data = conditional_byte_swap<64>(field.data, bSwap); + if ( option == Exiv2::kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) + { + for ( size_t k = 0 ; k < count ; k++ ) + { + size_t restore = io.tell(); + uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); + std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; + printIFD(io, out, option, offset, bSwap, depth); + io.seek(restore, Exiv2::BasicIo::beg); + } + } + else if ( option == Exiv2::kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) + { + size_t restore = io.tell(); // save + io.seek(offset, Exiv2::BasicIo::beg); // position + Exiv2::byte* bytes=new Exiv2::byte[count] ; // allocate memory + io.read(bytes,count) ; // read + io.seek(restore, Exiv2::BasicIo::beg); // restore + Exiv2::IptcData::printStructure(out,bytes,count,depth); + delete[] bytes; // free + } + else if ( option == Exiv2::kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) + { + size_t restore = io.tell(); // save - std::string sp = "" ; // output spacer + uint32_t jump= 10 ; + Exiv2::byte bytes[20] ; + const char* chars = (const char*) &bytes[0] ; + io.seek(offset, Exiv2::BasicIo::beg); // position + io.read(bytes,jump ) ; // read + bytes[jump]=0 ; + if ( ::strcmp("Nikon",chars) == 0 ) { + // tag is an embedded tiff + Exiv2::byte* bytes=new Exiv2::byte[count-jump] ; // allocate memory + io.read(bytes,count-jump) ; // read + Exiv2::MemIo memIo(bytes,count-jump) ; // create a file + std::cerr << "Nikon makernote" << std::endl; + // printTiffStructure(memIo,out,option,depth); TODO: fix it + delete[] bytes ; // free + } else { + // tag is an IFD + io.seek(0, Exiv2::BasicIo::beg); // position + std::cerr << "makernote" << std::endl; + //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me + } - //prepare to print the value - // TODO: figure out what's going on with kount - const uint64_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays - : count > 5 ? 5 - : count - ; - const uint32_t pad = isStringType(type) ? 1 : 0; - const uint32_t size = isStringType(type) ? 1 - : is2ByteType(type) ? 2 - : is4ByteType(type) ? 4 - : is8ByteType(type) ? 8 - : 1; + io.seek(restore,Exiv2::BasicIo::beg); // restore + } + } + } + uint64_t next_dir_offset_raw; + io.read(reinterpret_cast(&next_dir_offset_raw), 8); + offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); + out.flush(); + } while (offset) ; - Exiv2::DataBuf buf(size*count + pad); // allocate a buffer - - // big data? Use 'data' as pointer to real data - if ( count*size > 8 ) // read into buffer - { - size_t restore = io.tell(); // save - io.seek(data, Exiv2::BasicIo::beg); // position - io.read(buf.pData_,count*size); // read - io.seek(restore, Exiv2::BasicIo::beg); // restore - } - else // use 'data' as data :) - std::memcpy(buf.pData_, &data, 8); // copy data - - if ( bPrint ) { - uint64_t address = offset + 2 + i*12 ; - out << indent(depth) - << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " - ,address,tag,tagName(tag,25),typeName(type),count,offset); - if ( isShortType(type) ){ - for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<16>(&buf, k*size, bSwap); - sp = " "; - } - } else if ( isLongType(type) ){ - for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); - sp = " "; - } - - } else if ( isRationalType(type) ){ - for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = conditional_byte_swap_4_array<32>(&buf, k*size+0, bSwap); - uint32_t b = conditional_byte_swap_4_array<32>(&buf, k*size+4, bSwap); - out << sp << a << "/" << b; - sp = " "; - } - } else if ( isStringType(type) ) { - out << sp << Exiv2::Internal::binaryToString(buf, kount); - } - - sp = kount == count ? "" : " ..."; - out << sp << std::endl; - - if ( option == Exiv2::kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) { - for ( size_t k = 0 ; k < count ; k++ ) { - size_t restore = io.tell(); - uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); - std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; - printIFD(io, out, option, offset, bSwap, depth); - io.seek(restore, Exiv2::BasicIo::beg); - } - } else if ( option == Exiv2::kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { - size_t restore = io.tell(); // save - io.seek(offset, Exiv2::BasicIo::beg); // position - Exiv2::byte* bytes=new Exiv2::byte[count] ; // allocate memory - io.read(bytes,count) ; // read - io.seek(restore, Exiv2::BasicIo::beg); // restore - Exiv2::IptcData::printStructure(out,bytes,count,depth); - delete[] bytes; // free - } else if ( option == Exiv2::kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) { - size_t restore = io.tell(); // save - - uint32_t jump= 10 ; - Exiv2::byte bytes[20] ; - const char* chars = (const char*) &bytes[0] ; - io.seek(offset, Exiv2::BasicIo::beg); // position - io.read(bytes,jump ) ; // read - bytes[jump]=0 ; - if ( ::strcmp("Nikon",chars) == 0 ) { - // tag is an embedded tiff - Exiv2::byte* bytes=new Exiv2::byte[count-jump] ; // allocate memory - io.read(bytes,count-jump) ; // read - Exiv2::MemIo memIo(bytes,count-jump) ; // create a file - std::cerr << "Nikon makernote" << std::endl; - // printTiffStructure(memIo,out,option,depth); TODO: fix it - delete[] bytes ; // free - } else { - // tag is an IFD - io.seek(0, Exiv2::BasicIo::beg); // position - std::cerr << "makernote" << std::endl; - //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me - } - - io.seek(restore,Exiv2::BasicIo::beg); // restore - } - } - } - uint64_t next_dir_offset_raw; - io.read(reinterpret_cast(&next_dir_offset_raw), 8); - offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); - out.flush(); - } while (offset) ; - - if ( bPrint ) { - out << indent(depth) << "END " << io.path() << std::endl; - } - depth--; + if ( bPrint ) { + out << indent(depth) << "END " << io.path() << std::endl; + } + depth--; } int main(int argc,const char* argv[]) { - int result = 0; - bool bSwap = false; - uint64_t offset = 0; + int result = 0; + bool bSwap = false; + uint64_t offset = 0; - if ( argc > 0 ) { - FILE* f = fopen(argv[1],"rb"); - if ( f ) { - char buff[2*WIDTH]; - fread(buff,1,sizeof buff,f); + if ( argc > 0 ) + { + FILE* f = fopen(argv[1],"rb"); + if ( f ) + { + char buff[2*WIDTH]; + fread(buff,1,sizeof buff,f); - bSwap = (isLittleEndianPlatform() && buff[0] == 'M') - || (isBigEndianPlatform() && buff[0] == 'I') - ; + bSwap = (isLittleEndianPlatform() && buff[0] == 'M') + || (isBigEndianPlatform() && buff[0] == 'I') + ; - uint16_t magic = conditional_byte_swap_4_array<16>(buff, 2, bSwap); - uint16_t byteSize = conditional_byte_swap_4_array<16>(buff, 4, bSwap); - uint16_t zeroByte = conditional_byte_swap_4_array<16>(buff, 6, bSwap); - offset = conditional_byte_swap_4_array<64>(buff, 8, bSwap); + uint16_t magic = conditional_byte_swap_4_array<16>(buff, 2, bSwap); + uint16_t byteSize = conditional_byte_swap_4_array<16>(buff, 4, bSwap); + uint16_t zeroByte = conditional_byte_swap_4_array<16>(buff, 6, bSwap); + offset = conditional_byte_swap_4_array<64>(buff, 8, bSwap); - if ( buff[0] != buff[1] || - (buff[0] != 'I' && buff[0] != 'M') || - magic != 43 || - byteSize != 8 || - zeroByte != 0 - ) - { - std::cerr << "bSwap = " << bSwap << std::endl; - std::cerr << "magic = " << magic << std::endl; - std::cerr << "byteSize = " << byteSize << std::endl; - std::cerr << "zeroByte = " << zeroByte << std::endl; - std::cerr << "offset = " << offset << std::endl; - std::cerr << argv[1] << " is not a BigTIFF file" << std::endl; - result = 3 ; - } - fclose(f); - } else { - std::cerr << argv[0] << " unable to open " << argv[1] << std::endl; - result = 2 ; - } + if ( buff[0] != buff[1] || + (buff[0] != 'I' && buff[0] != 'M') || + magic != 43 || + byteSize != 8 || + zeroByte != 0 + ) + { + std::cerr << "bSwap = " << bSwap << std::endl; + std::cerr << "magic = " << magic << std::endl; + std::cerr << "byteSize = " << byteSize << std::endl; + std::cerr << "zeroByte = " << zeroByte << std::endl; + std::cerr << "offset = " << offset << std::endl; + std::cerr << argv[1] << " is not a BigTIFF file" << std::endl; + result = 3 ; + } - } else { - std::cerr << argv[0] << " path" << std::endl; - result = 1 ; - } + fclose(f); + } + else + { + std::cerr << argv[0] << " unable to open " << argv[1] << std::endl; + result = 2 ; + } - if ( result == 0 ) { - std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; - int depth = 0 ; - Exiv2::FileIo file(argv[1]); - file.open("rb"); - printIFD(file, std::cout, Exiv2::kpsRecursive, offset, bSwap, depth); - } + } else { + std::cerr << argv[0] << " path" << std::endl; + result = 1 ; + } - return result; + if ( result == 0 ) { + std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; + int depth = 0 ; + Exiv2::FileIo file(argv[1]); + file.open("rb"); + printIFD(file, std::cout, Exiv2::kpsRecursive, offset, bSwap, depth); + } + + return result; } From 62152aae38c857d8e307d2264340e6e145332e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:12:21 +0200 Subject: [PATCH 26/71] message cleanup --- bigtiff/parse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 56585c01..426b200e 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -260,7 +260,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption if ( bFirst && bPrint ) { - out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE") << io.path() << std::endl; + out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE ") << io.path() << std::endl; if (tooBig) out << indent(depth) << "entries = " << entries << std::endl; } From b9e6a2972f5a03e42b1524002f89dfd32829ce5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:13:38 +0200 Subject: [PATCH 27/71] fix address calculations --- bigtiff/parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 426b200e..53b47c72 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -279,7 +279,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption bFirst = false; field_t field; - io.read(reinterpret_cast(&field), sizeof(field)); + io.read(reinterpret_cast(&field), sizeof(field_t)); const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); @@ -315,7 +315,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption if ( bPrint ) { - uint64_t address = offset + 2 + i*12 ; + const uint64_t address = offset + 2 + i * sizeof(field_t) ; out << indent(depth) << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " ,address,tag,tagName(tag,25),typeName(type),count,offset); From 6dd15eb625098c73a64d24d319fd9986f2d0a65f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:16:40 +0200 Subject: [PATCH 28/71] more formatting changes --- bigtiff/parse.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 53b47c72..93ba1a1e 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -317,8 +317,9 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption { const uint64_t address = offset + 2 + i * sizeof(field_t) ; out << indent(depth) - << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | " - ,address,tag,tagName(tag,25),typeName(type),count,offset); + << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", + address, tag, tagName(tag,25), typeName(type), count, offset); + if ( isShortType(type) ) { for ( size_t k = 0 ; k < kount ; k++ ) @@ -343,9 +344,9 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption out << sp << a << "/" << b; sp = " "; } - } else if ( isStringType(type) ) { - out << sp << Exiv2::Internal::binaryToString(buf, kount); } + else if ( isStringType(type) ) + out << sp << Exiv2::Internal::binaryToString(buf, kount); sp = kount == count ? "" : " ..."; out << sp << std::endl; From 232dbd715f9f8b064ed38c78e81c4efba9d7a076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:18:27 +0200 Subject: [PATCH 29/71] more formatting --- bigtiff/parse.cpp | 58 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 93ba1a1e..675765ba 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -324,25 +324,26 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<16>(&buf, k*size, bSwap); - sp = " "; + out << sp << conditional_byte_swap_4_array<16>(&buf, k*size, bSwap); + sp = " "; } } else if ( isLongType(type) ) { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); - sp = " "; + out << sp << conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); + sp = " "; } } else if ( isRationalType(type) ) { - for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = conditional_byte_swap_4_array<32>(&buf, k*size+0, bSwap); - uint32_t b = conditional_byte_swap_4_array<32>(&buf, k*size+4, bSwap); - out << sp << a << "/" << b; - sp = " "; + for ( size_t k = 0 ; k < kount ; k++ ) + { + uint32_t a = conditional_byte_swap_4_array<32>(&buf, k*size+0, bSwap); + uint32_t b = conditional_byte_swap_4_array<32>(&buf, k*size+4, bSwap); + out << sp << a << "/" << b; + sp = " "; } } else if ( isStringType(type) ) @@ -355,11 +356,11 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption { for ( size_t k = 0 ; k < count ; k++ ) { - size_t restore = io.tell(); - uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); - std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; - printIFD(io, out, option, offset, bSwap, depth); - io.seek(restore, Exiv2::BasicIo::beg); + size_t restore = io.tell(); + uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); + std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; + printIFD(io, out, option, offset, bSwap, depth); + io.seek(restore, Exiv2::BasicIo::beg); } } else if ( option == Exiv2::kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) @@ -382,19 +383,22 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption io.seek(offset, Exiv2::BasicIo::beg); // position io.read(bytes,jump ) ; // read bytes[jump]=0 ; - if ( ::strcmp("Nikon",chars) == 0 ) { - // tag is an embedded tiff - Exiv2::byte* bytes=new Exiv2::byte[count-jump] ; // allocate memory - io.read(bytes,count-jump) ; // read - Exiv2::MemIo memIo(bytes,count-jump) ; // create a file - std::cerr << "Nikon makernote" << std::endl; - // printTiffStructure(memIo,out,option,depth); TODO: fix it - delete[] bytes ; // free - } else { - // tag is an IFD - io.seek(0, Exiv2::BasicIo::beg); // position - std::cerr << "makernote" << std::endl; - //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me + if ( ::strcmp("Nikon",chars) == 0 ) + { + // tag is an embedded tiff + Exiv2::byte* bytes=new Exiv2::byte[count-jump] ; // allocate memory + io.read(bytes,count-jump) ; // read + Exiv2::MemIo memIo(bytes,count-jump) ; // create a file + std::cerr << "Nikon makernote" << std::endl; + // printTiffStructure(memIo,out,option,depth); TODO: fix it + delete[] bytes ; // free + } + else + { + // tag is an IFD + io.seek(0, Exiv2::BasicIo::beg); // position + std::cerr << "makernote" << std::endl; + //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me } io.seek(restore,Exiv2::BasicIo::beg); // restore From abcc4b1283a0dda57342f0d999c5d73fefb3a33b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:29:01 +0200 Subject: [PATCH 30/71] fixing way of reading buffer with data --- bigtiff/parse.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 675765ba..0c21842e 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -324,7 +324,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<16>(&buf, k*size, bSwap); + out << sp << conditional_byte_swap_4_array<16>(buf.pData_, k*size, bSwap); sp = " "; } } @@ -332,7 +332,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); + out << sp << conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); sp = " "; } } @@ -340,8 +340,8 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption { for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = conditional_byte_swap_4_array<32>(&buf, k*size+0, bSwap); - uint32_t b = conditional_byte_swap_4_array<32>(&buf, k*size+4, bSwap); + uint32_t a = conditional_byte_swap_4_array<32>(buf.pData_, k*size+0, bSwap); + uint32_t b = conditional_byte_swap_4_array<32>(buf.pData_, k*size+4, bSwap); out << sp << a << "/" << b; sp = " "; } @@ -357,7 +357,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption for ( size_t k = 0 ; k < count ; k++ ) { size_t restore = io.tell(); - uint32_t offset = conditional_byte_swap_4_array<32>(&buf, k*size, bSwap); + uint32_t offset = conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; printIFD(io, out, option, offset, bSwap, depth); io.seek(restore, Exiv2::BasicIo::beg); From b343064afcecd43318adf4f5404facadfa17a5b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:29:43 +0200 Subject: [PATCH 31/71] comments format --- bigtiff/parse.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 0c21842e..5e46cd7b 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -303,7 +303,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption Exiv2::DataBuf buf(size*count + pad); // allocate a buffer // big data? Use 'data' as pointer to real data - if ( count*size > 8 ) // read into buffer + if ( count*size > 8 ) // read into buffer { size_t restore = io.tell(); // save io.seek(data, Exiv2::BasicIo::beg); // position @@ -311,7 +311,7 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption io.seek(restore, Exiv2::BasicIo::beg); // restore } else // use 'data' as data :) - std::memcpy(buf.pData_, &data, 8); // copy data + std::memcpy(buf.pData_, &data, 8); // copy data if ( bPrint ) { From 1429ae843a8fdf5d28824cc27f57b4e9ad7e52fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:39:04 +0200 Subject: [PATCH 32/71] fix memcpy bytes size --- bigtiff/parse.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 5e46cd7b..10417114 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -300,18 +300,18 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption : is8ByteType(type) ? 8 : 1; - Exiv2::DataBuf buf(size*count + pad); // allocate a buffer + Exiv2::DataBuf buf(size * count + pad); // big data? Use 'data' as pointer to real data if ( count*size > 8 ) // read into buffer { size_t restore = io.tell(); // save io.seek(data, Exiv2::BasicIo::beg); // position - io.read(buf.pData_,count*size); // read + io.read(buf.pData_, count * size); // read io.seek(restore, Exiv2::BasicIo::beg); // restore } else // use 'data' as data :) - std::memcpy(buf.pData_, &data, 8); // copy data + std::memcpy(buf.pData_, &data, count * size); // copy data if ( bPrint ) { From 0d1a556b90ab59223e72a87cbcb7d94c5258a7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:41:29 +0200 Subject: [PATCH 33/71] cleanups --- bigtiff/parse.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 10417114..4d5bfcb8 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -247,7 +247,8 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption // buffer bool bPrint = true; - do { + do + { // Read top of directory io.seek(offset, Exiv2::BasicIo::beg); @@ -411,9 +412,9 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption out.flush(); } while (offset) ; - if ( bPrint ) { - out << indent(depth) << "END " << io.path() << std::endl; - } + if ( bPrint ) + out << indent(depth) << "END " << io.path() << std::endl; + depth--; } From d2c634ec9d14b7954130d0d5f691ed0ba68c20de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:47:45 +0200 Subject: [PATCH 34/71] adding printer for (un)signed64 type --- bigtiff/parse.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 4d5bfcb8..234d4b6a 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -70,6 +70,12 @@ bool isLongType(uint16_t type) || type == signedLong; } +bool isLongLongType(uint16_t type) +{ + return type == unsigned64 + || type == signed64; +} + bool isRationalType(uint16_t type) { return type == unsignedRational @@ -227,6 +233,8 @@ static const char* typeName(uint16_t tag) case tiffFloat : result = "FLOAT" ; break; case tiffDouble : result = "DOUBLE" ; break; case tiffIfd : result = "IFD" ; break; + case unsigned64 : result = "UNSIGNED64"; break; + case signed64 : result = "SIGNED64" ; break; default : result = "unknown" ; break; } return result; @@ -337,6 +345,14 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption sp = " "; } } + else if ( isLongLongType(type) ) + { + for ( size_t k = 0 ; k < kount ; k++ ) + { + out << sp << conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap); + sp = " "; + } + } else if ( isRationalType(type) ) { for ( size_t k = 0 ; k < kount ; k++ ) From 5c50031cb690a03a115c21fbb3ae0322bb05f86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:50:25 +0200 Subject: [PATCH 35/71] dealing with 64-bit ifd recursive pointer --- bigtiff/parse.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 234d4b6a..c2b82a1e 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -369,12 +369,16 @@ void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption sp = kount == count ? "" : " ..."; out << sp << std::endl; - if ( option == Exiv2::kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd) ) + if ( option == Exiv2::kpsRecursive && + (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd || type == tiffIfd8) ) { for ( size_t k = 0 ; k < count ; k++ ) { - size_t restore = io.tell(); - uint32_t offset = conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); + const size_t restore = io.tell(); + const uint64_t offset = type == tiffIfd8? + conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap): + conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); + std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; printIFD(io, out, option, offset, bSwap, depth); io.seek(restore, Exiv2::BasicIo::beg); From 3c02a3a3a6b90015122e174dd54e13c23b6647cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:50:51 +0200 Subject: [PATCH 36/71] format --- bigtiff/parse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index c2b82a1e..c155316e 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -235,7 +235,7 @@ static const char* typeName(uint16_t tag) case tiffIfd : result = "IFD" ; break; case unsigned64 : result = "UNSIGNED64"; break; case signed64 : result = "SIGNED64" ; break; - default : result = "unknown" ; break; + default : result = "unknown" ; break; } return result; } From 56f5979168e2cea5e7f6f53a73f7d0897e081f83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sat, 9 Sep 2017 14:51:47 +0200 Subject: [PATCH 37/71] extending is8ByteType --- bigtiff/parse.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index c155316e..dae89ac6 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -97,7 +97,10 @@ bool is4ByteType(uint16_t type) bool is8ByteType(uint16_t type) { return isRationalType(type) - || type == tiffDouble; + || type == tiffDouble + || type == unsigned64 + || type == signed64 + || type == tiffIfd8; } constexpr bool isBigEndianPlatform() From bc6eed0b035cf795b549c15f9a9f71ac80128ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 12 Sep 2017 20:50:56 +0200 Subject: [PATCH 38/71] registering new file type --- include/exiv2/bigtiffimage.hpp | 16 ++++++++++++++++ src/CMakeLists.txt | 1 + src/bigtiffimage.cpp | 19 +++++++++++++++++++ src/image.cpp | 2 ++ 4 files changed, 38 insertions(+) create mode 100644 include/exiv2/bigtiffimage.hpp create mode 100644 src/bigtiffimage.cpp diff --git a/include/exiv2/bigtiffimage.hpp b/include/exiv2/bigtiffimage.hpp new file mode 100644 index 00000000..d0dc57ab --- /dev/null +++ b/include/exiv2/bigtiffimage.hpp @@ -0,0 +1,16 @@ + +#include "basicio.hpp" +#include "image.hpp" + +namespace Exiv2 +{ + +namespace ImageType +{ + const int bigtiff = 22; +} + +Image::AutoPtr newBigTiffInstance(BasicIo::AutoPtr, bool); +bool isBigTiffType(BasicIo &, bool); + +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d0b8a66b..99d9a90d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -84,6 +84,7 @@ set( LIBEXIV2_HDR ../include/exiv2/asfvideo.hpp # Add library C++ source files to this list set( LIBEXIV2_SRC asfvideo.cpp basicio.cpp + bigtiffimage.cpp bmpimage.cpp canonmn.cpp casiomn.cpp diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp new file mode 100644 index 00000000..a991c590 --- /dev/null +++ b/src/bigtiffimage.cpp @@ -0,0 +1,19 @@ + +#include "bigtiffimage.hpp" + + + +namespace Exiv2 +{ + +Image::AutoPtr newBigTiffInstance(BasicIo::AutoPtr, bool) +{ + return Image::AutoPtr(); +} + +bool isBigTiffType(BasicIo &, bool) +{ + return false; +} + +} diff --git a/src/image.cpp b/src/image.cpp index a7198328..d28e897c 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -47,6 +47,7 @@ EXIV2_RCSID("@(#) $Id$") #include "tiffimage_int.hpp" #include "tiffcomposite_int.hpp" #include "tiffvisitor_int.hpp" +#include "bigtiffimage.hpp" #include "webpimage.hpp" #include "orfimage.hpp" #include "gifimage.hpp" @@ -112,6 +113,7 @@ namespace { { ImageType::crw, newCrwInstance, isCrwType, amReadWrite, amNone, amNone, amReadWrite }, { ImageType::mrw, newMrwInstance, isMrwType, amRead, amRead, amRead, amNone }, { ImageType::tiff, newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone }, + { ImageType::bigtiff, newBigTiffInstance, isBigTiffType, amRead, amRead, amRead, amNone }, { ImageType::webp, newWebPInstance, isWebPType, amReadWrite, amNone, amReadWrite, amNone }, { ImageType::dng, newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone }, { ImageType::nef, newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone }, From b3aa2adf312f3aa9acee6061d54c3b3264bc7cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 12 Sep 2017 21:48:01 +0200 Subject: [PATCH 39/71] initial implementation of newBigTiffInstance() --- src/bigtiffimage.cpp | 45 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index a991c590..8e07e8c7 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -2,18 +2,45 @@ #include "bigtiffimage.hpp" - namespace Exiv2 { -Image::AutoPtr newBigTiffInstance(BasicIo::AutoPtr, bool) -{ - return Image::AutoPtr(); -} + namespace + { + class BigTiffImage: public Image + { + public: + BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io) {} -bool isBigTiffType(BasicIo &, bool) -{ - return false; -} + virtual ~BigTiffImage() {} + + // overrides + void readMetadata() + { + + } + + void writeMetadata() + { + + } + + std::string mimeType() const + { + + } + }; + } + + + Image::AutoPtr newBigTiffInstance(BasicIo::AutoPtr io, bool) + { + return Image::AutoPtr(new BigTiffImage(io)); + } + + bool isBigTiffType(BasicIo &, bool) + { + return false; + } } From 7e0b63142e41bc4bccd09a852548dd3e79d7c4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 12 Sep 2017 21:50:27 +0200 Subject: [PATCH 40/71] some code formatting --- bigtiff/parse.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index dae89ac6..4f6b8c1a 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -453,7 +453,7 @@ int main(int argc,const char* argv[]) if ( f ) { char buff[2*WIDTH]; - fread(buff,1,sizeof buff,f); + fread(buff, 1, sizeof buff, f); bSwap = (isLittleEndianPlatform() && buff[0] == 'M') || (isBigEndianPlatform() && buff[0] == 'I') @@ -462,12 +462,12 @@ int main(int argc,const char* argv[]) uint16_t magic = conditional_byte_swap_4_array<16>(buff, 2, bSwap); uint16_t byteSize = conditional_byte_swap_4_array<16>(buff, 4, bSwap); uint16_t zeroByte = conditional_byte_swap_4_array<16>(buff, 6, bSwap); - offset = conditional_byte_swap_4_array<64>(buff, 8, bSwap); + offset = conditional_byte_swap_4_array<64>(buff, 8, bSwap); if ( buff[0] != buff[1] || (buff[0] != 'I' && buff[0] != 'M') || - magic != 43 || - byteSize != 8 || + magic != 43 || + byteSize != 8 || zeroByte != 0 ) { @@ -488,7 +488,9 @@ int main(int argc,const char* argv[]) result = 2 ; } - } else { + } + else + { std::cerr << argv[0] << " path" << std::endl; result = 1 ; } From e64103a31d1debeffece30779a2be459d8a500e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 12 Sep 2017 21:52:27 +0200 Subject: [PATCH 41/71] removing c++14 stuff --- bigtiff/parse.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index 4f6b8c1a..fb62b829 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -1,4 +1,5 @@ +#include #include #include #include @@ -103,7 +104,7 @@ bool is8ByteType(uint16_t type) || type == tiffIfd8; } -constexpr bool isBigEndianPlatform() +bool isBigEndianPlatform() { union { @@ -114,7 +115,7 @@ constexpr bool isBigEndianPlatform() return e.c[0]?true:false; } -constexpr bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } +bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } template struct TypeForSize {}; @@ -140,7 +141,7 @@ struct TypeForSize<64> template typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) { - static_assert(size == 16 || size == 32 || size == 64, "unsupported data size"); + assert(size == 16 || size == 32 || size == 64); // supported sizes typename TypeForSize::Type result = 0; if (size == 16) From 0289b19571b4d57262dd07cf47b78fca6fcffcc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 12 Sep 2017 21:52:55 +0200 Subject: [PATCH 42/71] assert should not be necessary --- bigtiff/parse.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp index fb62b829..31fa53b3 100644 --- a/bigtiff/parse.cpp +++ b/bigtiff/parse.cpp @@ -1,5 +1,4 @@ -#include #include #include #include @@ -141,8 +140,6 @@ struct TypeForSize<64> template typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) { - assert(size == 16 || size == 32 || size == 64); // supported sizes - typename TypeForSize::Type result = 0; if (size == 16) result = __builtin_bswap16(v); From dc331ee44aa4fdea69c8ae5a98c7aff70ab9fc6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 14 Sep 2017 22:05:50 +0200 Subject: [PATCH 43/71] implementing isBigTiffType --- src/bigtiffimage.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 8e07e8c7..dea8195e 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -38,9 +38,29 @@ namespace Exiv2 return Image::AutoPtr(new BigTiffImage(io)); } - bool isBigTiffType(BasicIo &, bool) + bool isBigTiffType(BasicIo& io, bool) { - return false; + byte header[2]; + io.read(header, 2); + + ByteOrder byteOrder = invalidByteOrder; + if (header[0] == 'I' && header[1] == 'I') + byteOrder = littleEndian; + else if (header[0] == 'M' && header[1] == 'M') + byteOrder = bigEndian; + + bool isBigTiff = false; + if (byteOrder != invalidByteOrder) + { + byte version[2]; + io.read(version, 2); + + const uint16_t magic = getUShort(version, byteOrder); + + isBigTiff = magic == 0x2A || magic == 0x2B; + } + + return isBigTiff; } } From ab27bfab3c8d9f64c9cf4184a5c2b3b9e5c813a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 14 Sep 2017 22:38:48 +0200 Subject: [PATCH 44/71] introducing getULongLong() --- include/exiv2/types.hpp | 2 ++ src/types.cpp | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/include/exiv2/types.hpp b/include/exiv2/types.hpp index b19a79ab..70f3e453 100644 --- a/include/exiv2/types.hpp +++ b/include/exiv2/types.hpp @@ -266,6 +266,8 @@ namespace Exiv2 { EXIV2API uint16_t getUShort(const byte* buf, ByteOrder byteOrder); //! Read a 4 byte unsigned long value from the data buffer EXIV2API uint32_t getULong(const byte* buf, ByteOrder byteOrder); + //! Read a 8 byte unsigned long value from the data buffer + EXIV2API uint64_t getULongLong(const byte* buf, ByteOrder byteOrder); //! Read an 8 byte unsigned rational value from the data buffer EXIV2API URational getURational(const byte* buf, ByteOrder byteOrder); //! Read a 2 byte signed short value from the data buffer diff --git a/src/types.cpp b/src/types.cpp index df509703..3d539908 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -252,6 +252,22 @@ namespace Exiv2 { } } + uint64_t getULongLong(const byte* buf, ByteOrder byteOrder) + { + if (byteOrder == littleEndian) { + return (uint64_t)buf[7] << 56 | (uint64_t)buf[6] << 48 + | (uint64_t)buf[5] << 40 | (uint64_t)buf[4] << 32 + | (uint64_t)buf[3] << 24 | (uint64_t)buf[2] << 16 + | (uint64_t)buf[1] << 8 | (uint64_t)buf[0]; + } + else { + return (uint64_t)buf[0] << 56 | (uint64_t)buf[1] << 48 + | (uint64_t)buf[2] << 40 | (uint64_t)buf[3] << 32 + | (uint64_t)buf[4] << 24 | (uint64_t)buf[5] << 16 + | (uint64_t)buf[6] << 8 | (uint64_t)buf[7]; + } + } + URational getURational(const byte* buf, ByteOrder byteOrder) { uint32_t nominator = getULong(buf, byteOrder); From 307faae8304dd43ebf91e60c3415f0de2221f039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 14 Sep 2017 22:44:08 +0200 Subject: [PATCH 45/71] introducing tiff Header + header builder function --- src/bigtiffimage.cpp | 103 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 21 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index dea8195e..c36acb5a 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -1,16 +1,90 @@ #include "bigtiffimage.hpp" +#include namespace Exiv2 { namespace { + struct Header + { + ByteOrder byteOrder; + int version; // 42 or 43 - regular tiff or big tiff + int data_size; // 4 or 8 + uint64_t dir_offset; + + bool isValid() const { return version != -1; } + + Header(): byteOrder(invalidByteOrder), version(-1), data_size(0), dir_offset(0) {} + Header(const ByteOrder& order, int v, int size, uint64_t offset): + byteOrder(order), + version(v), + data_size(size), + dir_offset(offset) + { + + } + }; + + Header readHeader(BasicIo& io) + { + byte header[2]; + io.read(header, 2); + + ByteOrder byteOrder = invalidByteOrder; + if (header[0] == 'I' && header[1] == 'I') + byteOrder = littleEndian; + else if (header[0] == 'M' && header[1] == 'M') + byteOrder = bigEndian; + + if (byteOrder == invalidByteOrder) + return Header(); + + byte version[2]; + io.read(version, 2); + + const uint16_t magic = getUShort(version, byteOrder); + + if (magic != 0x2A && magic != 0x2B) + return Header(); + + Header result; + + if (magic == 0x2A) + { + byte buffer[4]; + io.read(buffer, 4); + + const uint32_t offset = getULong(buffer, byteOrder); + result = Header(byteOrder, magic, 4, offset); + } + else + { + byte buffer[8]; + io.read(buffer, 2); + const int size = getUShort(buffer, byteOrder); + assert(size == 8); + + io.read(buffer, 2); // null + + io.read(buffer, 8); + const uint64_t offset = getULongLong(buffer, byteOrder); + + result = Header(byteOrder, magic, size, offset); + } + + return result; + } + class BigTiffImage: public Image { public: - BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io) {} + BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io) + { + + } virtual ~BigTiffImage() {} @@ -29,6 +103,11 @@ namespace Exiv2 { } + + void printStructure(std::ostream& os, PrintStructureOption option, int depth) + { + + } }; } @@ -40,27 +119,9 @@ namespace Exiv2 bool isBigTiffType(BasicIo& io, bool) { - byte header[2]; - io.read(header, 2); + const Header header = readHeader(io); - ByteOrder byteOrder = invalidByteOrder; - if (header[0] == 'I' && header[1] == 'I') - byteOrder = littleEndian; - else if (header[0] == 'M' && header[1] == 'M') - byteOrder = bigEndian; - - bool isBigTiff = false; - if (byteOrder != invalidByteOrder) - { - byte version[2]; - io.read(version, 2); - - const uint16_t magic = getUShort(version, byteOrder); - - isBigTiff = magic == 0x2A || magic == 0x2B; - } - - return isBigTiff; + return header.isValid(); } } From ca1929d88a152b4019144942dc39dbb5abdafb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 15 Sep 2017 21:41:59 +0200 Subject: [PATCH 46/71] adding 64bit types --- include/exiv2/types.hpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/exiv2/types.hpp b/include/exiv2/types.hpp index 70f3e453..9cd2fef5 100644 --- a/include/exiv2/types.hpp +++ b/include/exiv2/types.hpp @@ -137,6 +137,9 @@ namespace Exiv2 { tiffFloat =11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. tiffDouble =12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. tiffIfd =13, //!< TIFF IFD type, 32-bit (4-byte) unsigned integer. + unsignedLongLong =16, //!< Exif LONG LONG type, 64-bit (8-byte) unsigned integer. + signedLongLong =17, //!< Exif LONG LONG type, 64-bit (8-byte) signed integer. + tiffIfd8 =18, //!< TIFF IFD type, 64-bit (8-byte) unsigned integer. string =0x10000, //!< IPTC string type. date =0x10001, //!< IPTC date type. time =0x10002, //!< IPTC time type. From c008ad240399d8a103e8c1d746fcfe97804446e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 15 Sep 2017 21:42:22 +0200 Subject: [PATCH 47/71] making tag related functions private --- include/exiv2/image.hpp | 10 +++++++--- src/image.cpp | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index 73edb813..47e31f14 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -345,6 +345,7 @@ namespace Exiv2 { bool isStringType(uint16_t type); bool isShortType(uint16_t type); bool isLongType(uint16_t type); + bool isLongLongType(uint16_t type); bool isRationalType(uint16_t type); bool is2ByteType(uint16_t type); bool is4ByteType(uint16_t type); @@ -493,6 +494,12 @@ namespace Exiv2 { int pixelHeight_; //!< image pixel height NativePreviewList nativePreviews_; //!< list of native previews + //! Return tag name for given tag id. + const std::string& tagName(uint16_t tag); + + //! Return tag type for given tag id. + const char* typeName(uint16_t tag) const; + private: //! @name NOT implemented //@{ @@ -502,9 +509,6 @@ namespace Exiv2 { Image& operator=(const Image& rhs); //@} - //! Return tag name for given tag id. - const std::string& tagName(uint16_t tag); - // DATA int imageType_; //!< Image type uint16_t supportedMetadata_; //!< Bitmap with all supported metadata types diff --git a/src/image.cpp b/src/image.cpp index d28e897c..4de3503a 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -197,6 +197,10 @@ namespace Exiv2 { || type == Exiv2::signedLong ; } + bool Image::isLongLongType(uint16_t type) { + return type == Exiv2::unsignedLongLong + || type == Exiv2::signedLongLong; + } bool Image::isRationalType(uint16_t type) { return type == Exiv2::unsignedRational || type == Exiv2::signedRational @@ -277,7 +281,7 @@ namespace Exiv2 { return Image::byteSwap(v,bSwap); } - static const char* typeName(uint16_t tag) + const char* Image::typeName(uint16_t tag) const { //! List of TIFF image tags const char* result = NULL; From 5fa328737a7d85e375226945e8dce78480e9b923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 15 Sep 2017 21:42:39 +0200 Subject: [PATCH 48/71] moving implementation from stand alone parser --- src/bigtiffimage.cpp | 280 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 278 insertions(+), 2 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index c36acb5a..b8358fc0 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -3,6 +3,10 @@ #include +#include "exif.hpp" +#include "image_int.hpp" + + namespace Exiv2 { @@ -28,6 +32,24 @@ namespace Exiv2 } }; + struct field_t + { + uint16_t tagID; + uint16_t tagType; + uint64_t count; + uint64_t data; + } __attribute__((packed)); + + std::string indent(int32_t d) + { + std::string result ; + if ( d > 0 ) + while ( d--) + result += " "; + + return result; + } + Header readHeader(BasicIo& io) { byte header[2]; @@ -78,12 +100,69 @@ namespace Exiv2 return result; } + template + struct TypeForSize {}; + + template<> + struct TypeForSize<16> + { + typedef int16_t Type; + }; + + template<> + struct TypeForSize<32> + { + typedef int32_t Type; + }; + + template<> + struct TypeForSize<64> + { + typedef int64_t Type; + }; + + template + typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) + { + typename TypeForSize::Type result = 0; + if (size == 16) + result = __builtin_bswap16(v); + else if (size == 32) + result = __builtin_bswap32(v); + else if (size == 64) + result = __builtin_bswap64(v); + + return result; + } + + template + typename TypeForSize::Type conditional_byte_swap(const typename TypeForSize::Type& v, bool swap) + { + const typename TypeForSize::Type result = swap? byte_swap(v): v; + + return result; + } + + + template + typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, uint64_t offset, bool swap) + { + typedef typename TypeForSize::Type Type; + + const uint8_t* bytes_buf = static_cast(buf); + const Type* value = reinterpret_cast(&bytes_buf[offset]); + + return conditional_byte_swap(*value, swap); + } + class BigTiffImage: public Image { public: - BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io) + BigTiffImage(BasicIo::AutoPtr io): + Image(ImageType::bigtiff, mdExif, io), + header_(readHeader(Image::io())) { - + assert(header_.isValid()); } virtual ~BigTiffImage() {} @@ -106,7 +185,204 @@ namespace Exiv2 void printStructure(std::ostream& os, PrintStructureOption option, int depth) { + const bool bSwap = (isLittleEndianPlatform() && header_.byteOrder == bigEndian) + || (isBigEndianPlatform() && header_.byteOrder == littleEndian); + printIFD(Image::io(), os, option, header_.dir_offset, bSwap, depth); + } + + private: + const Header header_; + + void printIFD(BasicIo& io, std::ostream& out, PrintStructureOption option, uint64_t offset, bool bSwap, int depth) + { + depth++; + bool bFirst = true; + + // buffer + bool bPrint = true; + + do + { + // Read top of directory + io.seek(offset, BasicIo::beg); + + uint64_t entries_raw; + io.read(reinterpret_cast(&entries_raw), 8); + + const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); + + const bool tooBig = entries > 500; + + if ( bFirst && bPrint ) + { + out << indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE ") << io.path() << std::endl; + if (tooBig) + out << indent(depth) << "entries = " << entries << std::endl; + } + + if (tooBig) + break; + + // Read the dictionary + for ( uint64_t i = 0; i < entries; i ++ ) + { + if ( bFirst && bPrint ) + out << indent(depth) + << " address | tag | " + << " type | count | offset | value\n"; + + bFirst = false; + field_t field; + + io.read(reinterpret_cast(&field), sizeof(field_t)); + const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); + const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); + const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); + const uint64_t data = conditional_byte_swap<64>(field.data, bSwap); + + std::string sp = "" ; // output spacer + + //prepare to print the value + // TODO: figure out what's going on with kount + const uint64_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays + : count > 5 ? 5 + : count + ; + const uint32_t pad = isStringType(type) ? 1 : 0; + const uint32_t size = isStringType(type) ? 1 + : is2ByteType(type) ? 2 + : is4ByteType(type) ? 4 + : is8ByteType(type) ? 8 + : 1; + + DataBuf buf(size * count + pad); + + // big data? Use 'data' as pointer to real data + if ( count*size > 8 ) // read into buffer + { + size_t restore = io.tell(); // save + io.seek(data, BasicIo::beg); // position + io.read(buf.pData_, count * size); // read + io.seek(restore, BasicIo::beg); // restore + } + else // use 'data' as data :) + std::memcpy(buf.pData_, &data, count * size); // copy data + + if ( bPrint ) + { + const uint64_t address = offset + 2 + i * sizeof(field_t) ; + out << indent(depth) + << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", + address, tag, tagName(tag), typeName(type), count, offset); + + if ( isShortType(type) ) + { + for ( size_t k = 0 ; k < kount ; k++ ) + { + out << sp << conditional_byte_swap_4_array<16>(buf.pData_, k*size, bSwap); + sp = " "; + } + } + else if ( isLongType(type) ) + { + for ( size_t k = 0 ; k < kount ; k++ ) + { + out << sp << conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); + sp = " "; + } + } + else if ( isLongLongType(type) ) + { + for ( size_t k = 0 ; k < kount ; k++ ) + { + out << sp << conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap); + sp = " "; + } + } + else if ( isRationalType(type) ) + { + for ( size_t k = 0 ; k < kount ; k++ ) + { + uint32_t a = conditional_byte_swap_4_array<32>(buf.pData_, k*size+0, bSwap); + uint32_t b = conditional_byte_swap_4_array<32>(buf.pData_, k*size+4, bSwap); + out << sp << a << "/" << b; + sp = " "; + } + } + else if ( isStringType(type) ) + out << sp << Internal::binaryToString(buf, kount); + + sp = kount == count ? "" : " ..."; + out << sp << std::endl; + + if ( option == kpsRecursive && + (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd || type == tiffIfd8) ) + { + for ( size_t k = 0 ; k < count ; k++ ) + { + const size_t restore = io.tell(); + const uint64_t offset = type == tiffIfd8? + conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap): + conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); + + std::cerr << "tag = " << Internal::stringFormat("%#x",tag) << std::endl; + printIFD(io, out, option, offset, bSwap, depth); + io.seek(restore, BasicIo::beg); + } + } + else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) + { + size_t restore = io.tell(); // save + io.seek(offset, BasicIo::beg); // position + byte* bytes=new byte[count] ; // allocate memory + io.read(bytes,count) ; // read + io.seek(restore, BasicIo::beg); // restore + IptcData::printStructure(out,bytes,count,depth); + delete[] bytes; // free + } + else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) + { + size_t restore = io.tell(); // save + + uint32_t jump= 10 ; + byte bytes[20] ; + const char* chars = (const char*) &bytes[0] ; + io.seek(offset, BasicIo::beg); // position + io.read(bytes,jump ) ; // read + bytes[jump]=0 ; + if ( ::strcmp("Nikon",chars) == 0 ) + { + // tag is an embedded tiff + byte* bytes=new byte[count-jump] ; // allocate memory + io.read(bytes,count-jump) ; // read + MemIo memIo(bytes,count-jump) ; // create a file + std::cerr << "Nikon makernote" << std::endl; + // printTiffStructure(memIo,out,option,depth); TODO: fix it + delete[] bytes ; // free + } + else + { + // tag is an IFD + io.seek(0, BasicIo::beg); // position + std::cerr << "makernote" << std::endl; + //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me + } + + io.seek(restore,BasicIo::beg); // restore + } + } + } + uint64_t next_dir_offset_raw; + io.read(reinterpret_cast(&next_dir_offset_raw), 8); + offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); + out.flush(); + } while (offset) ; + + if ( bPrint ) + out << indent(depth) << "END " << io.path() << std::endl; + + depth--; } }; } From 5ab1a0809df8128e522a449f7e1a9ac90e4e468b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 15 Sep 2017 21:53:41 +0200 Subject: [PATCH 49/71] adopt to style --- src/image.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/image.cpp b/src/image.cpp index 4de3503a..c8259708 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -199,7 +199,8 @@ namespace Exiv2 { } bool Image::isLongLongType(uint16_t type) { return type == Exiv2::unsignedLongLong - || type == Exiv2::signedLongLong; + || type == Exiv2::signedLongLong + ; } bool Image::isRationalType(uint16_t type) { return type == Exiv2::unsignedRational From cc8c4706208c50b160e938a80f419b94d990ad91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Fri, 15 Sep 2017 21:54:04 +0200 Subject: [PATCH 50/71] fix header read + tag name dump --- src/bigtiffimage.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index b8358fc0..709bb34d 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -160,8 +160,11 @@ namespace Exiv2 public: BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io), - header_(readHeader(Image::io())) + header_() { + Image::io().seek(0, BasicIo::beg); + header_ = readHeader(Image::io()); + assert(header_.isValid()); } @@ -192,7 +195,7 @@ namespace Exiv2 } private: - const Header header_; + Header header_; void printIFD(BasicIo& io, std::ostream& out, PrintStructureOption option, uint64_t offset, bool bSwap, int depth) { @@ -274,7 +277,7 @@ namespace Exiv2 const uint64_t address = offset + 2 + i * sizeof(field_t) ; out << indent(depth) << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", - address, tag, tagName(tag), typeName(type), count, offset); + address, tag, tagName(tag).c_str(), typeName(type), count, offset); if ( isShortType(type) ) { From ff21b5a9626546cb09a14a4ca1122d0bb8c6216c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:17:03 +0200 Subject: [PATCH 51/71] restore position if necessary --- src/bigtiffimage.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 709bb34d..76336638 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -396,11 +396,16 @@ namespace Exiv2 return Image::AutoPtr(new BigTiffImage(io)); } - bool isBigTiffType(BasicIo& io, bool) + bool isBigTiffType(BasicIo& io, bool advance) { + const long pos = io.tell(); const Header header = readHeader(io); + const bool valid = header.isValid(); - return header.isValid(); + if (valid == false || advance == false) + io.seek(pos, BasicIo::beg); + + return valid; } } From cb3857c675bc7fa47cda34721568f390fcc386c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:17:47 +0200 Subject: [PATCH 52/71] removing useles code --- src/bigtiffimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 76336638..d2d0c7c1 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -162,7 +162,6 @@ namespace Exiv2 Image(ImageType::bigtiff, mdExif, io), header_() { - Image::io().seek(0, BasicIo::beg); header_ = readHeader(Image::io()); assert(header_.isValid()); @@ -396,6 +395,7 @@ namespace Exiv2 return Image::AutoPtr(new BigTiffImage(io)); } + bool isBigTiffType(BasicIo& io, bool advance) { const long pos = io.tell(); From 7e291ef22602ee4659f4b1f84903803b1126349c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:21:53 +0200 Subject: [PATCH 53/71] Encapsulating Header's members --- src/bigtiffimage.cpp | 58 ++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index d2d0c7c1..40189948 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -14,22 +14,50 @@ namespace Exiv2 { struct Header { - ByteOrder byteOrder; - int version; // 42 or 43 - regular tiff or big tiff - int data_size; // 4 or 8 - uint64_t dir_offset; - - bool isValid() const { return version != -1; } - - Header(): byteOrder(invalidByteOrder), version(-1), data_size(0), dir_offset(0) {} + Header(): byteOrder_(invalidByteOrder), version_(-1), data_size_(0), dir_offset_(0) {} Header(const ByteOrder& order, int v, int size, uint64_t offset): - byteOrder(order), - version(v), - data_size(size), - dir_offset(offset) + byteOrder_(order), + version_(v), + data_size_(size), + dir_offset_(offset) { } + + bool isValid() const + { + return version_ != -1; + } + + ByteOrder byteOrder() const + { + assert(isValid()); + return byteOrder_; + } + + int version() const + { + assert(isValid()); + return version_; + } + + int dataSize() const + { + assert(isValid()); + return data_size_; + } + + uint64_t dirOffset() const + { + assert(isValid()); + return dir_offset_; + } + + private: + ByteOrder byteOrder_; + int version_; // 42 or 43 - regular tiff or big tiff + int data_size_; // 4 or 8 + uint64_t dir_offset_; }; struct field_t @@ -187,10 +215,10 @@ namespace Exiv2 void printStructure(std::ostream& os, PrintStructureOption option, int depth) { - const bool bSwap = (isLittleEndianPlatform() && header_.byteOrder == bigEndian) - || (isBigEndianPlatform() && header_.byteOrder == littleEndian); + const bool bSwap = (isLittleEndianPlatform() && header_.byteOrder() == bigEndian) + || (isBigEndianPlatform() && header_.byteOrder() == littleEndian); - printIFD(Image::io(), os, option, header_.dir_offset, bSwap, depth); + printIFD(Image::io(), os, option, header_.dirOffset(), bSwap, depth); } private: From 65722a002094a0116b80ee78a3335ceb4f0ae8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:29:52 +0200 Subject: [PATCH 54/71] dropping bSwap parameter Member is better. --- src/bigtiffimage.cpp | 45 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 40189948..7419733e 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -188,11 +188,14 @@ namespace Exiv2 public: BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io), - header_() + header_(), + doSwap_(false) { header_ = readHeader(Image::io()); - assert(header_.isValid()); + + doSwap_ = (isLittleEndianPlatform() && header_.byteOrder() == bigEndian) + || (isBigEndianPlatform() && header_.byteOrder() == littleEndian); } virtual ~BigTiffImage() {} @@ -215,16 +218,14 @@ namespace Exiv2 void printStructure(std::ostream& os, PrintStructureOption option, int depth) { - const bool bSwap = (isLittleEndianPlatform() && header_.byteOrder() == bigEndian) - || (isBigEndianPlatform() && header_.byteOrder() == littleEndian); - - printIFD(Image::io(), os, option, header_.dirOffset(), bSwap, depth); + printIFD(Image::io(), os, option, header_.dirOffset(), depth); } private: Header header_; + bool doSwap_; - void printIFD(BasicIo& io, std::ostream& out, PrintStructureOption option, uint64_t offset, bool bSwap, int depth) + void printIFD(BasicIo& io, std::ostream& out, PrintStructureOption option, uint64_t offset, int depth) { depth++; bool bFirst = true; @@ -240,7 +241,7 @@ namespace Exiv2 uint64_t entries_raw; io.read(reinterpret_cast(&entries_raw), 8); - const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); + const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, doSwap_); const bool tooBig = entries > 500; @@ -266,10 +267,10 @@ namespace Exiv2 field_t field; io.read(reinterpret_cast(&field), sizeof(field_t)); - const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); - const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); - const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); - const uint64_t data = conditional_byte_swap<64>(field.data, bSwap); + const uint16_t tag = conditional_byte_swap<16>(field.tagID, doSwap_); + const uint16_t type = conditional_byte_swap<16>(field.tagType, doSwap_); + const uint64_t count = conditional_byte_swap<64>(field.count, doSwap_); + const uint64_t data = conditional_byte_swap<64>(field.data, doSwap_); std::string sp = "" ; // output spacer @@ -310,7 +311,7 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<16>(buf.pData_, k*size, bSwap); + out << sp << conditional_byte_swap_4_array<16>(buf.pData_, k*size, doSwap_); sp = " "; } } @@ -318,7 +319,7 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); + out << sp << conditional_byte_swap_4_array<32>(buf.pData_, k*size, doSwap_); sp = " "; } } @@ -326,7 +327,7 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap); + out << sp << conditional_byte_swap_4_array<64>(buf.pData_, k*size, doSwap_); sp = " "; } } @@ -334,8 +335,8 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = conditional_byte_swap_4_array<32>(buf.pData_, k*size+0, bSwap); - uint32_t b = conditional_byte_swap_4_array<32>(buf.pData_, k*size+4, bSwap); + uint32_t a = conditional_byte_swap_4_array<32>(buf.pData_, k*size+0, doSwap_); + uint32_t b = conditional_byte_swap_4_array<32>(buf.pData_, k*size+4, doSwap_); out << sp << a << "/" << b; sp = " "; } @@ -353,11 +354,11 @@ namespace Exiv2 { const size_t restore = io.tell(); const uint64_t offset = type == tiffIfd8? - conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap): - conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); + conditional_byte_swap_4_array<64>(buf.pData_, k*size, doSwap_): + conditional_byte_swap_4_array<32>(buf.pData_, k*size, doSwap_); std::cerr << "tag = " << Internal::stringFormat("%#x",tag) << std::endl; - printIFD(io, out, option, offset, bSwap, depth); + printIFD(io, out, option, offset, depth); io.seek(restore, BasicIo::beg); } } @@ -396,7 +397,7 @@ namespace Exiv2 // tag is an IFD io.seek(0, BasicIo::beg); // position std::cerr << "makernote" << std::endl; - //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me + //printIFDStructure(io,out,option,offset,doSwap_,c,depth); // TODO: fix me } io.seek(restore,BasicIo::beg); // restore @@ -405,7 +406,7 @@ namespace Exiv2 } uint64_t next_dir_offset_raw; io.read(reinterpret_cast(&next_dir_offset_raw), 8); - offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); + offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, doSwap_); out.flush(); } while (offset) ; From 3c9817339acb35452f9408f5705ae1f40838b29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:31:22 +0200 Subject: [PATCH 55/71] Dropping BasicIo& io parameter. We already have acces to it via Image class --- src/bigtiffimage.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 7419733e..ceeeb771 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -218,15 +218,17 @@ namespace Exiv2 void printStructure(std::ostream& os, PrintStructureOption option, int depth) { - printIFD(Image::io(), os, option, header_.dirOffset(), depth); + printIFD(os, option, header_.dirOffset(), depth); } private: Header header_; bool doSwap_; - void printIFD(BasicIo& io, std::ostream& out, PrintStructureOption option, uint64_t offset, int depth) + void printIFD(std::ostream& out, PrintStructureOption option, uint64_t offset, int depth) { + BasicIo& io = Image::io(); + depth++; bool bFirst = true; @@ -358,7 +360,7 @@ namespace Exiv2 conditional_byte_swap_4_array<32>(buf.pData_, k*size, doSwap_); std::cerr << "tag = " << Internal::stringFormat("%#x",tag) << std::endl; - printIFD(io, out, option, offset, depth); + printIFD(out, option, offset, depth); io.seek(restore, BasicIo::beg); } } From 972e302cba366b103b8647ceea01017ae78cc716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:32:18 +0200 Subject: [PATCH 56/71] some cleanups --- src/bigtiffimage.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index ceeeb771..f513081d 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -406,11 +406,12 @@ namespace Exiv2 } } } + uint64_t next_dir_offset_raw; io.read(reinterpret_cast(&next_dir_offset_raw), 8); offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, doSwap_); out.flush(); - } while (offset) ; + } while (offset != 0); if ( bPrint ) out << indent(depth) << "END " << io.path() << std::endl; From c6cbf69c49f5382339af494f3e76c32b7d975a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 18:50:21 +0200 Subject: [PATCH 57/71] first attempt to read both - standard and big tiff --- src/bigtiffimage.cpp | 66 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index f513081d..1592ce99 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -14,6 +14,12 @@ namespace Exiv2 { struct Header { + enum Format + { + Tiff, + BigTiff, + }; + Header(): byteOrder_(invalidByteOrder), version_(-1), data_size_(0), dir_offset_(0) {} Header(const ByteOrder& order, int v, int size, uint64_t offset): byteOrder_(order), @@ -41,6 +47,12 @@ namespace Exiv2 return version_; } + Format format() const + { + assert(isValid()); + return version_ == 0x2A? Tiff: BigTiff; + } + int dataSize() const { assert(isValid()); @@ -60,7 +72,15 @@ namespace Exiv2 uint64_t dir_offset_; }; - struct field_t + struct DirEntry4StandardTiff + { + uint16_t tagID; + uint16_t tagType; + uint32_t count; + uint32_t data; + } __attribute__((packed)); + + struct DirEntry4BigTiff { uint16_t tagID; uint16_t tagType; @@ -68,6 +88,12 @@ namespace Exiv2 uint64_t data; } __attribute__((packed)); + union DirEntry + { + DirEntry4StandardTiff standardTiff; + DirEntry4BigTiff bigTiff; + }; + std::string indent(int32_t d) { std::string result ; @@ -189,6 +215,7 @@ namespace Exiv2 BigTiffImage(BasicIo::AutoPtr io): Image(ImageType::bigtiff, mdExif, io), header_(), + dataSize_(0), doSwap_(false) { header_ = readHeader(Image::io()); @@ -196,6 +223,8 @@ namespace Exiv2 doSwap_ = (isLittleEndianPlatform() && header_.byteOrder() == bigEndian) || (isBigEndianPlatform() && header_.byteOrder() == littleEndian); + + dataSize_ = header_.format() == Header::Tiff? 4 : 8; } virtual ~BigTiffImage() {} @@ -223,6 +252,7 @@ namespace Exiv2 private: Header header_; + int dataSize_; bool doSwap_; void printIFD(std::ostream& out, PrintStructureOption option, uint64_t offset, int depth) @@ -243,7 +273,9 @@ namespace Exiv2 uint64_t entries_raw; io.read(reinterpret_cast(&entries_raw), 8); - const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, doSwap_); + const uint64_t entries = header_.format() == Header::Tiff? + conditional_byte_swap_4_array<16>(&entries_raw, 0, doSwap_): + conditional_byte_swap_4_array<64>(&entries_raw, 0, doSwap_); const bool tooBig = entries > 500; @@ -266,13 +298,27 @@ namespace Exiv2 << " type | count | offset | value\n"; bFirst = false; - field_t field; + DirEntry entry; + const std::size_t entrySize = header_.format() == Header::Tiff? + sizeof(DirEntry4StandardTiff): + sizeof(DirEntry4BigTiff); - io.read(reinterpret_cast(&field), sizeof(field_t)); - const uint16_t tag = conditional_byte_swap<16>(field.tagID, doSwap_); - const uint16_t type = conditional_byte_swap<16>(field.tagType, doSwap_); - const uint64_t count = conditional_byte_swap<64>(field.count, doSwap_); - const uint64_t data = conditional_byte_swap<64>(field.data, doSwap_); + io.read(reinterpret_cast(&entry), entrySize); + const uint16_t tag = header_.format() == Header::Tiff? + conditional_byte_swap<16>(entry.standardTiff.tagID, doSwap_): + conditional_byte_swap<16>(entry.bigTiff.tagID, doSwap_); + + const uint16_t type = header_.format() == Header::Tiff? + conditional_byte_swap<16>(entry.standardTiff.tagType, doSwap_): + conditional_byte_swap<16>(entry.bigTiff.tagType, doSwap_); + + const uint64_t count = header_.format() == Header::Tiff? + conditional_byte_swap<32>(entry.standardTiff.count, doSwap_): + conditional_byte_swap<64>(entry.bigTiff.count, doSwap_); + + const uint64_t data = header_.format() == Header::Tiff? + conditional_byte_swap<32>(entry.standardTiff.data, doSwap_): + conditional_byte_swap<64>(entry.bigTiff.data, doSwap_); std::string sp = "" ; // output spacer @@ -304,7 +350,7 @@ namespace Exiv2 if ( bPrint ) { - const uint64_t address = offset + 2 + i * sizeof(field_t) ; + const uint64_t address = offset + 2 + i * entrySize; out << indent(depth) << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", address, tag, tagName(tag).c_str(), typeName(type), count, offset); @@ -408,7 +454,7 @@ namespace Exiv2 } uint64_t next_dir_offset_raw; - io.read(reinterpret_cast(&next_dir_offset_raw), 8); + io.read(reinterpret_cast(&next_dir_offset_raw), dataSize_); offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, doSwap_); out.flush(); } while (offset != 0); From 1a1dc3afd45fdacbf2888635983ad5daee0fcb8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Sun, 17 Sep 2017 21:03:12 +0200 Subject: [PATCH 58/71] simplifying code --- src/bigtiffimage.cpp | 72 +++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 1592ce99..46528665 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -270,13 +270,7 @@ namespace Exiv2 // Read top of directory io.seek(offset, BasicIo::beg); - uint64_t entries_raw; - io.read(reinterpret_cast(&entries_raw), 8); - - const uint64_t entries = header_.format() == Header::Tiff? - conditional_byte_swap_4_array<16>(&entries_raw, 0, doSwap_): - conditional_byte_swap_4_array<64>(&entries_raw, 0, doSwap_); - + const uint64_t entries = readData(header_.format() == Header::Tiff? 2: 8); const bool tooBig = entries > 500; if ( bFirst && bPrint ) @@ -298,27 +292,11 @@ namespace Exiv2 << " type | count | offset | value\n"; bFirst = false; - DirEntry entry; - const std::size_t entrySize = header_.format() == Header::Tiff? - sizeof(DirEntry4StandardTiff): - sizeof(DirEntry4BigTiff); - io.read(reinterpret_cast(&entry), entrySize); - const uint16_t tag = header_.format() == Header::Tiff? - conditional_byte_swap<16>(entry.standardTiff.tagID, doSwap_): - conditional_byte_swap<16>(entry.bigTiff.tagID, doSwap_); - - const uint16_t type = header_.format() == Header::Tiff? - conditional_byte_swap<16>(entry.standardTiff.tagType, doSwap_): - conditional_byte_swap<16>(entry.bigTiff.tagType, doSwap_); - - const uint64_t count = header_.format() == Header::Tiff? - conditional_byte_swap<32>(entry.standardTiff.count, doSwap_): - conditional_byte_swap<64>(entry.bigTiff.count, doSwap_); - - const uint64_t data = header_.format() == Header::Tiff? - conditional_byte_swap<32>(entry.standardTiff.data, doSwap_): - conditional_byte_swap<64>(entry.bigTiff.data, doSwap_); + const uint16_t tag = readData(2); + const uint16_t type = readData(2); + const uint64_t count = readData(dataSize_); + const DataBuf data = io.read(dataSize_); // Read data as raw value. what should be done about it will be decided depending on type std::string sp = "" ; // output spacer @@ -330,26 +308,31 @@ namespace Exiv2 ; const uint32_t pad = isStringType(type) ? 1 : 0; const uint32_t size = isStringType(type) ? 1 - : is2ByteType(type) ? 2 - : is4ByteType(type) ? 4 - : is8ByteType(type) ? 8 - : 1; + : is2ByteType(type) ? 2 + : is4ByteType(type) ? 4 + : is8ByteType(type) ? 8 + : 1; DataBuf buf(size * count + pad); // big data? Use 'data' as pointer to real data if ( count*size > 8 ) // read into buffer { + const uint64_t data_pointer = header_.format() == Header::Tiff? + conditional_byte_swap_4_array<32>(data.pData_, 0, doSwap_): + conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); + size_t restore = io.tell(); // save - io.seek(data, BasicIo::beg); // position + io.seek(data_pointer, BasicIo::beg); // position io.read(buf.pData_, count * size); // read - io.seek(restore, BasicIo::beg); // restore + io.seek(restore, BasicIo::beg); // restore } else // use 'data' as data :) - std::memcpy(buf.pData_, &data, count * size); // copy data + std::memcpy(buf.pData_, data.pData_, count * size); // copy data if ( bPrint ) { + const int entrySize = header_.format() == Header::Tiff? 12: 20; const uint64_t address = offset + 2 + i * entrySize; out << indent(depth) << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", @@ -464,6 +447,27 @@ namespace Exiv2 depth--; } + + uint64_t readData(int size) const + { + uint64_t data = 0; + + const int read = Image::io().read(reinterpret_cast(&data), size); + assert(read == size); + + if (size == 1) + {} + else if (size == 2) + data = conditional_byte_swap<16>(data, doSwap_); + else if (size == 4) + data = conditional_byte_swap<32>(data, doSwap_); + else if (size == 8) + data = conditional_byte_swap<64>(data, doSwap_); + else + assert(!"unexpected size"); + + return data; + } }; } From 8b07982bf2bf3d8fd7b265b3a108666bfe5551d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 21:56:40 +0200 Subject: [PATCH 59/71] variable names cleanup --- src/bigtiffimage.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 46528665..e73a6b82 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -255,7 +255,7 @@ namespace Exiv2 int dataSize_; bool doSwap_; - void printIFD(std::ostream& out, PrintStructureOption option, uint64_t offset, int depth) + void printIFD(std::ostream& out, PrintStructureOption option, uint64_t dir_offset, int depth) { BasicIo& io = Image::io(); @@ -268,7 +268,7 @@ namespace Exiv2 do { // Read top of directory - io.seek(offset, BasicIo::beg); + io.seek(dir_offset, BasicIo::beg); const uint64_t entries = readData(header_.format() == Header::Tiff? 2: 8); const bool tooBig = entries > 500; @@ -318,12 +318,12 @@ namespace Exiv2 // big data? Use 'data' as pointer to real data if ( count*size > 8 ) // read into buffer { - const uint64_t data_pointer = header_.format() == Header::Tiff? + const uint64_t offset = header_.format() == Header::Tiff? conditional_byte_swap_4_array<32>(data.pData_, 0, doSwap_): conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); size_t restore = io.tell(); // save - io.seek(data_pointer, BasicIo::beg); // position + io.seek(offset, BasicIo::beg); // position io.read(buf.pData_, count * size); // read io.seek(restore, BasicIo::beg); // restore } @@ -333,10 +333,10 @@ namespace Exiv2 if ( bPrint ) { const int entrySize = header_.format() == Header::Tiff? 12: 20; - const uint64_t address = offset + 2 + i * entrySize; + const uint64_t address = dir_offset + 2 + i * entrySize; out << indent(depth) << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", - address, tag, tagName(tag).c_str(), typeName(type), count, offset); + address, tag, tagName(tag).c_str(), typeName(type), count, dir_offset); if ( isShortType(type) ) { @@ -396,7 +396,7 @@ namespace Exiv2 else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { size_t restore = io.tell(); // save - io.seek(offset, BasicIo::beg); // position + io.seek(dir_offset, BasicIo::beg); // position byte* bytes=new byte[count] ; // allocate memory io.read(bytes,count) ; // read io.seek(restore, BasicIo::beg); // restore @@ -410,7 +410,7 @@ namespace Exiv2 uint32_t jump= 10 ; byte bytes[20] ; const char* chars = (const char*) &bytes[0] ; - io.seek(offset, BasicIo::beg); // position + io.seek(dir_offset, BasicIo::beg); // position io.read(bytes,jump ) ; // read bytes[jump]=0 ; if ( ::strcmp("Nikon",chars) == 0 ) @@ -438,9 +438,9 @@ namespace Exiv2 uint64_t next_dir_offset_raw; io.read(reinterpret_cast(&next_dir_offset_raw), dataSize_); - offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, doSwap_); + dir_offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, doSwap_); out.flush(); - } while (offset != 0); + } while (dir_offset != 0); if ( bPrint ) out << indent(depth) << "END " << io.path() << std::endl; From 874daede53366ed48ddaab9a749823ca291d2103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 21:58:21 +0200 Subject: [PATCH 60/71] fixing broken print for 'offset' column --- src/bigtiffimage.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index e73a6b82..29c4927b 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -315,13 +315,13 @@ namespace Exiv2 DataBuf buf(size * count + pad); - // big data? Use 'data' as pointer to real data - if ( count*size > 8 ) // read into buffer - { - const uint64_t offset = header_.format() == Header::Tiff? + const uint64_t offset = header_.format() == Header::Tiff? conditional_byte_swap_4_array<32>(data.pData_, 0, doSwap_): conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); + // big data? Use 'data' as pointer to real data + if ( count*size > 8 ) // read into buffer + { size_t restore = io.tell(); // save io.seek(offset, BasicIo::beg); // position io.read(buf.pData_, count * size); // read @@ -336,7 +336,7 @@ namespace Exiv2 const uint64_t address = dir_offset + 2 + i * entrySize; out << indent(depth) << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", - address, tag, tagName(tag).c_str(), typeName(type), count, dir_offset); + address, tag, tagName(tag).c_str(), typeName(type), count, offset); if ( isShortType(type) ) { From 81aa8828e09e563c53214aca15ef2cac13763897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 22:01:29 +0200 Subject: [PATCH 61/71] applying dff941ad7f203cacbb6a8ad0a4e86e2642d14d9f --- src/bigtiffimage.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 29c4927b..73ff2540 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -320,7 +320,9 @@ namespace Exiv2 conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); // big data? Use 'data' as pointer to real data - if ( count*size > 8 ) // read into buffer + const bool usePointer = count*size > 8; + + if ( usePointer ) // read into buffer { size_t restore = io.tell(); // save io.seek(offset, BasicIo::beg); // position @@ -334,9 +336,13 @@ namespace Exiv2 { const int entrySize = header_.format() == Header::Tiff? 12: 20; const uint64_t address = dir_offset + 2 + i * entrySize; + const std::string offsetString = usePointer? + Internal::stringFormat("%10u", offset): + ""; + out << indent(depth) - << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", - address, tag, tagName(tag).c_str(), typeName(type), count, offset); + << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10s | ", + address, tag, tagName(tag).c_str(), typeName(type), count, offsetString.c_str()); if ( isShortType(type) ) { From d460bbdb3f9502f6ddf0dd7f2bcc4f91a5f8d188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 22:05:32 +0200 Subject: [PATCH 62/71] fix for standard tiff case --- src/bigtiffimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 73ff2540..1f71e37f 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -320,7 +320,7 @@ namespace Exiv2 conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); // big data? Use 'data' as pointer to real data - const bool usePointer = count*size > 8; + const bool usePointer = count*size > dataSize_; if ( usePointer ) // read into buffer { From f8ac7a5dc32c211018bb6f9028047712217948d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 22:06:13 +0200 Subject: [PATCH 63/71] renaming Tiff to StandardTiff --- src/bigtiffimage.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 1f71e37f..4c522b57 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -16,7 +16,7 @@ namespace Exiv2 { enum Format { - Tiff, + StandardTiff, BigTiff, }; @@ -50,7 +50,7 @@ namespace Exiv2 Format format() const { assert(isValid()); - return version_ == 0x2A? Tiff: BigTiff; + return version_ == 0x2A? StandardTiff: BigTiff; } int dataSize() const @@ -224,7 +224,7 @@ namespace Exiv2 doSwap_ = (isLittleEndianPlatform() && header_.byteOrder() == bigEndian) || (isBigEndianPlatform() && header_.byteOrder() == littleEndian); - dataSize_ = header_.format() == Header::Tiff? 4 : 8; + dataSize_ = header_.format() == Header::StandardTiff? 4 : 8; } virtual ~BigTiffImage() {} @@ -270,7 +270,7 @@ namespace Exiv2 // Read top of directory io.seek(dir_offset, BasicIo::beg); - const uint64_t entries = readData(header_.format() == Header::Tiff? 2: 8); + const uint64_t entries = readData(header_.format() == Header::StandardTiff? 2: 8); const bool tooBig = entries > 500; if ( bFirst && bPrint ) @@ -315,7 +315,7 @@ namespace Exiv2 DataBuf buf(size * count + pad); - const uint64_t offset = header_.format() == Header::Tiff? + const uint64_t offset = header_.format() == Header::StandardTiff? conditional_byte_swap_4_array<32>(data.pData_, 0, doSwap_): conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); @@ -334,7 +334,7 @@ namespace Exiv2 if ( bPrint ) { - const int entrySize = header_.format() == Header::Tiff? 12: 20; + const int entrySize = header_.format() == Header::StandardTiff? 12: 20; const uint64_t address = dir_offset + 2 + i * entrySize; const std::string offsetString = usePointer? Internal::stringFormat("%10u", offset): From 50ecf672b5570a7d880f8426299b52951a5607df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 22:08:15 +0200 Subject: [PATCH 64/71] using Internal::indent() --- src/bigtiffimage.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 4c522b57..71a72fbb 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -94,16 +94,6 @@ namespace Exiv2 DirEntry4BigTiff bigTiff; }; - std::string indent(int32_t d) - { - std::string result ; - if ( d > 0 ) - while ( d--) - result += " "; - - return result; - } - Header readHeader(BasicIo& io) { byte header[2]; @@ -275,9 +265,9 @@ namespace Exiv2 if ( bFirst && bPrint ) { - out << indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE ") << io.path() << std::endl; + out << Internal::indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE ") << io.path() << std::endl; if (tooBig) - out << indent(depth) << "entries = " << entries << std::endl; + out << Internal::indent(depth) << "entries = " << entries << std::endl; } if (tooBig) @@ -287,7 +277,7 @@ namespace Exiv2 for ( uint64_t i = 0; i < entries; i ++ ) { if ( bFirst && bPrint ) - out << indent(depth) + out << Internal::indent(depth) << " address | tag | " << " type | count | offset | value\n"; @@ -340,7 +330,7 @@ namespace Exiv2 Internal::stringFormat("%10u", offset): ""; - out << indent(depth) + out << Internal::indent(depth) << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10s | ", address, tag, tagName(tag).c_str(), typeName(type), count, offsetString.c_str()); @@ -449,7 +439,7 @@ namespace Exiv2 } while (dir_offset != 0); if ( bPrint ) - out << indent(depth) << "END " << io.path() << std::endl; + out << Internal::indent(depth) << "END " << io.path() << std::endl; depth--; } From f96d84ba8cb23b916c51eb7edd7518b49f4aa7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Tue, 19 Sep 2017 22:08:40 +0200 Subject: [PATCH 65/71] dropping dead code --- src/bigtiffimage.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 71a72fbb..48bc84f0 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -72,28 +72,6 @@ namespace Exiv2 uint64_t dir_offset_; }; - struct DirEntry4StandardTiff - { - uint16_t tagID; - uint16_t tagType; - uint32_t count; - uint32_t data; - } __attribute__((packed)); - - struct DirEntry4BigTiff - { - uint16_t tagID; - uint16_t tagType; - uint64_t count; - uint64_t data; - } __attribute__((packed)); - - union DirEntry - { - DirEntry4StandardTiff standardTiff; - DirEntry4BigTiff bigTiff; - }; - Header readHeader(BasicIo& io) { byte header[2]; From b6e79357de3cd436a017ba29938f8526d951279a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 20 Sep 2017 21:23:35 +0200 Subject: [PATCH 66/71] Adding 8-byte swap functions + consts --- include/exiv2/image.hpp | 10 ++++++---- src/image.cpp | 31 +++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp index 47e31f14..1d7c4c25 100644 --- a/include/exiv2/image.hpp +++ b/include/exiv2/image.hpp @@ -353,10 +353,12 @@ namespace Exiv2 { bool isPrintXMP(uint16_t type, Exiv2::PrintStructureOption option); bool isPrintICC(uint16_t type, Exiv2::PrintStructureOption option); - uint32_t byteSwap(uint32_t value,bool bSwap); - uint16_t byteSwap(uint16_t value,bool bSwap); - uint16_t byteSwap2(DataBuf& buf,size_t offset,bool bSwap); - uint32_t byteSwap4(DataBuf& buf,size_t offset,bool bSwap); + uint64_t byteSwap(uint64_t value,bool bSwap) const; + uint32_t byteSwap(uint32_t value,bool bSwap) const; + uint16_t byteSwap(uint16_t value,bool bSwap) const; + uint16_t byteSwap2(const DataBuf& buf,size_t offset,bool bSwap) const; + uint32_t byteSwap4(const DataBuf& buf,size_t offset,bool bSwap) const; + uint64_t byteSwap8(const DataBuf& buf,size_t offset,bool bSwap) const; //@} diff --git a/src/image.cpp b/src/image.cpp index c8259708..ea78911b 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -244,7 +244,19 @@ namespace Exiv2 { } bool Image::isLittleEndianPlatform() { return !isBigEndianPlatform(); } - uint32_t Image::byteSwap(uint32_t value,bool bSwap) + uint64_t Image::byteSwap(uint64_t value,bool bSwap) const + { + uint64_t result = 0; + byte* source_value = reinterpret_cast(&value); + byte* destination_value = reinterpret_cast(&result); + + for (int i = 0; i < 8; i++) + destination_value[i] = source_value[8 - i - 1]; + + return bSwap ? result : value; + } + + uint32_t Image::byteSwap(uint32_t value,bool bSwap) const { uint32_t result = 0; result |= (value & 0x000000FF) << 24; @@ -254,7 +266,7 @@ namespace Exiv2 { return bSwap ? result : value; } - uint16_t Image::byteSwap(uint16_t value,bool bSwap) + uint16_t Image::byteSwap(uint16_t value,bool bSwap) const { uint16_t result = 0; result |= (value & 0x00FF) << 8; @@ -262,7 +274,7 @@ namespace Exiv2 { return bSwap ? result : value; } - uint16_t Image::byteSwap2(DataBuf& buf,size_t offset,bool bSwap) + uint16_t Image::byteSwap2(const DataBuf& buf,size_t offset,bool bSwap) const { uint16_t v; char* p = (char*) &v; @@ -271,7 +283,7 @@ namespace Exiv2 { return Image::byteSwap(v,bSwap); } - uint32_t Image::byteSwap4(DataBuf& buf,size_t offset,bool bSwap) + uint32_t Image::byteSwap4(const DataBuf& buf,size_t offset,bool bSwap) const { uint32_t v; char* p = (char*) &v; @@ -282,6 +294,17 @@ namespace Exiv2 { return Image::byteSwap(v,bSwap); } + uint64_t Image::byteSwap8(const DataBuf& buf,size_t offset,bool bSwap) const + { + uint64_t v; + byte* p = reinterpret_cast(&v); + + for(int i = 0; i < 8; i++) + p[i] = buf.pData_[offset + i]; + + return Image::byteSwap(v,bSwap); + } + const char* Image::typeName(uint16_t tag) const { //! List of TIFF image tags From 4f6f5b49461a584b1cc76d3c64f0c675adea5fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Wed, 20 Sep 2017 21:24:41 +0200 Subject: [PATCH 67/71] removing conditional_byte_swap* functions --- src/bigtiffimage.cpp | 93 +++++++++----------------------------------- 1 file changed, 19 insertions(+), 74 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 48bc84f0..197b51f6 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -122,61 +122,6 @@ namespace Exiv2 return result; } - template - struct TypeForSize {}; - - template<> - struct TypeForSize<16> - { - typedef int16_t Type; - }; - - template<> - struct TypeForSize<32> - { - typedef int32_t Type; - }; - - template<> - struct TypeForSize<64> - { - typedef int64_t Type; - }; - - template - typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) - { - typename TypeForSize::Type result = 0; - if (size == 16) - result = __builtin_bswap16(v); - else if (size == 32) - result = __builtin_bswap32(v); - else if (size == 64) - result = __builtin_bswap64(v); - - return result; - } - - template - typename TypeForSize::Type conditional_byte_swap(const typename TypeForSize::Type& v, bool swap) - { - const typename TypeForSize::Type result = swap? byte_swap(v): v; - - return result; - } - - - template - typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, uint64_t offset, bool swap) - { - typedef typename TypeForSize::Type Type; - - const uint8_t* bytes_buf = static_cast(buf); - const Type* value = reinterpret_cast(&bytes_buf[offset]); - - return conditional_byte_swap(*value, swap); - } - class BigTiffImage: public Image { public: @@ -284,8 +229,8 @@ namespace Exiv2 DataBuf buf(size * count + pad); const uint64_t offset = header_.format() == Header::StandardTiff? - conditional_byte_swap_4_array<32>(data.pData_, 0, doSwap_): - conditional_byte_swap_4_array<64>(data.pData_, 0, doSwap_); + byteSwap4(data, 0, doSwap_): + byteSwap8(data, 0, doSwap_); // big data? Use 'data' as pointer to real data const bool usePointer = count*size > dataSize_; @@ -316,7 +261,7 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<16>(buf.pData_, k*size, doSwap_); + out << sp << byteSwap2(buf, k*size, doSwap_); sp = " "; } } @@ -324,7 +269,7 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<32>(buf.pData_, k*size, doSwap_); + out << sp << byteSwap4(buf, k*size, doSwap_); sp = " "; } } @@ -332,7 +277,7 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - out << sp << conditional_byte_swap_4_array<64>(buf.pData_, k*size, doSwap_); + out << sp << byteSwap8(buf, k*size, doSwap_); sp = " "; } } @@ -340,8 +285,8 @@ namespace Exiv2 { for ( size_t k = 0 ; k < kount ; k++ ) { - uint32_t a = conditional_byte_swap_4_array<32>(buf.pData_, k*size+0, doSwap_); - uint32_t b = conditional_byte_swap_4_array<32>(buf.pData_, k*size+4, doSwap_); + uint32_t a = byteSwap4(buf, k*size+0, doSwap_); + uint32_t b = byteSwap4(buf, k*size+4, doSwap_); out << sp << a << "/" << b; sp = " "; } @@ -359,8 +304,8 @@ namespace Exiv2 { const size_t restore = io.tell(); const uint64_t offset = type == tiffIfd8? - conditional_byte_swap_4_array<64>(buf.pData_, k*size, doSwap_): - conditional_byte_swap_4_array<32>(buf.pData_, k*size, doSwap_); + byteSwap8(buf, k*size, doSwap_): + byteSwap4(buf, k*size, doSwap_); std::cerr << "tag = " << Internal::stringFormat("%#x",tag) << std::endl; printIFD(out, option, offset, depth); @@ -410,9 +355,9 @@ namespace Exiv2 } } - uint64_t next_dir_offset_raw; - io.read(reinterpret_cast(&next_dir_offset_raw), dataSize_); - dir_offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, doSwap_); + const uint64_t nextDirOffset = readData(dataSize_); + + dir_offset = tooBig ? 0 : nextDirOffset; out.flush(); } while (dir_offset != 0); @@ -424,23 +369,23 @@ namespace Exiv2 uint64_t readData(int size) const { - uint64_t data = 0; + const DataBuf data = Image::io().read(size); + assert(data.size_ != 0); - const int read = Image::io().read(reinterpret_cast(&data), size); - assert(read == size); + uint64_t result = 0; if (size == 1) {} else if (size == 2) - data = conditional_byte_swap<16>(data, doSwap_); + result = byteSwap2(data, 0, doSwap_); else if (size == 4) - data = conditional_byte_swap<32>(data, doSwap_); + result = byteSwap4(data, 0, doSwap_); else if (size == 8) - data = conditional_byte_swap<64>(data, doSwap_); + result = byteSwap8(data, 0, doSwap_); else assert(!"unexpected size"); - return data; + return result; } }; } From cc3633ea5974cb494d32ded251e6df63f4d0ea11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 21 Sep 2017 17:06:00 +0200 Subject: [PATCH 68/71] removing POC --- CMakeLists.txt | 2 - bigtiff/CMakeLists.txt | 11 - bigtiff/parse.cpp | 505 ----------------------------------------- 3 files changed, 518 deletions(-) delete mode 100644 bigtiff/CMakeLists.txt delete mode 100644 bigtiff/parse.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f7deff6..570e5742 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,8 +87,6 @@ if( EXIV2_ENABLE_BUILD_PO ) add_subdirectory( po ) endif() -add_subdirectory( bigtiff ) - ## # tests add_custom_target(tests COMMAND env EXIV2_BINDIR="${CMAKE_BINARY_DIR}"/bin make tests WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ) diff --git a/bigtiff/CMakeLists.txt b/bigtiff/CMakeLists.txt deleted file mode 100644 index 44f5798f..00000000 --- a/bigtiff/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ - -add_executable(big_tiff_parser - parse.cpp -) - -target_include_directories(big_tiff_parser PRIVATE - ${CMAKE_SOURCE_DIR}/include/exiv2 - ${CMAKE_SOURCE_DIR}/src -) - -target_link_libraries(big_tiff_parser PRIVATE exiv2lib) diff --git a/bigtiff/parse.cpp b/bigtiff/parse.cpp deleted file mode 100644 index 31fa53b3..00000000 --- a/bigtiff/parse.cpp +++ /dev/null @@ -1,505 +0,0 @@ - -#include -#include -#include -#include -#include - -#include "basicio.hpp" -#include "iptc.hpp" -#include "image_int.hpp" -#include "image.hpp" -#include "types.hpp" - -#define WIDTH 32 - -// helpful links: -// http://www.awaresystems.be/imaging/tiff/bigtiff.html -// http://bigtiff.org/ -// http://bigtiff.org/libtiff-4.1.zip -// https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c - -enum TypeId { - unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. - asciiString = 2, //!< Exif ASCII type, 8-bit byte. - unsignedShort = 3, //!< Exif SHORT type, 16-bit (2-byte) unsigned integer. - unsignedLong = 4, //!< Exif LONG type, 32-bit (4-byte) unsigned integer. - unsignedRational = 5, //!< Exif RATIONAL type, two LONGs: numerator and denumerator of a fraction. - signedByte = 6, //!< Exif SBYTE type, an 8-bit signed (twos-complement) integer. - undefined = 7, //!< Exif UNDEFINED type, an 8-bit byte that may contain anything. - signedShort = 8, //!< Exif SSHORT type, a 16-bit (2-byte) signed (twos-complement) integer. - signedLong = 9, //!< Exif SLONG type, a 32-bit (4-byte) signed (twos-complement) integer. - signedRational = 10, //!< Exif SRATIONAL type, two SLONGs: numerator and denumerator of a fraction. - tiffFloat = 11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. - tiffDouble = 12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. - tiffIfd = 13, //!< TIFF IFD type, 32-bit (4-byte) unsigned integer. - unsigned64 = 16, //!< 64-bit unsigned value - signed64 = 17, //!< 64-bit signed value - tiffIfd8 = 18, //!< 64-bit IFD offset - iptcString = 0x10000, //!< IPTC string type. - iptcDate = 0x10001, //!< IPTC date type. - iptcTime = 0x10002, //!< IPTC time type. - comment = 0x10003, //!< %Exiv2 type for the Exif user comment. - directory = 0x10004, //!< %Exiv2 type for a CIFF directory. - xmpText = 0x10005, //!< XMP text type. - xmpAlt = 0x10006, //!< XMP alternative type. - xmpBag = 0x10007, //!< XMP bag type. - xmpSeq = 0x10008, //!< XMP sequence type. - langAlt = 0x10009, //!< XMP language alternative type. - invalidTypeId = 0x1fffe, //!< Invalid type id. - lastTypeId = 0x1ffff //!< Last type id. -}; - -bool isStringType(uint16_t type) -{ - return type == asciiString - || type == unsignedByte - || type == signedByte - || type == undefined; -} - -bool isShortType(uint16_t type) -{ - return type == unsignedShort - || type == signedShort; -} - -bool isLongType(uint16_t type) -{ - return type == unsignedLong - || type == signedLong; -} - -bool isLongLongType(uint16_t type) -{ - return type == unsigned64 - || type == signed64; -} - -bool isRationalType(uint16_t type) -{ - return type == unsignedRational - || type == signedRational; -} - -bool is2ByteType(uint16_t type) -{ - return isShortType(type); -} - -bool is4ByteType(uint16_t type) -{ - return isLongType(type) - || type == tiffFloat - || type == tiffIfd; -} - -bool is8ByteType(uint16_t type) -{ - return isRationalType(type) - || type == tiffDouble - || type == unsigned64 - || type == signed64 - || type == tiffIfd8; -} - -bool isBigEndianPlatform() -{ - union - { - uint32_t i; - char c[4]; - } e = { 0x01000000 }; - - return e.c[0]?true:false; -} - -bool isLittleEndianPlatform() { return !isBigEndianPlatform(); } - -template -struct TypeForSize {}; - -template<> -struct TypeForSize<16> -{ - typedef int16_t Type; -}; - -template<> -struct TypeForSize<32> -{ - typedef int32_t Type; -}; - -template<> -struct TypeForSize<64> -{ - typedef int64_t Type; -}; - -template -typename TypeForSize::Type byte_swap(const typename TypeForSize::Type& v) -{ - typename TypeForSize::Type result = 0; - if (size == 16) - result = __builtin_bswap16(v); - else if (size == 32) - result = __builtin_bswap32(v); - else if (size == 64) - result = __builtin_bswap64(v); - - return result; -} - -template -typename TypeForSize::Type conditional_byte_swap(const typename TypeForSize::Type& v, bool swap) -{ - const typename TypeForSize::Type result = swap? byte_swap(v): v; - - return result; -} - - -template -typename TypeForSize::Type conditional_byte_swap_4_array(void* buf, uint64_t offset, bool swap) -{ - typedef typename TypeForSize::Type Type; - - const uint8_t* bytes_buf = static_cast(buf); - const Type* value = reinterpret_cast(&bytes_buf[offset]); - - return conditional_byte_swap(*value, swap); -} - - -std::string indent(int32_t d) -{ - std::string result ; - if ( d > 0 ) - while ( d--) - result += " "; - - return result; -} - -static const char* tagName(uint16_t tag,size_t nMaxLength) -{ - const char* result = NULL; -/* - // build a static map of tags for fast search - static std::map tags; - static bool init = true; - static char buffer[80]; - - if ( init ) { - int idx; - const TagInfo* ti ; - for (ti = mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = mpfTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - for (ti = Nikon1MakerNote::tagList(), idx = 0 - ; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_; - } - init = false; - - try { - result = tags[tag].c_str(); - if ( nMaxLength > sizeof(buffer) -2 ) - nMaxLength = sizeof(buffer) -2; - strncpy(buffer,result,nMaxLength); - result = buffer; - } catch ( ... ) {} -*/ - return result ; -} - -static const char* typeName(uint16_t tag) -{ - //! List of TIFF image tags - const char* result = NULL; - switch (tag ) { - case unsignedByte : result = "BYTE" ; break; - case asciiString : result = "ASCII" ; break; - case unsignedShort : result = "SHORT" ; break; - case unsignedLong : result = "LONG" ; break; - case unsignedRational : result = "RATIONAL" ; break; - case signedByte : result = "SBYTE" ; break; - case undefined : result = "UNDEFINED" ; break; - case signedShort : result = "SSHORT" ; break; - case signedLong : result = "SLONG" ; break; - case signedRational : result = "SRATIONAL" ; break; - case tiffFloat : result = "FLOAT" ; break; - case tiffDouble : result = "DOUBLE" ; break; - case tiffIfd : result = "IFD" ; break; - case unsigned64 : result = "UNSIGNED64"; break; - case signed64 : result = "SIGNED64" ; break; - default : result = "unknown" ; break; - } - return result; -} - -struct field_t { - uint16_t tagID; - uint16_t tagType; - uint64_t count; - uint64_t data; -} __attribute__((packed)); - -void printIFD(Exiv2::BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option, uint64_t offset, bool bSwap, int depth) -{ - depth++; - bool bFirst = true; - - // buffer - bool bPrint = true; - - do - { - // Read top of directory - io.seek(offset, Exiv2::BasicIo::beg); - - uint64_t entries_raw; - io.read(reinterpret_cast(&entries_raw), 8); - - const uint64_t entries = conditional_byte_swap_4_array<64>(&entries_raw, 0, bSwap); - - const bool tooBig = entries > 500; - - if ( bFirst && bPrint ) - { - out << indent(depth) << Exiv2::Internal::stringFormat("STRUCTURE OF TIFF FILE ") << io.path() << std::endl; - if (tooBig) - out << indent(depth) << "entries = " << entries << std::endl; - } - - if (tooBig) - break; - - // Read the dictionary - for ( uint64_t i = 0; i < entries; i ++ ) - { - if ( bFirst && bPrint ) - out << indent(depth) - << " address | tag | " - << " type | count | offset | value\n"; - - bFirst = false; - field_t field; - - io.read(reinterpret_cast(&field), sizeof(field_t)); - const uint16_t tag = conditional_byte_swap<16>(field.tagID, bSwap); - const uint16_t type = conditional_byte_swap<16>(field.tagType, bSwap); - const uint64_t count = conditional_byte_swap<64>(field.count, bSwap); - const uint64_t data = conditional_byte_swap<64>(field.data, bSwap); - - std::string sp = "" ; // output spacer - - //prepare to print the value - // TODO: figure out what's going on with kount - const uint64_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays - : count > 5 ? 5 - : count - ; - const uint32_t pad = isStringType(type) ? 1 : 0; - const uint32_t size = isStringType(type) ? 1 - : is2ByteType(type) ? 2 - : is4ByteType(type) ? 4 - : is8ByteType(type) ? 8 - : 1; - - Exiv2::DataBuf buf(size * count + pad); - - // big data? Use 'data' as pointer to real data - if ( count*size > 8 ) // read into buffer - { - size_t restore = io.tell(); // save - io.seek(data, Exiv2::BasicIo::beg); // position - io.read(buf.pData_, count * size); // read - io.seek(restore, Exiv2::BasicIo::beg); // restore - } - else // use 'data' as data :) - std::memcpy(buf.pData_, &data, count * size); // copy data - - if ( bPrint ) - { - const uint64_t address = offset + 2 + i * sizeof(field_t) ; - out << indent(depth) - << Exiv2::Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | ", - address, tag, tagName(tag,25), typeName(type), count, offset); - - if ( isShortType(type) ) - { - for ( size_t k = 0 ; k < kount ; k++ ) - { - out << sp << conditional_byte_swap_4_array<16>(buf.pData_, k*size, bSwap); - sp = " "; - } - } - else if ( isLongType(type) ) - { - for ( size_t k = 0 ; k < kount ; k++ ) - { - out << sp << conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); - sp = " "; - } - } - else if ( isLongLongType(type) ) - { - for ( size_t k = 0 ; k < kount ; k++ ) - { - out << sp << conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap); - sp = " "; - } - } - else if ( isRationalType(type) ) - { - for ( size_t k = 0 ; k < kount ; k++ ) - { - uint32_t a = conditional_byte_swap_4_array<32>(buf.pData_, k*size+0, bSwap); - uint32_t b = conditional_byte_swap_4_array<32>(buf.pData_, k*size+4, bSwap); - out << sp << a << "/" << b; - sp = " "; - } - } - else if ( isStringType(type) ) - out << sp << Exiv2::Internal::binaryToString(buf, kount); - - sp = kount == count ? "" : " ..."; - out << sp << std::endl; - - if ( option == Exiv2::kpsRecursive && - (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd || type == tiffIfd8) ) - { - for ( size_t k = 0 ; k < count ; k++ ) - { - const size_t restore = io.tell(); - const uint64_t offset = type == tiffIfd8? - conditional_byte_swap_4_array<64>(buf.pData_, k*size, bSwap): - conditional_byte_swap_4_array<32>(buf.pData_, k*size, bSwap); - - std::cerr << "tag = " << Exiv2::Internal::stringFormat("%#x",tag) << std::endl; - printIFD(io, out, option, offset, bSwap, depth); - io.seek(restore, Exiv2::BasicIo::beg); - } - } - else if ( option == Exiv2::kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) - { - size_t restore = io.tell(); // save - io.seek(offset, Exiv2::BasicIo::beg); // position - Exiv2::byte* bytes=new Exiv2::byte[count] ; // allocate memory - io.read(bytes,count) ; // read - io.seek(restore, Exiv2::BasicIo::beg); // restore - Exiv2::IptcData::printStructure(out,bytes,count,depth); - delete[] bytes; // free - } - else if ( option == Exiv2::kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) - { - size_t restore = io.tell(); // save - - uint32_t jump= 10 ; - Exiv2::byte bytes[20] ; - const char* chars = (const char*) &bytes[0] ; - io.seek(offset, Exiv2::BasicIo::beg); // position - io.read(bytes,jump ) ; // read - bytes[jump]=0 ; - if ( ::strcmp("Nikon",chars) == 0 ) - { - // tag is an embedded tiff - Exiv2::byte* bytes=new Exiv2::byte[count-jump] ; // allocate memory - io.read(bytes,count-jump) ; // read - Exiv2::MemIo memIo(bytes,count-jump) ; // create a file - std::cerr << "Nikon makernote" << std::endl; - // printTiffStructure(memIo,out,option,depth); TODO: fix it - delete[] bytes ; // free - } - else - { - // tag is an IFD - io.seek(0, Exiv2::BasicIo::beg); // position - std::cerr << "makernote" << std::endl; - //printIFDStructure(io,out,option,offset,bSwap,c,depth); // TODO: fix me - } - - io.seek(restore,Exiv2::BasicIo::beg); // restore - } - } - } - uint64_t next_dir_offset_raw; - io.read(reinterpret_cast(&next_dir_offset_raw), 8); - offset = tooBig ? 0 : conditional_byte_swap_4_array<64>(&next_dir_offset_raw, 0, bSwap); - out.flush(); - } while (offset) ; - - if ( bPrint ) - out << indent(depth) << "END " << io.path() << std::endl; - - depth--; -} - -int main(int argc,const char* argv[]) -{ - int result = 0; - bool bSwap = false; - uint64_t offset = 0; - - if ( argc > 0 ) - { - FILE* f = fopen(argv[1],"rb"); - if ( f ) - { - char buff[2*WIDTH]; - fread(buff, 1, sizeof buff, f); - - bSwap = (isLittleEndianPlatform() && buff[0] == 'M') - || (isBigEndianPlatform() && buff[0] == 'I') - ; - - uint16_t magic = conditional_byte_swap_4_array<16>(buff, 2, bSwap); - uint16_t byteSize = conditional_byte_swap_4_array<16>(buff, 4, bSwap); - uint16_t zeroByte = conditional_byte_swap_4_array<16>(buff, 6, bSwap); - offset = conditional_byte_swap_4_array<64>(buff, 8, bSwap); - - if ( buff[0] != buff[1] || - (buff[0] != 'I' && buff[0] != 'M') || - magic != 43 || - byteSize != 8 || - zeroByte != 0 - ) - { - std::cerr << "bSwap = " << bSwap << std::endl; - std::cerr << "magic = " << magic << std::endl; - std::cerr << "byteSize = " << byteSize << std::endl; - std::cerr << "zeroByte = " << zeroByte << std::endl; - std::cerr << "offset = " << offset << std::endl; - std::cerr << argv[1] << " is not a BigTIFF file" << std::endl; - result = 3 ; - } - - fclose(f); - } - else - { - std::cerr << argv[0] << " unable to open " << argv[1] << std::endl; - result = 2 ; - } - - } - else - { - std::cerr << argv[0] << " path" << std::endl; - result = 1 ; - } - - if ( result == 0 ) { - std::cout << "Congrats swap = " << (bSwap?"true":"false") << " offset = " << offset << std::endl; - int depth = 0 ; - Exiv2::FileIo file(argv[1]); - file.open("rb"); - printIFD(file, std::cout, Exiv2::kpsRecursive, offset, bSwap, depth); - } - - return result; -} From 46292273589ec14aa405a002dcc267497e2769da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 21 Sep 2017 17:32:16 +0200 Subject: [PATCH 69/71] fix for IPTCNAA dir_offset was used instead of offset --- src/bigtiffimage.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 197b51f6..4117b700 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -303,22 +303,22 @@ namespace Exiv2 for ( size_t k = 0 ; k < count ; k++ ) { const size_t restore = io.tell(); - const uint64_t offset = type == tiffIfd8? + const uint64_t ifdOffset = type == tiffIfd8? byteSwap8(buf, k*size, doSwap_): byteSwap4(buf, k*size, doSwap_); std::cerr << "tag = " << Internal::stringFormat("%#x",tag) << std::endl; - printIFD(out, option, offset, depth); + printIFD(out, option, ifdOffset, depth); io.seek(restore, BasicIo::beg); } } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) { - size_t restore = io.tell(); // save - io.seek(dir_offset, BasicIo::beg); // position - byte* bytes=new byte[count] ; // allocate memory - io.read(bytes,count) ; // read - io.seek(restore, BasicIo::beg); // restore + const size_t restore = io.tell(); // save + io.seek(offset, BasicIo::beg); // position + byte* bytes=new byte[count] ; // allocate memory + io.read(bytes,count) ; // read + io.seek(restore, BasicIo::beg); // restore IptcData::printStructure(out,bytes,count,depth); delete[] bytes; // free } From e3ff1ba694cf9e5c2f296d653a37283a586048c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 21 Sep 2017 17:33:25 +0200 Subject: [PATCH 70/71] fixing indent --- src/bigtiffimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 4117b700..080ed804 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -160,7 +160,7 @@ namespace Exiv2 void printStructure(std::ostream& os, PrintStructureOption option, int depth) { - printIFD(os, option, header_.dirOffset(), depth); + printIFD(os, option, header_.dirOffset(), depth - 1); } private: From 734a2c3d57def35d06bc8653ef66c05b6a12c6ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Walenciak?= Date: Thu, 21 Sep 2017 17:35:31 +0200 Subject: [PATCH 71/71] fixing TODO --- src/bigtiffimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bigtiffimage.cpp b/src/bigtiffimage.cpp index 080ed804..ecbe1f92 100644 --- a/src/bigtiffimage.cpp +++ b/src/bigtiffimage.cpp @@ -347,7 +347,7 @@ namespace Exiv2 // tag is an IFD io.seek(0, BasicIo::beg); // position std::cerr << "makernote" << std::endl; - //printIFDStructure(io,out,option,offset,doSwap_,c,depth); // TODO: fix me + printIFD(out,option,offset,depth); } io.seek(restore,BasicIo::beg); // restore