Improved/fixed Exif (TIFF) type handling.

This commit is contained in:
Andreas Huggel 2008-07-31 03:59:30 +00:00
parent a9577e6c25
commit 8f167ee426
9 changed files with 226 additions and 146 deletions

View File

@ -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 << " ";

View File

@ -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<uint16_t>(TypeInfo::typeSize(elTypeId))),
: TiffEntryBase(tag, group, elTiffType),
elSize_(static_cast<uint16_t>(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<uint16_t>(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<TiffEntryBase*>(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<int32_t>(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<uint32_t>(offset) > 0xffff) throw Error(26);
rc = s2Data(buf, static_cast<int16_t>(offset), byteOrder);
break;
case unsignedLong:
case signedLong:
case ttUnsignedLong:
case ttSignedLong:
rc = l2Data(buf, static_cast<int32_t>(offset), byteOrder);
break;
default:
@ -889,7 +889,7 @@ namespace Exiv2 {
+ static_cast<long>(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<uint32_t>(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<uint16_t>(typeId);
}
bool cmpTagLt(TiffComponent const* lhs, TiffComponent const* rhs)
{
assert(lhs != 0);

View File

@ -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<TypeId typeId, bool addSizeElement>
template<TiffType tiffType, bool addSizeElement>
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<TypeId typeId, ByteOrder byteOrder>
template<TiffType tiffType, ByteOrder byteOrder>
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<TypeId typeId>
template<TiffType tiffType>
TiffComponent::AutoPtr newTiffArrayElement(uint16_t tag,
const TiffStructure* ts)
{
return newTiffArrayElement<typeId, invalidByteOrder>(tag, ts);
return newTiffArrayElement<tiffType, invalidByteOrder>(tag, ts);
}
//! Function to create and initialize a new TIFF entry for a thumbnail (data)

View File

@ -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<unsignedLong, false> },
{ 0x0003, Group::olympmn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry<unsignedLong, false> },
{ 0x0001, Group::olympmn, Group::minocso, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedLong, false> },
{ 0x0003, Group::olympmn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedLong, false> },
{ 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<unsignedShort, true> },
{ 0x0004, Group::canonmn, Group::canonsi, 0x927c, Group::exif, newTiffArrayEntry<unsignedShort, true> },
{ 0x0005, Group::canonmn, Group::canonpa, 0x927c, Group::exif, newTiffArrayEntry<unsignedShort, true> },
{ 0x000f, Group::canonmn, Group::canoncf, 0x927c, Group::exif, newTiffArrayEntry<unsignedShort, true> },
{ 0x0012, Group::canonmn, Group::canonpi, 0x927c, Group::exif, newTiffArrayEntry<unsignedShort, true> },
{ 0x0001, Group::canonmn, Group::canoncs, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, true> },
{ 0x0004, Group::canonmn, Group::canonsi, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, true> },
{ 0x0005, Group::canonmn, Group::canonpa, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, true> },
{ 0x000f, Group::canonmn, Group::canoncf, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, true> },
{ 0x0012, Group::canonmn, Group::canonpi, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, true> },
{ 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<unsignedShort> },
{ Tag::all, Group::canonsi, Group::canonsi, 0x0004, Group::canonmn, newTiffArrayElement<unsignedShort> },
{ Tag::all, Group::canonpa, Group::canonpa, 0x0005, Group::canonmn, newTiffArrayElement<unsignedShort> },
{ Tag::all, Group::canoncf, Group::canoncf, 0x000f, Group::canonmn, newTiffArrayElement<unsignedShort> },
{ Tag::all, Group::canonpi, Group::canonpi, 0x0012, Group::canonmn, newTiffArrayElement<unsignedShort> },
{ Tag::all, Group::canoncs, Group::canoncs, 0x0001, Group::canonmn, newTiffArrayElement<ttUnsignedShort> },
{ Tag::all, Group::canonsi, Group::canonsi, 0x0004, Group::canonmn, newTiffArrayElement<ttUnsignedShort> },
{ Tag::all, Group::canonpa, Group::canonpa, 0x0005, Group::canonmn, newTiffArrayElement<ttUnsignedShort> },
{ Tag::all, Group::canoncf, Group::canoncf, 0x000f, Group::canonmn, newTiffArrayElement<ttUnsignedShort> },
{ Tag::all, Group::canonpi, Group::canonpi, 0x0012, Group::canonmn, newTiffArrayElement<ttUnsignedShort> },
// 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<unsignedLong, false> },
{ 0x0003, Group::minoltamn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry<unsignedLong, false> },
{ 0x0004, Group::minoltamn, Group::minocs7, 0x927c, Group::exif, newTiffArrayEntry<unsignedShort, false> },
{ 0x0001, Group::minoltamn, Group::minocso, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedLong, false> },
{ 0x0003, Group::minoltamn, Group::minocsn, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedLong, false> },
{ 0x0004, Group::minoltamn, Group::minocs7, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, false> },
{ 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<unsignedShort, false> },
{ 0x0114, Group::minoltamn, Group::minocs5, 0x927c, Group::exif, newTiffArrayEntry<ttUnsignedShort, false> },
{ 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<unsignedLong, bigEndian> },
{ Tag::all, Group::minocsn, Group::minocsn, 0x0003, Group::minoltamn, newTiffArrayElement<unsignedLong, bigEndian> },
{ Tag::all, Group::minocs7, Group::minocs7, 0x0004, Group::minoltamn, newTiffArrayElement<unsignedShort, bigEndian> },
{ Tag::all, Group::minocs5, Group::minocs5, 0x0114, Group::minoltamn, newTiffArrayElement<unsignedShort, bigEndian> },
{ Tag::all, Group::minocso, Group::minocso, 0x0001, Group::minoltamn, newTiffArrayElement<ttUnsignedLong, bigEndian> },
{ Tag::all, Group::minocsn, Group::minocsn, 0x0003, Group::minoltamn, newTiffArrayElement<ttUnsignedLong, bigEndian> },
{ Tag::all, Group::minocs7, Group::minocs7, 0x0004, Group::minoltamn, newTiffArrayElement<ttUnsignedShort, bigEndian> },
{ Tag::all, Group::minocs5, Group::minocs5, 0x0114, Group::minoltamn, newTiffArrayElement<ttUnsignedShort, bigEndian> },
// Tags which are not de/encoded
{ Tag::next, Group::ignr, Group::ignr, Tag::none, Group::none, newTiffDirectory },

View File

@ -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<TiffEntryBase*>(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<byte*>(pData_) + baseOffset() + offset;
if (size > static_cast<uint32_t>(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);

View File

@ -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)

View File

@ -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.

View File

@ -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<URational>);
break;
case signedByte:
value = AutoPtr(new DataValue(signedByte));
break;
case undefined:
value = AutoPtr(new DataValue);
break;

View File

@ -217,6 +217,8 @@ namespace Exiv2 {
<TR><TD class="indexkey">signedShort</TD><TD class="indexvalue">%ValueType &lt; int16_t &gt;</TD></TR>
<TR><TD class="indexkey">signedLong</TD><TD class="indexvalue">%ValueType &lt; int32_t &gt;</TD></TR>
<TR><TD class="indexkey">signedRational</TD><TD class="indexvalue">%ValueType &lt; Rational &gt;</TD></TR>
<TR><TD class="indexkey">tiffFloat</TD><TD class="indexvalue">%DataValue(tiffFloat)</TD></TR>
<TR><TD class="indexkey">tiffDouble</TD><TD class="indexvalue">%DataValue(tiffDouble)</TD></TR>
<TR><TD class="indexkey">date</TD><TD class="indexvalue">%DateValue</TD></TR>
<TR><TD class="indexkey">time</TD><TD class="indexvalue">%TimeValue</TD></TR>
<TR><TD class="indexkey">comment</TD><TD class="indexvalue">%CommentValue</TD></TR>