diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp index a87e03c9..491a9489 100644 --- a/src/pngchunk.cpp +++ b/src/pngchunk.cpp @@ -21,9 +21,6 @@ /* File: pngchunk.cpp Version: $Rev$ - Author(s): Gilles Caulier (cgilles) - History: 12-Jun-06, gc: submitted - Credits: See header file */ // ***************************************************************************** #include "rcsid_int.hpp" @@ -83,11 +80,6 @@ namespace Exiv2 { TxtChunkType type) { DataBuf key = keyTXTChunk(data); - -#ifdef DEBUG - std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk key: " - << std::string((const char*)key.pData_, key.size_) << "\n"; -#endif DataBuf arr = parseTXTChunk(data, key.size_, type); #ifdef DEBUG @@ -98,6 +90,19 @@ namespace Exiv2 { } // PngChunk::decodeTXTChunk + DataBuf PngChunk::decodeTXTChunk(const DataBuf& data, + TxtChunkType type) + { + DataBuf key = keyTXTChunk(data); + +#ifdef DEBUG + std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk key: " + << std::string((const char*)key.pData_, key.size_) << "\n"; +#endif + return parseTXTChunk(data, key.size_, type); + + } // PngChunk::decodeTXTChunk + DataBuf PngChunk::keyTXTChunk(const DataBuf& data, bool stripHeader) { // From a tEXt, zTXt, or iTXt chunk, @@ -230,7 +235,7 @@ namespace Exiv2 { || memcmp("Raw profile type APP1", key, 21) == 0) && pImage->exifData().empty()) { - DataBuf exifData = readRawProfile(arr); + DataBuf exifData = readRawProfile(arr,false); long length = exifData.size_; if (length > 0) @@ -279,7 +284,7 @@ namespace Exiv2 { if ( keySize >= 21 && memcmp("Raw profile type iptc", key, 21) == 0 && pImage->iptcData().empty()) { - DataBuf psData = readRawProfile(arr); + DataBuf psData = readRawProfile(arr,false); if (psData.size_ > 0) { Blob iptcBlob; const byte *record = 0; @@ -331,7 +336,7 @@ namespace Exiv2 { && memcmp("Raw profile type xmp", key, 20) == 0 && pImage->xmpData().empty()) { - DataBuf xmpBuf = readRawProfile(arr); + DataBuf xmpBuf = readRawProfile(arr,false); long length = xmpBuf.size_; if (length > 0) @@ -578,7 +583,7 @@ namespace Exiv2 { } // PngChunk::makeUtf8TxtChunk - DataBuf PngChunk::readRawProfile(const DataBuf& text) + DataBuf PngChunk::readRawProfile(const DataBuf& text,bool iTXt) { DataBuf info; register long i; @@ -596,6 +601,13 @@ namespace Exiv2 { return DataBuf(); } + if ( iTXt ) { + info.alloc(text.size_); + ::memcpy(info.pData_,text.pData_,text.size_); + return info; + } + + sp = (char*)text.pData_+1; // Look for newline @@ -620,7 +632,6 @@ namespace Exiv2 { #ifdef DEBUG std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: invalid profile length\n"; #endif - return DataBuf(); } info.alloc(length); diff --git a/src/pngchunk_int.hpp b/src/pngchunk_int.hpp index a9af64f7..3c4d4666 100644 --- a/src/pngchunk_int.hpp +++ b/src/pngchunk_int.hpp @@ -25,19 +25,20 @@ PNG tTXt and zTXt chunks structures from PNG definitive guide,
PNG tags list by Phil Harvey
Email communication with caulier dot gilles at gmail dot com
- @version $Rev$ - @author Andreas Huggel (ahu) - ahuggel@gmx.net - @author Gilles Caulier (cgilles) - caulier dot gilles at gmail dot com - @date 12-Jun-06, gc: submitted */ + + /* + File: pngchunk.cpp + Version: $Rev$ + */ + #ifndef PNGCHUNK_INT_HPP_ #define PNGCHUNK_INT_HPP_ // ***************************************************************************** // included header files #include "types.hpp" +#include "pngimage.hpp" // + standard includes #include @@ -97,6 +98,17 @@ namespace Exiv2 { const DataBuf& data, TxtChunkType type); + /*! + @brief Decode PNG tEXt, zTXt, or iTXt chunk data from \em pImage passed by data buffer + \em data and extract Comment, Exif, Iptc, Xmp to DataBuf + + @param data PNG Chunk data buffer. + @param type PNG Chunk TXT type. + */ + static DataBuf decodeTXTChunk(const DataBuf& data, + TxtChunkType type); + + /*! @brief Return PNG TXT chunk key as data buffer. @@ -180,7 +192,7 @@ namespace Exiv2 { /*! @brief Decode from ImageMagick raw text profile which host encoded Exif/Iptc/Xmp metadata byte array. */ - static DataBuf readRawProfile(const DataBuf& text); + static DataBuf readRawProfile(const DataBuf& text,bool iTXt); /*! @brief Encode to ImageMagick raw text profile, which host encoded @@ -189,6 +201,8 @@ namespace Exiv2 { static std::string writeRawProfile(const std::string& profileData, const char* profileType); + friend class Exiv2::PngImage; + }; // class PngChunk }} // namespace Internal, Exiv2 diff --git a/src/pngimage.cpp b/src/pngimage.cpp index 119c4296..4c9d5991 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -216,9 +216,12 @@ namespace Exiv2 { const std::string xmpKey = "XML:com.adobe.xmp"; const std::string exifKey = "Raw profile type exif"; + const std::string app1Key = "Raw profile type APP1"; const std::string iptcKey = "Raw profile type iptc"; const std::string iccKey = "icc"; const std::string softKey = "Software"; + const std::string commKey = "Comment"; + const std::string descKey = "Description"; bool bPrint = option == kpsBasic || option == kpsRecursive ; if ( bPrint ) { @@ -252,15 +255,16 @@ namespace Exiv2 { throw Exiv2::Error(14); } - // format output - uint32_t blen = dataOffset > 32 ? 32 : dataOffset ; - std::string dataString ; - DataBuf buff(blen); - io_->read(buff.pData_,blen); + DataBuf buff(dataOffset); + io_->read(buff.pData_,dataOffset); io_->seek(restore, BasicIo::beg); - dataString = Internal::binaryToString(buff, blen); - while ( dataString.size() < 32 ) dataString += ' '; - dataString = dataString.substr(0,30); + + // format output + const int iMax = 30 ; + uint32_t blen = dataOffset > iMax ? iMax : dataOffset ; + std::string dataString = Internal::binaryToString(buff, blen); + while ( dataString.size() < iMax ) dataString += ' '; + dataString = dataString.substr(0,iMax); if ( bPrint ) { io_->seek(dataOffset, BasicIo::cur);// jump to checksum @@ -285,19 +289,22 @@ namespace Exiv2 { // for XMP, ICC etc: read and format data bool bXMP = option == kpsXMP && findi(dataString,xmpKey)==0; bool bICC = option == kpsIccProfile && findi(dataString,iccKey)==0; - bool bExif = option == kpsRecursive && findi(dataString,exifKey)==0; + bool bExif = option == kpsRecursive &&(findi(dataString,exifKey)==0 || findi(dataString,app1Key)==0); bool bIptc = option == kpsRecursive && findi(dataString,iptcKey)==0; bool bSoft = option == kpsRecursive && findi(dataString,softKey)==0; - bool bDump = bXMP || bICC || bExif || bIptc || bSoft ; + bool bComm = option == kpsRecursive && findi(dataString,commKey)==0; + bool bDesc = option == kpsRecursive && findi(dataString,descKey)==0; + bool bDump = bXMP || bICC || bExif || bIptc || bSoft || bComm || bDesc ; if( bDump ) { DataBuf dataBuf; - byte* data = new byte[dataOffset+1]; - data[dataOffset]=0; + byte* data = new byte[dataOffset+1]; + data[dataOffset] = 0; io_->read(data,dataOffset); io_->seek(restore, BasicIo::beg); - uint32_t name_l = (uint32_t) std::strlen((const char*)data)+1; // leading string length - uint32_t start = name_l; + uint32_t name_l = (uint32_t) std::strlen((const char*)data)+1; // leading string length + uint32_t start = name_l; + bool bLF = false; // decode the chunk bool bGood = false; @@ -305,26 +312,34 @@ namespace Exiv2 { bGood = tEXtToDataBuf(data+name_l,dataOffset-name_l,dataBuf); } if ( zTXt || iCCP ) { - name_l++ ; // +1 = 'compressed' flag - bGood = zlibToDataBuf(data+name_l,dataOffset-name_l,dataBuf); + bGood = zlibToDataBuf(data+name_l+1,dataOffset-name_l-1,dataBuf); // +1 = 'compressed' flag } if ( iTXt ) { - while ( data[start] == 0 && start < dataOffset ) start++; // crawl over the '\0' bytes between XML:....\0\050?50:parsedBuf.size_,0) << std::endl; +#endif + if ( parsedBuf.size_ ) { + 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); + } + if ( bIptc ) { + IptcData::printStructure(out,parsedBuf.pData_,parsedBuf.size_,depth); + } + } } if ( bSoft && dataBuf.size_ > 0) { @@ -332,16 +347,22 @@ namespace Exiv2 { memcpy(s.pData_,dataBuf.pData_,dataBuf.size_);// copy in the dataBuf s.pData_[dataBuf.size_] = 0 ; // nul terminate it const char* str = (const char*) s.pData_; // give it name - out << Internal::indent(depth) << (const char*) buff.pData_ << ": " << str << std::endl; + out << Internal::indent(depth) << (const char*) buff.pData_ << ": " << str ; + bLF=true; } - if ( bICC ) { + if ( bICC || bComm ) { out.write((const char*) dataBuf.pData_,dataBuf.size_); + bLF = bComm ; } - if ( bIptc ) { - IptcData::printStructure(out,dataBuf.pData_,dataBuf.size_,depth); + if ( bDesc && iTXt ) { + DataBuf decoded = PngChunk::decodeTXTChunk(buff,PngChunk::iTXt_Chunk ); + out.write((const char*)decoded.pData_,decoded.size_); + bLF = true; } + + if ( bLF ) out << std::endl; } delete[] data; }