|
|
@ -500,10 +500,7 @@ ByteOrder ExifParser::decode(ExifData& exifData, const byte* pData, size_t size)
|
|
|
|
enum Ptt { pttLen, pttTag, pttIfd };
|
|
|
|
enum Ptt { pttLen, pttTag, pttIfd };
|
|
|
|
//! @endcond
|
|
|
|
//! @endcond
|
|
|
|
|
|
|
|
|
|
|
|
WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteOrder byteOrder,
|
|
|
|
WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteOrder byteOrder, ExifData& exifData) {
|
|
|
|
const ExifData& exifData) {
|
|
|
|
|
|
|
|
ExifData ed = exifData;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Delete IFD0 tags that are "not recorded" in compressed images
|
|
|
|
// Delete IFD0 tags that are "not recorded" in compressed images
|
|
|
|
// Reference: Exif 2.2 specs, 4.6.8 Tag Support Levels, section A
|
|
|
|
// Reference: Exif 2.2 specs, 4.6.8 Tag Support Levels, section A
|
|
|
|
static constexpr auto filteredIfd0Tags = std::array{
|
|
|
|
static constexpr auto filteredIfd0Tags = std::array{
|
|
|
@ -533,12 +530,12 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
|
|
|
|
"Exif.Canon.AFFineRotation",
|
|
|
|
"Exif.Canon.AFFineRotation",
|
|
|
|
};
|
|
|
|
};
|
|
|
|
for (auto&& filteredIfd0Tag : filteredIfd0Tags) {
|
|
|
|
for (auto&& filteredIfd0Tag : filteredIfd0Tags) {
|
|
|
|
auto pos = ed.findKey(ExifKey(filteredIfd0Tag));
|
|
|
|
auto pos = exifData.findKey(ExifKey(filteredIfd0Tag));
|
|
|
|
if (pos != ed.end()) {
|
|
|
|
if (pos != exifData.end()) {
|
|
|
|
#ifdef EXIV2_DEBUG_MESSAGES
|
|
|
|
#ifdef EXIV2_DEBUG_MESSAGES
|
|
|
|
std::cerr << "Warning: Exif tag " << pos->key() << " not encoded\n";
|
|
|
|
std::cerr << "Warning: Exif tag " << pos->key() << " not encoded\n";
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
ed.erase(pos);
|
|
|
|
exifData.erase(pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -552,7 +549,7 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
|
|
|
|
#ifdef EXIV2_DEBUG_MESSAGES
|
|
|
|
#ifdef EXIV2_DEBUG_MESSAGES
|
|
|
|
std::cerr << "Warning: Exif IFD " << filteredIfd << " not encoded\n";
|
|
|
|
std::cerr << "Warning: Exif IFD " << filteredIfd << " not encoded\n";
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
eraseIfd(ed, filteredIfd);
|
|
|
|
eraseIfd(exifData, filteredIfd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// IPTC and XMP are stored elsewhere, not in the Exif APP1 segment.
|
|
|
|
// IPTC and XMP are stored elsewhere, not in the Exif APP1 segment.
|
|
|
@ -562,7 +559,7 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
|
|
|
|
// Encode and check if the result fits into a JPEG Exif APP1 segment
|
|
|
|
// Encode and check if the result fits into a JPEG Exif APP1 segment
|
|
|
|
MemIo mio1;
|
|
|
|
MemIo mio1;
|
|
|
|
TiffHeader header(byteOrder, 0x00000008, false);
|
|
|
|
TiffHeader header(byteOrder, 0x00000008, false);
|
|
|
|
WriteMethod wm = TiffParserWorker::encode(mio1, pData, size, ed, emptyIptc, emptyXmp, Tag::root,
|
|
|
|
WriteMethod wm = TiffParserWorker::encode(mio1, pData, size, exifData, emptyIptc, emptyXmp, Tag::root,
|
|
|
|
TiffMapping::findEncoder, &header, nullptr);
|
|
|
|
TiffMapping::findEncoder, &header, nullptr);
|
|
|
|
if (mio1.size() <= 65527) {
|
|
|
|
if (mio1.size() <= 65527) {
|
|
|
|
append(blob, mio1.mmap(), mio1.size());
|
|
|
|
append(blob, mio1.mmap(), mio1.size());
|
|
|
@ -609,22 +606,22 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
|
|
|
|
switch (ptt) {
|
|
|
|
switch (ptt) {
|
|
|
|
case pttLen: {
|
|
|
|
case pttLen: {
|
|
|
|
delTags = false;
|
|
|
|
delTags = false;
|
|
|
|
if (auto pos = ed.findKey(ExifKey(key)); pos != ed.end() && sumToLong(*pos) > 32768) {
|
|
|
|
if (auto pos = exifData.findKey(ExifKey(key)); pos != exifData.end() && sumToLong(*pos) > 32768) {
|
|
|
|
delTags = true;
|
|
|
|
delTags = true;
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
|
|
|
|
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
ed.erase(pos);
|
|
|
|
exifData.erase(pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case pttTag: {
|
|
|
|
case pttTag: {
|
|
|
|
if (delTags) {
|
|
|
|
if (delTags) {
|
|
|
|
if (auto pos = ed.findKey(ExifKey(key)); pos != ed.end()) {
|
|
|
|
if (auto pos = exifData.findKey(ExifKey(key)); pos != exifData.end()) {
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
|
|
|
|
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
ed.erase(pos);
|
|
|
|
exifData.erase(pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
@ -634,19 +631,19 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
EXV_WARNING << "Exif IFD " << key << " not encoded\n";
|
|
|
|
EXV_WARNING << "Exif IFD " << key << " not encoded\n";
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
eraseIfd(ed, Internal::groupId(key));
|
|
|
|
eraseIfd(exifData, Internal::groupId(key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Delete unknown tags larger than 4kB and known tags larger than 20kB.
|
|
|
|
// Delete unknown tags larger than 4kB and known tags larger than 20kB.
|
|
|
|
for (auto tag_iter = ed.begin(); tag_iter != ed.end();) {
|
|
|
|
for (auto tag_iter = exifData.begin(); tag_iter != exifData.end();) {
|
|
|
|
if ((tag_iter->size() > 4096 && tag_iter->tagName().substr(0, 2) == "0x") || tag_iter->size() > 20480) {
|
|
|
|
if ((tag_iter->size() > 4096 && tag_iter->tagName().substr(0, 2) == "0x") || tag_iter->size() > 20480) {
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
#ifndef SUPPRESS_WARNINGS
|
|
|
|
EXV_WARNING << "Exif tag " << tag_iter->key() << " not encoded\n";
|
|
|
|
EXV_WARNING << "Exif tag " << tag_iter->key() << " not encoded\n";
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
tag_iter = ed.erase(tag_iter);
|
|
|
|
tag_iter = exifData.erase(tag_iter);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
++tag_iter;
|
|
|
|
++tag_iter;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -654,7 +651,7 @@ WriteMethod ExifParser::encode(Blob& blob, const byte* pData, size_t size, ByteO
|
|
|
|
|
|
|
|
|
|
|
|
// Encode the remaining Exif tags again, don't care if it fits this time
|
|
|
|
// Encode the remaining Exif tags again, don't care if it fits this time
|
|
|
|
MemIo mio2;
|
|
|
|
MemIo mio2;
|
|
|
|
wm = TiffParserWorker::encode(mio2, pData, size, ed, emptyIptc, emptyXmp, Tag::root, TiffMapping::findEncoder,
|
|
|
|
wm = TiffParserWorker::encode(mio2, pData, size, exifData, emptyIptc, emptyXmp, Tag::root, TiffMapping::findEncoder,
|
|
|
|
&header, nullptr);
|
|
|
|
&header, nullptr);
|
|
|
|
append(blob, mio2.mmap(), mio2.size());
|
|
|
|
append(blob, mio2.mmap(), mio2.size());
|
|
|
|
#ifdef EXIV2_DEBUG_MESSAGES
|
|
|
|
#ifdef EXIV2_DEBUG_MESSAGES
|
|
|
|