Added Value et al.
This commit is contained in:
parent
9bf351c60b
commit
bb6380825d
194
src/exif.cpp
194
src/exif.cpp
@ -12,7 +12,7 @@
|
||||
|
||||
RCS information
|
||||
$Name: $
|
||||
$Revision: 1.2 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
@ -149,7 +149,7 @@ namespace Exif {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TiffHeader::data(char* buf) const
|
||||
long TiffHeader::copy(char* buf) const
|
||||
{
|
||||
switch (byteOrder_) {
|
||||
case littleEndian:
|
||||
@ -163,17 +163,111 @@ namespace Exif {
|
||||
}
|
||||
us2Data(buf+2, tag_, byteOrder_);
|
||||
ul2Data(buf+4, offset_, byteOrder_);
|
||||
return size();
|
||||
}
|
||||
|
||||
Value* Value::create(TypeId typeId, ByteOrder byteOrder)
|
||||
{
|
||||
Value* value = 0;
|
||||
switch (typeId) {
|
||||
case invalid:
|
||||
break;
|
||||
case unsignedByte:
|
||||
value = new AsciiValue;
|
||||
break;
|
||||
case asciiString:
|
||||
value = new AsciiValue;
|
||||
break;
|
||||
case unsignedShort:
|
||||
value = new UShortValue(byteOrder);
|
||||
break;
|
||||
case unsignedLong:
|
||||
case unsignedRational:
|
||||
case signedByte:
|
||||
case undefined:
|
||||
case signedShort:
|
||||
case signedLong:
|
||||
case signedRational:
|
||||
case singleFloat:
|
||||
case doubleFloat:
|
||||
value = new AsciiValue;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
} // Value::create
|
||||
|
||||
void AsciiValue::read(const char* buf, long len)
|
||||
{
|
||||
value_ = std::string(buf, len);
|
||||
}
|
||||
|
||||
void AsciiValue::read(const std::string& buf)
|
||||
{
|
||||
value_ = buf;
|
||||
}
|
||||
|
||||
long AsciiValue::copy(char* buf) const
|
||||
{
|
||||
return value_.copy(buf, value_.size());
|
||||
}
|
||||
|
||||
long AsciiValue::size() const
|
||||
{
|
||||
return value_.size();
|
||||
}
|
||||
|
||||
Value* AsciiValue::clone() const
|
||||
{
|
||||
return new AsciiValue(*this);
|
||||
}
|
||||
|
||||
std::ostream& AsciiValue::write(std::ostream& os) const
|
||||
{
|
||||
return os << value_;
|
||||
}
|
||||
|
||||
void UShortValue::read(const char* buf, long len)
|
||||
{
|
||||
// Todo: Should we check to make sure that len is 2
|
||||
value_ = getUShort(buf, byteOrder_);
|
||||
}
|
||||
|
||||
void UShortValue::read(const std::string& buf)
|
||||
{
|
||||
std::istringstream is(buf);
|
||||
is >> value_;
|
||||
}
|
||||
|
||||
long UShortValue::copy(char* buf) const
|
||||
{
|
||||
us2Data(buf, value_, byteOrder_);
|
||||
return size();
|
||||
}
|
||||
|
||||
long UShortValue::size() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
Value* UShortValue::clone() const
|
||||
{
|
||||
return new UShortValue(*this);
|
||||
}
|
||||
|
||||
std::ostream& UShortValue::write(std::ostream& os) const
|
||||
{
|
||||
return os << value_;
|
||||
}
|
||||
|
||||
Metadatum::Metadatum()
|
||||
: tag_(0), type_(0), count_(0), offset_(0), size_(0),
|
||||
ifdId_(IfdIdNotSet), ifdIdx_(-1), data_(0)
|
||||
ifdId_(IfdIdNotSet), ifdIdx_(-1), value_(0)
|
||||
{
|
||||
}
|
||||
|
||||
Metadatum::~Metadatum()
|
||||
{
|
||||
delete[] data_;
|
||||
delete value_;
|
||||
}
|
||||
|
||||
Metadatum::Metadatum(const Metadatum& rhs)
|
||||
@ -187,12 +281,8 @@ namespace Exif {
|
||||
ifdId_ = rhs.ifdId_;
|
||||
ifdIdx_ = rhs.ifdIdx_;
|
||||
|
||||
// deep copy
|
||||
data_ = 0;
|
||||
if (rhs.data_ != 0) {
|
||||
data_ = new char[rhs.size_];
|
||||
::memcpy(data_, rhs.data_, rhs.size_);
|
||||
}
|
||||
value_ = 0;
|
||||
if (rhs.value_ != 0) value_ = rhs.value_->clone(); // deep copy
|
||||
}
|
||||
|
||||
Metadatum& Metadatum::operator=(const Metadatum& rhs)
|
||||
@ -206,11 +296,9 @@ namespace Exif {
|
||||
ifdId_ = rhs.ifdId_;
|
||||
ifdIdx_ = rhs.ifdIdx_;
|
||||
|
||||
delete[] data_;
|
||||
if (rhs.data_ != 0) {
|
||||
data_ = new char[rhs.size_];
|
||||
::memcpy(data_, rhs.data_, rhs.size_);
|
||||
}
|
||||
delete value_;
|
||||
value_ = 0;
|
||||
if (rhs.value_ != 0) value_ = rhs.value_->clone(); // deep copy
|
||||
|
||||
return *this;
|
||||
} // Metadatum::operator=
|
||||
@ -245,7 +333,7 @@ namespace Exif {
|
||||
// offset will be converted to a relative offset below
|
||||
e.offset_ = getULong(buf+o+8, byteOrder);
|
||||
e.size_ = e.count_ * e.typeSize();
|
||||
// data_ is set later, see below
|
||||
// value_ is set later, see below
|
||||
entries_.push_back(e);
|
||||
o += 12;
|
||||
}
|
||||
@ -268,19 +356,20 @@ namespace Exif {
|
||||
}
|
||||
}
|
||||
|
||||
// Assign the data to each IFD entry and
|
||||
// Assign the values to each IFD entry and
|
||||
// calculate offsets relative to the start of the IFD
|
||||
for (i = eb; i != ee; ++i) {
|
||||
delete[] i->data_;
|
||||
i->data_ = 0;
|
||||
delete i->value_;
|
||||
//! Todo: Create the correct type here, once we have them
|
||||
i->value_ = Value::create(TypeId(i->type_), byteOrder);
|
||||
if (i->size_ > 4) {
|
||||
i->offset_ = i->offset_ - offset_;
|
||||
i->data_ = new char[i->size_];
|
||||
::memcpy(i->data_, buf + i->offset_, i->size_);
|
||||
i->value_->read(buf + i->offset_, i->size_);
|
||||
}
|
||||
else {
|
||||
i->data_ = new char[4];
|
||||
ul2Data(i->data_, i->offset_, byteOrder);
|
||||
char value[4];
|
||||
ul2Data(value, i->offset_, byteOrder);
|
||||
i->value_->read(value, 4);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -300,7 +389,7 @@ namespace Exif {
|
||||
return rc;
|
||||
} // Ifd::readSubIfd
|
||||
|
||||
char* Ifd::data(char* buf, ByteOrder byteOrder, long offset) const
|
||||
long Ifd::copy(char* buf, ByteOrder byteOrder, long offset) const
|
||||
{
|
||||
if (offset == 0) offset = offset_;
|
||||
|
||||
@ -340,12 +429,14 @@ namespace Exif {
|
||||
// Add the data of all IFD entries to the data buffer
|
||||
for (i = b; i != e; ++i) {
|
||||
if (i->size_ > 4) {
|
||||
::memcpy(buf+o, i->data_, i->size_);
|
||||
o += i->size_;
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
return buf;
|
||||
return o;
|
||||
} // Ifd::data
|
||||
|
||||
void Ifd::print(std::ostream& os, const std::string& prefix) const
|
||||
@ -367,16 +458,19 @@ namespace Exif {
|
||||
for (; i != e; ++i) {
|
||||
std::ostringstream offset;
|
||||
if (i->typeSize() * i->count_ <= 4) {
|
||||
// Minor cheat here: we use data_ instead of offset_ to avoid
|
||||
// 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*)i->data_ << " "
|
||||
<< (int)*(unsigned char*)tmpbuf << " "
|
||||
<< std::setw(2) << std::setfill('0') << std::hex
|
||||
<< (int)*(unsigned char*)(i->data_+1) << " "
|
||||
<< (int)*(unsigned char*)(tmpbuf+1) << " "
|
||||
<< std::setw(2) << std::setfill('0') << std::hex
|
||||
<< (int)*(unsigned char*)(i->data_+2) << " "
|
||||
<< (int)*(unsigned char*)(tmpbuf+2) << " "
|
||||
<< std::setw(2) << std::setfill('0') << std::hex
|
||||
<< (int)*(unsigned char*)(i->data_+3) << " ";
|
||||
<< (int)*(unsigned char*)(tmpbuf+3) << " ";
|
||||
}
|
||||
else {
|
||||
offset << " 0x" << std::setw(8) << std::setfill('0') << std::hex
|
||||
@ -399,12 +493,13 @@ namespace Exif {
|
||||
<< std::setw(8) << std::setfill('0') << std::hex
|
||||
<< std::right << next_ << "\n";
|
||||
|
||||
for (i = b; i != e; ++i) {
|
||||
if (i->size_ > 4) {
|
||||
os << "Data of entry " << i-b << ":\n";
|
||||
hexdump(os, i->data_, i->size_);
|
||||
}
|
||||
}
|
||||
// Todo: Fix me! This does not work with Value anymore
|
||||
// for (i = b; i != e; ++i) {
|
||||
// if (i->size_ > 4) {
|
||||
// os << "Data of entry " << i-b << ":\n";
|
||||
// hexdump(os, i->data_, i->size_);
|
||||
// }
|
||||
// }
|
||||
|
||||
} // Ifd::print
|
||||
|
||||
@ -422,48 +517,48 @@ namespace Exif {
|
||||
int rc = tiffHeader_.read(buf);
|
||||
if (rc) return rc;
|
||||
|
||||
const ByteOrder byteOrder = tiffHeader_.byteOrder(); // shortcut
|
||||
|
||||
// Read IFD0
|
||||
Ifd ifd0(ifd0);
|
||||
rc = ifd0.read(buf + tiffHeader_.offset(), byteOrder, tiffHeader_.offset());
|
||||
rc = ifd0.read(buf + tiffHeader_.offset(),
|
||||
byteOrder(),
|
||||
tiffHeader_.offset());
|
||||
if (rc) return rc;
|
||||
|
||||
// Find and read ExifIFD sub-IFD of IFD0
|
||||
Ifd exifIfd(exifIfd);
|
||||
rc = ifd0.readSubIfd(exifIfd, buf, byteOrder, 0x8769);
|
||||
rc = ifd0.readSubIfd(exifIfd, buf, byteOrder(), 0x8769);
|
||||
if (rc) return rc;
|
||||
|
||||
// Find and read Interoperability IFD in ExifIFD
|
||||
Ifd iopIfd(iopIfd);
|
||||
rc = exifIfd.readSubIfd(iopIfd, buf, byteOrder, 0xa005);
|
||||
rc = exifIfd.readSubIfd(iopIfd, buf, byteOrder(), 0xa005);
|
||||
if (rc) return rc;
|
||||
|
||||
// Find and read GPSInfo sub-IFD in IFD0
|
||||
Ifd gpsIfd(gpsIfd);
|
||||
rc = ifd0.readSubIfd(gpsIfd, buf, byteOrder, 0x8825);
|
||||
rc = ifd0.readSubIfd(gpsIfd, buf, byteOrder(), 0x8825);
|
||||
if (rc) return rc;
|
||||
|
||||
// Read IFD1
|
||||
Ifd ifd1(ifd1);
|
||||
if (ifd0.next()) {
|
||||
rc = ifd1.read(buf + ifd0.next(), byteOrder, ifd0.next());
|
||||
rc = ifd1.read(buf + ifd0.next(), byteOrder(), ifd0.next());
|
||||
if (rc) return rc;
|
||||
}
|
||||
|
||||
// Find and read ExifIFD sub-IFD of IFD1
|
||||
Ifd ifd1ExifIfd(ifd1ExifIfd);
|
||||
rc = ifd1.readSubIfd(ifd1ExifIfd, buf, byteOrder, 0x8769);
|
||||
rc = ifd1.readSubIfd(ifd1ExifIfd, buf, byteOrder(), 0x8769);
|
||||
if (rc) return rc;
|
||||
|
||||
// Find and read Interoperability IFD in ExifIFD of IFD1
|
||||
Ifd ifd1IopIfd(ifd1IopIfd);
|
||||
rc = ifd1ExifIfd.readSubIfd(ifd1IopIfd, buf, byteOrder, 0xa005);
|
||||
rc = ifd1ExifIfd.readSubIfd(ifd1IopIfd, buf, byteOrder(), 0xa005);
|
||||
if (rc) return rc;
|
||||
|
||||
// Find and read GPSInfo sub-IFD in IFD1
|
||||
Ifd ifd1GpsIfd(ifd1GpsIfd);
|
||||
rc = ifd1.readSubIfd(ifd1GpsIfd, buf, byteOrder, 0x8825);
|
||||
rc = ifd1.readSubIfd(ifd1GpsIfd, buf, byteOrder(), 0x8825);
|
||||
if (rc) return rc;
|
||||
|
||||
// Finally, copy all metadata from the IFDs to the internal metadata
|
||||
@ -480,9 +575,10 @@ namespace Exif {
|
||||
return 0;
|
||||
} // ExifData::read
|
||||
|
||||
void ExifData::data(char* buf) const
|
||||
long ExifData::copy(char* buf) const
|
||||
{
|
||||
// Todo: implement me!
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ExifData::size() const
|
||||
|
||||
150
src/exif.hpp
150
src/exif.hpp
@ -8,7 +8,7 @@
|
||||
/*!
|
||||
@file exif.hpp
|
||||
@brief Encoding and decoding of %Exif data
|
||||
@version $Name: $ $Revision: 1.2 $
|
||||
@version $Name: $ $Revision: 1.3 $
|
||||
@author Andreas Huggel (ahu)
|
||||
@date 09-Jan-03, ahu: created
|
||||
*/
|
||||
@ -116,20 +116,23 @@ namespace Exif {
|
||||
public:
|
||||
//! Default constructor.
|
||||
TiffHeader();
|
||||
//! Reads the Tiff header from a data buffer. Returns 0 if successful.
|
||||
//! Read the Tiff header from a data buffer. Returns 0 if successful.
|
||||
int read(const char* buf);
|
||||
//! Writes the Tiff header into buf as a data string.
|
||||
void data(char* buf) const;
|
||||
//! Returns the lengths of the Tiff header in bytes.
|
||||
/*!
|
||||
@brief Write the Tiff header into buf as a data string, return number
|
||||
of bytes copied.
|
||||
*/
|
||||
long copy(char* buf) const;
|
||||
//! Return the lengths of the Tiff header in bytes.
|
||||
long size() const { return 8; }
|
||||
//! @name Accessors
|
||||
//@{
|
||||
//! Returns the byte order (little or big endian).
|
||||
//! Return the byte order (little or big endian).
|
||||
ByteOrder byteOrder() const { return byteOrder_; }
|
||||
//! Returns the tag value.
|
||||
//! Return the tag value.
|
||||
uint16 tag() const { return tag_; }
|
||||
/*!
|
||||
@brief Returns the offset to IFD0 from the start of the Tiff header.
|
||||
@brief Return the offset to IFD0 from the start of the Tiff header.
|
||||
The offset is 0x00000008 if IFD0 begins immediately after the
|
||||
Tiff header.
|
||||
*/
|
||||
@ -142,9 +145,102 @@ namespace Exif {
|
||||
uint32 offset_;
|
||||
}; // class TiffHeader
|
||||
|
||||
//! Common interface for all values
|
||||
class Value {
|
||||
public:
|
||||
//! Constructor, taking a type id to initialize the base class with
|
||||
explicit Value(TypeId typeId) : typeId_(typeId) {}
|
||||
//! Virtual destructor.
|
||||
virtual ~Value() {}
|
||||
/*!
|
||||
@brief Read the value from a character buffer.
|
||||
|
||||
@param buf Pointer to the data buffer to read from
|
||||
@param len Number of bytes in the data buffer
|
||||
*/
|
||||
virtual void read(const char* buf, long len) =0;
|
||||
//! Set the value from a string buffer
|
||||
virtual void read(const std::string& buf) =0;
|
||||
/*!
|
||||
@brief Write value to a character data buffer.
|
||||
|
||||
The user must ensure that the buffer has enough memory. Otherwise
|
||||
the call results in undefined behaviour.
|
||||
|
||||
@param buf Data buffer to write to.
|
||||
@return Number of characters written.
|
||||
*/
|
||||
virtual long copy(char* buf) const =0;
|
||||
//! Returns the size of the value in bytes
|
||||
virtual long size() const =0;
|
||||
/*!
|
||||
@brief Returns 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;
|
||||
//! Write the value to an output stream, return the stream
|
||||
virtual std::ostream& write(std::ostream& os) const =0;
|
||||
|
||||
/*!
|
||||
@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);
|
||||
|
||||
protected:
|
||||
const TypeId typeId_; //!< Format type identifier
|
||||
|
||||
};
|
||||
|
||||
//! Output operator for Value types
|
||||
inline std::ostream& operator<<(std::ostream& os, const Value& value)
|
||||
{
|
||||
return value.write(os);
|
||||
}
|
||||
|
||||
//! %Value representing 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 std::string& buf);
|
||||
virtual long copy(char* buf) const;
|
||||
virtual long size() const;
|
||||
virtual Value* clone() const;
|
||||
virtual std::ostream& write(std::ostream& os) const;
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
|
||||
};
|
||||
|
||||
//! %Value representing one unsigned short type.
|
||||
class UShortValue : 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);
|
||||
virtual void read(const std::string& buf);
|
||||
virtual long copy(char* buf) const;
|
||||
virtual long size() const;
|
||||
virtual Value* clone() const;
|
||||
virtual std::ostream& write(std::ostream& os) const;
|
||||
|
||||
private:
|
||||
ByteOrder byteOrder_;
|
||||
uint16 value_;
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
@brief Information related to one %Exif tag.
|
||||
|
||||
*/
|
||||
class Metadatum {
|
||||
public:
|
||||
@ -153,21 +249,27 @@ namespace Exif {
|
||||
Metadatum(const Metadatum& rhs); //!< Copy constructor
|
||||
Metadatum& operator=(const Metadatum& rhs); //!< Assignment operator
|
||||
|
||||
//! Returns the name of the type
|
||||
//! Return the name of the type
|
||||
const char* tagName() const { return ExifTags::tagName(tag_, ifdId_); }
|
||||
//! Returns the name of the type
|
||||
//! Return the name of the type
|
||||
const char* typeName() const { return ExifTags::typeName(type_); }
|
||||
//! Returns the size in bytes of one element of this type
|
||||
//! Return the size in bytes of one element of this type
|
||||
long typeSize() const { return ExifTags::typeSize(type_); }
|
||||
//! Returns the name of the IFD
|
||||
//! Return the name of the IFD
|
||||
const char* ifdName() const { return ExifTags::ifdName(ifdId_); }
|
||||
//! Returns the related image item (image or thumbnail)
|
||||
//! Return the related image item (image or thumbnail)
|
||||
const char* ifdItem() const { return ExifTags::ifdItem(ifdId_); }
|
||||
//! Returns the name of the section
|
||||
//! Return the name of the section
|
||||
const char* sectionName() const
|
||||
{ return ExifTags::sectionName(tag_, ifdId_); }
|
||||
//! Returns a unique key of the tag (ifdItem.sectionName.tagName)
|
||||
//! Return a unique key of the tag (ifdItem.sectionName.tagName)
|
||||
std::string key() const;
|
||||
/*!
|
||||
@brief Return a reference the the value. The behaviour is undefined
|
||||
if the value has not been initialized.
|
||||
Todo: should we make sure there is a value?
|
||||
*/
|
||||
const Value& value() const { return *value_; }
|
||||
|
||||
public:
|
||||
uint16 tag_; //!< Tag value
|
||||
@ -179,7 +281,7 @@ namespace Exif {
|
||||
IfdId ifdId_; //!< The IFD associated with this tag
|
||||
int ifdIdx_; //!< Position in the IFD (-1: not set)
|
||||
|
||||
char* data_; //!< Pointer to the data
|
||||
Value* value_; //!< Pointer to the value
|
||||
|
||||
}; // struct Metadatum
|
||||
|
||||
@ -244,7 +346,7 @@ namespace Exif {
|
||||
Ifd& dest, const char* buf, ByteOrder byteOrder, uint16 tag
|
||||
) const;
|
||||
/*!
|
||||
@brief Convert the IFD to a data array, returns a reference to the
|
||||
@brief Copy the IFD to a data array, returns a reference to the
|
||||
data buffer. The pointer to the next IFD will be adjusted to an
|
||||
offset from the start of the Tiff header to the position
|
||||
immediately following the converted IFD.
|
||||
@ -255,9 +357,9 @@ namespace Exif {
|
||||
data array. The IFD offsets will be adjusted as
|
||||
necessary. If not given, then it is assumed that the IFD
|
||||
will remain at its original position.
|
||||
@return Returns buf
|
||||
@return Returns the number of characters written.
|
||||
*/
|
||||
char* data(char* buf, ByteOrder byteOrder, long offset =0) const;
|
||||
long copy(char* buf, ByteOrder byteOrder, long offset =0) const;
|
||||
/*!
|
||||
@brief Print the IFD in human readable format to the given stream;
|
||||
begin each line with prefix.
|
||||
@ -319,10 +421,12 @@ namespace Exif {
|
||||
@return 0 if successful
|
||||
*/
|
||||
int read(const char* buf, long len);
|
||||
//! Write %Exif data to a data buffer
|
||||
void data(char* buf) const;
|
||||
//! Returns the size of all %Exif data (Tiff Header plus metadata)
|
||||
//! Write %Exif data to a data buffer, return number of bytes written
|
||||
long copy(char* buf) const;
|
||||
//! Returns the size of all %Exif data (Tiff header plus metadata)
|
||||
long size() const;
|
||||
//! Returns the byte order as specified in the Tiff header
|
||||
ByteOrder byteOrder() const { return tiffHeader_.byteOrder(); }
|
||||
|
||||
//! Add all entries of src to the Exif metadata
|
||||
void add(const Metadata& src);
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace Exif;
|
||||
|
||||
int main(int argc, char* const argv[])
|
||||
{
|
||||
if (argc != 2) {
|
||||
@ -9,31 +11,43 @@ int main(int argc, char* const argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
Exif::ExifData exifData;
|
||||
ExifData exifData;
|
||||
int rc = exifData.read(argv[1]);
|
||||
|
||||
if (rc == 0) {
|
||||
|
||||
Exif::ExifData::const_iterator beg = exifData.begin();
|
||||
Exif::ExifData::const_iterator end = exifData.end();
|
||||
Exif::ExifData::const_iterator i = beg;
|
||||
ExifData::const_iterator beg = exifData.begin();
|
||||
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() << " "
|
||||
<< 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_ << "\n";
|
||||
<< i->key() << " ";
|
||||
|
||||
if (i->type_ == 2 || i->type_ == 3) {
|
||||
std::cout << std::dec << i->value() << "\n";
|
||||
}
|
||||
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_ << "\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
std::string tmp = "12";
|
||||
Value* val = Value::create(unsignedShort, littleEndian);
|
||||
val->read(tmp);
|
||||
std::cout << "And the answer is: " << *val << "\n";
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
32
src/tags.cpp
32
src/tags.cpp
@ -12,7 +12,7 @@
|
||||
|
||||
RCS information
|
||||
$Name: $
|
||||
$Revision: 1.2 $
|
||||
$Revision: 1.3 $
|
||||
*/
|
||||
// *****************************************************************************
|
||||
// included header files
|
||||
@ -67,26 +67,26 @@ namespace Exif {
|
||||
SectionInfo(iopTags, "Interoperability", "Interoperability information")
|
||||
};
|
||||
|
||||
TagFormat::TagFormat(uint16 type, const char* name, long size)
|
||||
: type_(type), name_(name), size_(size)
|
||||
TagFormat::TagFormat(TypeId typeId, const char* name, long size)
|
||||
: typeId_(typeId), name_(name), size_(size)
|
||||
{
|
||||
}
|
||||
|
||||
//! Lookup list of IFD tag data formats and their properties
|
||||
const TagFormat ExifTags::tagFormat_[] = {
|
||||
TagFormat( 0, "invalid", 0),
|
||||
TagFormat( 1, "unsigned byte", 1),
|
||||
TagFormat( 2, "ascii strings", 1),
|
||||
TagFormat( 3, "unsigned short", 2),
|
||||
TagFormat( 4, "unsigned long", 4),
|
||||
TagFormat( 5, "unsigned rational", 8),
|
||||
TagFormat( 6, "signed byte", 1),
|
||||
TagFormat( 7, "undefined", 1),
|
||||
TagFormat( 8, "signed short", 2),
|
||||
TagFormat( 9, "signed long", 4),
|
||||
TagFormat(10, "signed rational", 8),
|
||||
TagFormat(11, "single float", 4),
|
||||
TagFormat(12, "double float", 8)
|
||||
TagFormat(invalid, "invalid", 0),
|
||||
TagFormat(unsignedByte, "unsigned byte", 1),
|
||||
TagFormat(asciiString, "ascii strings", 1),
|
||||
TagFormat(unsignedShort, "unsigned short", 2),
|
||||
TagFormat(unsignedLong, "unsigned long", 4),
|
||||
TagFormat(unsignedRational, "unsigned rational", 8),
|
||||
TagFormat(signedByte, "signed byte", 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)
|
||||
};
|
||||
|
||||
TagInfo::TagInfo(
|
||||
|
||||
18
src/tags.hpp
18
src/tags.hpp
@ -8,7 +8,7 @@
|
||||
/*!
|
||||
@file tags.hpp
|
||||
@brief %Exif tag and type information
|
||||
@version $Name: $ $Revision: 1.2 $
|
||||
@version $Name: $ $Revision: 1.3 $
|
||||
@author Andreas Huggel (ahu)
|
||||
@date 15-Jan-03, ahu: created
|
||||
*/
|
||||
@ -19,6 +19,7 @@
|
||||
// included header files
|
||||
|
||||
// + standard includes
|
||||
#include <utility> // for std::pair
|
||||
|
||||
// *****************************************************************************
|
||||
// namespace extensions
|
||||
@ -36,6 +37,17 @@ namespace Exif {
|
||||
//! 4 byte signed integer type.
|
||||
typedef long int32;
|
||||
|
||||
//! 8 byte unsigned rational type.
|
||||
typedef std::pair<uint32, uint32> URational;
|
||||
//! 8 byte signed rational type.
|
||||
typedef std::pair<int32, int32> Rational;
|
||||
|
||||
//! Type identifiers for IFD format types
|
||||
enum TypeId { invalid, unsignedByte, asciiString, unsignedShort,
|
||||
unsignedLong, unsignedRational, signedByte, undefined,
|
||||
signedShort, signedLong, signedRational, singleFloat,
|
||||
doubleFloat };
|
||||
|
||||
//! Type to specify the IFD to which a metadata belongs
|
||||
enum IfdId { IfdIdNotSet,
|
||||
ifd0, exifIfd, gpsIfd, makerIfd, iopIfd,
|
||||
@ -71,8 +83,8 @@ namespace Exif {
|
||||
//! Description of the format of a metadatum
|
||||
struct TagFormat {
|
||||
//! Constructor
|
||||
TagFormat(uint16 type, const char* name, long size);
|
||||
uint16 type_; //!< Format type id
|
||||
TagFormat(TypeId typeId, const char* name, long size);
|
||||
TypeId typeId_; //!< Format type id
|
||||
const char* name_; //!< Name of the format
|
||||
long size_; //!< Bytes per data entry
|
||||
}; // struct TagFormat
|
||||
|
||||
Loading…
Reference in New Issue
Block a user