[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a
Maximiliano Curia
maxy at moszumanska.debian.org
Thu Jul 13 17:35:56 UTC 2017
Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=440571b
The following commit has been merged in the master branch:
commit 440571b5447dde7eba1c735091344f1fa7f99b9c
Author: Andreas Huggel <ahuggel at gmx.net>
Date: Sun Jan 18 16:53:12 2004 +0000
Values implemented
---
src/exif.cpp | 226 +++++++++++++++++++++++++++++++------------
src/exif.hpp | 286 ++++++++++++++++++++++++++++++++++++++++++++++++-------
src/exiftest.cpp | 48 ++++++----
src/tags.cpp | 52 ++++++++--
src/tags.hpp | 45 +++++++--
5 files changed, 524 insertions(+), 133 deletions(-)
diff --git a/src/exif.cpp b/src/exif.cpp
index 70cfd0a..4183ccc 100644
--- a/src/exif.cpp
+++ b/src/exif.cpp
@@ -12,7 +12,7 @@
RCS information
$Name: $
- $Revision: 1.3 $
+ $Revision: 1.4 $
*/
// *****************************************************************************
// included header files
@@ -24,6 +24,7 @@
#include <iomanip>
#include <sstream>
#include <fstream>
+#include <utility>
#include <cstring>
@@ -101,15 +102,15 @@ namespace Exif {
if (getUShort(marker, bigEndian) != app1_) return 3;
// Read the length of the APP1 field and the Exif identifier
- char buf[8];
- ::memset(buf, 0x0, 8);
- is.read(buf, 8);
+ char tmpbuf[8];
+ ::memset(tmpbuf, 0x0, 8);
+ is.read(tmpbuf, 8);
if (!is.good()) return 1;
// Get the length of the APP1 field and do a plausibility check
- long app1Length = getUShort(buf, bigEndian);
+ long app1Length = getUShort(tmpbuf, bigEndian);
if (app1Length < 8) return 4;
// Check the Exif identifier
- if (::memcmp(buf+2, exifId_, 6) != 0) return 4;
+ if (::memcmp(tmpbuf+2, exifId_, 6) != 0) return 4;
// Read the rest of the APP1 field (Exif data)
long sizeExifData = app1Length - 8;
@@ -166,95 +167,112 @@ namespace Exif {
return size();
}
- Value* Value::create(TypeId typeId, ByteOrder byteOrder)
+ Value* Value::create(TypeId typeId)
{
Value* value = 0;
switch (typeId) {
case invalid:
+ value = new DataValue(invalid);
break;
case unsignedByte:
- value = new AsciiValue;
+ value = new DataValue(unsignedByte);
break;
case asciiString:
value = new AsciiValue;
break;
case unsignedShort:
- value = new UShortValue(byteOrder);
+ value = new ValueType<uint16>;
break;
case unsignedLong:
+ value = new ValueType<uint32>;
+ break;
case unsignedRational:
- case signedByte:
+ value = new ValueType<URational>;
+ break;
+ case invalid6:
+ value = new DataValue(invalid6);
+ break;
case undefined:
+ value = new DataValue;
+ break;
case signedShort:
+ value = new ValueType<int16>;
+ break;
case signedLong:
+ value = new ValueType<int32>;
+ break;
case signedRational:
- case singleFloat:
- case doubleFloat:
- value = new AsciiValue;
+ value = new ValueType<Rational>;
break;
}
return value;
} // Value::create
- void AsciiValue::read(const char* buf, long len)
+ void DataValue::read(const char* buf, long len, ByteOrder byteOrder)
{
+ // byteOrder not needed
value_ = std::string(buf, len);
}
- void AsciiValue::read(const std::string& buf)
+ void DataValue::read(const std::string& buf)
{
+ // Todo: read from a string of bytes??
value_ = buf;
}
- long AsciiValue::copy(char* buf) const
+ long DataValue::copy(char* buf, ByteOrder byteOrder) const
{
+ // byteOrder not needed
return value_.copy(buf, value_.size());
}
- long AsciiValue::size() const
+ long DataValue::size() const
{
return value_.size();
}
- Value* AsciiValue::clone() const
+ Value* DataValue::clone() const
{
- return new AsciiValue(*this);
+ return new DataValue(*this);
}
- std::ostream& AsciiValue::write(std::ostream& os) const
+ std::ostream& DataValue::write(std::ostream& os) const
{
- return os << value_;
+ std::string::size_type end = value_.size();
+ for (std::string::size_type i = 0; i != end; ++i) {
+ os << (int)(unsigned char)value_[i] << " ";
+ }
+ return os;
}
- void UShortValue::read(const char* buf, long len)
+ void AsciiValue::read(const char* buf, long len, ByteOrder byteOrder)
{
- // Todo: Should we check to make sure that len is 2
- value_ = getUShort(buf, byteOrder_);
+ // byteOrder not needed
+ value_ = std::string(buf, len);
}
- void UShortValue::read(const std::string& buf)
+ void AsciiValue::read(const std::string& buf)
{
- std::istringstream is(buf);
- is >> value_;
+ value_ = buf;
}
- long UShortValue::copy(char* buf) const
+ long AsciiValue::copy(char* buf, ByteOrder byteOrder) const
{
- us2Data(buf, value_, byteOrder_);
- return size();
+ // byteOrder not needed
+ return value_.copy(buf, value_.size());
}
- long UShortValue::size() const
+ long AsciiValue::size() const
{
- return 2;
+ return value_.size();
}
- Value* UShortValue::clone() const
+ Value* AsciiValue::clone() const
{
- return new UShortValue(*this);
+ return new AsciiValue(*this);
}
- std::ostream& UShortValue::write(std::ostream& os) const
+ std::ostream& AsciiValue::write(std::ostream& os) const
{
return os << value_;
}
@@ -287,6 +305,8 @@ namespace Exif {
Metadatum& Metadatum::operator=(const Metadatum& rhs)
{
+ if (this == &rhs) return *this;
+
tag_ = rhs.tag_;
type_ = rhs.type_;
count_ = rhs.count_;
@@ -361,15 +381,15 @@ namespace Exif {
for (i = eb; i != ee; ++i) {
delete i->value_;
//! Todo: Create the correct type here, once we have them
- i->value_ = Value::create(TypeId(i->type_), byteOrder);
+ i->value_ = Value::create(TypeId(i->type_));
if (i->size_ > 4) {
i->offset_ = i->offset_ - offset_;
- i->value_->read(buf + i->offset_, i->size_);
+ i->value_->read(buf + i->offset_, i->size_, byteOrder);
}
else {
- char value[4];
- ul2Data(value, i->offset_, byteOrder);
- i->value_->read(value, 4);
+ char tmpbuf[4];
+ ul2Data(tmpbuf, i->offset_, byteOrder);
+ i->value_->read(tmpbuf, i->size_, byteOrder);
}
}
return 0;
@@ -411,7 +431,10 @@ namespace Exif {
dataSize += i->size_;
}
else {
- ul2Data(buf+o+8, i->offset_, byteOrder);
+ char tmpbuf[4];
+ ::memset(tmpbuf, 0x0, 4);
+ i->value_->copy(tmpbuf, byteOrder);
+ ::memcpy(buf+o+8, tmpbuf, 4);
}
o += 12;
}
@@ -432,7 +455,7 @@ namespace Exif {
// Todo: Check this! There seems to be an inconsistency
// in the use of size_ and the return value of copy() here
// Todo: And can value_ be 0?
- o += i->value_->copy(buf+o);
+ o += i->value_->copy(buf+o, byteOrder);
}
}
@@ -449,7 +472,7 @@ namespace Exif {
<< ", IFD Entries: "
<< std::setfill(' ') << std::dec << std::right
<< entries_.size() << "
"
- << prefix << "Entry Tag Format (Bytes each) Number Offset/Data
"
+ << prefix << "Entry Tag Format (Bytes each) Number Offset
"
<< prefix << "----- ------ --------------------- ------ -----------
";
const Metadata::const_iterator b = entries_.begin();
@@ -458,19 +481,22 @@ namespace Exif {
for (; i != e; ++i) {
std::ostringstream offset;
if (i->typeSize() * i->count_ <= 4) {
- // Minor cheat here: we use value_ instead of offset_ to avoid
- // having to invoke ul2Data() which would require byte order.
- // Todo: can value_ be 0 here?
- char tmpbuf[4];
- i->value_->copy(tmpbuf);
- offset << std::setw(2) << std::setfill('0') << std::hex
- << (int)*(unsigned char*)tmpbuf << " "
- << std::setw(2) << std::setfill('0') << std::hex
- << (int)*(unsigned char*)(tmpbuf+1) << " "
- << std::setw(2) << std::setfill('0') << std::hex
- << (int)*(unsigned char*)(tmpbuf+2) << " "
- << std::setw(2) << std::setfill('0') << std::hex
- << (int)*(unsigned char*)(tmpbuf+3) << " ";
+
+// Todo: Fix me! This doesn't work with Value anymore because we do not know
+// the byte order here. (Wait for Ifd to use a more special type)
+//
+// char tmpbuf[4];
+// i->value_->copy(tmpbuf, byteOrder);
+// offset << std::setw(2) << std::setfill('0') << std::hex
+// << (int)*(unsigned char*)tmpbuf << " "
+// << std::setw(2) << std::setfill('0') << std::hex
+// << (int)*(unsigned char*)(tmpbuf+1) << " "
+// << std::setw(2) << std::setfill('0') << std::hex
+// << (int)*(unsigned char*)(tmpbuf+2) << " "
+// << std::setw(2) << std::setfill('0') << std::hex
+// << (int)*(unsigned char*)(tmpbuf+3) << " ";
+
+ offset << "n/a";
}
else {
offset << " 0x" << std::setw(8) << std::setfill('0') << std::hex
@@ -622,13 +648,80 @@ namespace Exif {
}
}
- std::string getString(const char* buf, long len)
+ URational getURational(const char* buf, ByteOrder byteOrder)
+ {
+ uint32 nominator = getULong(buf, byteOrder);
+ uint32 denominator = getULong(buf + 4, byteOrder);
+ return std::make_pair(nominator, denominator);
+ }
+
+ int16 getShort(const char* buf, ByteOrder byteOrder)
+ {
+ if (byteOrder == littleEndian) {
+ return (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
+ }
+ else {
+ return (unsigned char)buf[0] << 8 | (unsigned char)buf[1];
+ }
+ }
+
+ int32 getLong(const char* buf, ByteOrder byteOrder)
+ {
+ if (byteOrder == littleEndian) {
+ return (unsigned char)buf[3] << 24 | (unsigned char)buf[2] << 16
+ | (unsigned char)buf[1] << 8 | (unsigned char)buf[0];
+ }
+ else {
+ return (unsigned char)buf[0] << 24 | (unsigned char)buf[1] << 16
+ | (unsigned char)buf[2] << 8 | (unsigned char)buf[3];
+ }
+ }
+
+ Rational getRational(const char* buf, ByteOrder byteOrder)
+ {
+ int32 nominator = getLong(buf, byteOrder);
+ int32 denominator = getLong(buf + 4, byteOrder);
+ return std::make_pair(nominator, denominator);
+ }
+
+ long us2Data(char* buf, uint16 s, ByteOrder byteOrder)
+ {
+ if (byteOrder == littleEndian) {
+ buf[0] = s & 0x00ff;
+ buf[1] = (s & 0xff00) >> 8;
+ }
+ else {
+ buf[0] = (s & 0xff00) >> 8;
+ buf[1] = s & 0x00ff;
+ }
+ return 2;
+ }
+
+ long ul2Data(char* buf, uint32 l, ByteOrder byteOrder)
+ {
+ if (byteOrder == littleEndian) {
+ buf[0] = l & 0x000000ff;
+ buf[1] = (l & 0x0000ff00) >> 8;
+ buf[2] = (l & 0x00ff0000) >> 16;
+ buf[3] = (l & 0xff000000) >> 24;
+ }
+ else {
+ buf[0] = (l & 0xff000000) >> 24;
+ buf[1] = (l & 0x00ff0000) >> 16;
+ buf[2] = (l & 0x0000ff00) >> 8;
+ buf[3] = l & 0x000000ff;
+ }
+ return 4;
+ }
+
+ long ur2Data(char* buf, URational l, ByteOrder byteOrder)
{
- std::string txt(buf, len);
- return txt;
+ long o = ul2Data(buf, l.first, byteOrder);
+ o += ul2Data(buf+o, l.second, byteOrder);
+ return o;
}
- char* us2Data(char* buf, uint16 s, ByteOrder byteOrder)
+ long s2Data(char* buf, int16 s, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
buf[0] = s & 0x00ff;
@@ -638,10 +731,10 @@ namespace Exif {
buf[0] = (s & 0xff00) >> 8;
buf[1] = s & 0x00ff;
}
- return buf;
+ return 2;
}
- char* ul2Data(char* buf, uint32 l, ByteOrder byteOrder)
+ long l2Data(char* buf, int32 l, ByteOrder byteOrder)
{
if (byteOrder == littleEndian) {
buf[0] = l & 0x000000ff;
@@ -655,7 +748,14 @@ namespace Exif {
buf[2] = (l & 0x0000ff00) >> 8;
buf[3] = l & 0x000000ff;
}
- return buf;
+ return 4;
+ }
+
+ long r2Data(char* buf, Rational l, ByteOrder byteOrder)
+ {
+ long o = l2Data(buf, l.first, byteOrder);
+ o += l2Data(buf+o, l.second, byteOrder);
+ return o;
}
void hexdump(std::ostream& os, const char* buf, long len)
diff --git a/src/exif.hpp b/src/exif.hpp
index a5f2b11..5150842 100644
--- a/src/exif.hpp
+++ b/src/exif.hpp
@@ -8,7 +8,7 @@
/*!
@file exif.hpp
@brief Encoding and decoding of %Exif data
- @version $Name: $ $Revision: 1.3 $
+ @version $Name: $ $Revision: 1.4 $
@author Andreas Huggel (ahu)
@date 09-Jan-03, ahu: created
*/
@@ -22,7 +22,8 @@
// + standard includes
#include <string>
#include <vector>
-#include <iosfwd>
+#include <iostream>
+#include <sstream>
// *****************************************************************************
// namespace extensions
@@ -145,7 +146,14 @@ namespace Exif {
uint32 offset_;
}; // class TiffHeader
- //! Common interface for all values
+ /*!
+ @brief Common interface for all values. The interface provides a uniform
+ way to access values independent from their actual C++ type for
+ simple tasks like reading the values. For other tasks, like modifying
+ values you need to downcast it to the actual subclass of Value so
+ that you can access the subclass specific interface (e.g., assignment
+ operator for a vector of unsigned longs).
+ */
class Value {
public:
//! Constructor, taking a type id to initialize the base class with
@@ -157,8 +165,9 @@ namespace Exif {
@param buf Pointer to the data buffer to read from
@param len Number of bytes in the data buffer
+ @param byteOrder Applicable byte order (little or big endian).
*/
- virtual void read(const char* buf, long len) =0;
+ virtual void read(const char* buf, long len, ByteOrder byteOrder) =0;
//! Set the value from a string buffer
virtual void read(const std::string& buf) =0;
/*!
@@ -168,13 +177,14 @@ namespace Exif {
the call results in undefined behaviour.
@param buf Data buffer to write to.
+ @param byteOrder Applicable byte order (little or big endian).
@return Number of characters written.
*/
- virtual long copy(char* buf) const =0;
- //! Returns the size of the value in bytes
+ virtual long copy(char* buf, ByteOrder byteOrder) const =0;
+ //! Return the size of the value in bytes
virtual long size() const =0;
/*!
- @brief Returns a pointer to a copy of itself (deep copy).
+ @brief Return a pointer to a copy of itself (deep copy).
The caller owns this copy and is responsible to delete it!
*/
virtual Value* clone() const =0;
@@ -185,12 +195,10 @@ namespace Exif {
@brief A (simple) factory to create a Value type.
@param typeId Type of the value.
- @param byteOrder Applicable byte order (little or big endian).
-
@return Pointer to the newly created Value.
The caller owns this copy and is responsible to delete it!
*/
- static Value* create(TypeId typeId, ByteOrder byteOrder);
+ static Value* create(TypeId typeId);
protected:
const TypeId typeId_; //!< Format type identifier
@@ -203,14 +211,31 @@ namespace Exif {
return value.write(os);
}
- //! %Value representing an Ascii string type.
+ //! %Value for an undefined data type.
+ class DataValue : public Value {
+ public:
+ //! Default constructor.
+ DataValue(TypeId typeId =undefined) : Value(typeId) {}
+ virtual void read(const char* buf, long len, ByteOrder byteOrder);
+ virtual void read(const std::string& buf);
+ virtual long copy(char* buf, ByteOrder byteOrder) const;
+ virtual long size() const;
+ virtual Value* clone() const;
+ virtual std::ostream& write(std::ostream& os) const;
+
+ private:
+ std::string value_;
+
+ };
+
+ //! %Value for an Ascii string type.
class AsciiValue : public Value {
public:
//! Default constructor.
AsciiValue() : Value(asciiString) {}
- virtual void read(const char* buf, long len);
+ virtual void read(const char* buf, long len, ByteOrder byteOrder);
virtual void read(const std::string& buf);
- virtual long copy(char* buf) const;
+ virtual long copy(char* buf, ByteOrder byteOrder) const;
virtual long size() const;
virtual Value* clone() const;
virtual std::ostream& write(std::ostream& os) const;
@@ -220,22 +245,25 @@ namespace Exif {
};
- //! %Value representing one unsigned short type.
- class UShortValue : public Value {
+ /*!
+ @brief Template for a %Value for a basic Type. This is used for unsigned
+ and signed short, long and rational.
+ */
+ template<typename T>
+ class ValueType : public Value {
public:
- //! Constructor, taking the byte order (endianness) as argument
- UShortValue(ByteOrder byteOrder)
- : Value(unsignedShort), byteOrder_(byteOrder) {}
- virtual void read(const char* buf, long len);
+ //! Default constructor.
+ ValueType() : Value(getType<T>()) {}
+ virtual void read(const char* buf, long len, ByteOrder byteOrder);
virtual void read(const std::string& buf);
- virtual long copy(char* buf) const;
+ virtual long copy(char* buf, ByteOrder byteOrder) const;
virtual long size() const;
virtual Value* clone() const;
virtual std::ostream& write(std::ostream& os) const;
private:
- ByteOrder byteOrder_;
- uint16 value_;
+ typedef std::vector<T> ValueList;
+ ValueList value_;
};
@@ -252,9 +280,9 @@ namespace Exif {
//! Return the name of the type
const char* tagName() const { return ExifTags::tagName(tag_, ifdId_); }
//! Return the name of the type
- const char* typeName() const { return ExifTags::typeName(type_); }
+ const char* typeName() const { return ExifTags::typeName(TypeId(type_)); }
//! Return the size in bytes of one element of this type
- long typeSize() const { return ExifTags::typeSize(type_); }
+ long typeSize() const { return ExifTags::typeSize(TypeId(type_)); }
//! Return the name of the IFD
const char* ifdName() const { return ExifTags::ifdName(ifdId_); }
//! Return the related image item (image or thumbnail)
@@ -273,7 +301,7 @@ namespace Exif {
public:
uint16 tag_; //!< Tag value
- uint16 type_; //!< Type of the data
+ uint16 type_; //!< Type of the data Todo: change to TypeId?
uint32 count_; //!< Number of components
uint32 offset_; //!< Offset of the data from start of IFD
long size_; //!< Size of the data in bytes
@@ -445,28 +473,220 @@ namespace Exif {
TiffHeader tiffHeader_;
Metadata metadata_;
}; // class ExifData
-
+
// *****************************************************************************
// free functions
//! Read a 2 byte unsigned short value from the data buffer
uint16 getUShort(const char* buf, ByteOrder byteOrder);
-
//! Read a 4 byte unsigned long value from the data buffer
uint32 getULong(const char* buf, ByteOrder byteOrder);
+ //! Read an 8 byte unsigned rational value from the data buffer
+ URational getURational(const char* buf, ByteOrder byteOrder);
+ //! Read a 2 byte signed short value from the data buffer
+ int16 getShort(const char* buf, ByteOrder byteOrder);
+ //! Read a 4 byte signed long value from the data buffer
+ int32 getLong(const char* buf, ByteOrder byteOrder);
+ //! Read an 8 byte signed rational value from the data buffer
+ Rational getRational(const char* buf, ByteOrder byteOrder);
+
+ /*!
+ @brief Read a value of type T from the data buffer.
+
+ We need this template function for the ValueType template classes.
+ There are only specializations of this function available; no default
+ implementation is provided.
+
+ @param buf Pointer to the data buffer to read from.
+ @param byteOrder Applicable byte order (little or big endian).
+ @return A value of type T.
+ */
+ template<typename T> T getValue(const char* buf, ByteOrder byteOrder);
+ // Specialization for a 2 byte unsigned short value.
+ template<> inline uint16 getValue(const char* buf, ByteOrder byteOrder)
+ {
+ return getUShort(buf, byteOrder);
+ }
+ // Specialization for a 4 byte unsigned long value.
+ template<> inline uint32 getValue(const char* buf, ByteOrder byteOrder)
+ {
+ return getULong(buf, byteOrder);
+ }
+ // Specialization for an 8 byte unsigned rational value.
+ template<> inline URational getValue(const char* buf, ByteOrder byteOrder)
+ {
+ return getURational(buf, byteOrder);
+ }
+ // Specialization for a 2 byte signed short value.
+ template<> inline int16 getValue(const char* buf, ByteOrder byteOrder)
+ {
+ return getShort(buf, byteOrder);
+ }
+ // Specialization for a 4 byte signed long value.
+ template<> inline int32 getValue(const char* buf, ByteOrder byteOrder)
+ {
+ return getLong(buf, byteOrder);
+ }
+ // Specialization for an 8 byte signed rational value.
+ template<> inline Rational getValue(const char* buf, ByteOrder byteOrder)
+ {
+ return getRational(buf, byteOrder);
+ }
+
+ /*!
+ @brief Convert an unsigned short to data, write the data to the buffer,
+ return number of bytes written.
+ */
+ long us2Data(char* buf, uint16 s, ByteOrder byteOrder);
+ /*!
+ @brief Convert an unsigned long to data, write the data to the buffer,
+ return number of bytes written.
+ */
+ long ul2Data(char* buf, uint32 l, ByteOrder byteOrder);
+ /*!
+ @brief Convert an unsigned rational to data, write the data to the buffer,
+ return number of bytes written.
+ */
+ long ur2Data(char* buf, URational l, ByteOrder byteOrder);
+ /*!
+ @brief Convert a signed short to data, write the data to the buffer,
+ return number of bytes written.
+ */
+ long s2Data(char* buf, int16 s, ByteOrder byteOrder);
+ /*!
+ @brief Convert a signed long to data, write the data to the buffer,
+ return number of bytes written.
+ */
+ long l2Data(char* buf, int32 l, ByteOrder byteOrder);
+ /*!
+ @brief Convert a signed rational to data, write the data to the buffer,
+ return number of bytes written.
+ */
+ long r2Data(char* buf, Rational l, ByteOrder byteOrder);
- //! Convert len bytes from the data buffer into a string
- std::string getString(const char* buf, long len);
+ /*!
+ @brief Convert a value of type T to data, write the data to the data buffer.
- //! Write an unsigned short to the data buffer
- char* us2Data(char* buf, uint16 s, ByteOrder byteOrder);
+ We need this template function for the ValueType template classes.
+ There are only specializations of this function available; no default
+ implementation is provided.
- //! Convert an unsigned long to data, write the data to the buffer
- char* ul2Data(char* buf, uint32 l, ByteOrder byteOrder);
+ @param buf Pointer to the data buffer to write to.
+ @param t Value to be converted.
+ @param byteOrder Applicable byte order (little or big endian).
+ @return The number of bytes written to the buffer.
+ */
+ template<typename T> long toData(char* buf, T t, ByteOrder byteOrder);
+ /*!
+ @brief Specialization to write an unsigned short to the data buffer.
+ Return the number of bytes written.
+ */
+ template<> inline long toData(char* buf, uint16 t, ByteOrder byteOrder)
+ {
+ return us2Data(buf, t, byteOrder);
+ }
+ /*!
+ @brief Specialization to write an unsigned long to the data buffer.
+ Return the number of bytes written.
+ */
+ template<> inline long toData(char* buf, uint32 t, ByteOrder byteOrder)
+ {
+ return ul2Data(buf, t, byteOrder);
+ }
+ /*!
+ @brief Specialization to write an unsigned rational to the data buffer.
+ Return the number of bytes written.
+ */
+ template<> inline long toData(char* buf, URational t, ByteOrder byteOrder)
+ {
+ return ur2Data(buf, t, byteOrder);
+ }
+ /*!
+ @brief Specialization to write a signed short to the data buffer.
+ Return the number of bytes written.
+ */
+ template<> inline long toData(char* buf, int16 t, ByteOrder byteOrder)
+ {
+ return s2Data(buf, t, byteOrder);
+ }
+ /*!
+ @brief Specialization to write a signed long to the data buffer.
+ Return the number of bytes written.
+ */
+ template<> inline long toData(char* buf, int32 t, ByteOrder byteOrder)
+ {
+ return l2Data(buf, t, byteOrder);
+ }
+ /*!
+ @brief Specialization to write a signed rational to the data buffer.
+ Return the number of bytes written.
+ */
+ template<> inline long toData(char* buf, Rational t, ByteOrder byteOrder)
+ {
+ return r2Data(buf, t, byteOrder);
+ }
//! Print len bytes from buf in hex and ASCII format to the given stream
void hexdump(std::ostream& os, const char* buf, long len);
+// *****************************************************************************
+// template definitions
+
+ template<typename T>
+ void ValueType<T>::read(const char* buf, long len, ByteOrder byteOrder)
+ {
+ value_.clear();
+ for (long i = 0; i < len; i += ExifTags::typeSize(typeId_)) {
+ value_.push_back(getValue<T>(buf + i, byteOrder));
+ }
+ }
+
+ template<typename T>
+ void ValueType<T>::read(const std::string& buf)
+ {
+ std::istringstream is(buf);
+ T tmp;
+ value_.clear();
+ while (is >> tmp) {
+ value_.push_back(tmp);
+ }
+ }
+
+ template<typename T>
+ long ValueType<T>::copy(char* buf, ByteOrder byteOrder) const
+ {
+ long offset = 0;
+ typename ValueList::const_iterator end = value_.end();
+ for (typename ValueList::const_iterator i = value_.begin(); i != end; ++i) {
+ offset += toData(buf + offset, *i, byteOrder);
+ }
+ return offset;
+ }
+
+ template<typename T>
+ long ValueType<T>::size() const
+ {
+ return ExifTags::typeSize(typeId_) * value_.size();
+ }
+
+ template<typename T>
+ Value* ValueType<T>::clone() const
+ {
+ return new ValueType(*this);
+ }
+
+ template<typename T>
+ std::ostream& ValueType<T>::write(std::ostream& os) const
+ {
+ typename ValueList::const_iterator end = value_.end();
+ typename ValueList::const_iterator i = value_.begin();
+ while (i != end) {
+ os << *i;
+ if (++i != end) os << " ";
+ }
+ return os;
+ }
+
} // namespace Exif
#endif // #ifndef _EXIF_HPP_
diff --git a/src/exiftest.cpp b/src/exiftest.cpp
index 4c7dd81..2bcb1ef 100644
--- a/src/exiftest.cpp
+++ b/src/exiftest.cpp
@@ -1,3 +1,4 @@
+#include "tags.hpp"
#include "exif.hpp"
#include <iostream>
#include <iomanip>
@@ -19,34 +20,39 @@ int main(int argc, char* const argv[])
ExifData::const_iterator end = exifData.end();
ExifData::const_iterator i = beg;
for (; i != end; ++i) {
-
std::cout << "0x"
<< std::hex << std::setw(4) << std::setfill('0') << std::right
<< i->tag_ << " "
- << std::setw(50) << std::setfill(' ') << std::left
- << i->key() << " ";
-
- if (i->type_ == 2 || i->type_ == 3) {
- std::cout << std::dec << i->value() << "
";
- }
- else {
- std::cout << std::setw(17) << std::setfill(' ') << std::left
- << i->typeName() << " "
- << std::dec << std::setw(3)
- << std::setfill(' ') << std::right
- << i->count_ << " "
- << std::dec << std::setw(3)
- << std::setfill(' ') << std::right
- << i->typeSize() * i->count_ << "
";
- }
-
+ << std::setw(27) << std::setfill(' ') << std::left
+ << i->tagName() << " "
+ << std::setw(17) << std::setfill(' ') << std::left
+ << i->typeName() << " "
+ << std::dec << std::setw(3)
+ << std::setfill(' ') << std::right
+ << i->count_ << " "
+ << std::dec << i->value() << "
";
}
}
- std::string tmp = "12";
- Value* val = Value::create(unsignedShort, littleEndian);
+// std::string tmp = "12 2ddd4. xd35";
+ std::string tmp = " 1 2 3";
+ Value* val = Value::create(unsignedShort);
+ std::cout << "Reading test string \"" << tmp << "\"
";
val->read(tmp);
- std::cout << "And the answer is: " << *val << "
";
+ std::cout << "And the answer is: " << *val << ", size is " << val->size() << "
";
+ Rational r = std::make_pair(1,72);
+ URational ur = std::make_pair(2,3);
+
+ std::cout << "Rational r = " << r << "
";
+ std::cout << "URational ur = " << ur << "
";
+
+ ValueType<Rational> vr;
+ ValueType<URational> vur;
+
+ std::string str(" 4 / 5 x2 5/3");
+ vr.read(str);
+ std::cout << "ValueType<Rational> vr = " << vr
+ << ", size is " << vr.size() << "
";
return rc;
diff --git a/src/tags.cpp b/src/tags.cpp
index beed3df..31441d3 100644
--- a/src/tags.cpp
+++ b/src/tags.cpp
@@ -12,12 +12,14 @@
RCS information
$Name: $
- $Revision: 1.3 $
+ $Revision: 1.4 $
*/
// *****************************************************************************
// included header files
#include "tags.hpp"
+#include <iostream>
+
// *****************************************************************************
// class member definitions
namespace Exif {
@@ -80,13 +82,11 @@ namespace Exif {
TagFormat(unsignedShort, "unsigned short", 2),
TagFormat(unsignedLong, "unsigned long", 4),
TagFormat(unsignedRational, "unsigned rational", 8),
- TagFormat(signedByte, "signed byte", 1),
+ TagFormat(invalid6, "invalid (6)", 1),
TagFormat(undefined, "undefined", 1),
TagFormat(signedShort, "signed short", 2),
TagFormat(signedLong, "signed long", 4),
- TagFormat(signedRational, "signed rational", 8),
- TagFormat(singleFloat, "single float", 4),
- TagFormat(doubleFloat, "double float", 8)
+ TagFormat(signedRational, "signed rational", 8)
};
TagInfo::TagInfo(
@@ -281,14 +281,14 @@ namespace Exif {
return sectionInfo_[tagInfo[tagInfoIdx(tag, ifdId)].sectionId_].name_;
}
- const char* ExifTags::typeName(uint16 type)
+ const char* ExifTags::typeName(TypeId typeId)
{
- return tagFormat_[type].name_;
+ return tagFormat_[typeId].name_;
}
- long ExifTags::typeSize(uint16 type)
+ long ExifTags::typeSize(TypeId typeId)
{
- return tagFormat_[type].size_;
+ return tagFormat_[typeId].size_;
}
const char* ExifTags::ifdName(IfdId ifdId)
@@ -306,4 +306,38 @@ namespace Exif {
return sectionInfo_[sectionId].name_;
}
+
+ // *************************************************************************
+ // free functions
+
+ std::ostream& operator<<(std::ostream& os, const Rational& r)
+ {
+ return os << r.first << "/" << r.second;
+ }
+
+ std::istream& operator>>(std::istream& is, Rational& r)
+ {
+ int32 nominator;
+ int32 denominator;
+ char c;
+ is >> nominator >> c >> denominator;
+ if (is && c == '/') r = std::make_pair(nominator, denominator);
+ return is;
+ }
+
+ std::ostream& operator<<(std::ostream& os, const URational& r)
+ {
+ return os << r.first << "/" << r.second;
+ }
+
+ std::istream& operator>>(std::istream& is, URational& r)
+ {
+ uint32 nominator;
+ uint32 denominator;
+ char c;
+ is >> nominator >> c >> denominator;
+ if (is && c == '/') r = std::make_pair(nominator, denominator);
+ return is;
+ }
+
} // namespace Exif
diff --git a/src/tags.hpp b/src/tags.hpp
index fedb288..0eff1df 100644
--- a/src/tags.hpp
+++ b/src/tags.hpp
@@ -8,7 +8,7 @@
/*!
@file tags.hpp
@brief %Exif tag and type information
- @version $Name: $ $Revision: 1.3 $
+ @version $Name: $ $Revision: 1.4 $
@author Andreas Huggel (ahu)
@date 15-Jan-03, ahu: created
*/
@@ -20,6 +20,7 @@
// + standard includes
#include <utility> // for std::pair
+#include <iosfwd>
// *****************************************************************************
// namespace extensions
@@ -44,16 +45,18 @@ namespace Exif {
//! Type identifiers for IFD format types
enum TypeId { invalid, unsignedByte, asciiString, unsignedShort,
- unsignedLong, unsignedRational, signedByte, undefined,
- signedShort, signedLong, signedRational, singleFloat,
- doubleFloat };
+ unsignedLong, unsignedRational, invalid6, undefined,
+ signedShort, signedLong, signedRational };
//! Type to specify the IFD to which a metadata belongs
enum IfdId { IfdIdNotSet,
ifd0, exifIfd, gpsIfd, makerIfd, iopIfd,
ifd1, ifd1ExifIfd, ifd1GpsIfd, ifd1MakerIfd, ifd1IopIfd };
- //! Section identifiers to logically group tags
+ /*!
+ @brief Section identifiers to logically group tags. A section consists
+ of nothing more than a name, based on the Exif standard.
+ */
enum SectionId { SectionIdNotSet,
imgStruct, recOffset, imgCharacter, otherTags, exifFormat,
exifVersion, imgConfig, userInfo, relatedFile, dateTime,
@@ -119,9 +122,9 @@ namespace Exif {
//! Returns the name of the tag
static const char* tagName(uint16 tag, IfdId ifdId);
//! Returns the name of the type
- static const char* typeName(uint16 type);
+ static const char* typeName(TypeId typeId);
//! Returns the size in bytes of one element of this type
- static long typeSize(uint16 type);
+ static long typeSize(TypeId typeId);
//! Returns the name of the IFD
static const char* ifdName(IfdId ifdId);
//! Returns the related image item (image or thumbnail)
@@ -145,6 +148,34 @@ namespace Exif {
// *****************************************************************************
// free functions
+ //! Output operator for our fake rational
+ std::ostream& operator<<(std::ostream& os, const Rational& r);
+ //! Input operator for our fake rational
+ std::istream& operator>>(std::istream& is, Rational& r);
+ //! Output operator for our fake unsigned rational
+ std::ostream& operator<<(std::ostream& os, const URational& r);
+ //! Input operator for our fake unsigned rational
+ std::istream& operator>>(std::istream& is, URational& r);
+
+ //! Template to determine the TypeId for a type T
+ template<typename T> TypeId getType();
+
+ //! Specialization for an unsigned short
+ template<> inline TypeId getType<uint16>() { return unsignedShort; }
+ //! Specialization for an unsigned long
+ template<> inline TypeId getType<uint32>() { return unsignedLong; }
+ //! Specialization for an unsigned rational
+ template<> inline TypeId getType<URational>() { return unsignedRational; }
+ //! Specialization for a signed short
+ template<> inline TypeId getType<int16>() { return signedShort; }
+ //! Specialization for a signed long
+ template<> inline TypeId getType<int32>() { return signedLong; }
+ //! Specialization for a signed rational
+ template<> inline TypeId getType<Rational>() { return signedRational; }
+
+ // No default implementation: let the compiler/linker complain
+// template<typename T> inline TypeId getType() { return invalid; }
+
} // namespace Exif
#endif // #ifndef _TAGS_HPP_
--
exiv2 packaging
More information about the pkg-kde-commits
mailing list