Changed ImageFactory to use a static registry (to make it re-entrant without using a locking mechanism), introduced new ImageType namespace (for identifiers for image formats, these can be added without modifying image.*), tweaked image related documentation

v0.27.3
Andreas Huggel 20 years ago
parent bcf10895aa
commit ef7aae6fa3

@ -52,7 +52,7 @@ CCHDR = exv_conf.h exv_msvc.h mn.hpp rcsid.hpp
# Add library C++ source files to this list # Add library C++ source files to this list
CCSRC = basicio.cpp canonmn.cpp crwimage.cpp datasets.cpp error.cpp exif.cpp \ CCSRC = basicio.cpp canonmn.cpp crwimage.cpp datasets.cpp error.cpp exif.cpp \
futils.cpp fujimn.cpp ifd.cpp image.cpp iptc.cpp jpgimage.cpp \ futils.cpp fujimn.cpp ifd.cpp image.cpp imgreg.cpp iptc.cpp jpgimage.cpp \
makernote.cpp metadatum.cpp nikonmn.cpp olympusmn.cpp panasonicmn.cpp \ makernote.cpp metadatum.cpp nikonmn.cpp olympusmn.cpp panasonicmn.cpp \
sigmamn.cpp sonymn.cpp tags.cpp types.cpp value.cpp sigmamn.cpp sonymn.cpp tags.cpp types.cpp value.cpp

@ -38,6 +38,7 @@ EXIV2_RCSID("@(#) $Id$");
#include "actions.hpp" #include "actions.hpp"
#include "image.hpp" #include "image.hpp"
#include "jpgimage.hpp"
#include "exiv2.hpp" #include "exiv2.hpp"
#include "utils.hpp" #include "utils.hpp"
#include "types.hpp" #include "types.hpp"
@ -1289,7 +1290,7 @@ namespace {
} }
else { else {
targetImage targetImage
= Exiv2::ImageFactory::create(Exiv2::Image::exv, target); = Exiv2::ImageFactory::create(Exiv2::ImageType::exv, target);
assert(targetImage.get() != 0); assert(targetImage.get() != 0);
} }
if ( Params::instance().target_ & Params::ctExif if ( Params::instance().target_ & Params::ctExif

@ -60,18 +60,6 @@ EXIV2_RCSID("@(#) $Id$");
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2 {
// Local functions. These could be static private functions on Image
// subclasses but then ImageFactory needs to be made a friend.
/*!
@brief Create a new CrwImage instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is a CRW image.
bool isCrwType(BasicIo& iIo, bool advance);
const byte CrwImage::blank_[] = { const byte CrwImage::blank_[] = {
0x00 0x00
}; };
@ -182,14 +170,6 @@ namespace Exiv2 {
// Todo: implement me! // Todo: implement me!
} // CrwImage::writeMetadata } // CrwImage::writeMetadata
//! @cond IGNORE
CrwImage::CrwRegister::CrwRegister()
{
ImageFactory::registerImage(
Image::crw, newCrwInstance, isCrwType);
}
//! @endcond
bool CrwImage::isThisType(BasicIo& iIo, bool advance) const bool CrwImage::isThisType(BasicIo& iIo, bool advance) const
{ {
return isCrwType(iIo, advance); return isCrwType(iIo, advance);

@ -20,7 +20,7 @@
*/ */
/*! /*!
@file crwimage.hpp @file crwimage.hpp
@brief Class CrwImage to access Canon CRW images.<BR> @brief Class CrwImage to access Canon Crw images.<BR>
References:<BR> References:<BR>
<a href="http://www.sno.phy.queensu.ca/~phil/exiftool/canon_raw.html">The Canon RAW (CRW) File Format</a> by Phil Harvey <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/canon_raw.html">The Canon RAW (CRW) File Format</a> by Phil Harvey
@version $Rev$ @version $Rev$
@ -56,29 +56,38 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// type definitions // type definitions
//! Function pointer for functions to extract Exif tags from a CRW entry //! Function pointer for functions to extract Exif tags from a Crw entry
typedef void (*CrwExtractFct)(const CiffComponent&, typedef void (*CrwExtractFct)(const CiffComponent&,
const CrwMapInfo*, const CrwMapInfo*,
Image&, Image&,
ByteOrder); ByteOrder);
//! Function pointer for functions to insert CRW entries from an Exif tag //! Function pointer for functions to insert Crw entries from an Exif tag
typedef void (*CrwInsertFct)(); typedef void (*CrwInsertFct)();
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
// Add Crw to the supported image formats
namespace ImageType {
const int crw = 3; //!< Crw image type (see class CrwImage)
}
/*! /*!
@brief Class to access Canon CRW images. @brief Class to access raw Canon Crw images. Only Exif metadata and a
comment are supported. Crw format does not contain Iptc metadata.
*/ */
class CrwImage : public Image { class CrwImage : public Image {
friend bool isCrwType(BasicIo& iIo, bool advance); friend bool isCrwType(BasicIo& iIo, bool advance);
// NOT Implemented //! @name NOT Implemented
//@{
//! Copy constructor //! Copy constructor
CrwImage(const CrwImage& rhs); CrwImage(const CrwImage& rhs);
//! Assignment operator //! Assignment operator
CrwImage& operator=(const CrwImage& rhs); CrwImage& operator=(const CrwImage& rhs);
//@}
public: public:
//! @name Creators //! @name Creators
//@{ //@{
@ -104,39 +113,23 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Read all metadata from the image. Before this method
is called, the various metadata types (Iptc, Exif) will be empty.
This method returns success even when no metadata is found in
the image. Callers must therefore check the size of individual
metadata types before accessing the data.
@throw Error if opening or reading of the file fails or the image
data is not valid (does not look like CRW data).
*/
void readMetadata(); void readMetadata();
/*! /*!
@brief Write metadata back to the image. @brief Todo: Write metadata back to the image. This method is not
yet implemented.
All existing metadata sections in the image are either created,
replaced, or erased. If values for a given metadata type have been
assigned, a section for that metadata type will either be created or
replaced. If no values have been assigned to a given metadata type,
any exists section for that metadata type will be removed from the
image.
@throw Error if the operation fails
*/ */
void writeMetadata(); void writeMetadata();
/*!
@brief Assign new exif data. The new exif data is not written
to the image until the writeMetadata() method is called.
@param exifData An ExifData instance holding exif data to be copied
*/
void setExifData(const ExifData& exifData); void setExifData(const ExifData& exifData);
void clearExifData(); void clearExifData();
/*!
@brief Not supported. Crw format does not contain Iptc metadata.
Calling this function will raise an exception (Error).
*/
void setIptcData(const IptcData& iptcData); void setIptcData(const IptcData& iptcData);
/*!
@brief Not supported. Crw format does not contain Iptc metadata.
Calling this function will raise an exception (Error).
*/
void clearIptcData(); void clearIptcData();
void setComment(const std::string& comment); void setComment(const std::string& comment);
void clearComment(); void clearComment();
@ -155,13 +148,6 @@ namespace Exiv2 {
BasicIo& io() const { return *io_; } BasicIo& io() const { return *io_; }
//@} //@}
//! @cond IGNORE
// Public only so that we can create a static instance
struct CrwRegister{
CrwRegister();
};
//! @endcond
private: private:
//! @name Manipulators //! @name Manipulators
@ -191,18 +177,13 @@ namespace Exiv2 {
*/ */
bool isThisType(BasicIo& iIo, bool advance) const; bool isThisType(BasicIo& iIo, bool advance) const;
/*! /*!
@brief Writes a Crw header (aka signature) to the BasicIo instance. @brief Todo: Write Crw header. Not implemented yet.
@param oIo BasicIo instance that the header is written to.
@return 0 if successful;<BR>
2 if the input image is invalid or can not be read;<BR>
4 if the temporary image can not be written to;<BR>
-3 other temporary errors;<BR>
*/ */
int writeHeader(BasicIo& oIo) const; int writeHeader(BasicIo& oIo) const;
//@} //@}
// DATA // DATA
static const byte blank_[]; //!< Minimal CRW image static const byte blank_[]; //!< Minimal Crw image
BasicIo::AutoPtr io_; //!< Image data io pointer BasicIo::AutoPtr io_; //!< Image data io pointer
ExifData exifData_; //!< Exif data container ExifData exifData_; //!< Exif data container
@ -211,8 +192,6 @@ namespace Exiv2 {
}; // class CrwImage }; // class CrwImage
static CrwImage::CrwRegister crwReg;
/*! /*!
Base class for all objects in a raw metadata parse tree. Base class for all objects in a raw metadata parse tree.
Defines the interface for raw metadata composites. Defines the interface for raw metadata composites.
@ -280,7 +259,7 @@ namespace Exiv2 {
/*! /*!
@brief Interface class for components of the CIFF directory hierarchy of @brief Interface class for components of the CIFF directory hierarchy of
a CRW (Canon Raw data) image. Both CIFF directories as well as a Crw (Canon Raw data) image. Both CIFF directories as well as
entries implement this interface. entries implement this interface.
*/ */
class CiffComponent : public RawMetadata { class CiffComponent : public RawMetadata {
@ -371,7 +350,7 @@ namespace Exiv2 {
/*! /*!
@brief This class models one directory entry of a CIFF directory of @brief This class models one directory entry of a CIFF directory of
a CRW (Canon Raw data) image. a Crw (Canon Raw data) image.
*/ */
class CiffEntry : public CiffComponent { class CiffEntry : public CiffComponent {
public: public:
@ -399,7 +378,7 @@ namespace Exiv2 {
}; // class CiffEntry }; // class CiffEntry
//! This class models a CIFF directory of a CRW (Canon Raw data) image. //! This class models a CIFF directory of a Crw (Canon Raw data) image.
class CiffDirectory : public CiffComponent { class CiffDirectory : public CiffComponent {
public: public:
//! @name Creators //! @name Creators
@ -458,7 +437,7 @@ namespace Exiv2 {
}; // class CiffDirectory }; // class CiffDirectory
//! This class models the header of a CRW (Canon Raw data) image. //! This class models the header of a Crw (Canon Raw data) image.
class CiffHeader : public RawMetadata { class CiffHeader : public RawMetadata {
public: public:
//! @name Creators //! @name Creators
@ -499,7 +478,7 @@ namespace Exiv2 {
//@} //@}
// DATA // DATA
static const char signature_[]; //!< Canon CRW signature "HEAPCCDR" static const char signature_[]; //!< Canon Crw signature "HEAPCCDR"
private: private:
// DATA // DATA
@ -533,8 +512,8 @@ namespace Exiv2 {
//@} //@}
// DATA // DATA
uint16_t crwTagId_; //!< CRW tag id uint16_t crwTagId_; //!< Crw tag id
uint16_t crwDir_; //!< CRW directory tag uint16_t crwDir_; //!< Crw directory tag
uint32_t size_; //!< Data size (overwrites the size from the entry) uint32_t size_; //!< Data size (overwrites the size from the entry)
uint16_t tag_; //!< Exif tag to map to uint16_t tag_; //!< Exif tag to map to
IfdId ifdId_; //!< Exif Ifd id to map to IfdId ifdId_; //!< Exif Ifd id to map to
@ -544,7 +523,7 @@ namespace Exiv2 {
}; // struct CrwMapInfo }; // struct CrwMapInfo
/*! /*!
@brief Static class providing mapping functionality from CRW entries @brief Static class providing mapping functionality from Crw entries
to image metadata and vice versa to image metadata and vice versa
*/ */
class CrwMap { class CrwMap {
@ -556,7 +535,7 @@ namespace Exiv2 {
public: public:
/*! /*!
@brief Extract image metadata from a CRW entry convert and add it @brief Extract image metadata from a Crw entry convert and add it
to the image metadata. to the image metadata.
@param ciffComponent Source CIFF entry @param ciffComponent Source CIFF entry
@ -569,11 +548,11 @@ namespace Exiv2 {
ByteOrder byteOrder); ByteOrder byteOrder);
private: private:
//! Return conversion information for one CRW \em dir and \em tagId //! Return conversion information for one Crw \em dir and \em tagId
static const CrwMapInfo* crwMapInfo(uint16_t dir, uint16_t tagId); static const CrwMapInfo* crwMapInfo(uint16_t dir, uint16_t tagId);
/*! /*!
@brief Standard extraction function to convert CRW entries to @brief Standard extraction function to convert Crw entries to
Exif metadata. Exif metadata.
Uses the mapping defined in the conversion structure \em crwMapInfo Uses the mapping defined in the conversion structure \em crwMapInfo
@ -633,6 +612,21 @@ namespace Exiv2 {
}; // class CrwMap }; // class CrwMap
// *****************************************************************************
// template, inline and free functions
// These could be static private functions on Image subclasses but then
// ImageFactory needs to be made a friend.
/*!
@brief Create a new CrwImage instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is a Crw image.
bool isCrwType(BasicIo& iIo, bool advance);
} // namespace Exiv2 } // namespace Exiv2
#endif // #ifndef CRWIMAGE_HPP_ #endif // #ifndef CRWIMAGE_HPP_

@ -11,6 +11,7 @@
// ***************************************************************************** // *****************************************************************************
// included header files // included header files
#include "image.hpp" #include "image.hpp"
#include "jpgimage.hpp"
#include "exif.hpp" #include "exif.hpp"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
@ -79,7 +80,7 @@ catch (Exiv2::AnyError& e) {
void write(const std::string& file, Exiv2::ExifData& ed) void write(const std::string& file, Exiv2::ExifData& ed)
{ {
Image::AutoPtr image = ImageFactory::create(Image::exv, file); Image::AutoPtr image = ImageFactory::create(Exiv2::ImageType::exv, file);
assert(image.get() != 0); assert(image.get() != 0);
image->setExifData(ed); image->setExifData(ed);

@ -78,6 +78,7 @@ namespace Exiv2 {
ErrMsg( 32, "%1: CRW images don't support JPEG comments"), // %1=function ErrMsg( 32, "%1: CRW images don't support JPEG comments"), // %1=function
ErrMsg( 33, "This does not look like a CRW image"), ErrMsg( 33, "This does not look like a CRW image"),
ErrMsg( 34, "%1: Not supported"), // %1=function ErrMsg( 34, "%1: Not supported"), // %1=function
ErrMsg( 35, "ImageFactory registry full"),
// Last error message (message is not used) // Last error message (message is not used)
ErrMsg( -2, "(Unknown Error)") ErrMsg( -2, "(Unknown Error)")

@ -44,10 +44,6 @@ EXIV2_RCSID("@(#) $Id$");
#include "error.hpp" #include "error.hpp"
#include "futils.hpp" #include "futils.hpp"
// Ensure registration with factory
#include "jpgimage.hpp"
#include "crwimage.hpp"
// + standard includes // + standard includes
#include <cerrno> #include <cerrno>
#include <cstdio> #include <cstdio>
@ -67,70 +63,50 @@ EXIV2_RCSID("@(#) $Id$");
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2 {
int ImageFactory::Init::count = 0; const ImageFactory::Registry* ImageFactory::find(int imageType)
ImageFactory::Init::Init()
{
++count;
}
ImageFactory::Init::~Init()
{ {
if (--count == 0) { for (unsigned int i = 0; registry_[i].imageType_ != ImageType::none; ++i) {
Exiv2::ImageFactory::cleanup(); if (registry_[i].imageType_ == imageType) return &registry_[i];
} }
return 0;
} }
ImageFactory::Registry* ImageFactory::registry_ = 0; void ImageFactory::registerImage(int type,
NewInstanceFct newInst,
void ImageFactory::cleanup() IsThisTypeFct isType)
{
delete registry_;
registry_ = 0;
}
void ImageFactory::init()
{ {
if (0 == registry_) { unsigned int i = 0;
registry_ = new Registry; for (; i < MAX_IMAGE_FORMATS; ++i) {
if (registry_[i].imageType_ == ImageType::none) {
registry_[i] = Registry(type, newInst, isType);
break;
} }
} }
if (i == MAX_IMAGE_FORMATS) throw Error(35);
void ImageFactory::registerImage(Image::Type type,
NewInstanceFct newInst, IsThisTypeFct isType)
{
init();
assert (newInst && isType);
(*registry_)[type] = ImageFcts(newInst, isType);
} }
Image::Type ImageFactory::getType(const std::string& path) int ImageFactory::getType(const std::string& path)
{ {
FileIo fileIo(path); FileIo fileIo(path);
return getType(fileIo); return getType(fileIo);
} }
Image::Type ImageFactory::getType(const byte* data, long size) int ImageFactory::getType(const byte* data, long size)
{ {
MemIo memIo(data, size); MemIo memIo(data, size);
return getType(memIo); return getType(memIo);
} }
Image::Type ImageFactory::getType(BasicIo& io) int ImageFactory::getType(BasicIo& io)
{ {
if (io.open() != 0) return Image::none; if (io.open() != 0) return ImageType::none;
IoCloser closer(io); IoCloser closer(io);
Image::Type type = Image::none; for (unsigned int i = 0; registry_[i].imageType_ != ImageType::none; ++i) {
Registry::const_iterator b = registry_->begin(); if (registry_[i].isThisType_(io, false)) {
Registry::const_iterator e = registry_->end(); return registry_[i].imageType_;
for (Registry::const_iterator i = b; i != e; ++i)
{
if (i->second.isThisType(io, false)) {
type = i->first;
break;
} }
} }
return type; return ImageType::none;
} // ImageFactory::getType } // ImageFactory::getType
Image::AutoPtr ImageFactory::open(const std::string& path) Image::AutoPtr ImageFactory::open(const std::string& path)
@ -154,19 +130,15 @@ namespace Exiv2 {
if (io->open() != 0) { if (io->open() != 0) {
throw Error(9, io->path(), strError()); throw Error(9, io->path(), strError());
} }
Image::AutoPtr image; for (unsigned int i = 0; registry_[i].imageType_ != ImageType::none; ++i) {
Registry::const_iterator b = registry_->begin(); if (registry_[i].isThisType_(*io, false)) {
Registry::const_iterator e = registry_->end(); return registry_[i].newInstance_(io, false);
for (Registry::const_iterator i = b; i != e; ++i) {
if (i->second.isThisType(*io, false)) {
image = i->second.newInstance(io, false);
break;
} }
} }
return image; return Image::AutoPtr();
} // ImageFactory::open } // ImageFactory::open
Image::AutoPtr ImageFactory::create(Image::Type type, Image::AutoPtr ImageFactory::create(int type,
const std::string& path) const std::string& path)
{ {
std::auto_ptr<FileIo> fileIo(new FileIo(path)); std::auto_ptr<FileIo> fileIo(new FileIo(path));
@ -181,7 +153,7 @@ namespace Exiv2 {
return image; return image;
} }
Image::AutoPtr ImageFactory::create(Image::Type type) Image::AutoPtr ImageFactory::create(int type)
{ {
BasicIo::AutoPtr io(new MemIo); BasicIo::AutoPtr io(new MemIo);
Image::AutoPtr image = create(type, io); Image::AutoPtr image = create(type, io);
@ -189,13 +161,13 @@ namespace Exiv2 {
return image; return image;
} }
Image::AutoPtr ImageFactory::create(Image::Type type, Image::AutoPtr ImageFactory::create(int type,
BasicIo::AutoPtr io) BasicIo::AutoPtr io)
{ {
// BasicIo instance does not need to be open // BasicIo instance does not need to be open
Registry::const_iterator i = registry_->find(type); const Registry* r = find(type);
if (i != registry_->end()) { if (0 != r) {
return i->second.newInstance(io, true); return r->newInstance_(io, true);
} }
return Image::AutoPtr(); return Image::AutoPtr();
} // ImageFactory::create } // ImageFactory::create

@ -54,6 +54,12 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
//! Supported image formats
namespace ImageType {
const int none = 0; //!< Not an image
}
/*! /*!
@brief Abstract base class defining the interface for an image. This is @brief Abstract base class defining the interface for an image. This is
the top-level interface to the Exiv2 library. the top-level interface to the Exiv2 library.
@ -64,9 +70,6 @@ namespace Exiv2 {
*/ */
class Image { class Image {
public: public:
//! Supported image formats
enum Type { none, jpeg, exv, crw };
//! Image auto_ptr type //! Image auto_ptr type
typedef std::auto_ptr<Image> AutoPtr; typedef std::auto_ptr<Image> AutoPtr;
@ -79,9 +82,17 @@ namespace Exiv2 {
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*! /*!
@brief Read metadata from assigned image. Before this method @brief Read all metadata supported by a specific image format from the
is called, the various metadata types (Iptc, Exif) will be empty. image. Before this method is called, the various metadata types
@throw Error In case of failure. will be empty.
This method returns success even if no metadata is found in the
image. Callers must therefore check the size of individual metadata
types before accessing the data.
@throw Error if opening or reading of the file fails or the image
data is not valid (does not look like data of the specific image
type).
*/ */
virtual void readMetadata() =0; virtual void readMetadata() =0;
/*! /*!
@ -154,50 +165,50 @@ namespace Exiv2 {
virtual bool good() const =0; virtual bool good() const =0;
/*! /*!
@brief Returns an ExifData instance containing currently buffered @brief Returns an ExifData instance containing currently buffered
exif data. Exif data.
The exif data may have been read from the image by The Exif data may have been read from the image by
a previous call to readMetadata() or added directly. The exif a previous call to readMetadata() or added directly. The Exif
data in the returned instance will be written to the image when data in the returned instance will be written to the image when
writeMetadata() is called. writeMetadata() is called.
@return read only ExifData instance containing exif values @return read only ExifData instance containing Exif values
*/ */
virtual const ExifData& exifData() const =0; virtual const ExifData& exifData() const =0;
/*! /*!
@brief Returns an ExifData instance containing currently buffered @brief Returns an ExifData instance containing currently buffered
exif data. Exif data.
The contained exif data may have been read from the image by The contained Exif data may have been read from the image by
a previous call to readMetadata() or added directly. The exif a previous call to readMetadata() or added directly. The Exif
data in the returned instance will be written to the image when data in the returned instance will be written to the image when
writeMetadata() is called. writeMetadata() is called.
@return modifiable ExifData instance containing exif values @return modifiable ExifData instance containing Exif values
*/ */
virtual ExifData& exifData() =0; virtual ExifData& exifData() =0;
/*! /*!
@brief Returns an IptcData instance containing currently buffered @brief Returns an IptcData instance containing currently buffered
iptc data. Iptc data.
The contained iptc data may have been read from the image by The contained Iptc data may have been read from the image by
a previous call to readMetadata() or added directly. The iptc a previous call to readMetadata() or added directly. The Iptc
data in the returned instance will be written to the image when data in the returned instance will be written to the image when
writeMetadata() is called. writeMetadata() is called.
@return modifiable IptcData instance containing iptc values @return modifiable IptcData instance containing Iptc values
*/ */
virtual const IptcData& iptcData() const =0; virtual const IptcData& iptcData() const =0;
/*! /*!
@brief Returns an ExifData instance containing currently buffered @brief Returns an IptcData instance containing currently buffered
exif data. Iptc data.
The contained iptc data may have been read from the image by The contained Iptc data may have been read from the image by
a previous call to readMetadata() or added directly. The iptc a previous call to readMetadata() or added directly. The Iptc
data in the returned instance will be written to the image when data in the returned instance will be written to the image when
writeMetadata() is called. writeMetadata() is called.
@return modifiable IptcData instance containing iptc values @return modifiable IptcData instance containing Iptc values
*/ */
virtual IptcData& iptcData() =0; virtual IptcData& iptcData() =0;
/*! /*!
@ -266,7 +277,7 @@ namespace Exiv2 {
@param newInst Function pointer for creating image instances. @param newInst Function pointer for creating image instances.
@param isType Function pointer to test for matching image types. @param isType Function pointer to test for matching image types.
*/ */
static void registerImage(Image::Type type, static void registerImage(int type,
NewInstanceFct newInst, NewInstanceFct newInst,
IsThisTypeFct isType); IsThisTypeFct isType);
//@} //@}
@ -324,7 +335,7 @@ namespace Exiv2 {
type. type.
@throw Error If the image type is not supported. @throw Error If the image type is not supported.
*/ */
static Image::AutoPtr create(Image::Type type, const std::string& path); static Image::AutoPtr create(int type, const std::string& path);
/*! /*!
@brief Create an Image subclass of the requested type by creating a @brief Create an Image subclass of the requested type by creating a
new image in memory. new image in memory.
@ -333,7 +344,7 @@ namespace Exiv2 {
type. type.
@throw Error If the image type is not supported @throw Error If the image type is not supported
*/ */
static Image::AutoPtr create(Image::Type type); static Image::AutoPtr create(int type);
/*! /*!
@brief Create an Image subclass of the requested type by writing a @brief Create an Image subclass of the requested type by writing a
new image to a BasicIo instance. If the BasicIo instance already new image to a BasicIo instance. If the BasicIo instance already
@ -348,14 +359,14 @@ namespace Exiv2 {
@return An auto-pointer that owns an Image instance of the requested @return An auto-pointer that owns an Image instance of the requested
type. If the image type is not supported, the pointer is 0. type. If the image type is not supported, the pointer is 0.
*/ */
static Image::AutoPtr create(Image::Type type, BasicIo::AutoPtr io); static Image::AutoPtr create(int type, BasicIo::AutoPtr io);
/*! /*!
@brief Returns the image type of the provided file. @brief Returns the image type of the provided file.
@param path %Image file. The contents of the file are tested to @param path %Image file. The contents of the file are tested to
determine the image type. File extension is ignored. determine the image type. File extension is ignored.
@return %Image type or Image::none if the type is not recognized. @return %Image type or Image::none if the type is not recognized.
*/ */
static Image::Type getType(const std::string& path); static int getType(const std::string& path);
/*! /*!
@brief Returns the image type of the provided data buffer. @brief Returns the image type of the provided data buffer.
@param data Pointer to a data buffer containing an image. The contents @param data Pointer to a data buffer containing an image. The contents
@ -363,7 +374,7 @@ namespace Exiv2 {
@param size Number of bytes pointed to by \em data. @param size Number of bytes pointed to by \em data.
@return %Image type or Image::none if the type is not recognized. @return %Image type or Image::none if the type is not recognized.
*/ */
static Image::Type getType(const byte* data, long size); static int getType(const byte* data, long size);
/*! /*!
@brief Returns the image type of data provided by a BasicIo instance. @brief Returns the image type of data provided by a BasicIo instance.
The passed in \em io instance is (re)opened by this method. The passed in \em io instance is (re)opened by this method.
@ -371,27 +382,8 @@ namespace Exiv2 {
of the image data are tested to determine the type. of the image data are tested to determine the type.
@return %Image type or Image::none if the type is not recognized. @return %Image type or Image::none if the type is not recognized.
*/ */
static Image::Type getType(BasicIo& io); static int getType(BasicIo& io);
//@}
/*!
@brief Class Init is used to execute initialisation and termination
code exactly once, at the begin and end of the program.
See Bjarne Stroustrup, 'The C++ Programming Language 3rd
Edition', section 21.5.2 for details about this pattern.
*/
class Init {
static int count; //!< Counts calls to constructor
public:
//! @name Creators
//@{
//! Perform one-time initialisations.
Init();
//! Perform one-time cleanup operations.
~Init();
//@} //@}
};
private: private:
//! @name Creators //! @name Creators
@ -400,28 +392,39 @@ namespace Exiv2 {
ImageFactory(); ImageFactory();
//! Prevent copy construction: not implemented. //! Prevent copy construction: not implemented.
ImageFactory(const ImageFactory& rhs); ImageFactory(const ImageFactory& rhs);
//! Creates the private static instance
static void init();
//@} //@}
//! Struct for storing image function pointers. //! Struct for storing image types and function pointers.
struct ImageFcts struct Registry
{ {
NewInstanceFct newInstance; //! Default constructor
IsThisTypeFct isThisType; Registry()
ImageFcts(NewInstanceFct newInst, IsThisTypeFct isType) : imageType_(ImageType::none),
: newInstance(newInst), isThisType(isType) {} newInstance_(0),
ImageFcts() : newInstance(0), isThisType(0) {} isThisType_(0)
{}
//! Constructor
Registry(int imageType,
NewInstanceFct newInstance,
IsThisTypeFct isThisType)
: imageType_(imageType),
newInstance_(newInstance),
isThisType_(isThisType)
{}
int imageType_;
NewInstanceFct newInstance_;
IsThisTypeFct isThisType_;
}; };
//! Return the registry entry for type
static const Registry* find(int imageType);
// DATA // DATA
//! Type used to store Image creation functions static const unsigned int MAX_IMAGE_FORMATS = 32;
typedef std::map<Image::Type, ImageFcts> Registry;
//! List of image types and corresponding creation functions. //! List of image types and corresponding creation functions.
static Registry* registry_; static Registry registry_[MAX_IMAGE_FORMATS];
}; // class ImageFactory }; // class ImageFactory
//! Helper class modelling the TIFF header structure. //! Helper class modelling the TIFF header structure.
class TiffHeader { class TiffHeader {
public: public:
@ -478,16 +481,4 @@ namespace Exiv2 {
} // namespace Exiv2 } // namespace Exiv2
namespace {
/*!
Each translation unit that includes image.hpp declares its own
Init object. The destructor ensures that the factory is properly
freed exactly once.
See Bjarne Stroustrup, 'The C++ Programming Language 3rd
Edition', section 21.5.2 for details about this pattern.
*/
Exiv2::ImageFactory::Init imageFactoryInit;
}
#endif // #ifndef IMAGE_HPP_ #endif // #ifndef IMAGE_HPP_

@ -0,0 +1,50 @@
// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2005 Andreas Huggel <ahuggel@gmx.net>
*
* This program is part of the Exiv2 distribution.
*
* 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.
*
* 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.
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
File: imgreg.cpp
Version: $Rev$
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 19-Sep-05, ahu: created
*/
// *****************************************************************************
#include "rcsid.hpp"
EXIV2_RCSID("@(#) $Id$");
// *****************************************************************************
// included header files
#include "image.hpp"
#include "jpgimage.hpp"
#include "crwimage.hpp"
// + standard includes
// *****************************************************************************
// class member definitions
namespace Exiv2 {
ImageFactory::Registry ImageFactory::registry_[] = {
Registry(ImageType::jpeg, newJpegInstance, isJpegType),
Registry(ImageType::exv, newExvInstance, isExvType),
Registry(ImageType::crw, newCrwInstance, isCrwType)
};
} // namespace Exiv2

@ -50,25 +50,6 @@ EXIV2_RCSID("@(#) $Id$");
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2 {
// Local functions. These could be static private functions on Image
// subclasses but then ImageFactory needs to be made a friend.
/*!
@brief Create a new ExvImage instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newExvInstance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is an EXV file
bool isExvType(BasicIo& iIo, bool advance);
/*!
@brief Create a new JpegImage instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newJpegInstance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is a JPEG image.
bool isJpegType(BasicIo& iIo, bool advance);
const byte JpegBase::sos_ = 0xda; const byte JpegBase::sos_ = 0xda;
const byte JpegBase::eoi_ = 0xd9; const byte JpegBase::eoi_ = 0xd9;
const byte JpegBase::app0_ = 0xe0; const byte JpegBase::app0_ = 0xe0;
@ -550,14 +531,6 @@ namespace Exiv2 {
{ {
} }
//! @cond IGNORE
JpegImage::JpegRegister::JpegRegister()
{
ImageFactory::registerImage(
Image::jpeg, newJpegInstance, isJpegType);
}
//! @endcond
int JpegImage::writeHeader(BasicIo& outIo) const int JpegImage::writeHeader(BasicIo& outIo) const
{ {
// Jpeg header // Jpeg header
@ -605,14 +578,6 @@ namespace Exiv2 {
{ {
} }
//! @cond IGNORE
ExvImage::ExvRegister::ExvRegister()
{
ImageFactory::registerImage(
Image::exv, newExvInstance, isExvType);
}
//! @endcond
int ExvImage::writeHeader(BasicIo& outIo) const int ExvImage::writeHeader(BasicIo& outIo) const
{ {
// Exv header // Exv header

@ -50,6 +50,12 @@ namespace Exiv2 {
// ***************************************************************************** // *****************************************************************************
// class definitions // class definitions
// Supported jpeg image formats
namespace ImageType {
const int jpeg = 1; //!< Jpeg image type (see class JpegImage)
const int exv = 2; //!< Exv image type (see class ExvImage)
}
/*! /*!
@brief Abstract helper base class to access JPEG images. @brief Abstract helper base class to access JPEG images.
*/ */
@ -62,36 +68,8 @@ namespace Exiv2 {
//@} //@}
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Read all metadata from the image. Before this method
is called, the various metadata types (Iptc, Exif) will be empty.
This method returns success even when no metadata is found in
the image. Callers must therefore check the size of individual
metadata types before accessing the data.
@throw Error if opening or reading of the file fails or the image
data is not valid (does not look like JPEG data).
*/
void readMetadata(); void readMetadata();
/*!
@brief Write metadata back to the image.
All existing metadata sections in the image are either created,
replaced, or erased. If values for a given metadata type have been
assigned, a section for that metadata type will either be created or
replaced. If no values have been assigned to a given metadata type,
any exists section for that metadata type will be removed from the
image.
@throw Error if the operation fails
*/
void writeMetadata(); void writeMetadata();
/*!
@brief Assign new exif data. The new exif data is not written
to the image until the writeMetadata() method is called.
@param exifData An ExifData instance holding exif data to be copied
*/
void setExifData(const ExifData& exifData); void setExifData(const ExifData& exifData);
void clearExifData(); void clearExifData();
void setIptcData(const IptcData& iptcData); void setIptcData(const IptcData& iptcData);
@ -141,7 +119,7 @@ namespace Exiv2 {
@brief Writes the image header (aka signature) to the BasicIo instance. @brief Writes the image header (aka signature) to the BasicIo instance.
@param oIo BasicIo instance that the header is written to. @param oIo BasicIo instance that the header is written to.
@return 0 if successful;<BR> @return 0 if successful;<BR>
4 if the output file can not be written to;<BR> 4 if the output file can not be written to
*/ */
virtual int writeHeader(BasicIo& oIo) const =0; virtual int writeHeader(BasicIo& oIo) const =0;
//@} //@}
@ -164,7 +142,7 @@ namespace Exiv2 {
analyse the data (true) or left at its original analyse the data (true) or left at its original
position (false). This applies only if the type matches. position (false). This applies only if the type matches.
@return true if the data matches the type of this class;<BR> @return true if the data matches the type of this class;<BR>
false if the data does not match;<BR> false if the data does not match
*/ */
virtual bool isThisType(BasicIo& iIo, bool advance) const =0; virtual bool isThisType(BasicIo& iIo, bool advance) const =0;
//@} //@}
@ -196,7 +174,7 @@ namespace Exiv2 {
when the BasicIo instance is positioned one byte past the end of a when the BasicIo instance is positioned one byte past the end of a
Jpeg segment. Jpeg segment.
@return the next Jpeg segment marker if successful;<BR> @return the next Jpeg segment marker if successful;<BR>
-1 if a maker was not found before EOF;<BR> -1 if a maker was not found before EOF
*/ */
int advanceToMarker() const; int advanceToMarker() const;
/*! /*!
@ -275,27 +253,9 @@ namespace Exiv2 {
//! Destructor //! Destructor
~JpegImage() {} ~JpegImage() {}
//@} //@}
//! @cond IGNORE
// Public only so that we can create a static instance
struct JpegRegister{
JpegRegister();
};
//! @endcond
protected: protected:
//! @name Accessors //! @name Accessors
//@{ //@{
/*!
@brief Determine if the content of the BasicIo instance is a Jpeg image.
See base class for more details.
@param iIo BasicIo instance to read from.
@param advance Flag indicating whether the position of the io
should be advanced by the number of characters read to
analyse the data (true) or left at its original
position (false). This applies only if the type matches.
@return true if the data matches a Jpeg image;<BR>
false if the data does not match;<BR>
*/
bool isThisType(BasicIo& iIo, bool advance) const; bool isThisType(BasicIo& iIo, bool advance) const;
//@} //@}
//! @name Manipulators //! @name Manipulators
@ -306,7 +266,7 @@ namespace Exiv2 {
@return 0 if successful;<BR> @return 0 if successful;<BR>
2 if the input image is invalid or can not be read;<BR> 2 if the input image is invalid or can not be read;<BR>
4 if the temporary image can not be written to;<BR> 4 if the temporary image can not be written to;<BR>
-3 other temporary errors;<BR> -3 other temporary errors
*/ */
int writeHeader(BasicIo& oIo) const; int writeHeader(BasicIo& oIo) const;
//@} //@}
@ -324,8 +284,6 @@ namespace Exiv2 {
JpegImage& operator=(const JpegImage& rhs); JpegImage& operator=(const JpegImage& rhs);
}; // class JpegImage }; // class JpegImage
static JpegImage::JpegRegister jpegReg;
//! Helper class to access %Exiv2 files //! Helper class to access %Exiv2 files
class ExvImage : public JpegBase { class ExvImage : public JpegBase {
friend bool isExvType(BasicIo& iIo, bool advance); friend bool isExvType(BasicIo& iIo, bool advance);
@ -351,37 +309,13 @@ namespace Exiv2 {
//! Destructor //! Destructor
~ExvImage() {} ~ExvImage() {}
//@} //@}
//! @cond IGNORE
// Public only so that we can create a static instance
struct ExvRegister{
ExvRegister();
};
//! @endcond
protected: protected:
//! @name Accessors //! @name Accessors
//@{ //@{
/*!
@brief Determine if the content of the BasicIo instance is an Exv
image. See base class for more details.
@param iIo BasicIo instance to read from.
@param advance Flag indicating whether the position of the io
should be advanced by the number of characters read to
analyse the data (true) or left at its original
position (false). This applies only if the type matches.
@return true if the data matches a Jpeg image;<BR>
false if the data does not match;<BR>
*/
virtual bool isThisType(BasicIo& iIo, bool advance) const; virtual bool isThisType(BasicIo& iIo, bool advance) const;
//@} //@}
//! @name Manipulators //! @name Manipulators
//@{ //@{
/*!
@brief Writes an Exv header (aka signature) to the BasicIo instance.
@param oIo BasicIo instance that the header is written to.
@return 0 if successful;<BR>
4 if the output file can not be written to;<BR>
*/
int writeHeader(BasicIo& oIo) const; int writeHeader(BasicIo& oIo) const;
//@} //@}
private: private:
@ -398,8 +332,28 @@ namespace Exiv2 {
ExvImage& operator=(const ExvImage& rhs); ExvImage& operator=(const ExvImage& rhs);
}; // class ExvImage }; // class ExvImage
static ExvImage::ExvRegister exvReg; // *****************************************************************************
} // namespace Exiv2 // template, inline and free functions
// These could be static private functions on Image subclasses but then
// ImageFactory needs to be made a friend.
/*!
@brief Create a new JpegImage instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newJpegInstance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is a JPEG image.
bool isJpegType(BasicIo& iIo, bool advance);
/*!
@brief Create a new ExvImage instance and return an auto-pointer to it.
Caller owns the returned object and the auto-pointer ensures that
it will be deleted.
*/
Image::AutoPtr newExvInstance(BasicIo::AutoPtr io, bool create);
//! Check if the file iIo is an EXV file
bool isExvType(BasicIo& iIo, bool advance);
} // namespace Exiv2
#endif // #ifndef JPGIMAGE_HPP_ #endif // #ifndef JPGIMAGE_HPP_

Loading…
Cancel
Save