- Reverted exifprint idx display
- Fixed/enhanced ExifParser::encode - Added API ExifData::erase(beg, end) - Enhanced logic to find matching tags in non-intrusive writing - Disabled sorting of IFD entries when writing makernote IFDs
This commit is contained in:
parent
d4aa0f49ad
commit
cbebc753fa
@ -28,9 +28,7 @@ try {
|
||||
}
|
||||
Exiv2::ExifData::const_iterator end = exifData.end();
|
||||
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) {
|
||||
std::cout << std::setw(3) << std::right
|
||||
<< i->idx() << " "
|
||||
<< std::setw(44) << std::setfill(' ') << std::left
|
||||
std::cout << std::setw(44) << std::setfill(' ') << std::left
|
||||
<< i->key() << " "
|
||||
<< "0x" << std::setw(4) << std::setfill('0') << std::right
|
||||
<< std::hex << i->tag() << " "
|
||||
|
||||
64
src/exif.cpp
64
src/exif.cpp
@ -57,6 +57,19 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
|
||||
// *****************************************************************************
|
||||
namespace {
|
||||
//! Unary predicate that matches an Exifdatum with a given IfdId.
|
||||
class FindExifdatum {
|
||||
public:
|
||||
//! Constructor, initializes the object with the IfdId to look for.
|
||||
FindExifdatum(Exiv2::IfdId ifdId) : ifdId_(ifdId) {}
|
||||
//! Returns true if IFD id matches.
|
||||
bool operator()(const Exiv2::Exifdatum& md) const { return ifdId_ == md.ifdId(); }
|
||||
|
||||
private:
|
||||
Exiv2::IfdId ifdId_;
|
||||
|
||||
}; // class FindExifdatum
|
||||
|
||||
/*!
|
||||
@brief Exif %Thumbnail image. This abstract base class provides the
|
||||
interface for the thumbnail image that is optionally embedded in
|
||||
@ -145,7 +158,7 @@ namespace {
|
||||
long sumToLong(const Exiv2::Exifdatum& md);
|
||||
|
||||
//! Helper function to delete all tags of a specific IFD from the metadata.
|
||||
void eraseIfd(Exiv2::ExifData& ed, const char* ifdItem);
|
||||
void eraseIfd(Exiv2::ExifData& ed, Exiv2::IfdId ifdId);
|
||||
|
||||
}
|
||||
|
||||
@ -353,17 +366,7 @@ namespace Exiv2 {
|
||||
|
||||
void ExifThumb::erase()
|
||||
{
|
||||
// Delete all Exif.Thumbnail.* (IFD1) metadata
|
||||
// Todo: Do it the C++ way(TM)
|
||||
ExifMetadata::iterator i = exifData_.begin();
|
||||
while (i != exifData_.end()) {
|
||||
if (i->ifdId() == ifd1Id) {
|
||||
i = exifData_.erase(i);
|
||||
}
|
||||
else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
eraseIfd(exifData_, ifd1Id);
|
||||
}
|
||||
|
||||
Exifdatum& ExifData::operator[](const std::string& key)
|
||||
@ -415,6 +418,11 @@ namespace Exiv2 {
|
||||
std::sort(exifMetadata_.begin(), exifMetadata_.end(), cmpMetadataByTag);
|
||||
}
|
||||
|
||||
ExifData::iterator ExifData::erase(ExifData::iterator beg, ExifData::iterator end)
|
||||
{
|
||||
return exifMetadata_.erase(beg, end);
|
||||
}
|
||||
|
||||
ExifData::iterator ExifData::erase(ExifData::iterator pos)
|
||||
{
|
||||
return exifMetadata_.erase(pos);
|
||||
@ -461,7 +469,6 @@ namespace Exiv2 {
|
||||
)
|
||||
{
|
||||
ExifData ed = exifData;
|
||||
ed.sortByKey();
|
||||
|
||||
// Delete IFD0 tags that are "not recorded" in compressed images
|
||||
// Reference: Exif 2.2 specs, 4.6.8 Tag Support Levels, section A
|
||||
@ -485,12 +492,12 @@ namespace Exiv2 {
|
||||
}
|
||||
|
||||
// Delete IFDs which do not occur in JPEGs
|
||||
static const char* filteredIfds[] = {
|
||||
"SubImage1",
|
||||
"SubImage2",
|
||||
"SubImage3",
|
||||
"SubImage4",
|
||||
"Image2"
|
||||
static const IfdId filteredIfds[] = {
|
||||
subImage1Id,
|
||||
subImage2Id,
|
||||
subImage3Id,
|
||||
subImage4Id,
|
||||
ifd2Id
|
||||
};
|
||||
for (unsigned int i = 0; i < EXV_COUNTOF(filteredIfds); ++i) {
|
||||
#ifdef DEBUG
|
||||
@ -527,8 +534,8 @@ namespace Exiv2 {
|
||||
{ pttIfd, "NikonPreview" },
|
||||
{ pttLen, "Exif.Olympus.ThumbnailLength" },
|
||||
{ pttTag, "Exif.Olympus.ThumbnailOffset" },
|
||||
{ pttTag, "Exif.Olympus.ThumbnailImage" },
|
||||
{ pttTag, "Exif.Olympus.Thumbnail" },
|
||||
{ pttLen, "Exif.Olympus.ThumbnailImage" },
|
||||
{ pttLen, "Exif.Olympus.Thumbnail" },
|
||||
{ pttLen, "Exif.Olympus2.ThumbnailLength" },
|
||||
{ pttTag, "Exif.Olympus2.ThumbnailOffset" },
|
||||
{ pttLen, "Exif.Olympus2.ThumbnailImage" },
|
||||
@ -575,7 +582,7 @@ namespace Exiv2 {
|
||||
#ifndef SUPPRESS_WARNINGS
|
||||
std::cerr << "Warning: Exif IFD " << filteredPvTags[i].key_ << " not encoded\n";
|
||||
#endif
|
||||
eraseIfd(ed, filteredPvTags[i].key_);
|
||||
eraseIfd(ed, ExifTags::ifdIdByIfdItem(filteredPvTags[i].key_));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -702,18 +709,9 @@ namespace {
|
||||
return sum;
|
||||
}
|
||||
|
||||
void eraseIfd(Exiv2::ExifData& ed, const char* ifdItem)
|
||||
void eraseIfd(Exiv2::ExifData& ed, Exiv2::IfdId ifdId)
|
||||
{
|
||||
// Prerequisite: Exif metadata must be sorted by IFD
|
||||
Exiv2::ExifData::iterator pos;
|
||||
for (pos = ed.begin(); pos != ed.end(); ++pos) {
|
||||
if (0 == strcmp(pos->ifdItem().c_str(), ifdItem)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (pos != ed.end() && 0 == strcmp(pos->ifdItem().c_str(), ifdItem)) {
|
||||
pos = ed.erase(pos);
|
||||
}
|
||||
ed.erase(std::remove_if(ed.begin(), ed.end(), FindExifdatum(ifdId)), ed.end());
|
||||
}
|
||||
//! @endcond
|
||||
}
|
||||
|
||||
@ -465,6 +465,12 @@ namespace Exiv2 {
|
||||
by this call.
|
||||
*/
|
||||
iterator erase(iterator pos);
|
||||
/*!
|
||||
@brief Remove all elements of the range \em beg, \em end, return the
|
||||
position of the next element. Note that iterators into
|
||||
the metadata are potentially invalidated by this call.
|
||||
*/
|
||||
iterator erase(iterator beg, iterator end);
|
||||
/*!
|
||||
@brief Delete all Exifdatum instances resulting in an empty container.
|
||||
Note that this also removes thumbnails.
|
||||
|
||||
@ -734,9 +734,11 @@ namespace Exiv2 {
|
||||
// Size of all directory entries, without values and additional data
|
||||
const uint32_t sizeDir = 2 + 12 * compCount + (hasNext_ ? 4 : 0);
|
||||
|
||||
// TIFF standard requires IFD entries to be sorted in ascending order by tag
|
||||
std::sort(components_.begin(), components_.end(), cmpTagLt);
|
||||
|
||||
// TIFF standard requires IFD entries to be sorted in ascending order by tag.
|
||||
// Not sorting makernote directories sometimes preserves them better.
|
||||
if (group() < Group::mn) {
|
||||
std::sort(components_.begin(), components_.end(), cmpTagLt);
|
||||
}
|
||||
// Size of IFD values and additional data
|
||||
uint32_t sizeValue = 0;
|
||||
uint32_t sizeData = 0;
|
||||
@ -1020,6 +1022,7 @@ namespace Exiv2 {
|
||||
|
||||
// Tags must be sorted in ascending order
|
||||
std::sort(elements_.begin(), elements_.end(), cmpTagLt);
|
||||
|
||||
uint32_t seq = 0;
|
||||
for (Components::const_iterator i = elements_.begin(); i != elements_.end(); ++i) {
|
||||
// Skip deleted entries at the end of the array
|
||||
|
||||
@ -55,18 +55,23 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
|
||||
// *****************************************************************************
|
||||
namespace {
|
||||
//! Unary predicate that matches an Exifdatum with a given index.
|
||||
class FindExifdatumByIdx {
|
||||
//! Unary predicate that matches an Exifdatum with a given group and index.
|
||||
class FindExifdatum {
|
||||
public:
|
||||
//! Constructor, initializes the object with the index to look for.
|
||||
FindExifdatumByIdx(int idx) : idx_(idx) {}
|
||||
//! Returns true if the index matches.
|
||||
bool operator()(const Exiv2::Exifdatum& md) const { return idx_ == md.idx(); }
|
||||
//! Constructor, initializes the object with the group and index to look for.
|
||||
FindExifdatum(uint16_t group, int idx)
|
||||
: groupName_(Exiv2::Internal::tiffGroupName(group)), idx_(idx) {}
|
||||
//! Returns true if group and index match.
|
||||
bool operator()(const Exiv2::Exifdatum& md) const
|
||||
{
|
||||
return idx_ == md.idx() && 0 == strcmp(md.ifdItem().c_str(), groupName_);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* groupName_;
|
||||
int idx_;
|
||||
|
||||
}; // class FindExifdatumByIdx
|
||||
}; // class FindExifdatum
|
||||
}
|
||||
|
||||
// *****************************************************************************
|
||||
@ -626,24 +631,27 @@ namespace Exiv2 {
|
||||
ExifData::iterator pos = exifData_.end();
|
||||
const Exifdatum* ed = datum;
|
||||
if (ed == 0) {
|
||||
// Attempting non-intrusive writing. Look for the corresponding Exif
|
||||
// datum by index rather than the key to be able to handle duplicate tags.
|
||||
pos = std::find_if(exifData_.begin(), exifData_.end(),
|
||||
FindExifdatumByIdx(object->idx()));
|
||||
// Non-intrusive writing: find matching tag
|
||||
ExifKey key(object->tag(), tiffGroupName(object->group()));
|
||||
if (pos == exifData_.end() || key.key() != pos->key()) {
|
||||
#ifdef DEBUG
|
||||
if (pos == exifData_.end()) { // metadatum not found
|
||||
std::cerr << "DELETING " << key << ", idx = " << object->idx() << "\n";
|
||||
pos = exifData_.findKey(key);
|
||||
if (pos != exifData_.end()) {
|
||||
ed = &(*pos);
|
||||
if (object->idx() != pos->idx()) {
|
||||
// Try to find exact match (in case of duplicate tags)
|
||||
ExifData::iterator pos2 =
|
||||
std::find_if(exifData_.begin(), exifData_.end(),
|
||||
FindExifdatum(object->group(), object->idx()));
|
||||
if (pos2 != exifData_.end() && pos2->key() == key.key()) {
|
||||
ed = &(*pos2);
|
||||
pos = pos2; // make sure we delete the correct tag below
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::cerr << "KEY/IDX MISMATCH " << key << ", idx = " << object->idx() << "\n";
|
||||
}
|
||||
#endif
|
||||
setDirty();
|
||||
}
|
||||
else {
|
||||
ed = &(*pos);
|
||||
setDirty();
|
||||
#ifdef DEBUG
|
||||
std::cerr << "DELETING " << key << ", idx = " << object->idx() << "\n";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -669,7 +677,6 @@ namespace Exiv2 {
|
||||
#ifdef DEBUG
|
||||
std::cerr << "\n";
|
||||
#endif
|
||||
|
||||
} // TiffEncoder::encodeTiffComponent
|
||||
|
||||
void TiffEncoder::encodeArrayElement(TiffArrayElement* object, const Exifdatum* datum)
|
||||
@ -1038,8 +1045,7 @@ namespace Exiv2 {
|
||||
pLast_(pData + size),
|
||||
pRoot_(pRoot),
|
||||
pState_(state.release()),
|
||||
pOrigState_(pState_),
|
||||
idxSeq_(0)
|
||||
pOrigState_(pState_)
|
||||
{
|
||||
assert(pData_);
|
||||
assert(size_ > 0);
|
||||
@ -1145,9 +1151,9 @@ namespace Exiv2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
int TiffReader::nextIdx()
|
||||
int TiffReader::nextIdx(uint16_t group)
|
||||
{
|
||||
return ++idxSeq_;
|
||||
return ++idxSeq_[group];
|
||||
}
|
||||
|
||||
void TiffReader::visitDirectory(TiffDirectory* object)
|
||||
@ -1428,7 +1434,7 @@ namespace Exiv2 {
|
||||
object->setValue(v);
|
||||
object->setData(pData, size);
|
||||
object->setOffset(offset);
|
||||
object->setIdx(nextIdx());
|
||||
object->setIdx(nextIdx(object->group()));
|
||||
|
||||
} // TiffReader::readTiffEntry
|
||||
|
||||
@ -1485,7 +1491,7 @@ namespace Exiv2 {
|
||||
object->setValue(v);
|
||||
object->setData(pData, size);
|
||||
object->setOffset(0);
|
||||
object->setIdx(nextIdx());
|
||||
object->setIdx(nextIdx(object->group()));
|
||||
object->setCount(1);
|
||||
|
||||
} // TiffReader::visitArrayElement
|
||||
|
||||
@ -615,8 +615,8 @@ namespace Exiv2 {
|
||||
void resetState();
|
||||
//! Check IFD directory pointer \em start for circular reference
|
||||
bool circularReference(const byte* start, uint16_t group);
|
||||
//! Return the next idx sequence number
|
||||
int nextIdx();
|
||||
//! Return the next idx sequence number for \em group
|
||||
int nextIdx(uint16_t group);
|
||||
//@}
|
||||
|
||||
//! @name Accessors
|
||||
@ -632,6 +632,7 @@ namespace Exiv2 {
|
||||
|
||||
private:
|
||||
typedef std::map<const byte*, uint16_t> DirList;
|
||||
typedef std::map<uint16_t, int> IdxSeq;
|
||||
|
||||
// DATA
|
||||
const byte* pData_; //!< Pointer to the memory buffer
|
||||
@ -641,7 +642,7 @@ namespace Exiv2 {
|
||||
TiffRwState* pState_; //!< State class
|
||||
TiffRwState* pOrigState_; //!< State class as set in the c'tor
|
||||
DirList dirList_; //!< List of IFD pointers and their groups
|
||||
int idxSeq_; //!< Sequence used for the entry's idx
|
||||
IdxSeq idxSeq_; //!< Sequences for group, used for the entry's idx
|
||||
|
||||
}; // class TiffReader
|
||||
|
||||
|
||||
@ -318,11 +318,9 @@ Exif.Photo.MaxApertureValue 0x9205 Exif Rational 1
|
||||
Exif.Photo.MeteringMode 0x9207 Exif Short 6 1 2 3 4 5 6
|
||||
Exif.Photo.Flash 0x9209 Exif Short 1 24
|
||||
Exif.Photo.FocalLength 0x920a Exif Rational 1 682/32
|
||||
Exif.Photo.MakerNote 0x927c Exif Undefined 450 12 0 0 0 3 0 6 0 0 0 88 3 0 0 0 0 3 0 4 0 0 0 100 3 0 0 1 0 3 0 40 0 0 0 108 3 0 0 2 0 3 0 4 0 0 0 188 3 0 0 3 0 3 0 4 0 0 0 196 3 0 0 4 0 3 0 27 0 0 0 204 3 0 0 6 0 2 0 32 0 0 0 2 4 0 0 7 0 2 0 24 0 0 0 34 4 0 0 8 0 4 0 1 0 0 0 59 225 17 0 9 0 2 0 32 0 0 0 58 4 0 0 13 0 3 0 21 0 0 0 90 4 0 0 16 0 4 0 1 0 0 0 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 80 0 2 0 0 0 5 0 1 0 0 0 0 0 4 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 17 0 5 0 1 0 3 48 1 0 255 255 255 255 170 2 227 0 32 0 149 0 192 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 49 0 224 8 224 8 0 0 1 0 2 0 170 2 30 1 215 0 0 0 0 0 0 0 0 0 54 0 0 0 160 0 20 1 149 0 31 1 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 2 48 0 0 0 0 0 0 1 0 14 3 0 0 149 0 33 1 0 0 0 0 0 0 250 0 73 77 71 58 80 111 119 101 114 83 104 111 116 32 83 52 48 32 74 80 69 71 0 0 0 0 0 0 0 0 0 0 70 105 114 109 119 97 114 101 32 86 101 114 115 105 111 110 32 49 46 49 48 0 0 0 65 110 100 114 101 97 115 32 72 117 103 103 101 108 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0 3 0 1 128 122 1 1 128 0 0 0 0 0 0 3 1 2 0 0 0 10 0 0 0 0 0 0 0 57 0 198 0 5 0 0 0 0 0 0 0
|
||||
Exif.Photo.MakerNote 0x927c Exif Undefined 450 12 0 1 0 3 0 40 0 0 0 88 3 0 0 2 0 3 0 4 0 0 0 168 3 0 0 3 0 3 0 4 0 0 0 176 3 0 0 4 0 3 0 27 0 0 0 184 3 0 0 0 0 3 0 6 0 0 0 238 3 0 0 0 0 3 0 4 0 0 0 250 3 0 0 6 0 2 0 32 0 0 0 2 4 0 0 7 0 2 0 24 0 0 0 34 4 0 0 8 0 4 0 1 0 0 0 59 225 17 0 9 0 2 0 32 0 0 0 58 4 0 0 16 0 4 0 1 0 0 0 0 0 17 1 13 0 3 0 21 0 0 0 90 4 0 0 0 0 0 0 80 0 2 0 0 0 5 0 1 0 0 0 0 0 4 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 17 0 5 0 1 0 3 48 1 0 255 255 255 255 170 2 227 0 32 0 149 0 192 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 49 0 224 8 224 8 0 0 1 0 2 0 170 2 30 1 215 0 0 0 0 0 0 0 0 0 54 0 0 0 160 0 20 1 149 0 31 1 0 0 0 0 0 0 0 0 6 0 0 0 0 0 0 0 2 48 0 0 0 0 0 0 1 0 14 3 0 0 149 0 33 1 0 0 0 0 0 0 250 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 73 77 71 58 80 111 119 101 114 83 104 111 116 32 83 52 48 32 74 80 69 71 0 0 0 0 0 0 0 0 0 0 70 105 114 109 119 97 114 101 32 86 101 114 115 105 111 110 32 49 46 49 48 0 0 0 65 110 100 114 101 97 115 32 72 117 103 103 101 108 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 42 0 3 0 1 128 122 1 1 128 0 0 0 0 0 0 3 1 2 0 0 0 10 0 0 0 0 0 0 0 57 0 198 0 5 0 0 0 0 0 0 0
|
||||
Exif.MakerNote.Offset 0x0001 Makernote Long 1 706
|
||||
Exif.MakerNote.ByteOrder 0x0002 Makernote Ascii 3 II
|
||||
Exif.Canon.0x0000 0x0000 Makernote Short 6 0 0 0 0 0 0
|
||||
Exif.Canon.0x0000 0x0000 Makernote Short 4 0 0 0 0
|
||||
Exif.CanonCs.0x0000 0x0000 Makernote Short 1 80
|
||||
Exif.CanonCs.Macro 0x0001 Makernote Short 1 2
|
||||
Exif.CanonCs.Selftimer 0x0002 Makernote Short 1 0
|
||||
@ -390,12 +388,14 @@ Exif.CanonSi.0x0017 0x0017 Makernote Short 1
|
||||
Exif.CanonSi.0x0018 0x0018 Makernote Short 1 0
|
||||
Exif.CanonSi.0x0019 0x0019 Makernote Short 1 0
|
||||
Exif.CanonSi.0x001a 0x001a Makernote Short 1 250
|
||||
Exif.Canon.0x0000 0x0000 Makernote Short 6 0 0 0 0 0 0
|
||||
Exif.Canon.0x0000 0x0000 Makernote Short 4 0 0 0 0
|
||||
Exif.Canon.ImageType 0x0006 Makernote Ascii 32 IMG:PowerShot S40 JPEG
|
||||
Exif.Canon.FirmwareVersion 0x0007 Makernote Ascii 24 Firmware Version 1.10
|
||||
Exif.Canon.ImageNumber 0x0008 Makernote Long 1 1171771
|
||||
Exif.Canon.OwnerName 0x0009 Makernote Ascii 32 Andreas Huggel
|
||||
Exif.Canon.0x000d 0x000d Makernote Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0
|
||||
Exif.Canon.ModelID 0x0010 Makernote Long 1 17891328
|
||||
Exif.Canon.0x000d 0x000d Makernote Short 21 42 3 32769 378 32769 0 0 0 259 2 0 10 0 0 0 57 198 5 0 0 0
|
||||
Exif.Photo.UserComment 0x9286 Exif Undefined 264 | ||||