diff --git a/src/actions.cpp b/src/actions.cpp index 0958b1a9..873f6b0a 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -1187,7 +1187,7 @@ namespace Action { std::cerr << _("No embedded iccProfile: ") << path_ << std::endl; rc = -2; } else { - + if ( Params::instance().target_ & Params::ctStdInOut ) { // -eC- std::cout.write((const char*)image->iccProfile()->pData_,image->iccProfile()->size_); } else { diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp index 14638fd4..a87e03c9 100644 --- a/src/pngchunk.cpp +++ b/src/pngchunk.cpp @@ -541,21 +541,6 @@ namespace Exiv2 { } // PngChunk::makeAsciiTxtChunk - std::string PngChunk::makeICCPChunkHeader(const std::string& keyword,long compressedLength) - { - // Chunk structure: length (4 bytes) + chunk type - std::string chunkData = keyword + '\0'; - std::string chunkType; - chunkData += '\0' ;// byte 0 = standard compression - chunkType = "iCCP"; - // Determine length of the chunk data - byte length[4]; - ul2Data(length, static_cast(chunkData.size()+compressedLength), bigEndian); - - // Assemble chunk - return std::string((const char*)length, 4) + chunkType + chunkData; - } // PngChunk::makeICCPChunkHeader - std::string PngChunk::makeUtf8TxtChunk(const std::string& keyword, const std::string& text, bool compress) diff --git a/src/pngchunk_int.hpp b/src/pngchunk_int.hpp index 54c08566..a9af64f7 100644 --- a/src/pngchunk_int.hpp +++ b/src/pngchunk_int.hpp @@ -116,17 +116,6 @@ namespace Exiv2 { static std::string makeMetadataChunk(const std::string& metadata, MetadataId type); - /*! - @brief Return PNG iCCP chunk header - (length + chunk type) as a string. - - @param keyword Keyword for the PNG iCCP chunk - @param compressLength length of compress data to follow chunk header - - @return string containing the PNG chunk header - */ - static std::string makeICCPChunkHeader(const std::string& keyword,long compressedLength); - private: /*! @brief Parse PNG Text chunk to determine type and extract content. diff --git a/src/pngimage.cpp b/src/pngimage.cpp index 9dd8b386..800c4226 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -21,11 +21,9 @@ /* File: pngimage.cpp Version: $Rev$ - Author(s): Gilles Caulier (cgilles) - History: 12-Jun-06, gc: submitted - Credits: See header file */ // ***************************************************************************** + #include "rcsid_int.hpp" EXIV2_RCSID("@(#) $Id$") @@ -53,7 +51,6 @@ EXIV2_RCSID("@(#) $Id$") #include #include // To uncompress IccProfiles - // Signature from front of PNG file const unsigned char pngSignature[8] = { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }; @@ -106,6 +103,12 @@ namespace Exiv2 { do { result.alloc(uncompressedLen); zlibResult = uncompress((Bytef*)result.pData_,&uncompressedLen,bytes,length); + // if result buffer is large than necessary, redo to fit perfectly. + if (zlibResult == Z_OK && (long) uncompressedLen < result.size_ ) { + result.release(); + result.alloc(uncompressedLen); + zlibResult = uncompress((Bytef*)result.pData_,&uncompressedLen,bytes,length); + } if (zlibResult == Z_BUF_ERROR) { // the uncompressed buffer needs to be larger result.release(); @@ -132,6 +135,7 @@ namespace Exiv2 { result.release(); compressedLen *= 2; } else { + result.release(); result.alloc(compressedLen); zlibResult = compress((Bytef*)result.pData_,&compressedLen,bytes,length); } @@ -512,6 +516,10 @@ namespace Exiv2 { if (io_->error()) throw Error(14); if (bufRead != (long)(dataOffset + 4)) throw Error(20); + char szChunk[5]; + memcpy(szChunk,cheaderBuf.pData_ + 4,4); + szChunk[4] = 0; + if (!memcmp(cheaderBuf.pData_ + 4, "IEND", 4)) { // Last chunk found: we write it and done. @@ -575,12 +583,34 @@ namespace Exiv2 { if ( iccProfileDefined() ) { DataBuf compressed; if ( zlibToCompressed(iccProfile_.pData_,iccProfile_.size_,compressed) ) { - std::string chunk = PngChunk::makeICCPChunkHeader("ICC Profile",compressed.size_); - if( outIo.write((const byte*)chunk.data(), static_cast(chunk.size())) != (long)chunk.size() - || outIo.write (compressed.pData_,compressed.size_) != compressed.size_ + + const byte* header = (const byte*) "ICC PROFILE\0\0" ; // \0 = default compression + const byte* type = (const byte*) "iCCP"; + uint32_t headerLen = 13 ; + uint32_t typeLen = 4; + uint32_t chunkLength = headerLen + compressed.size_ ; + byte length[4]; + ul2Data (length,chunkLength,bigEndian); + + // calculate CRC + uLong tmp = crc32(0L, Z_NULL, 0); + tmp = crc32(tmp, (const Bytef*)header ,headerLen); + tmp = crc32(tmp, (const Bytef*)compressed.pData_,compressed.size_); + byte crc[4]; + ul2Data(crc, tmp, bigEndian); + + if( outIo.write(length,4) != 4 + || outIo.write(type ,typeLen) != typeLen + || outIo.write(header,headerLen) != headerLen + || outIo.write (compressed.pData_,compressed.size_) != compressed.size_ + || outIo.write(crc,4) != 4 ){ throw Error(21); } +#ifdef DEBUG + std::cout << "Exiv2::PngImage::doWriteMetadata: build iCCP" + << " chunk (length: " << compressed.size_ + headerLen << ")" << std::endl; +#endif } } @@ -610,19 +640,20 @@ namespace Exiv2 { memcmp("Raw profile type iptc", key.pData_, 21) == 0 || memcmp("Raw profile type xmp", key.pData_, 20) == 0 || memcmp("XML:com.adobe.xmp", key.pData_, 17) == 0 || - memcmp("icc", key.pData_, 3) == 0 || + memcmp("icc", key.pData_, 3) == 0 || // see test/data/imagemagick.png + memcmp("ICC", key.pData_, 3) == 0 || memcmp("Description", key.pData_, 11) == 0) { #ifdef DEBUG - std::cout << "Exiv2::PngImage::doWriteMetadata: strip " << cheaderBuf.pData_ + 4 - << " chunk (key: " << key.pData_ << ")\n"; + std::cout << "Exiv2::PngImage::doWriteMetadata: strip " << szChunk + << " chunk (length: " << dataOffset << ")" << std::endl; #endif } else { #ifdef DEBUG - std::cout << "Exiv2::PngImage::doWriteMetadata: write " << cheaderBuf.pData_ + 4 - << " chunk (length: " << dataOffset << ")\n"; + std::cout << "Exiv2::PngImage::doWriteMetadata: write " << szChunk + << " chunk (length: " << dataOffset << ")" << std::endl; #endif if (outIo.write(chunkBuf.pData_, chunkBuf.size_) != chunkBuf.size_) throw Error(21); } @@ -631,8 +662,8 @@ namespace Exiv2 { { // Write all others chunk as well. #ifdef DEBUG - std::cout << "Exiv2::PngImage::doWriteMetadata: write " << cheaderBuf.pData_ + 4 - << " chunk (length: " << dataOffset << ")\n"; + std::cout << "Exiv2::PngImage::doWriteMetadata: copy " << szChunk + << " chunk (length: " << dataOffset << ")" << std::endl; #endif if (outIo.write(chunkBuf.pData_, chunkBuf.size_) != chunkBuf.size_) throw Error(21); diff --git a/test/data/ReaganSmall.png b/test/data/ReaganSmallPng.png similarity index 100% rename from test/data/ReaganSmall.png rename to test/data/ReaganSmallPng.png diff --git a/test/data/bugfixes-test.out b/test/data/bugfixes-test.out index 30b283c8..201d012b 100644 Binary files a/test/data/bugfixes-test.out and b/test/data/bugfixes-test.out differ diff --git a/test/data/icc-test.out b/test/data/icc-test.out index 78ab1b63..9e301c59 100644 --- a/test/data/icc-test.out +++ b/test/data/icc-test.out @@ -152,124 +152,50 @@ STRUCTURE OF JPEG FILE: Reagan.jpg 1628273 | 0xffdd DRI | 4 1628279 | 0xffc4 DHT | 418 1628699 | 0xffda SOS -Exiv2 exception in insert action for file Reagan.jpg: -Not a valid ICC Profile STRUCTURE OF JPEG FILE: Reagan.jpg address | marker | length | data 0 | 0xffd8 SOI 2 | 0xffe1 APP1 | 5704 | Exif..MM.*...................... 5708 | 0xffe1 APP1 | 5287 | http://ns.adobe.com/xap/1.0/.J...a.`1 chunk 12/59 - 797177 | 0xffe2 APP2 | 65512 | ICC_PROFILE....up............... chunk 13/-1 - 862692 | 0xffe2 APP2 | 65512 | ICC_PROFILE.....<............... chunk 14/-1 - 928207 | 0xffe2 APP2 | 65512 | ICC_PROFILE...........,...'..... chunk 15/-96 - 993722 | 0xffe2 APP2 | 65512 | ICC_PROFILE....g.....m%....qw.. chunk 16/0 - 1059237 | 0xffe2 APP2 | 65512 | ICC_PROFILE...s....xX.M..n.....g chunk 17/-126 - 1124752 | 0xffe2 APP2 | 65512 | ICC_PROFILE.........0......E.... chunk 18/22 - 1190267 | 0xffe2 APP2 | 65512 | ICC_PROFILE.....(.n.B.........J} chunk 19/-1 - 1255782 | 0xffe2 APP2 | 65512 | ICC_PROFILE..0.282.0.282.0.281.0 chunk 20/48 - 1321297 | 0xffe2 APP2 | 65512 | ICC_PROFILE..5.0.176.0.175.0.174 chunk 21/53 - 1386812 | 0xffe2 APP2 | 65512 | ICC_PROFILE..3.0.114.0.126.0.136 chunk 22/51 - 1452327 | 0xffe2 APP2 | 65512 | ICC_PROFILE..0.049.0.053.0.059.0 chunk 23/48 - 1517842 | 0xffe2 APP2 | 65512 | ICC_PROFILE...670.0.653.0.634.0. chunk 24/46 - 1583357 | 0xffe2 APP2 | 41712 | ICC_PROFILE...0.584.0.555.0.509. chunk 25/9 - 1625072 | 0xffed APP13 | 3030 | Photoshop 3.0.8BIM..........Z... - 1628104 | 0xffee APP14 | 14 | Adobe.d@...... - 1628120 | 0xffdb DQT | 132 - 1628254 | 0xffc0 SOF0 | 17 - 1628273 | 0xffdd DRI | 4 - 1628279 | 0xffc4 DHT | 418 - 1628699 | 0xffda SOS + 10997 | 0xffe2 APP2 | 576 | ICC_PROFILE.....0ADBE....mntrRGB chunk 1/0 + 11576 | 0xffed APP13 | 3030 | Photoshop 3.0.8BIM..........Z... + 14608 | 0xffee APP14 | 14 | Adobe.d@...... + 14624 | 0xffdb DQT | 132 + 14758 | 0xffc0 SOF0 | 17 + 14777 | 0xffdd DRI | 4 + 14783 | 0xffc4 DHT | 418 + 15203 | 0xffda SOS STRUCTURE OF JPEG FILE: Reagan.jpg address | marker | length | data 0 | 0xffd8 SOI 2 | 0xffe1 APP1 | 5704 | Exif..MM.*...................... 5708 | 0xffe1 APP1 | 5287 | http://ns.adobe.com/xap/1.0/.J...a.`1. chunk 12/-113 - 797177 | 0xffe2 APP2 | 65512 | ICC_PROFILE...up................ chunk 13/-1 - 862692 | 0xffe2 APP2 | 65512 | ICC_PROFILE....<................ chunk 14/-1 - 928207 | 0xffe2 APP2 | 65512 | ICC_PROFILE..........,...'.....` chunk 15/9 - 993722 | 0xffe2 APP2 | 65512 | ICC_PROFILE...g.....m%....qw... chunk 16/0 - 1059237 | 0xffe2 APP2 | 65512 | ICC_PROFILE..s....xX.M..n.....gO chunk 17/115 - 1124752 | 0xffe2 APP2 | 65512 | ICC_PROFILE........0......E..... chunk 18/-31 - 1190267 | 0xffe2 APP2 | 65512 | ICC_PROFILE....(.n.B.........J}a chunk 19/-1 - 1255782 | 0xffe2 APP2 | 65512 | ICC_PROFILE...282.0.282.0.281.0. chunk 20/46 - 1321297 | 0xffe2 APP2 | 65512 | ICC_PROFILE...0.176.0.175.0.174. chunk 21/9 - 1386812 | 0xffe2 APP2 | 65512 | ICC_PROFILE...0.114.0.126.0.136. chunk 22/9 - 1452327 | 0xffe2 APP2 | 65512 | ICC_PROFILE...049.0.053.0.059.0. chunk 23/46 - 1517842 | 0xffe2 APP2 | 65512 | ICC_PROFILE..670.0.653.0.634.0.6 chunk 24/54 - 1583357 | 0xffe2 APP2 | 41712 | ICC_PROFILE..0.584.0.555.0.509.0 chunk 25/48 - 1625072 | 0xffed APP13 | 3030 | Photoshop 3.0.8BIM..........Z... - 1628104 | 0xffee APP14 | 14 | Adobe.d@...... - 1628120 | 0xffdb DQT | 132 - 1628254 | 0xfffe COM | 10 | abcdefg - 1628266 | 0xffc0 SOF0 | 17 - 1628285 | 0xffdd DRI | 4 - 1628291 | 0xffc4 DHT | 418 - 1628711 | 0xffda SOS + 10997 | 0xffe2 APP2 | 576 | ICC_PROFILE....0ADBE....mntrRGB chunk 1/0 + 11576 | 0xffed APP13 | 3030 | Photoshop 3.0.8BIM..........Z... + 14608 | 0xffee APP14 | 14 | Adobe.d@...... + 14624 | 0xffdb DQT | 132 + 14758 | 0xfffe COM | 10 | abcdefg + 14770 | 0xffc0 SOF0 | 17 + 14789 | 0xffdd DRI | 4 + 14795 | 0xffc4 DHT | 418 + 15215 | 0xffda SOS abcdefg STRUCTURE OF JPEG FILE: Reagan.jpg address | marker | length | data 0 | 0xffd8 SOI 2 | 0xffe1 APP1 | 5704 | Exif..MM.*...................... 5708 | 0xffe1 APP1 | 5287 | http://ns.adobe.com/xap/1.0/.J...a.`1..g chunk 12/79 - 797177 | 0xffe2 APP2 | 65512 | ICC_PROFILE..up................. chunk 13/117 - 862692 | 0xffe2 APP2 | 65512 | ICC_PROFILE...<................. chunk 14/-102 - 928207 | 0xffe2 APP2 | 65512 | ICC_PROFILE.........,...'.....` chunk 15/9 - 993722 | 0xffe2 APP2 | 65512 | ICC_PROFILE..g.....m%....qw....u chunk 16/103 - 1059237 | 0xffe2 APP2 | 65512 | ICC_PROFILE......xX.M..n.....gO. chunk 17/-112 - 1124752 | 0xffe2 APP2 | 65512 | ICC_PROFILE.......0......E.....H chunk 18/-120 - 1190267 | 0xffe2 APP2 | 65512 | ICC_PROFILE...(.n.B.........J}am chunk 19/-9 - 1255782 | 0xffe2 APP2 | 65512 | ICC_PROFILE..282.0.282.0.281.0.2 chunk 20/50 - 1321297 | 0xffe2 APP2 | 65512 | ICC_PROFILE..0.176.0.175.0.174.0 chunk 21/48 - 1386812 | 0xffe2 APP2 | 65512 | ICC_PROFILE..0.114.0.126.0.136.0 chunk 22/48 - 1452327 | 0xffe2 APP2 | 65512 | ICC_PROFILE..049.0.053.0.059.0.0 chunk 23/48 - 1517842 | 0xffe2 APP2 | 65512 | ICC_PROFILE..70.0.653.0.634.0.60 chunk 24/55 - 1583357 | 0xffe2 APP2 | 41712 | ICC_PROFILE...584.0.555.0.509.0. chunk 25/46 - 1625072 | 0xffed APP13 | 3030 | Photoshop 3.0.8BIM..........Z... - 1628104 | 0xffee APP14 | 14 | Adobe.d@...... - 1628120 | 0xffdb DQT | 132 - 1628254 | 0xffc0 SOF0 | 17 - 1628273 | 0xffdd DRI | 4 - 1628279 | 0xffc4 DHT | 418 - 1628699 | 0xffda SOS + 10997 | 0xffe2 APP2 | 576 | ICC_PROFILE...0ADBE....mntrRGB X chunk 1/2 + 11576 | 0xffed APP13 | 3030 | Photoshop 3.0.8BIM..........Z... + 14608 | 0xffee APP14 | 14 | Adobe.d@...... + 14624 | 0xffdb DQT | 132 + 14758 | 0xffc0 SOF0 | 17 + 14777 | 0xffdd DRI | 4 + 14783 | 0xffc4 DHT | 418 + 15203 | 0xffda SOS 50b9125494306a6fc1b7c4f2a1a8d49d 50b9125494306a6fc1b7c4f2a1a8d49d -daa5193ef28659d126c48d4010479428 -daa5193ef28659d126c48d4010479428 +a78f7a71f1ea79f2f6708be6394e1305 +a78f7a71f1ea79f2f6708be6394e1305 d890d988d312ae8d497d21e936628ecc d890d988d312ae8d497d21e936628ecc diff --git a/test/data/small.icc b/test/data/small.icc index 90d13cae..817c1572 100644 Binary files a/test/data/small.icc and b/test/data/small.icc differ