diff --git a/src/actions.cpp b/src/actions.cpp index 83710e6a..b71d68cf 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -665,8 +665,16 @@ namespace Action { if (Params::instance().printItems_ & Params::prType) { if (!first) std::cout << " "; first = false; - std::cout << std::setw(9) << std::setfill(' ') << std::left - << md->typeName(); + std::cout << std::setw(9) << std::setfill(' ') << std::left; + const char* tn = md->typeName(); + if (tn) { + std::cout << tn; + } + else { + std::ostringstream os; + os << "0x" << std::setw(4) << std::setfill('0') << std::hex << md->typeId(); + std::cout << os.str(); + } } if (Params::instance().printItems_ & Params::prCount) { if (!first) std::cout << " "; diff --git a/src/tiffcomposite.cpp b/src/tiffcomposite.cpp index 79b93501..6a354ac2 100644 --- a/src/tiffcomposite.cpp +++ b/src/tiffcomposite.cpp @@ -145,31 +145,31 @@ namespace Exiv2 { { } - TiffEntryBase::TiffEntryBase(uint16_t tag, uint16_t group, TypeId typeId) + TiffEntryBase::TiffEntryBase(uint16_t tag, uint16_t group, TiffType tiffType) : TiffComponent(tag, group), - type_(typeId), count_(0), offset_(0), + tiffType_(tiffType), count_(0), offset_(0), size_(0), pData_(0), isMalloced_(false), pValue_(0) { } TiffSubIfd::TiffSubIfd(uint16_t tag, uint16_t group, uint16_t newGroup) - : TiffEntryBase(tag, group, unsignedLong), newGroup_(newGroup) + : TiffEntryBase(tag, group, ttUnsignedLong), newGroup_(newGroup) { } TiffMnEntry::TiffMnEntry(uint16_t tag, uint16_t group, uint16_t mnGroup) - : TiffEntryBase(tag, group, undefined), mnGroup_(mnGroup), mn_(0) + : TiffEntryBase(tag, group, ttUndefined), mnGroup_(mnGroup), mn_(0) { } TiffArrayEntry::TiffArrayEntry(uint16_t tag, uint16_t group, uint16_t elGroup, - TypeId elTypeId, + TiffType elTiffType, bool addSizeElement) - : TiffEntryBase(tag, group, elTypeId), - elSize_(static_cast(TypeInfo::typeSize(elTypeId))), + : TiffEntryBase(tag, group, elTiffType), + elSize_(static_cast(TypeInfo::typeSize(toTypeId(elTiffType, 0, elGroup)))), elGroup_(elGroup), addSizeElement_(addSizeElement) { @@ -241,7 +241,7 @@ namespace Exiv2 { void TiffEntryBase::setValue(Value::AutoPtr value) { - type_ = static_cast(value->typeId()); + tiffType_ = toTiffType(value->typeId()); count_ = value->count(); delete pValue_; pValue_ = value.release(); @@ -643,7 +643,7 @@ namespace Exiv2 { uint32_t TiffMnEntry::doCount() const { // Count of tag Exif.Photo.MakerNote is the size of the Makernote in bytes - assert(typeId() == undefined); + assert(tiffType() == ttUndefined); return size(); } @@ -809,9 +809,9 @@ namespace Exiv2 { TiffEntryBase* pDirEntry = dynamic_cast(pTiffComponent); assert(pDirEntry); byte buf[8]; - us2Data(buf, pDirEntry->tag(), byteOrder); - us2Data(buf + 2, pDirEntry->typeId(), byteOrder); - ul2Data(buf + 4, pDirEntry->count(), byteOrder); + us2Data(buf, pDirEntry->tag(), byteOrder); + us2Data(buf + 2, pDirEntry->tiffType(), byteOrder); + ul2Data(buf + 4, pDirEntry->count(), byteOrder); append(blob, buf, 8); if (pDirEntry->size() > 4) { pDirEntry->setOffset(offset + static_cast(valueIdx)); @@ -851,18 +851,18 @@ namespace Exiv2 { uint32_t TiffEntryBase::writeOffset(byte* buf, int32_t offset, - TypeId type, + TiffType tiffType, ByteOrder byteOrder) { uint32_t rc = 0; - switch(type) { - case unsignedShort: - case signedShort: + switch(tiffType) { + case ttUnsignedShort: + case ttSignedShort: if (static_cast(offset) > 0xffff) throw Error(26); rc = s2Data(buf, static_cast(offset), byteOrder); break; - case unsignedLong: - case signedLong: + case ttUnsignedLong: + case ttSignedLong: rc = l2Data(buf, static_cast(offset), byteOrder); break; default: @@ -889,7 +889,7 @@ namespace Exiv2 { + static_cast(dataIdx); idx += writeOffset(buf.pData_ + idx, offset + newDataIdx, - typeId(), + tiffType(), byteOrder); } append(blob, buf.pData_, buf.size_); @@ -906,7 +906,7 @@ namespace Exiv2 { DataBuf buf(strips_.size() * 4); uint32_t idx = 0; for (Strips::const_iterator i = strips_.begin(); i != strips_.end(); ++i) { - idx += writeOffset(buf.pData_ + idx, offset + imageIdx, typeId(), byteOrder); + idx += writeOffset(buf.pData_ + idx, offset + imageIdx, tiffType(), byteOrder); imageIdx += i->second; } append(blob, buf.pData_, buf.size_); @@ -923,7 +923,7 @@ namespace Exiv2 { DataBuf buf(ifds_.size() * 4); uint32_t idx = 0; for (Ifds::const_iterator i = ifds_.begin(); i != ifds_.end(); ++i) { - idx += writeOffset(buf.pData_ + idx, offset + dataIdx, typeId(), byteOrder); + idx += writeOffset(buf.pData_ + idx, offset + dataIdx, tiffType(), byteOrder); dataIdx += (*i)->size(); } append(blob, buf.pData_, buf.size_); @@ -1004,7 +1004,7 @@ namespace Exiv2 { { Value const* pv = pValue(); if (!pv || pv->count() == 0) return 0; - if (pv->typeId() != elTypeId_) { + if (toTiffType(pv->typeId()) != elTiffType_) { throw Error(51, tag()); } DataBuf buf(pv->size()); @@ -1236,6 +1236,29 @@ namespace Exiv2 { // ************************************************************************* // free functions + TypeId toTypeId(TiffType tiffType, uint16_t tag, uint16_t group) + { + TypeId ti = TypeId(tiffType); + // On the fly type conversion for Exif.Photo.UserComment + if (tag == 0x9286 && group == Group::exif && ti == undefined) { + ti = comment; + } + return ti; + } + + TiffType toTiffType(TypeId typeId) + { + if (static_cast(typeId) > 0xffff) { +#ifndef SUPPRESS_WARNINGS + std::cerr << "Error: '" << TypeInfo::typeName(typeId) + << "' is not a valid Exif (TIFF) type; using type '" + << TypeInfo::typeName(undefined) << "'.\n"; +#endif + return undefined; + } + return static_cast(typeId); + } + bool cmpTagLt(TiffComponent const* lhs, TiffComponent const* rhs) { assert(lhs != 0); diff --git a/src/tiffcomposite_int.hpp b/src/tiffcomposite_int.hpp index 721ef0be..76799acc 100644 --- a/src/tiffcomposite_int.hpp +++ b/src/tiffcomposite_int.hpp @@ -49,6 +49,27 @@ namespace Exiv2 { // ***************************************************************************** // class definitions + //! TIFF value type. + typedef uint16_t TiffType; + + const TiffType ttUnsignedByte = 1; //!< Exif BYTE type + const TiffType ttAsciiString = 2; //!< Exif ASCII type + const TiffType ttUnsignedShort = 3; //!< Exif SHORT type + const TiffType ttUnsignedLong = 4; //!< Exif LONG type + const TiffType ttUnsignedRational = 5; //!< Exif RATIONAL type + const TiffType ttSignedByte = 6; //!< Exif SBYTE type + const TiffType ttUndefined = 7; //!< Exif UNDEFINED type + const TiffType ttSignedShort = 8; //!< Exif SSHORT type + const TiffType ttSignedLong = 9; //!< Exif SLONG type + const TiffType ttSignedRational =10; //!< Exif SRATIONAL type + const TiffType ttTiffFloat =11; //!< TIFF FLOAT type + const TiffType ttTiffDouble =12; //!< TIFF DOUBLE type + + //! Convert the \em tiffType of a \em tag and \em group to an Exiv2 \em typeId. + TypeId toTypeId(TiffType tiffType, uint16_t tag, uint16_t group); + //! Convert the %Exiv2 \em typeId to a TIFF value type. + TiffType toTiffType(TypeId typeId); + /*! Known TIFF groups @@ -362,7 +383,7 @@ namespace Exiv2 { //! @name Creators //@{ //! Default constructor - TiffEntryBase(uint16_t tag, uint16_t group, TypeId typeId =invalidTypeId); + TiffEntryBase(uint16_t tag, uint16_t group, TiffType tiffType =ttUndefined); //! Virtual destructor. virtual ~TiffEntryBase(); //@} @@ -396,8 +417,8 @@ namespace Exiv2 { //! @name Accessors //@{ - //! Return the Exiv2 type which corresponds to the field type - TypeId typeId() const { return TypeId(type_); } + //! Return the TIFF type + TiffType tiffType() const { return tiffType_; } /*! @brief Return the offset to the data area relative to the base for the component (usually the start of the TIFF header) @@ -470,7 +491,7 @@ namespace Exiv2 { //! Helper function to write an \em offset to a preallocated binary buffer static uint32_t writeOffset(byte* buf, int32_t offset, - TypeId type, + TiffType tiffType, ByteOrder byteOrder); private: @@ -481,8 +502,8 @@ namespace Exiv2 { //@} // DATA - uint16_t type_; //!< Field Type - uint32_t count_; //!< The number of values of the indicated Type + TiffType tiffType_; //!< Field TIFF type + uint32_t count_; //!< The number of values of the indicated type int32_t offset_; //!< Offset to the data area /*! Size of the data buffer holding the value in bytes, there is no @@ -1033,7 +1054,7 @@ namespace Exiv2 { TiffArrayEntry(uint16_t tag, uint16_t group, uint16_t elGroup, - TypeId elTypeId, + TiffType elTiffType, bool addSizeElement); //! Virtual destructor virtual ~TiffArrayEntry(); @@ -1041,7 +1062,7 @@ namespace Exiv2 { //! @name Accessors //@{ - //! Return the type for the array elements + //! Return the size of the array elements uint16_t elSize() const { return elSize_; } //! Return the group for the array elements uint16_t elGroup() const { return elGroup_; } @@ -1107,10 +1128,10 @@ namespace Exiv2 { //! Constructor TiffArrayElement(uint16_t tag, uint16_t group, - TypeId elTypeId, + TiffType elTiffType, ByteOrder elByteOrder) : TiffEntryBase(tag, group), - elTypeId_(elTypeId), + elTiffType_(elTiffType), elByteOrder_(elByteOrder) {} //! Virtual destructor. virtual ~TiffArrayElement() {} @@ -1118,7 +1139,7 @@ namespace Exiv2 { //! @name Accessors //@{ - TypeId elTypeId() const { return elTypeId_; } + TiffType elTiffType() const { return elTiffType_; } ByteOrder elByteOrder() const { return elByteOrder_; } //@} @@ -1151,7 +1172,7 @@ namespace Exiv2 { private: // DATA - TypeId elTypeId_; //!< Type of the element + TiffType elTiffType_; //!< TIFF type of the element ByteOrder elByteOrder_; //!< Byte order to read/write the element }; // class TiffArrayElement @@ -1188,30 +1209,30 @@ namespace Exiv2 { const TiffStructure* ts); //! Function to create and initialize a new array entry - template + template TiffComponent::AutoPtr newTiffArrayEntry(uint16_t tag, const TiffStructure* ts) { assert(ts); return TiffComponent::AutoPtr( - new TiffArrayEntry(tag, ts->group_, ts->newGroup_, typeId, addSizeElement)); + new TiffArrayEntry(tag, ts->group_, ts->newGroup_, tiffType, addSizeElement)); } //! Function to create and initialize a new array element - template + template TiffComponent::AutoPtr newTiffArrayElement(uint16_t tag, const TiffStructure* ts) { assert(ts); return TiffComponent::AutoPtr( - new TiffArrayElement(tag, ts->group_, typeId, byteOrder)); + new TiffArrayElement(tag, ts->group_, tiffType, byteOrder)); } - template + template TiffComponent::AutoPtr newTiffArrayElement(uint16_t tag, const TiffStructure* ts) { - return newTiffArrayElement(tag, ts); + return newTiffArrayElement(tag, ts); } //! Function to create and initialize a new TIFF entry for a thumbnail (data) diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp index 276b8e85..ce335d4c 100644 --- a/src/tiffimage.cpp +++ b/src/tiffimage.cpp @@ -333,8 +333,8 @@ namespace Exiv2 { // Olympus makernote - some Olympus cameras use Minolta structures // Todo: Adding such tags will not work (maybe result in a Minolta makernote), need separate groups - { 0x0001, Group::olympmn, Group::minocso, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x0003, Group::olympmn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0001, Group::olympmn, Group::minocso, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0003, Group::olympmn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry }, { Tag::next, Group::olympmn, Group::ignr, 0x927c, Group::exif, newTiffDirectory }, { Tag::all, Group::olympmn, Group::olympmn, 0x927c, Group::exif, newTiffEntry }, @@ -343,20 +343,20 @@ namespace Exiv2 { { Tag::all, Group::fujimn, Group::fujimn, 0x927c, Group::exif, newTiffEntry }, // Canon makernote - { 0x0001, Group::canonmn, Group::canoncs, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x0004, Group::canonmn, Group::canonsi, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x0005, Group::canonmn, Group::canonpa, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x000f, Group::canonmn, Group::canoncf, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x0012, Group::canonmn, Group::canonpi, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0001, Group::canonmn, Group::canoncs, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0004, Group::canonmn, Group::canonsi, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0005, Group::canonmn, Group::canonpa, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x000f, Group::canonmn, Group::canoncf, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0012, Group::canonmn, Group::canonpi, 0x927c, Group::exif, newTiffArrayEntry }, { Tag::next, Group::canonmn, Group::ignr, 0x927c, Group::exif, newTiffDirectory }, { Tag::all, Group::canonmn, Group::canonmn, 0x927c, Group::exif, newTiffEntry }, // Canon makernote composite tags - { Tag::all, Group::canoncs, Group::canoncs, 0x0001, Group::canonmn, newTiffArrayElement }, - { Tag::all, Group::canonsi, Group::canonsi, 0x0004, Group::canonmn, newTiffArrayElement }, - { Tag::all, Group::canonpa, Group::canonpa, 0x0005, Group::canonmn, newTiffArrayElement }, - { Tag::all, Group::canoncf, Group::canoncf, 0x000f, Group::canonmn, newTiffArrayElement }, - { Tag::all, Group::canonpi, Group::canonpi, 0x0012, Group::canonmn, newTiffArrayElement }, + { Tag::all, Group::canoncs, Group::canoncs, 0x0001, Group::canonmn, newTiffArrayElement }, + { Tag::all, Group::canonsi, Group::canonsi, 0x0004, Group::canonmn, newTiffArrayElement }, + { Tag::all, Group::canonpa, Group::canonpa, 0x0005, Group::canonmn, newTiffArrayElement }, + { Tag::all, Group::canoncf, Group::canoncf, 0x000f, Group::canonmn, newTiffArrayElement }, + { Tag::all, Group::canonpi, Group::canonpi, 0x0012, Group::canonmn, newTiffArrayElement }, // Nikon1 makernote { Tag::next, Group::nikon1mn, Group::ignr, 0x927c, Group::exif, newTiffDirectory }, @@ -391,20 +391,20 @@ namespace Exiv2 { { Tag::all, Group::sony2mn, Group::sony2mn, 0x927c, Group::exif, newTiffEntry }, // Minolta makernote - { 0x0001, Group::minoltamn, Group::minocso, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x0003, Group::minoltamn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry }, - { 0x0004, Group::minoltamn, Group::minocs7, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0001, Group::minoltamn, Group::minocso, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0003, Group::minoltamn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0004, Group::minoltamn, Group::minocs7, 0x927c, Group::exif, newTiffArrayEntry }, { 0x0088, Group::minoltamn, Group::minoltamn, 0x927c, Group::exif, newTiffThumbData<0x0089, Group::minoltamn> }, { 0x0089, Group::minoltamn, Group::minoltamn, 0x927c, Group::exif, newTiffThumbSize<0x0088, Group::minoltamn> }, - { 0x0114, Group::minoltamn, Group::minocs5, 0x927c, Group::exif, newTiffArrayEntry }, + { 0x0114, Group::minoltamn, Group::minocs5, 0x927c, Group::exif, newTiffArrayEntry }, { Tag::next, Group::minoltamn, Group::ignr, 0x927c, Group::exif, newTiffDirectory }, { Tag::all, Group::minoltamn, Group::minoltamn, 0x927c, Group::exif, newTiffEntry }, // Minolta makernote composite tags - { Tag::all, Group::minocso, Group::minocso, 0x0001, Group::minoltamn, newTiffArrayElement }, - { Tag::all, Group::minocsn, Group::minocsn, 0x0003, Group::minoltamn, newTiffArrayElement }, - { Tag::all, Group::minocs7, Group::minocs7, 0x0004, Group::minoltamn, newTiffArrayElement }, - { Tag::all, Group::minocs5, Group::minocs5, 0x0114, Group::minoltamn, newTiffArrayElement }, + { Tag::all, Group::minocso, Group::minocso, 0x0001, Group::minoltamn, newTiffArrayElement }, + { Tag::all, Group::minocsn, Group::minocsn, 0x0003, Group::minoltamn, newTiffArrayElement }, + { Tag::all, Group::minocs7, Group::minocs7, 0x0004, Group::minoltamn, newTiffArrayElement }, + { Tag::all, Group::minocs5, Group::minocs5, 0x0114, Group::minoltamn, newTiffArrayElement }, // Tags which are not de/encoded { Tag::next, Group::ignr, Group::ignr, Tag::none, Group::none, newTiffDirectory }, diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp index 741cc67c..34f99fca 100644 --- a/src/tiffvisitor.cpp +++ b/src/tiffvisitor.cpp @@ -348,8 +348,11 @@ namespace Exiv2 { { assert(object != 0); + // Don't decode the entry if value is not set + if (!object->pValue()) return; + // Remember NewSubfileType - if (object->tag() == 0x00fe && object->pValue()) { + if (object->tag() == 0x00fe) { groupType_[object->group()] = object->pValue()->toLong(); } @@ -567,8 +570,8 @@ namespace Exiv2 { assert(pTiffComponent); TiffEntryBase* pTiffEntry = dynamic_cast(pTiffComponent); assert(pTiffEntry); - us2Data(buf + 2, pTiffEntry->typeId(), byteOrder); - ul2Data(buf + 4, pTiffEntry->count(), byteOrder); + us2Data(buf + 2, pTiffEntry->tiffType(), byteOrder); + ul2Data(buf + 4, pTiffEntry->count(), byteOrder); // Move data to offset field, if it fits and is not yet there. if (pTiffEntry->size() <= 4 && buf + 8 != pTiffEntry->pData()) { #ifdef DEBUG @@ -997,7 +1000,7 @@ namespace Exiv2 { os_ << px << tiffGroupName(object->group()) << " " << _("tag") << " 0x" << std::setw(4) << std::setfill('0') << std::hex << std::right << object->tag() - << ", " << _("type") << " " << TypeInfo::typeName(object->typeId()) + << ", " << _("type") << " 0x" << std::hex << object->tiffType() << ", " << std::dec << object->count() << " "<< _("component"); if (object->count() > 1) os_ << "s"; os_ << " in " << object->size() << " " << _("bytes"); @@ -1212,8 +1215,8 @@ namespace Exiv2 { assert(object != 0); readTiffEntry(object); - if ((object->typeId() == unsignedLong || object->typeId() == signedLong) - && object->count() >= 1) { + if ( (object->tiffType() == ttUnsignedLong || object->tiffType() == ttSignedLong) + && object->count() >= 1) { for (uint32_t i = 0; i < object->count(); ++i) { int32_t offset = getLong(object->pData() + 4*i, byteOrder()); if ( baseOffset() + offset > size_ @@ -1302,8 +1305,7 @@ namespace Exiv2 { void TiffReader::visitIfdMakernoteEnd(TiffIfdMakernote* /*object*/) { - // Reset state (byte order, create function, offset) back to that - // for the image + // Reset state (byte order, create function, offset) back to that for the image resetState(); } // TiffReader::visitIfdMakernoteEnd @@ -1324,17 +1326,18 @@ namespace Exiv2 { } // Component already has tag p += 2; - uint16_t type = getUShort(p, byteOrder()); - long typeSize = TypeInfo::typeSize(TypeId(type)); + TiffType tiffType = getUShort(p, byteOrder()); + TypeId typeId = toTypeId(tiffType, object->tag(), object->group()); + long typeSize = TypeInfo::typeSize(typeId); if (0 == typeSize) { #ifndef SUPPRESS_WARNINGS - std::cerr << "Error: Directory " << tiffGroupName(object->group()) + std::cerr << "Warning: Directory " << tiffGroupName(object->group()) << ", entry 0x" << std::setw(4) << std::setfill('0') << std::hex << object->tag() - << " has an invalid type " << std::dec << type - << "; skipping entry.\n"; + << " has unknown Exif (TIFF) type " << std::dec << tiffType + << "; setting type size 1.\n"; #endif - return; + typeSize = 1; } p += 2; uint32_t count = getULong(p, byteOrder()); @@ -1353,8 +1356,7 @@ namespace Exiv2 { uint32_t size = typeSize * count; uint32_t offset = getLong(p, byteOrder()); byte* pData = p; - if (size > 4) { - if (baseOffset() + offset >= size_) { + if (size > 4 && baseOffset() + offset >= size_) { #ifndef SUPPRESS_WARNINGS std::cerr << "Error: Offset of " << "directory " << tiffGroupName(object->group()) @@ -1365,12 +1367,13 @@ namespace Exiv2 { << std::setfill('0') << std::hex << offset << "; truncating the entry\n"; #endif - return; - } + size = 0; + } + if (size > 4) { pData = const_cast(pData_) + baseOffset() + offset; if (size > static_cast(pLast_ - pData)) { #ifndef SUPPRESS_WARNINGS - std::cerr << "Warning: Upper boundary of data for " + std::cerr << "Error: Upper boundary of data for " << "directory " << tiffGroupName(object->group()) << ", entry 0x" << std::setw(4) << std::setfill('0') << std::hex << object->tag() @@ -1387,16 +1390,7 @@ namespace Exiv2 { // Todo: adjust count, make size a multiple of typeSize } } - // On the fly type conversion for Exif.Photo.UserComment - // Todo: This should be somewhere else, maybe in a Value factory - // which takes a Key and Type - TypeId t = TypeId(type); - if ( object->tag() == 0x9286 - && object->group() == Group::exif - && t == undefined) { - t = comment; - } - Value::AutoPtr v = Value::create(t); + Value::AutoPtr v = Value::create(typeId); assert(v.get()); v->read(pData, size, byteOrder()); @@ -1431,8 +1425,8 @@ namespace Exiv2 { { assert(object != 0); - uint16_t type = object->elTypeId(); - uint32_t size = TypeInfo::typeSize(TypeId(type)); + TypeId typeId = toTypeId(object->elTiffType(), object->tag(), object->group()); + uint32_t size = TypeInfo::typeSize(typeId); // Hack: Exif.CanonCs.Lens has 3 components if (object->group() == Group::canoncs && object->tag() == 0x0017) { size *= 3; @@ -1452,7 +1446,7 @@ namespace Exiv2 { ByteOrder bo = object->elByteOrder(); if (bo == invalidByteOrder) bo = byteOrder(); - Value::AutoPtr v = Value::create(TypeId(type)); + Value::AutoPtr v = Value::create(typeId); assert(v.get()); v->read(pData, size, bo); diff --git a/src/types.cpp b/src/types.cpp index 89acf04c..86af0efd 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -51,55 +51,64 @@ EXIV2_RCSID("@(#) $Id$") // class member definitions namespace Exiv2 { - TypeInfoTable::TypeInfoTable(TypeId typeId, const char* name, long size) - : typeId_(typeId), name_(name), size_(size) - { - } - //! Lookup list of supported IFD type information const TypeInfoTable TypeInfo::typeInfoTable_[] = { - TypeInfoTable(invalidTypeId, "Invalid", 0), - TypeInfoTable(unsignedByte, "Byte", 1), - TypeInfoTable(asciiString, "Ascii", 1), - TypeInfoTable(unsignedShort, "Short", 2), - TypeInfoTable(unsignedLong, "Long", 4), - TypeInfoTable(unsignedRational, "Rational", 8), - TypeInfoTable(signedByte, "SByte", 1), - TypeInfoTable(undefined, "Undefined", 1), - TypeInfoTable(signedShort, "SShort", 2), - TypeInfoTable(signedLong, "SLong", 4), - TypeInfoTable(signedRational, "SRational", 8), - TypeInfoTable(string, "String", 1), - TypeInfoTable(date, "Date", 8), - TypeInfoTable(time, "Time", 11), - TypeInfoTable(comment, "Comment", 1), - TypeInfoTable(directory, "Directory", 1), - TypeInfoTable(xmpText, "XmpText", 1), - TypeInfoTable(xmpAlt, "XmpAlt", 1), - TypeInfoTable(xmpBag, "XmpBag", 1), - TypeInfoTable(xmpSeq, "XmpSeq", 1), - TypeInfoTable(langAlt, "LangAlt", 1), + { invalidTypeId, "Invalid", 0 }, + { unsignedByte, "Byte", 1 }, + { asciiString, "Ascii", 1 }, + { unsignedShort, "Short", 2 }, + { unsignedLong, "Long", 4 }, + { unsignedRational, "Rational", 8 }, + { signedByte, "SByte", 1 }, + { undefined, "Undefined", 1 }, + { signedShort, "SShort", 2 }, + { signedLong, "SLong", 4 }, + { signedRational, "SRational", 8 }, + { tiffFloat, "Float", 4 }, + { tiffDouble, "Double", 8 }, + { string, "String", 1 }, + { date, "Date", 8 }, + { time, "Time", 11 }, + { comment, "Comment", 1 }, + { directory, "Directory", 1 }, + { xmpText, "XmpText", 1 }, + { xmpAlt, "XmpAlt", 1 }, + { xmpBag, "XmpBag", 1 }, + { xmpSeq, "XmpSeq", 1 }, + { langAlt, "LangAlt", 1 }, // End of list marker - TypeInfoTable(lastTypeId, "(Unknown)", 0) + { lastTypeId, "(Unknown)", 0 } }; + bool TypeInfoTable::operator==(TypeId typeId) const + { + return typeId_ == typeId; + } + + bool TypeInfoTable::operator==(const std::string& name) const + { + return std::string(name_) == name; + } + const char* TypeInfo::typeName(TypeId typeId) { - return typeInfoTable_[ typeId < lastTypeId ? typeId : 0 ].name_; + const TypeInfoTable* tit = find(typeInfoTable_, typeId); + if (!tit) return 0; + return tit->name_; } TypeId TypeInfo::typeId(const std::string& typeName) { - int i = 0; - for (; typeInfoTable_[i].typeId_ != lastTypeId - && typeInfoTable_[i].name_ != typeName; ++i) {} - return typeInfoTable_[i].typeId_ == lastTypeId ? - invalidTypeId : typeInfoTable_[i].typeId_; + const TypeInfoTable* tit = find(typeInfoTable_, typeName); + if (!tit) return invalidTypeId; + return tit->typeId_; } long TypeInfo::typeSize(TypeId typeId) { - return typeInfoTable_[ typeId < lastTypeId ? typeId : 0 ].size_; + const TypeInfoTable* tit = find(typeInfoTable_, typeId); + if (!tit) return 0; + return tit->size_; } DataBuf::DataBuf(DataBuf& rhs) diff --git a/src/types.hpp b/src/types.hpp index 9c65b179..299c21d5 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -99,15 +99,38 @@ namespace Exiv2 { //! An identifier for each mode of metadata support enum AccessMode { amNone=0, amRead=1, amWrite=2, amReadWrite=3 }; - //! Type identifiers for IFD format types - enum TypeId { invalidTypeId, unsignedByte, asciiString, unsignedShort, - unsignedLong, unsignedRational, signedByte, undefined, - signedShort, signedLong, signedRational, - string, date, time, - comment, - directory, - xmpText, xmpAlt, xmpBag, xmpSeq, langAlt, - lastTypeId }; + /*! + @brief %Exiv2 value type identifiers. + + Used primarily as identifiers when creating %Exiv2 Value instances. + See Value::create. 0x0000 to 0xffff are reserved for TIFF (Exif) types. + */ + enum TypeId { + unsignedByte = 1, //!< Exif BYTE type, 8-bit unsigned integer. + asciiString = 2, //!< Exif ASCII type, 8-bit byte. + unsignedShort = 3, //!< Exif SHORT type, 16-bit (2-byte) unsigned integer. + unsignedLong = 4, //!< Exif LONG type, 32-bit (4-byte) unsigned integer. + unsignedRational = 5, //!< Exif RATIONAL type, two LONGs: numerator and denumerator of a fraction. + signedByte = 6, //!< Exif SBYTE type, an 8-bit signed (twos-complement) integer. + undefined = 7, //!< Exif UNDEFINED type, an 8-bit byte that may contain anything. + signedShort = 8, //!< Exif SSHORT type, a 16-bit (2-byte) signed (twos-complement) integer. + signedLong = 9, //!< Exif SLONG type, a 32-bit (4-byte) signed (twos-complement) integer. + signedRational =10, //!< Exif SRATIONAL type, two SLONGs: numerator and denumerator of a fraction. + tiffFloat =11, //!< TIFF FLOAT type, single precision (4-byte) IEEE format. + tiffDouble =12, //!< TIFF DOUBLE type, double precision (8-byte) IEEE format. + string =0x10000, //!< IPTC string type. + date =0x10001, //!< IPTC date type. + time =0x10002, //!< IPTC time type. + comment =0x10003, //!< %Exiv2 type for the Exif user comment. + directory =0x10004, //!< %Exiv2 type for a CIFF directory. + xmpText =0x10005, //!< XMP text type. + xmpAlt =0x10006, //!< XMP alternative type. + xmpBag =0x10007, //!< XMP bag type. + xmpSeq =0x10008, //!< XMP sequence type. + langAlt =0x10009, //!< XMP language alternative type. + invalidTypeId =0x1fffe, //!< Invalid type id. + lastTypeId =0x1ffff //!< Last type id. + }; // Todo: decentralize IfdId, so that new ids can be defined elsewhere //! Type to specify the IFD to which a metadata belongs @@ -133,13 +156,15 @@ namespace Exiv2 { // ***************************************************************************** // class definitions - //! Information pertaining to the defined types + //! Information pertaining to the defined %Exiv2 value type identifiers. struct TypeInfoTable { - //! Constructor - TypeInfoTable(TypeId typeId, const char* name, long size); TypeId typeId_; //!< Type id const char* name_; //!< Name of the type long size_; //!< Bytes per data entry + //! Comparison operator for \em typeId + bool operator==(TypeId typeId) const; + //! Comparison operator for \em name + bool operator==(const std::string& name) const; }; // struct TypeInfoTable //! Type information lookup functions. Implemented as a static class. diff --git a/src/value.cpp b/src/value.cpp index 0b9670b2..043b4910 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -68,10 +68,11 @@ namespace Exiv2 { AutoPtr value; switch (typeId) { case invalidTypeId: - value = AutoPtr(new DataValue(invalidTypeId)); - break; + case signedByte: case unsignedByte: - value = AutoPtr(new DataValue(unsignedByte)); + case tiffFloat: + case tiffDouble: + value = AutoPtr(new DataValue(typeId)); break; case asciiString: value = AutoPtr(new AsciiValue); @@ -85,9 +86,6 @@ namespace Exiv2 { case unsignedRational: value = AutoPtr(new ValueType); break; - case signedByte: - value = AutoPtr(new DataValue(signedByte)); - break; case undefined: value = AutoPtr(new DataValue); break; diff --git a/src/value.hpp b/src/value.hpp index 375b5f94..bfde77b5 100644 --- a/src/value.hpp +++ b/src/value.hpp @@ -217,6 +217,8 @@ namespace Exiv2 { signedShort%ValueType < int16_t > signedLong%ValueType < int32_t > signedRational%ValueType < Rational > + tiffFloat%DataValue(tiffFloat) + tiffDouble%DataValue(tiffDouble) date%DateValue time%TimeValue comment%CommentValue