diff --git a/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp
index 669eed6a..1c849f18 100644
--- a/include/exiv2/basicio.hpp
+++ b/include/exiv2/basicio.hpp
@@ -18,13 +18,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
-/*!
- @file basicio.hpp
- @brief Simple binary IO abstraction
- @version $Rev: 3091 $
- @author Brad Schick (brad)
- brad@robotbattle.com
- @date 04-Dec-04, brad: created
+/*
+ File: basicio.hpp
+ Version: $Rev: 4633 $
*/
#ifndef BASICIO_HPP_
#define BASICIO_HPP_
@@ -97,6 +93,7 @@ namespace Exiv2 {
Nonzero if failure.
*/
virtual int open() = 0;
+
/*!
@brief Close the IO source. After closing a BasicIo instance can not
be read or written. Closing flushes any unwritten data. It is
@@ -259,6 +256,18 @@ namespace Exiv2 {
*/
virtual BasicIo::AutoPtr temporary() const = 0;
+ /*!
+ @brief markBlocks that we know for certain are not metadata
+ @note This method is designed to enable TIFF files to mark StripOffsets/StringByteCounts
+ */
+ virtual void markRead(long offset,long count);
+
+ /*!
+ @brief read all blocks that are not marked
+ @note This method is designed to enable TIFF file to read everything except the markRead blocks!
+ */
+ virtual void readUnmarked();
+
/*!
@brief Mark all the bNone blocks to bKnow. This avoids allocating memory
for parts of the file that contain image-date (non-metadata/pixel data)
@@ -945,6 +954,13 @@ namespace Exiv2 {
Nonzero if failure.
*/
virtual int open();
+
+ virtual void markRead(long offset,long count);
+
+ virtual void readUnmarked();
+
+ byte* bigBlock_;
+
/*!
@brief Reset the IO position to the start. It does not release the data.
@return 0 if successful;
@@ -1097,6 +1113,7 @@ namespace Exiv2 {
are all downloaded from the remote file to memory.
*/
virtual void populateFakeData();
+
//@}
protected:
diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp
index 6eee4ff1..8e26b13f 100644
--- a/include/exiv2/image.hpp
+++ b/include/exiv2/image.hpp
@@ -318,6 +318,42 @@ namespace Exiv2 {
little-endian byte order (II) is used by default.
*/
void setByteOrder(ByteOrder byteOrder);
+
+ /*!
+ @brief Print out the structure of image file.
+ @throw Error if reading of the file fails or the image data is
+ not valid (does not look like data of the specific image type).
+ */
+ void printTiffStructure(BasicIo& io,std::ostream& out, PrintStructureOption option,int depth,size_t offset=0);
+
+ /*!
+ @brief Print out the structure of a TIFF IFD
+ */
+ void printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,uint32_t start,bool bSwap,char c,int depth);
+
+ /*!
+ @brief is the host platform bigEndian
+ */
+ bool isBigEndianPlatform();
+
+ /*!
+ @brief is the host platform littleEndian
+ */
+ bool isLittleEndianPlatform();
+ bool isStringType(uint16_t type);
+ bool isShortType(uint16_t type);
+ bool isLongType(uint16_t type);
+ bool isRationalType(uint16_t type);
+ bool is2ByteType(uint16_t type);
+ bool is4ByteType(uint16_t type);
+ 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);
+
//@}
//! @name Accessors
@@ -452,6 +488,9 @@ namespace Exiv2 {
int pixelHeight_; //!< image pixel height
NativePreviewList nativePreviews_; //!< list of native previews
+ std::vector stripOffsets; //!< StripOffset data
+ std::vector stripByteCounts ; //!< StripByteCount data
+
private:
//! @name NOT implemented
//@{
diff --git a/include/exiv2/tiffimage.hpp b/include/exiv2/tiffimage.hpp
index cf5dc15e..d1fe35ca 100644
--- a/include/exiv2/tiffimage.hpp
+++ b/include/exiv2/tiffimage.hpp
@@ -18,14 +18,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
-/*!
- @file tiffimage.hpp
- @brief Class TiffImage
- @version $Rev: 3090 $
- @author Andreas Huggel (ahu)
- ahuggel@gmx.net
- @date 15-Mar-06, ahu: created
+/*
+ File: tiffimage.hpp
+ Version: $Rev: 4633 $
*/
+
#ifndef TIFFIMAGE_HPP_
#define TIFFIMAGE_HPP_
@@ -95,20 +92,6 @@ namespace Exiv2 {
*/
virtual void printStructure(std::ostream& out, PrintStructureOption option,int depth=-1);
- /*!
- @brief Print out the structure of image file.
- @throw Error if reading of the file fails or the image data is
- not valid (does not look like data of the specific image type).
- @caution This function is not thread safe. See TiffImage::printStructure for more details
- */
- static void printTiffStructure(BasicIo& io,std::ostream& out, PrintStructureOption option,int depth,size_t offset=0);
-
- /*!
- @brief Print out the structure of a TIFF IFD
- @caution This function is not thread safe. See TiffImage::printStructure for more details
- */
- static void printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,uint32_t start,bool bSwap,char c,int depth);
-
/*!
@brief Not supported. TIFF format does not contain a comment.
Calling this function will throw an Error(32).
diff --git a/src/basicio.cpp b/src/basicio.cpp
index 201bc056..93677531 100644
--- a/src/basicio.cpp
+++ b/src/basicio.cpp
@@ -21,8 +21,6 @@
/*
File: basicio.cpp
Version: $Rev$
- Author(s): Brad Schick (brad)
- History: 04-Dec-04, brad: created
*/
// *****************************************************************************
#include "rcsid_int.hpp"
@@ -86,6 +84,10 @@ namespace Exiv2 {
{
}
+ void BasicIo::markRead(long /*offset*/,long /*count*/) { return ; }
+
+ void BasicIo::readUnmarked() { return ; }
+
//! Internal Pimpl structure of class FileIo.
class FileIo::Impl {
public:
@@ -620,25 +622,25 @@ namespace Exiv2 {
std::string FileIo::temporaryPath()
{
- static int count = 0 ;
- char sCount[12];
- sprintf(sCount,"_%d",count++);
+ static int count = 0 ;
+ char sCount[12];
+ sprintf(sCount,"_%d",count++);
#if defined(_MSC_VER) || defined(__MINGW__)
char lpTempPathBuffer[MAX_PATH];
- GetTempPath(MAX_PATH,lpTempPathBuffer);
- std::string tmp(lpTempPathBuffer);
- tmp += "\\";
+ GetTempPath(MAX_PATH,lpTempPathBuffer);
+ std::string tmp(lpTempPathBuffer);
+ tmp += "\\";
#else
- std::string tmp = "/tmp/";
+ std::string tmp = "/tmp/";
#endif
- pid_t pid = ::getpid();
- std::string result = tmp + toString(pid) + sCount ;
- if ( Exiv2::fileExists(result) ) std::remove(result.c_str());
+ pid_t pid = ::getpid();
+ std::string result = tmp + toString(pid) + sCount ;
+ if ( Exiv2::fileExists(result) ) std::remove(result.c_str());
- return result;
- }
+ return result;
+ }
long FileIo::write(const byte* data, long wcount)
{
@@ -1562,6 +1564,7 @@ namespace Exiv2 {
bool isMalloced_; //!< Was the blocksMap_ allocated?
bool eof_; //!< EOF indicator
Protocol protocol_; //!< the protocol of url
+ uint32_t totalRead_;
// METHODS
/*!
@@ -1604,7 +1607,7 @@ namespace Exiv2 {
RemoteIo::Impl::Impl(const std::string& url, size_t blockSize)
: path_(url), blockSize_(blockSize), blocksMap_(0), size_(0),
- idx_(0), isMalloced_(false), eof_(false), protocol_(fileProtocol(url))
+ idx_(0), isMalloced_(false), eof_(false), protocol_(fileProtocol(url)),totalRead_(0)
{
}
#ifdef EXV_UNICODE_PATH
@@ -1663,6 +1666,7 @@ namespace Exiv2 {
int RemoteIo::open()
{
close(); // reset the IO position
+ bigBlock_ = NULL;
if (p_->isMalloced_ == false) {
long length = p_->getFileLength();
if (length < 0) { // unable to get the length of remote file, get the whole file content.
@@ -1693,12 +1697,68 @@ namespace Exiv2 {
return 0; // means OK
}
+ void RemoteIo::markRead(long offset,long count)
+ {
+ // std::cout << "RemoteIo::markRead offset = " << offset << " count = " << count << std::endl;
+ int blockLow = (offset )/p_->blockSize_ ;
+ int blockHigh = (offset + count )/p_->blockSize_ ;
+ for ( int block = blockLow+1 ; block < blockHigh-1 ; block++ ) {
+ p_->blocksMap_[block].markKnown(p_->blockSize_);
+ }
+ }
+
+ void RemoteIo::readUnmarked()
+ {
+ long blockSize = p_->blockSize_;
+ int nBlocks = (p_->size_ + blockSize -1) / blockSize ;
+#ifdef DEBUG
+ int nRead = 0;
+ int nHigh = 0;
+ int nGulp = 0;
+ int nBytes = 0;
+ for ( int block = 0 ; block < nBlocks ; block++ ) {
+ if ( p_->blocksMap_[block].isNone() ) {
+ nRead++ ;
+ nHigh = block;
+ }
+ }
+ std::cerr << "RemoteIo::readUnmarked nBlocks = " << nBlocks << " nRead = " << nRead << " nHigh = " << nHigh << std::endl;
+ for ( int block = 0 ; block < nBlocks ; block ++ ) {
+ char x = 'X';
+ if ( p_->blocksMap_[block].isNone() ) x='.';
+ if ( p_->blocksMap_[block].isInMem() ) x='R';
+ if ( p_->blocksMap_[block].isKnown() ) x='-';
+ std::cerr << x ;
+ }
+ std::cerr << std::endl;
+#endif
+ for ( int block = 0 ; block < nBlocks ; block ++ ) {
+ if ( p_->blocksMap_[block].isNone() ) {
+ int b = block;
+ if ( b < (nBlocks -1)) while ( p_->blocksMap_[b+1].isNone() && b < nBlocks ) b++;
+ seek(block*blockSize,BasicIo::beg);
+ read(blockSize);
+#ifdef DEBUG
+ nBytes += blockSize*(b-block+1);
+ nGulp ++ ;
+#endif
+ block = b ;
+ }
+ }
+#ifdef DEBUG
+ std::cerr << "RemoteIo::readUnmarked nGulp = " << nGulp << " nBytes = " << nBytes << std::endl;
+#endif
+ }
+
int RemoteIo::close()
{
if (p_->isMalloced_) {
p_->eof_ = false;
p_->idx_ = 0;
}
+#ifdef DEBUG
+ std::cerr << "RemoteIo::close totalRead_ = " << p_->totalRead_ << std::endl;
+#endif
return 0;
}
@@ -1746,7 +1806,6 @@ namespace Exiv2 {
blockIndex++;
}
-
// find $right
findDiff = false;
blockIndex = nBlocks - 1;
@@ -1802,6 +1861,7 @@ namespace Exiv2 {
{
assert(p_->isMalloced_);
if (p_->eof_) return 0;
+ p_->totalRead_ += rcount;
size_t allow = EXV_MIN(rcount, (long)( p_->size_ - p_->idx_));
size_t lowBlock = p_->idx_ /p_->blockSize_;
@@ -1900,7 +1960,23 @@ namespace Exiv2 {
byte* RemoteIo::mmap(bool /*isWriteable*/)
{
- return NULL;
+ long nRealData = 0 ;
+ if ( !bigBlock_ ) {
+ int blockSize = p_->blockSize_;
+ int blocks = (p_->size_ + blockSize -1)/blockSize ;
+ bigBlock_ = new byte[blocks*blockSize] ;
+ for ( int block = 0 ; block < blocks ; block ++ ) {
+ void* p = p_->blocksMap_[block].getData();
+ if ( p ) {
+ nRealData += blockSize ;
+ memcpy(bigBlock_+(block*blockSize),p,blockSize);
+ }
+ }
+ }
+#ifdef DEBUG
+ std::cerr << "RemoteIo::mmap nRealData = " << nRealData << std::endl;
+#endif
+ return bigBlock_;
}
int RemoteIo::munmap()
diff --git a/src/cr2image.cpp b/src/cr2image.cpp
index aedd48a9..0808a3a8 100644
--- a/src/cr2image.cpp
+++ b/src/cr2image.cpp
@@ -21,9 +21,6 @@
/*
File: cr2image.cpp
Version: $Rev$
- Author(s): Andreas Huggel (ahu)
- History: 22-Apr-06, ahu: created
-
*/
// *****************************************************************************
#include "rcsid_int.hpp"
@@ -86,10 +83,9 @@ namespace Exiv2 {
{
if (io_->open() != 0) throw Error(9, io_->path(), strError());
io_->seek(0,BasicIo::beg);
- TiffImage::printTiffStructure(io(),out,option,depth-1);
+ printTiffStructure(io(),out,option,depth-1);
}
-
void Cr2Image::setComment(const std::string& /*comment*/)
{
// not supported
diff --git a/src/image.cpp b/src/image.cpp
index fde1fac8..621391e8 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -44,6 +44,9 @@ EXIV2_RCSID("@(#) $Id$")
#endif // EXV_HAVE_LIBZ
#include "rafimage.hpp"
#include "tiffimage.hpp"
+#include "tiffimage_int.hpp"
+#include "tiffcomposite_int.hpp"
+#include "tiffvisitor_int.hpp"
#include "webpimage.hpp"
#include "orfimage.hpp"
#include "gifimage.hpp"
@@ -51,6 +54,8 @@ EXIV2_RCSID("@(#) $Id$")
#include "tgaimage.hpp"
#include "bmpimage.hpp"
#include "jp2image.hpp"
+#include "nikonmn_int.hpp"
+
#ifdef EXV_ENABLE_VIDEO
#include "matroskavideo.hpp"
#include "quicktimevideo.hpp"
@@ -170,6 +175,335 @@ namespace Exiv2 {
throw Error(13, io_->path());
}
+ bool Image::isStringType(uint16_t type)
+ {
+ return type == Exiv2::asciiString
+ || type == Exiv2::unsignedByte
+ || type == Exiv2::signedByte
+ || type == Exiv2::undefined
+ ;
+ }
+ bool Image::isShortType(uint16_t type) {
+ return type == Exiv2::unsignedShort
+ || type == Exiv2::signedShort
+ ;
+ }
+ bool Image::isLongType(uint16_t type) {
+ return type == Exiv2::unsignedLong
+ || type == Exiv2::signedLong
+ ;
+ }
+ bool Image::isRationalType(uint16_t type) {
+ return type == Exiv2::unsignedRational
+ || type == Exiv2::signedRational
+ ;
+ }
+ bool Image::is2ByteType(uint16_t type)
+ {
+ return isShortType(type);
+ }
+ bool Image::is4ByteType(uint16_t type)
+ {
+ return isLongType(type)
+ || isRationalType(type)
+ ;
+ }
+ bool Image::isPrintXMP(uint16_t type, Exiv2::PrintStructureOption option)
+ {
+ return type == 700 && option == kpsXMP;
+ }
+ bool Image::isPrintICC(uint16_t type, Exiv2::PrintStructureOption option)
+ {
+ return type == 0x8773 && option == kpsIccProfile;
+ }
+
+ bool Image::isBigEndianPlatform()
+ {
+ union {
+ uint32_t i;
+ char c[4];
+ } e = { 0x01000000 };
+
+ return e.c[0]?true:false;
+ }
+ bool Image::isLittleEndianPlatform() { return !isBigEndianPlatform(); }
+
+ uint32_t Image::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 Image::byteSwap(uint16_t value,bool bSwap)
+ {
+ uint16_t result = 0;
+ result |= (value & 0x00FF) << 8;
+ result |= (value & 0xFF00) >> 8;
+ return bSwap ? result : value;
+ }
+
+ uint16_t Image::byteSwap2(DataBuf& buf,size_t offset,bool bSwap)
+ {
+ uint16_t v;
+ char* p = (char*) &v;
+ p[0] = buf.pData_[offset];
+ p[1] = buf.pData_[offset+1];
+ return Image::byteSwap(v,bSwap);
+ }
+
+ uint32_t Image::byteSwap4(DataBuf& buf,size_t offset,bool bSwap)
+ {
+ uint32_t v;
+ char* p = (char*) &v;
+ p[0] = buf.pData_[offset];
+ p[1] = buf.pData_[offset+1];
+ p[2] = buf.pData_[offset+2];
+ p[3] = buf.pData_[offset+3];
+ return Image::byteSwap(v,bSwap);
+ }
+
+ 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 = Internal:: mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
+ for (ti = Internal:: iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
+ for (ti = Internal:: gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
+ for (ti = Internal:: ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
+ for (ti = Internal::exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
+ for (ti = Internal:: mpfTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
+ for (ti = Internal::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 Exiv2::unsignedByte : result = "BYTE" ; break;
+ case Exiv2::asciiString : result = "ASCII" ; break;
+ case Exiv2::unsignedShort : result = "SHORT" ; break;
+ case Exiv2::unsignedLong : result = "LONG" ; break;
+ case Exiv2::unsignedRational : result = "RATIONAL" ; break;
+ case Exiv2::signedByte : result = "SBYTE" ; break;
+ case Exiv2::undefined : result = "UNDEFINED" ; break;
+ case Exiv2::signedShort : result = "SSHORT" ; break;
+ case Exiv2::signedLong : result = "SLONG" ; break;
+ case Exiv2::signedRational : result = "SRATIONAL" ; break;
+ case Exiv2::tiffFloat : result = "FLOAT" ; break;
+ case Exiv2::tiffDouble : result = "DOUBLE" ; break;
+ default : result = "unknown" ; break;
+ }
+ return result;
+ }
+
+ void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,uint32_t start,bool bSwap,char c,int depth)
+ {
+ depth++;
+ bool bFirst = true ;
+
+ // buffer
+ const size_t dirSize = 32;
+ DataBuf dir(dirSize);
+ bool bPrint = option == kpsBasic || option == kpsRecursive;
+
+ do {
+ // Read top of directory
+ io.seek(start,BasicIo::beg);
+ io.read(dir.pData_, 2);
+ uint16_t dirLength = byteSwap2(dir,0,bSwap);
+
+ bool tooBig = dirLength > 500;
+
+ if ( bFirst && bPrint ) {
+ out << Internal::indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE (%c%c): ",c,c) << io.path() << std::endl;
+ if ( tooBig ) out << Internal::indent(depth) << "dirLength = " << dirLength << std::endl;
+ }
+ if (tooBig) break;
+
+ // Read the dictionary
+ for ( int i = 0 ; i < dirLength ; i ++ ) {
+ if ( bFirst && bPrint ) {
+ out << Internal::indent(depth)
+ << " address | tag | "
+ << " type | count | offset | value\n";
+ }
+ bFirst = false;
+
+ io.read(dir.pData_, 12);
+ uint16_t tag = byteSwap2(dir,0,bSwap);
+ uint16_t type = byteSwap2(dir,2,bSwap);
+ uint32_t count = byteSwap4(dir,4,bSwap);
+ uint32_t offset = byteSwap4(dir,8,bSwap);
+
+ std::string sp = "" ; // output spacer
+
+ //prepare to print the value
+ uint32_t kount = isPrintXMP(tag,option) ? count // haul in all the data
+ : isPrintICC(tag,option) ? count // ditto
+ : 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
+ : 1
+ ;
+
+ // if ( offset > io.size() ) offset = 0; // Denial of service?
+ 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 << Internal::indent(depth)
+ << 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);
+ sp = " ";
+ }
+ } else if ( isLongType(type) ){
+ for ( size_t k = 0 ; k < kount ; k++ ) {
+ out << sp << byteSwap4(buf,k*size,bSwap);
+ sp = " ";
+ }
+ // populate strips and bytes
+ if ( tag == 0x0111 ) {
+ for ( size_t k = 0 ; k < count ; k++ ) // stripOffsets
+ stripOffsets.push_back(byteSwap4(buf,k*size,bSwap));
+ }
+ if ( tag == 0x0117 ) {
+ for ( size_t k = 0 ; k < count ; k++ ) // stripByteCounts
+ stripByteCounts.push_back(byteSwap4(buf,k*size,bSwap));
+ }
+
+ } else if ( isRationalType(type) ){
+ for ( size_t k = 0 ; k < kount ; k++ ) {
+ uint16_t a = byteSwap2(buf,k*size+0,bSwap);
+ uint16_t b = byteSwap2(buf,k*size+2,bSwap);
+ if ( isLittleEndianPlatform() ) {
+ if ( bSwap ) out << sp << b << "/" << a;
+ else out << sp << a << "/" << b;
+ } else {
+ if ( bSwap ) out << sp << a << "/" << b;
+ else out << sp << b << "/" << a;
+ }
+ 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*/ ) ) {
+ for ( size_t k = 0 ; k < count ; k++ ) {
+ size_t restore = io.tell();
+ uint32_t offset = byteSwap4(buf,k*size,bSwap);
+ 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) {
+ uint32_t jump= 10 ;
+ byte bytes[20] ;
+ const char* chars = (const char*) &bytes[0] ;
+ size_t restore = io.tell(); // save
+ 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
+ printTiffStructure(memIo,out,option,depth);
+ delete[] bytes ; // free
+ }
+ io.seek(restore,BasicIo::beg); // restore
+ }
+ }
+
+ if ( isPrintXMP(tag,option) ) {
+ buf.pData_[count]=0;
+ out << (char*) buf.pData_;
+ }
+ if ( isPrintICC(tag,option) ) {
+ out.write((const char*)buf.pData_,count);
+ }
+ }
+ io.read(dir.pData_, 4);
+ start = tooBig ? 0 : byteSwap4(dir,0,bSwap);
+ out.flush();
+ } while (start) ;
+
+ if ( bPrint ) {
+ out << Internal::indent(depth) << "END " << io.path() << std::endl;
+ }
+ depth--;
+ }
+
+ void Image::printTiffStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,int depth,size_t offset /*=0*/)
+ {
+ if ( option == kpsBasic || option == kpsXMP || option == kpsRecursive || option == kpsIccProfile ) {
+ // buffer
+ const size_t dirSize = 32;
+ DataBuf dir(dirSize);
+
+ // read header (we already know for certain that we have a Tiff file)
+ io.read(dir.pData_, 8);
+ char c = (char) dir.pData_[0] ;
+ bool bSwap = ( c == 'M' && isLittleEndianPlatform() )
+ || ( c == 'I' && isBigEndianPlatform() )
+ ;
+ uint32_t start = byteSwap4(dir,4,bSwap);
+ printIFDStructure(io,out,option,start+(uint32_t)offset,bSwap,c,depth);
+ }
+ }
+
void Image::clearMetadata()
{
clearExifData();
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index 4e56072b..385d49fa 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -553,7 +553,7 @@ namespace Exiv2
&& (rawData.pData_[0]=='I' || rawData.pData_[0]=='M' )
) {
BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(rawData.pData_,rawData.size_));
- TiffImage::printTiffStructure(*p,out,option,depth);
+ printTiffStructure(*p,out,option,depth);
}
}
diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp
index 7059aae3..21d3d79e 100644
--- a/src/jpgimage.cpp
+++ b/src/jpgimage.cpp
@@ -769,7 +769,7 @@ namespace Exiv2 {
} else {
// create a copy on write memio object with the data, then print the structure
BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(exif+start,size-start));
- if ( start < max ) TiffImage::printTiffStructure(*p,out,option,depth);
+ if ( start < max ) printTiffStructure(*p,out,option,depth);
}
// restore and clean up
diff --git a/src/pgfimage.cpp b/src/pgfimage.cpp
index 358ab588..8b399d92 100644
--- a/src/pgfimage.cpp
+++ b/src/pgfimage.cpp
@@ -64,19 +64,7 @@ const unsigned char pgfBlank[] = { 0x50,0x47,0x46,0x36,0x10,0x00,0x00,0x00,0x01,
namespace Exiv2 {
- // http://en.wikipedia.org/wiki/Endianness
- static bool isBigEndian()
- {
- union {
- uint32_t i;
- char c[4];
- } e = { 0x01000000 };
-
- return e.c[0]?true:false;
- }
- // static bool isLittleEndian() { return !isBigEndian(); }
-
- static uint32_t byteSwap(uint32_t value,bool bSwap)
+ static uint32_t byteSwap_(uint32_t value,bool bSwap)
{
uint32_t result = 0;
result |= (value & 0x000000FF) << 24;
@@ -85,31 +73,14 @@ namespace Exiv2 {
result |= (value & 0xFF000000) >> 24;
return bSwap ? result : value;
}
-/*
- static uint16_t byteSwap(uint16_t value,bool bSwap)
- {
- uint16_t result = 0;
- result |= (value & 0x00FF) << 8;
- result |= (value & 0xFF00) >> 8;
- return bSwap ? result : value;
- }
- static uint16_t byteSwap2(Exiv2::DataBuf& buf,size_t offset,bool bSwap)
- {
- uint16_t v;
- char* p = (char*) &v;
- p[0] = buf.pData_[offset];
- p[1] = buf.pData_[offset+1];
- return byteSwap(v,bSwap);
- }
-*/
- static uint32_t byteSwap(Exiv2::DataBuf& buf,size_t offset,bool bSwap)
+ static uint32_t byteSwap_(Exiv2::DataBuf& buf,size_t offset,bool bSwap)
{
uint32_t v;
char* p = (char*) &v;
int i;
for ( i = 0 ; i < 4 ; i++ ) p[i] = buf.pData_[offset+i];
- uint32_t result = byteSwap(v,bSwap);
+ uint32_t result = byteSwap_(v,bSwap);
p = (char*) &result;
for ( i = 0 ; i < 4 ; i++ ) buf.pData_[offset+i] = p[i];
return result;
@@ -117,7 +88,7 @@ namespace Exiv2 {
PgfImage::PgfImage(BasicIo::AutoPtr io, bool create)
: Image(ImageType::pgf, mdExif | mdIptc| mdXmp | mdComment, io)
- , bSwap_(isBigEndian())
+ , bSwap_(isBigEndianPlatform())
{
if (create)
{
@@ -251,7 +222,7 @@ namespace Exiv2 {
uint32_t newHeaderSize = header.size_ + imgSize;
DataBuf buffer(4);
memcpy (buffer.pData_, &newHeaderSize, 4);
- byteSwap(buffer,0,bSwap_);
+ byteSwap_(buffer,0,bSwap_);
if (outIo.write(buffer.pData_, 4) != 4) throw Error(21);
#ifdef DEBUG
@@ -304,7 +275,7 @@ namespace Exiv2 {
if (iIo.error()) throw Error(14);
if (bufRead != buffer.size_) throw Error(20);
- int headerSize = (int) byteSwap(buffer,0,bSwap_);
+ int headerSize = (int) byteSwap_(buffer,0,bSwap_);
if (headerSize <= 0 ) throw Error(22);
#ifdef DEBUG
@@ -323,8 +294,8 @@ namespace Exiv2 {
DataBuf work(8); // don't disturb the binary data - doWriteMetadata reuses it
memcpy (work.pData_,header.pData_,8);
- width = byteSwap(work,0,bSwap_);
- height = byteSwap(work,4,bSwap_);
+ width = byteSwap_(work,0,bSwap_);
+ height = byteSwap_(work,4,bSwap_);
/* NOTE: properties not yet used
byte nLevels = buffer.pData_[8];
diff --git a/src/pngimage.cpp b/src/pngimage.cpp
index 4c9d5991..b0a288e3 100644
--- a/src/pngimage.cpp
+++ b/src/pngimage.cpp
@@ -334,7 +334,7 @@ namespace Exiv2 {
if ( bExif ) {
// create memio object with the data, then print the structure
BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(parsedBuf.pData_+6,parsedBuf.size_-6));
- TiffImage::printTiffStructure(*p,out,option,depth);
+ printTiffStructure(*p,out,option,depth);
}
if ( bIptc ) {
IptcData::printStructure(out,parsedBuf.pData_,parsedBuf.size_,depth);
diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp
index f0eb1f1f..ef78fa35 100644
--- a/src/tiffimage.cpp
+++ b/src/tiffimage.cpp
@@ -41,6 +41,7 @@ EXIV2_RCSID("@(#) $Id$")
#include "error.hpp"
#include "futils.hpp"
#include "types.hpp"
+#include "basicio.hpp"
#include "i18n.h" // NLS support.
// + standard includes
@@ -183,6 +184,25 @@ namespace Exiv2 {
throw Error(3, "TIFF");
}
clearMetadata();
+
+ // recursively print the structure to /dev/null to ensure all metadata is in memory
+ // must be recursive to handle NEFs which stores the raw image in a subIFDs
+ std::ofstream devnull;
+ printStructure(devnull,kpsRecursive,0);
+#ifdef DEBUG
+ assert(stripOffsets.size() == stripByteCounts.size());
+ int ignored =0 ;
+ for ( int strip = 0 ; strip < stripOffsets.size() ; strip ++ )
+ ignored += stripByteCounts[strip];
+ std::cout << "TiffImage::readMetadata ignored = " << ignored << " size = " << io().size() << std::endl;
+#endif
+#if 0
+ assert(stripOffsets.size() == stripByteCounts.size());
+ // tell io_ to ignore the strips and read everything else into memory
+ for ( size_t strip = 0 ; strip < stripOffsets.size() ; strip ++ )
+ io_->markRead(stripOffsets[strip],stripByteCounts[strip]);
+ io_->readUnmarked();
+#endif
ByteOrder bo = TiffParser::decode(exifData_,
iptcData_,
xmpData_,
@@ -327,157 +347,6 @@ namespace Exiv2 {
return rc;
}
- bool isBigEndian()
- {
- union {
- uint32_t i;
- char c[4];
- } e = { 0x01000000 };
-
- return e.c[0]?true:false;
- }
- bool isLittleEndian() { return !isBigEndian(); }
-
-
- // http://en.wikipedia.org/wiki/Endianness
- static 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;
- }
-
- static uint16_t byteSwap(uint16_t value,bool bSwap)
- {
- uint16_t result = 0;
- result |= (value & 0x00FF) << 8;
- result |= (value & 0xFF00) >> 8;
- return bSwap ? result : value;
- }
-
- static uint16_t byteSwap2(DataBuf& buf,size_t offset,bool bSwap)
- {
- uint16_t v;
- char* p = (char*) &v;
- p[0] = buf.pData_[offset];
- p[1] = buf.pData_[offset+1];
- return byteSwap(v,bSwap);
- }
-
- static uint32_t byteSwap4(DataBuf& buf,size_t offset,bool bSwap)
- {
- uint32_t v;
- char* p = (char*) &v;
- p[0] = buf.pData_[offset];
- p[1] = buf.pData_[offset+1];
- p[2] = buf.pData_[offset+2];
- p[3] = buf.pData_[offset+3];
- return byteSwap(v,bSwap);
- }
-
- static const char* typeName(uint16_t tag)
- {
- //! List of TIFF image tags
- const char* result = NULL;
- switch (tag ) {
- case Exiv2::unsignedByte : result = "BYTE" ; break;
- case Exiv2::asciiString : result = "ASCII" ; break;
- case Exiv2::unsignedShort : result = "SHORT" ; break;
- case Exiv2::unsignedLong : result = "LONG" ; break;
- case Exiv2::unsignedRational : result = "RATIONAL" ; break;
- case Exiv2::signedByte : result = "SBYTE" ; break;
- case Exiv2::undefined : result = "UNDEFINED" ; break;
- case Exiv2::signedShort : result = "SSHORT" ; break;
- case Exiv2::signedLong : result = "SLONG" ; break;
- case Exiv2::signedRational : result = "SRATIONAL" ; break;
- case Exiv2::tiffFloat : result = "FLOAT" ; break;
- case Exiv2::tiffDouble : result = "DOUBLE" ; break;
- default : result = "unknown" ; break;
- }
- 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 = Exiv2:: mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
- for (ti = Exiv2:: iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
- for (ti = Exiv2:: gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
- for (ti = Exiv2:: ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
- for (ti = Exiv2::exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags[ti[idx].tag_] = ti[idx].name_;
- for (ti = Exiv2:: 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 bool isStringType(uint16_t type)
- {
- return type == Exiv2::asciiString
- || type == Exiv2::unsignedByte
- || type == Exiv2::signedByte
- || type == Exiv2::undefined
- ;
- }
- static bool isShortType(uint16_t type) {
- return type == Exiv2::unsignedShort
- || type == Exiv2::signedShort
- ;
- }
- static bool isLongType(uint16_t type) {
- return type == Exiv2::unsignedLong
- || type == Exiv2::signedLong
- ;
- }
- static bool isRationalType(uint16_t type) {
- return type == Exiv2::unsignedRational
- || type == Exiv2::signedRational
- ;
- }
- static bool is2ByteType(uint16_t type)
- {
- return isShortType(type);
- }
- static bool is4ByteType(uint16_t type)
- {
- return isLongType(type)
- || isRationalType(type)
- ;
- }
- static bool isPrintXMP(uint16_t type, Exiv2::PrintStructureOption option)
- {
- return type == 700 && option == kpsXMP;
- }
- static bool isPrintICC(uint16_t type, Exiv2::PrintStructureOption option)
- {
- return type == 0x8773 && option == kpsIccProfile;
- }
-
-#define MIN(a,b) ((a)<(b))?(b):(a)
-
void TiffImage::printStructure(std::ostream& out, Exiv2::PrintStructureOption option,int depth)
{
if (io_->open() != 0) throw Error(9, io_->path(), strError());
@@ -493,178 +362,6 @@ namespace Exiv2 {
printTiffStructure(io(),out,option,depth-1);
}
- void TiffImage::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,uint32_t start,bool bSwap,char c,int depth)
- {
- depth++;
- bool bFirst = true ;
-
- // buffer
- const size_t dirSize = 32;
- DataBuf dir(dirSize);
- bool bPrint = option == kpsBasic || option == kpsRecursive;
-
- do {
- // Read top of directory
- io.seek(start,BasicIo::beg);
- io.read(dir.pData_, 2);
- uint16_t dirLength = byteSwap2(dir,0,bSwap);
-
- bool tooBig = dirLength > 500;
-
- if ( bFirst && bPrint ) {
- out << Internal::indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE (%c%c): ",c,c) << io.path() << std::endl;
- if ( tooBig ) out << Internal::indent(depth) << "dirLength = " << dirLength << std::endl;
- }
- if (tooBig) break;
-
- // Read the dictionary
- for ( int i = 0 ; i < dirLength ; i ++ ) {
- if ( bFirst && bPrint ) {
- out << Internal::indent(depth)
- << " address | tag | "
- << " type | count | offset | value\n";
- }
- bFirst = false;
-
- io.read(dir.pData_, 12);
- uint16_t tag = byteSwap2(dir,0,bSwap);
- uint16_t type = byteSwap2(dir,2,bSwap);
- uint32_t count = byteSwap4(dir,4,bSwap);
- uint32_t offset = byteSwap4(dir,8,bSwap);
-
- std::string sp = "" ; // output spacer
-
- //prepare to print the value
- uint32_t kount = isPrintXMP(tag,option) ? count // haul in all the data
- : isPrintICC(tag,option) ? count // ditto
- : 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
- : 1
- ;
-
- // if ( offset > io.size() ) offset = 0; // Denial of service?
- DataBuf buf(MIN(size*kount + pad,48)); // 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_,kount*size);// read
- io.seek(restore,BasicIo::beg); // restore
- }
-
- uint32_t Offset = isLongType(type) ? byteSwap4(buf,0,bSwap) : 0 ;
-
- if ( bPrint ) {
- uint32_t address = start + 2 + i*12 ;
- out << Internal::indent(depth)
- << Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |%10u | "
- ,address,tag,tagName(tag,25),typeName(type),count,offset);
- if ( isShortType(type) ){
- for ( uint16_t k = 0 ; k < kount ; k++ ) {
- out << sp << byteSwap2(buf,k*size,bSwap);
- sp = " ";
- }
- } else if ( isLongType(type) ){
- for ( uint16_t k = 0 ; k < kount ; k++ ) {
- out << sp << byteSwap4(buf,k*size,bSwap);
- sp = " ";
- }
- } else if ( isRationalType(type) ){
- for ( uint16_t k = 0 ; k < kount ; k++ ) {
- uint16_t a = byteSwap2(buf,k*size+0,bSwap);
- uint16_t b = byteSwap2(buf,k*size+2,bSwap);
- if ( isLittleEndian() ) {
- if ( bSwap ) out << sp << b << "/" << a;
- else out << sp << a << "/" << b;
- } else {
- if ( bSwap ) out << sp << a << "/" << b;
- else out << sp << b << "/" << a;
- }
- 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*/ ) ) {
- size_t restore = io.tell();
- 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) {
- uint32_t jump= 10 ;
- byte bytes[20] ;
- const char* chars = (const char*) &bytes[0] ;
- size_t restore = io.tell(); // save
- 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
- printTiffStructure(memIo,out,option,depth);
- delete[] bytes ; // free
- }
- io.seek(restore,BasicIo::beg); // restore
- }
-
- }
-
- if ( isPrintXMP(tag,option) ) {
- buf.pData_[count]=0;
- out << (char*) buf.pData_;
- }
- if ( isPrintICC(tag,option) ) {
- out.write((const char*)buf.pData_,count);
- }
- }
- io.read(dir.pData_, 4);
- start = tooBig ? 0 : byteSwap4(dir,0,bSwap);
- out.flush();
- } while (start) ;
-
- if ( bPrint ) {
- out << Internal::indent(depth) << "END " << io.path() << std::endl;
- }
- depth--;
- }
-
- void TiffImage::printTiffStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,int depth,size_t offset /*=0*/)
- {
- if ( option == kpsBasic || option == kpsXMP || option == kpsRecursive || option == kpsIccProfile ) {
- // buffer
- const size_t dirSize = 32;
- DataBuf dir(dirSize);
-
- // read header (we already know for certain that we have a Tiff file)
- io.read(dir.pData_, 8);
- char c = (char) dir.pData_[0] ;
- bool bSwap = ( c == 'M' && isLittleEndian() )
- || ( c == 'I' && isBigEndian() )
- ;
-
- uint32_t start = byteSwap4(dir,4,bSwap)+(uint32_t)offset;
- printIFDStructure(io,out,option,start,bSwap,c,depth);
- }
- }
-
} // namespace Exiv2
// Shortcuts for the newTiffBinaryArray templates.
diff --git a/src/webpimage.cpp b/src/webpimage.cpp
index 2e1f65e6..86cc94ba 100644
--- a/src/webpimage.cpp
+++ b/src/webpimage.cpp
@@ -19,11 +19,8 @@
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
/*
- File: webpimage.cpp
- Version: $Rev: 3845 $
- Author(s): Ben Touchette
- History: 10-Aug-16
- Credits: See header file
+ File: webpimage.cpp
+ Version: $Rev: 4633 $
*/
/*
Google's WEBP container spec can be found at the link below:
@@ -461,7 +458,7 @@ namespace Exiv2 {
if ( equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_EXIF) && option==kpsRecursive ) {
// create memio object with the payload, then print the structure
BasicIo::AutoPtr p = BasicIo::AutoPtr(new MemIo(payload.pData_,payload.size_));
- TiffImage::printTiffStructure(*p,out,option,depth);
+ printTiffStructure(*p,out,option,depth);
}
bool bPrintPayload = (equalsWebPTag(chunkId, WEBP_CHUNK_HEADER_XMP) && option==kpsXMP)