From b52ade814ba685d624781252cffa99a324684041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Komar=C4=8Devi=C4=87?= Date: Mon, 26 Dec 2022 12:34:20 +0100 Subject: [PATCH] Prefer writing PNG eXIf chunk --- src/pngchunk_int.cpp | 4 +- src/pngimage.cpp | 29 ++- test/data/test_reference_files/icc-test.out | 240 ++++++++++---------- test/data/test_reference_files/png-test.out | 12 +- 4 files changed, 147 insertions(+), 138 deletions(-) diff --git a/src/pngchunk_int.cpp b/src/pngchunk_int.cpp index 0bf19ece..d9f3abb1 100644 --- a/src/pngchunk_int.cpp +++ b/src/pngchunk_int.cpp @@ -321,14 +321,12 @@ std::string PngChunk::makeMetadataChunk(const std::string& metadata, MetadataId switch (type) { case mdComment: return makeUtf8TxtChunk("Description", metadata, true); - case mdExif: - rawProfile = writeRawProfile(metadata, "exif"); - return makeAsciiTxtChunk("Raw profile type exif", rawProfile, true); case mdIptc: rawProfile = writeRawProfile(metadata, "iptc"); return makeAsciiTxtChunk("Raw profile type iptc", rawProfile, true); case mdXmp: return makeUtf8TxtChunk("XML:com.adobe.xmp", metadata, false); + case mdExif: case mdIccProfile: case mdNone: return {}; diff --git a/src/pngimage.cpp b/src/pngimage.cpp index f9a6bbd8..f95fc719 100644 --- a/src/pngimage.cpp +++ b/src/pngimage.cpp @@ -39,6 +39,7 @@ constexpr unsigned char pngBlank[] = { }; const auto nullComp = reinterpret_cast("\0\0"); +const auto typeExif = reinterpret_cast("eXIf"); const auto typeICCP = reinterpret_cast("iCCP"); inline bool compare(std::string_view str, const Exiv2::DataBuf& buf) { const auto minlen = std::min(str.size(), buf.size()); @@ -306,7 +307,7 @@ void PngImage::printStructure(std::ostream& out, PrintStructureOption option, si bGood = (3 <= dataOffset) && (start < dataOffset - 3); // good if not a nul chunk } if (eXIf) { - bGood = true; // eXIf requires no pre-processing) + bGood = true; // eXIf requires no pre-processing } // format is content dependent @@ -548,8 +549,7 @@ void PngImage::doWriteMetadata(BasicIo& outIo) { } if (!strcmp(szChunk, "eXIf") || !strcmp(szChunk, "iCCP")) { // do nothing (strip): Exif metadata is written following IHDR - // as zTXt chunk with signature "Raw profile type exif", - // together with the ICC profile as a fresh iCCP chunk + // together with the ICC profile as fresh eXIf and iCCP chunks #ifdef EXIV2_DEBUG_MESSAGES std::cout << "Exiv2::PngImage::doWriteMetadata: strip " << szChunk << " chunk (length: " << dataOffset << ")" << std::endl; @@ -575,13 +575,24 @@ void PngImage::doWriteMetadata(BasicIo& outIo) { Blob blob; ExifParser::encode(blob, littleEndian, exifData_); if (!blob.empty()) { - static const char exifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00}; - std::string rawExif = - std::string(exifHeader, 6) + std::string(reinterpret_cast(blob.data()), blob.size()); - std::string chunk = PngChunk::makeMetadataChunk(rawExif, mdExif); - if (outIo.write(reinterpret_cast(chunk.data()), chunk.size()) != chunk.size()) { + byte length[4]; + ul2Data(length, static_cast(blob.size()), bigEndian); + + // calculate CRC + uLong tmp = crc32(0L, Z_NULL, 0); + tmp = crc32(tmp, typeExif, 4); + tmp = crc32(tmp, blob.data(), static_cast(blob.size())); + byte crc[4]; + ul2Data(crc, tmp, bigEndian); + + if (outIo.write(length, 4) != 4 || outIo.write(typeExif, 4) != 4 || + outIo.write(blob.data(), blob.size()) != blob.size() || outIo.write(crc, 4) != 4) { throw Error(ErrorCode::kerImageWriteFailed); } +#ifdef EXIV2_DEBUG_MESSAGES + std::cout << "Exiv2::PngImage::doWriteMetadata: build eXIf" + << " chunk (length: " << blob.size() << ")" << std::endl; +#endif } } @@ -623,7 +634,7 @@ void PngImage::doWriteMetadata(BasicIo& outIo) { } #ifdef EXIV2_DEBUG_MESSAGES std::cout << "Exiv2::PngImage::doWriteMetadata: build iCCP" - << " chunk (length: " << compressed.size() + chunkLength << ")" << std::endl; + << " chunk (length: " << chunkLength << ")" << std::endl; #endif } } diff --git a/test/data/test_reference_files/icc-test.out b/test/data/test_reference_files/icc-test.out index 928709bb..1d51cdf1 100644 --- a/test/data/test_reference_files/icc-test.out +++ b/test/data/test_reference_files/icc-test.out @@ -308,152 +308,152 @@ STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 33 | iTXt | 31 | Description.....x.KLJNIMK..... | 0xc1fefec8 - 76 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8549 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9197 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 - 1168394 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 1200538 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 1208742 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 1215927 | IEND | 0 | | 0xae426082 + 76 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8496 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9144 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 + 1168341 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 1200485 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 1208689 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 1215874 | IEND | 0 | | 0xae426082 abcdefg STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 - 33 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8506 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9154 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 - 1168351 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 1200495 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 1208699 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 1215884 | IEND | 0 | | 0xae426082 + 33 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8453 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9101 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 + 1168298 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 1200442 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 1208646 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 1215831 | IEND | 0 | | 0xae426082 STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 - 33 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8506 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9154 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 - 1168351 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 1200495 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 1208699 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 1215884 | IEND | 0 | | 0xae426082 + 33 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8453 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9101 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 + 1168298 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 1200442 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 1208646 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 1215831 | IEND | 0 | | 0xae426082 STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 33 | iTXt | 31 | Description.....x.KLJNIMK..... | 0xc1fefec8 - 76 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8549 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9197 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 - 1168394 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 1200538 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 1208742 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 1215927 | IEND | 0 | | 0xae426082 + 76 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8496 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9144 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 + 1168341 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 1200485 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 1208689 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 1215874 | IEND | 0 | | 0xae426082 abcdefg STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 - 33 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8506 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9154 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 - 1168351 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 1200495 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 1208699 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 1215884 | IEND | 0 | | 0xae426082 + 33 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8453 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9101 | iCCP | 1159185 | ICC profile..x...uP.[..9@.HB.D | 0xd3dbe519 + 1168298 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 1200442 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 1208646 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 1215831 | IEND | 0 | | 0xae426082 STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 - 33 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8506 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9154 | iCCP | 293 | ICC profile..x.c``2ptqre.``..+ | 0x7d41600b - 9459 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 41603 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 49807 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 56992 | IEND | 0 | | 0xae426082 + 33 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8453 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9101 | iCCP | 293 | ICC profile..x.c``2ptqre.``..+ | 0x7d41600b + 9406 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 41550 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 49754 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 56939 | IEND | 0 | | 0xae426082 STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 33 | iTXt | 31 | Description.....x.KLJNIMK..... | 0xc1fefec8 - 76 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8549 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9197 | iCCP | 293 | ICC profile..x.c``2ptqre.``..+ | 0x7d41600b - 9502 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 41646 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 49850 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 57035 | IEND | 0 | | 0xae426082 + 76 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8496 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9144 | iCCP | 293 | ICC profile..x.c``2ptqre.``..+ | 0x7d41600b + 9449 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 41593 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 49797 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 56982 | IEND | 0 | | 0xae426082 abcdefg STRUCTURE OF PNG FILE: ReaganLargePng.png address | chunk | length | data | checksum 8 | IHDR | 13 | ............ | 0x8cf910c3 - 33 | zTXt | 8461 | Raw profile type exif..x...iv. | 0x91fbf6a0 - 8506 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 - 9154 | iCCP | 293 | ICC profile..x.c``2ptqre.``..+ | 0x7d41600b - 9459 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb - 41603 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 - 49807 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 - 56992 | IEND | 0 | | 0xae426082 + 33 | eXIf | 8408 | II*.......................... | 0x81634e71 + 8453 | zTXt | 636 | Raw profile type iptc..x..TKn. | 0x4e5178d3 + 9101 | iCCP | 293 | ICC profile..x.c``2ptqre.``..+ | 0x7d41600b + 9406 | iTXt | 7156 | XML:com.adobe.xmp.........3..p.....$....E.Bj | 0x65a90ffb + 41550 | IDAT | 8192 | ....S....?..G.....G........... | 0xf44da161 + 49754 | IDAT | 7173 | .evl...3K..j.S.....x......Z .D | 0xbe6d3574 + 56939 | IEND | 0 | | 0xae426082 45ed3c125cc6041b37b44ee4cb881cd8 45ed3c125cc6041b37b44ee4cb881cd8 50b9125494306a6fc1b7c4f2a1a8d49d diff --git a/test/data/test_reference_files/png-test.out b/test/data/test_reference_files/png-test.out index ced4cd3f..a2d22efe 100644 --- a/test/data/test_reference_files/png-test.out +++ b/test/data/test_reference_files/png-test.out @@ -57,12 +57,12 @@ STRUCTURE OF PNG FILE: 1343_exif.png address | chunk | length | data | checksum 8 | IHDR | 13 | .......d.... | 0x4ce4e85c 33 | iTXt | 39 | Description.....x.K.H.KOMQH... | 0xe0a1c8ce - 84 | zTXt | 145 | Raw profile type exif..x.U.... | 0x2f6d89e8 - 241 | sRGB | 1 | | 0xaece1ce9 - 254 | gAMA | 4 | .... | 0x0bfc6105 - 270 | pHYs | 9 | ......... | 0xc76fa864 - 291 | IDAT | 257 | x^..1..0......t.....h......z.. | 0x64465429 - 560 | IEND | 0 | | 0xae426082 + 84 | eXIf | 108 | II*...............J.......... | 0xe863fbc7 + 204 | sRGB | 1 | | 0xaece1ce9 + 217 | gAMA | 4 | .... | 0x0bfc6105 + 233 | pHYs | 9 | ......... | 0xc76fa864 + 254 | IDAT | 257 | x^..1..0......t.....h......z.. | 0x64465429 + 523 | IEND | 0 | | 0xae426082 changed comment Exif.Image.ImageDescription Ascii 17 Can you read me? Exif.Image.XResolution Rational 1 72