You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

567 lines
22 KiB
C++

22 years ago
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2008 Andreas Huggel <ahuggel@gmx.net>
*
22 years ago
* This program is part of the Exiv2 distribution.
22 years ago
*
22 years ago
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
22 years ago
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
22 years ago
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
22 years ago
*/
/*!
22 years ago
@file exif.hpp
@brief Encoding and decoding of Exif data
@version $Rev$
22 years ago
@author Andreas Huggel (ahu)
22 years ago
<a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
22 years ago
@date 09-Jan-04, ahu: created
22 years ago
*/
#ifndef EXIF_HPP_
#define EXIF_HPP_
22 years ago
// *****************************************************************************
// included header files
#include "metadatum.hpp"
#include "tags.hpp"
#include "value.hpp"
#include "types.hpp"
22 years ago
// + standard includes
#include <string>
#include <vector>
#include <memory>
22 years ago
// *****************************************************************************
// namespace extensions
/*!
@brief Provides classes and functions to encode and decode Exif and Iptc data.
The <b>libexiv2</b> API consists of the objects of this namespace.
*/
namespace Exiv2 {
22 years ago
// *****************************************************************************
22 years ago
// class declarations
class ExifData;
22 years ago
// *****************************************************************************
// class definitions
/*!
@brief An Exif metadatum, consisting of an ExifKey and a Value and
methods to manipulate these.
22 years ago
*/
class Exifdatum : public Metadatum {
template<typename T> friend Exifdatum& setValue(Exifdatum&, const T&);
public:
//! @name Creators
//@{
22 years ago
/*!
@brief Constructor for new tags created by an application. The
%Exifdatum is created from a \em key / value pair. %Exifdatum copies
(clones) the \em key and value if one is provided. Alternatively,
a program can create an 'empty' %Exifdatum with only a key
and set the value using setValue().
@param key %ExifKey.
@param pValue Pointer to an %Exifdatum value.
@throw Error if the key cannot be parsed and converted.
*/
explicit Exifdatum(const ExifKey& key, const Value* pValue =0);
22 years ago
//! Copy constructor
Exifdatum(const Exifdatum& rhs);
//! Destructor
virtual ~Exifdatum();
//@}
//! @name Manipulators
//@{
22 years ago
//! Assignment operator
Exifdatum& operator=(const Exifdatum& rhs);
/*!
@brief Assign \em value to the %Exifdatum. The type of the new Value
is set to UShortValue.
*/
Exifdatum& operator=(const uint16_t& value);
/*!
@brief Assign \em value to the %Exifdatum. The type of the new Value
is set to ULongValue.
*/
Exifdatum& operator=(const uint32_t& value);
/*!
@brief Assign \em value to the %Exifdatum. The type of the new Value
is set to URationalValue.
*/
Exifdatum& operator=(const URational& value);
/*!
@brief Assign \em value to the %Exifdatum. The type of the new Value
is set to ShortValue.
*/
Exifdatum& operator=(const int16_t& value);
/*!
@brief Assign \em value to the %Exifdatum. The type of the new Value
is set to LongValue.
*/
Exifdatum& operator=(const int32_t& value);
/*!
@brief Assign \em value to the %Exifdatum. The type of the new Value
is set to RationalValue.
*/
Exifdatum& operator=(const Rational& value);
/*!
@brief Assign \em value to the %Exifdatum.
Calls setValue(const std::string&).
*/
Exifdatum& operator=(const std::string& value);
/*!
@brief Assign \em value to the %Exifdatum.
Calls setValue(const Value*).
*/
Exifdatum& operator=(const Value& value);
void setValue(const Value* pValue);
/*!
@brief Set the value to the string \em value. Uses Value::read(const
std::string&). If the %Exifdatum does not have a Value yet,
then a %Value of the correct type for this %Exifdatum is
created. An AsciiValue is created for unknown tags.
*/
void setValue(const std::string& value);
/*!
@brief Set the data area by copying (cloning) the buffer pointed to
by \em buf.
Values may have a data area, which can contain additional
information besides the actual value. This method is used to set such
a data area.
@param buf Pointer to the source data area
@param len Size of the data area
@return Return -1 if the %Exifdatum does not have a value yet or the
value has no data area, else 0.
*/
int setDataArea(const byte* buf, long len)
{ return value_.get() == 0 ? -1 : value_->setDataArea(buf, len); }
//@}
//! @name Accessors
//@{
//! Return the key of the %Exifdatum.
std::string key() const
{ return key_.get() == 0 ? "" : key_->key(); }
std::string groupName() const
{ return key_.get() == 0 ? "" : key_->groupName(); }
std::string tagName() const
{ return key_.get() == 0 ? "" : key_->tagName(); }
std::string tagLabel() const
{ return key_.get() == 0 ? "" : key_->tagLabel(); }
uint16_t tag() const
{ return key_.get() == 0 ? 0xffff : key_->tag(); }
//! Return the IFD id
IfdId ifdId() const
{ return key_.get() == 0 ? ifdIdNotSet : key_->ifdId(); }
//! Return the name of the IFD
const char* ifdName() const
{ return key_.get() == 0 ? "" : key_->ifdName(); }
//! Return the related image item (deprecated)
std::string ifdItem() const
{ return key_.get() == 0 ? "" : key_->ifdItem(); }
//! Return the index (unique id of this key within the original IFD)
int idx() const
{ return key_.get() == 0 ? 0 : key_->idx(); }
/*!
@brief Write value to a data buffer and return the number
of bytes written.
The user must ensure that the buffer has enough memory. Otherwise
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.
*/
long copy(byte* buf, ByteOrder byteOrder) const
{ return value_.get() == 0 ? 0 : value_->copy(buf, byteOrder); }
std::ostream& write(std::ostream& os) const;
//! Return the type id of the value
TypeId typeId() const
{ return value_.get() == 0 ? invalidTypeId : value_->typeId(); }
//! Return the name of the type
const char* typeName() const
{ return TypeInfo::typeName(typeId()); }
//! Return the size in bytes of one component of this type
long typeSize() const
{ return TypeInfo::typeSize(typeId()); }
//! Return the number of components in the value
long count() const
{ return value_.get() == 0 ? 0 : value_->count(); }
//! Return the size of the value in bytes
long size() const
{ return value_.get() == 0 ? 0 : value_->size(); }
//! Return the value as a string.
std::string toString() const
{ return value_.get() == 0 ? "" : value_->toString(); }
std::string toString(long n) const
{ return value_.get() == 0 ? "" : value_->toString(n); }
long toLong(long n =0) const
{ return value_.get() == 0 ? -1 : value_->toLong(n); }
float toFloat(long n =0) const
{ return value_.get() == 0 ? -1 : value_->toFloat(n); }
Rational toRational(long n =0) const
{ return value_.get() == 0 ? Rational(-1, 1) : value_->toRational(n); }
Value::AutoPtr getValue() const
{ return value_.get() == 0 ? Value::AutoPtr(0) : value_->clone(); }
const Value& value() const;
//! Return the size of the data area.
long sizeDataArea() const
{ return value_.get() == 0 ? 0 : value_->sizeDataArea(); }
/*!
@brief Return a copy of the data area of the value. The caller owns
this copy and %DataBuf ensures that it will be deleted.
Values may have a data area, which can contain additional
information besides the actual value. This method is used to access
such a data area.
@return A %DataBuf containing a copy of the data area or an empty
%DataBuf if the value does not have a data area assigned or the
value is not set.
*/
DataBuf dataArea() const
{ return value_.get() == 0 ? DataBuf(0, 0) : value_->dataArea(); }
22 years ago
//@}
private:
// DATA
ExifKey::AutoPtr key_; //!< Key
Value::AutoPtr value_; //!< Value
22 years ago
}; // class Exifdatum
22 years ago
/*!
@brief Access to a Exif %thumbnail image. This class provides higher level
accessors to the thumbnail image that is optionally embedded in IFD1
of the Exif data. These methods do not write to the Exif metadata.
Manipulators are provided in subclass ExifThumb.
@note Various other preview and thumbnail images may be contained in an
image, depending on its format and the camera make and model. This
class only provides access to the Exif thumbnail as specified in the
Exif standard.
*/
class ExifThumbC {
22 years ago
public:
//! @name Creators
//@{
//! Constructor.
ExifThumbC(const ExifData& exifData);
//@}
//! @name Accessors
//@{
/*!
@brief Return the thumbnail image in a %DataBuf. The caller owns the
data buffer and %DataBuf ensures that it will be deleted.
*/
DataBuf copy() const;
/*!
@brief Write the thumbnail image to a file.
A filename extension is appended to \em path according to the image
type of the thumbnail, so \em path should not include an extension.
The function will overwrite an existing file of the same name.
@param path File name of the thumbnail without extension.
@return The number of bytes written.
*/
long writeFile(const std::string& path) const;
/*!
@brief Return the MIME type of the thumbnail, either \c "image/tiff"
or \c "image/jpeg".
*/
const char* mimeType() const;
/*!
@brief Return the file extension for the format of the thumbnail
(".tif" or ".jpg").
*/
const char* extension() const;
//@}
private:
const ExifData& exifData_; //!< Const reference to the Exif metadata.
}; // class ExifThumb
/*!
@brief Access and modify an Exif %thumbnail image. This class implements
manipulators to set and erase the thumbnail image that is optionally
embedded in IFD1 of the Exif data. Accessors are provided by the
base class, ExifThumbC.
@note Various other preview and thumbnail images may be contained in an
image, depending on its format and the camera make and model. This
class only provides access to the Exif thumbnail as specified in the
Exif standard.
*/
class ExifThumb : public ExifThumbC {
public:
//! @name Creators
//@{
//! Constructor.
ExifThumb(ExifData& exifData);
//@}
//! @name Manipulators
//@{
/*!
@brief Set the Exif thumbnail to the JPEG image \em path. Set
XResolution, YResolution and ResolutionUnit to \em xres,
\em yres and \em unit, respectively.
22 years ago
This results in the minimal thumbnail tags being set for a JPEG
thumbnail, as mandated by the Exif standard.
@throw Error if reading the file fails.
@note No checks on the file format or size are performed.
@note Additional existing Exif thumbnail tags are not modified.
@note The JPEG image inserted as thumbnail image should not
itself contain Exif data (or other metadata), as existing
applications may have problems with that. (The preview
application that comes with OS X for one.) - David Harvey.
*/
void setJpegThumbnail(
const std::string& path,
URational xres,
URational yres,
uint16_t unit
);
/*!
@brief Set the Exif thumbnail to the JPEG image pointed to by \em buf,
and size \em size. Set XResolution, YResolution and
ResolutionUnit to \em xres, \em yres and \em unit, respectively.
This results in the minimal thumbnail tags being set for a JPEG
thumbnail, as mandated by the Exif standard.
@throw Error if reading the file fails.
22 years ago
@note No checks on the image format or size are performed.
@note Additional existing Exif thumbnail tags are not modified.
@note The JPEG image inserted as thumbnail image should not
itself contain Exif data (or other metadata), as existing
applications may have problems with that. (The preview
application that comes with OS X for one.) - David Harvey.
*/
void setJpegThumbnail(
const byte* buf,
long size,
URational xres,
URational yres,
uint16_t unit
);
/*!
@brief Set the Exif thumbnail to the JPEG image \em path.
This sets only the Compression, JPEGInterchangeFormat and
JPEGInterchangeFormatLength tags, which is not all the thumbnail
Exif information mandatory according to the Exif standard. (But it's
enough to work with the thumbnail.)
@throw Error if reading the file fails.
@note No checks on the file format or size are performed.
@note Additional existing Exif thumbnail tags are not modified.
*/
void setJpegThumbnail(const std::string& path);
/*!
@brief Set the Exif thumbnail to the JPEG image pointed to by \em buf,
and size \em size.
This sets only the Compression, JPEGInterchangeFormat and
JPEGInterchangeFormatLength tags, which is not all the thumbnail
Exif information mandatory according to the Exif standard. (But it's
enough to work with the thumbnail.)
@note No checks on the image format or size are performed.
@note Additional existing Exif thumbnail tags are not modified.
*/
void setJpegThumbnail(const byte* buf, long size);
/*!
@brief Delete the thumbnail from the Exif data. Removes all
Exif.%Thumbnail.*, i.e., Exif IFD1 tags.
*/
void erase();
//@}
private:
ExifData& exifData_; //!< Reference to the related Exif metadata.
}; // class ExifThumb
//! Container type to hold all metadata
typedef std::vector<Exifdatum> ExifMetadata;
22 years ago
/*!
@brief A container for Exif data. This is a top-level class of the %Exiv2
library. The container holds Exifdatum objects.
22 years ago
Provide high-level access to the Exif data of an image:
- read Exif information from JPEG files
- access metadata through keys and standard C++ iterators
- add, modify and delete metadata
- write Exif data to JPEG files
- extract Exif metadata to files, insert from these files
- extract and delete Exif thumbnail (JPEG and TIFF thumbnails)
22 years ago
*/
class ExifData {
public:
//! ExifMetadata iterator type
typedef ExifMetadata::iterator iterator;
//! ExifMetadata const iterator type
typedef ExifMetadata::const_iterator const_iterator;
//! @name Manipulators
//@{
/*!
@brief Returns a reference to the %Exifdatum that is associated with a
particular \em key. If %ExifData does not already contain such
an %Exifdatum, operator[] adds object \em Exifdatum(key).
@note Since operator[] might insert a new element, it can't be a const
member function.
*/
Exifdatum& operator[](const std::string& key);
22 years ago
/*!
@brief Add an Exifdatum from the supplied key and value pair. This
method copies (clones) key and value. No duplicate checks are
performed, i.e., it is possible to add multiple metadata with
the same key.
22 years ago
*/
void add(const ExifKey& key, const Value* pValue);
/*!
@brief Add a copy of the \em exifdatum to the Exif metadata. No
duplicate checks are performed, i.e., it is possible to add
multiple metadata with the same key.
21 years ago
@throw Error if the makernote cannot be created
*/
void add(const Exifdatum& exifdatum);
/*!
@brief Delete the Exifdatum at iterator position \em pos, return the
position of the next exifdatum. Note that iterators into
the metadata, including \em pos, are potentially invalidated
by this call.
*/
iterator erase(iterator pos);
/*!
@brief Delete all Exifdatum instances resulting in an empty container.
Note that this also removes thumbnails.
*/
void clear();
//! Sort metadata by key
void sortByKey();
//! Sort metadata by tag
void sortByTag();
22 years ago
//! Begin of the metadata
iterator begin() { return exifMetadata_.begin(); }
22 years ago
//! End of the metadata
iterator end() { return exifMetadata_.end(); }
/*!
@brief Find the first Exifdatum with the given \em key, return an
iterator to it.
*/
iterator findKey(const ExifKey& key);
//@}
//! @name Accessors
//@{
//! Begin of the metadata
const_iterator begin() const { return exifMetadata_.begin(); }
//! End of the metadata
const_iterator end() const { return exifMetadata_.end(); }
/*!
@brief Find the first Exifdatum with the given \em key, return a const
iterator to it.
*/
const_iterator findKey(const ExifKey& key) const;
//! Return true if there is no Exif metadata
bool empty() const { return count() == 0; }
//! Get the number of metadata entries
long count() const { return static_cast<long>(exifMetadata_.size()); }
//@}
22 years ago
22 years ago
private:
// DATA
ExifMetadata exifMetadata_;
22 years ago
}; // class ExifData
/*!
@brief Stateless parser class for Exif data. Images use this class to
decode and encode binary Exif data. See class TiffParser for details.
*/
class ExifParser {
public:
/*!
@brief Decode metadata from a buffer \em pData of length \em size
with binary Exif data to the provided metadata container.
Return byte order in which the data is encoded.
See TiffParser::decode().
*/
static ByteOrder decode(
ExifData& exifData,
const byte* pData,
uint32_t size
);
/*!
@brief Encode metadata from the provided metadata to Exif format.
See TiffParser::encode().
*/
static WriteMethod encode(
Blob& blob,
const byte* pData,
uint32_t size,
ByteOrder byteOrder,
const ExifData& exifData
);
/*!
@brief Encode metadata from the provided metadata to Exif format.
See TiffParser::encode().
Encode Exif metadata from the \em ExifData container to binary format
in the \em blob encoded in \em byteOrder.
This simpler encode method uses "intrusive" writing, i.e., it builds
the binary representation of the metadata from scratch. It does not
attempt "non-intrusive", i.e., in-place updating. It's better to use
the other encode() method, if the metadata is already available in
binary format, in order to allow for "non-intrusive" updating of the
existing binary representation.
This is just an inline wrapper for
ExifParser::encode(blob, 0, 0, byteOrder, exifData).
*/
static void encode(
Blob& blob,
ByteOrder byteOrder,
const ExifData& exifData
)
{
encode(blob, 0, 0, byteOrder, exifData);
}
}; // class ExifParser
} // namespace Exiv2
22 years ago
#endif // #ifndef EXIF_HPP_