From b2f2b95bcbda17aec76bddd8dfd342671cb3ba7b Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Mon, 5 Feb 2007 14:33:25 +0000 Subject: [PATCH] Added Fujifilm read-support for RAF images. --- src/Makefile | 3 +- src/image.cpp | 6 +- src/rafimage.cpp | 190 +++++++++++++++++++++++++++++++++++++++++++++++ src/rafimage.hpp | 176 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 src/rafimage.cpp create mode 100644 src/rafimage.hpp diff --git a/src/Makefile b/src/Makefile index 069f3ac6..249d2a5a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -80,7 +80,8 @@ ifdef HAVE_LIBZ CCSRC += pngimage.cpp \ pngchunk.cpp endif -CCSRC += sigmamn.cpp \ +CCSRC += rafimage.cpp \ + sigmamn.cpp \ sonymn.cpp \ tags.cpp \ tiffcomposite.cpp \ diff --git a/src/image.cpp b/src/image.cpp index 75451b87..ef42b50f 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -44,14 +44,15 @@ EXIV2_RCSID("@(#) $Id$") #include "error.hpp" #include "futils.hpp" -#include "jpgimage.hpp" #include "cr2image.hpp" #include "crwimage.hpp" +#include "jpgimage.hpp" #include "mrwimage.hpp" -#include "tiffimage.hpp" #ifdef EXV_HAVE_LIBZ # include "pngimage.hpp" #endif // EXV_HAVE_LIBZ +#include "rafimage.hpp" +#include "tiffimage.hpp" // + standard includes #include @@ -83,6 +84,7 @@ namespace Exiv2 { #ifdef EXV_HAVE_LIBZ { ImageType::png, newPngInstance, isPngType, amRead, amRead, amNone }, #endif // EXV_HAVE_LIBZ + { ImageType::raf, newRafInstance, isRafType, amRead, amRead, amNone }, // End of list marker { ImageType::none, 0, 0, amNone, amNone, amNone } }; diff --git a/src/rafimage.cpp b/src/rafimage.cpp new file mode 100644 index 00000000..543c7251 --- /dev/null +++ b/src/rafimage.cpp @@ -0,0 +1,190 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2007 Andreas Huggel + * + * 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., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. + */ +/* + File: rafimage.cpp + Version: $Rev$ + Author(s): Andreas Huggel (ahu) + History: 05-Feb-07, ahu: created + Credits: See header file + */ +// ***************************************************************************** +#include "rcsid.hpp" +EXIV2_RCSID("@(#) $Id$") + +// ***************************************************************************** +// included header files +#ifdef _MSC_VER +# include "exv_msvc.h" +#else +# include "exv_conf.h" +#endif + +#include "rafimage.hpp" +#include "tiffparser.hpp" +#include "image.hpp" +#include "basicio.hpp" +#include "error.hpp" +#include "futils.hpp" + +// + standard includes +#include +#include +#include +#include + +// ***************************************************************************** +// class member definitions +namespace Exiv2 { + + RafImage::RafImage(BasicIo::AutoPtr io, bool create) + : Image(mdExif | mdIptc), io_(io) + { + if (create) { + IoCloser closer(*io_); + io_->open(); + } + } // RafImage::RafImage + + bool RafImage::good() const + { + if (io_->open() != 0) return false; + IoCloser closer(*io_); + return isThisType(*io_, false); + } + + AccessMode RafImage::checkMode(MetadataId metadataId) const + { + return ImageFactory::checkMode(ImageType::raf, metadataId); + } + + void RafImage::clearMetadata() + { + clearExifData(); + clearIptcData(); + } + + void RafImage::setMetadata(const Image& image) + { + setExifData(image.exifData()); + setIptcData(image.iptcData()); + } + + void RafImage::clearExifData() + { + exifData_.clear(); + } + + void RafImage::setExifData(const ExifData& exifData) + { + exifData_ = exifData; + } + + void RafImage::clearIptcData() + { + iptcData_.clear(); + } + + void RafImage::setIptcData(const IptcData& iptcData) + { + iptcData_ = iptcData; + } + + void RafImage::clearComment() + { + // not supported, do nothing + } + + void RafImage::setComment(const std::string& /*comment*/) + { + // not supported + throw(Error(32, "Image comment", "RAF")); + } + + void RafImage::readMetadata() + { +#ifdef DEBUG + std::cerr << "Reading RAF file " << io_->path() << "\n"; +#endif + if (io_->open() != 0) throw Error(9, io_->path(), strError()); + IoCloser closer(*io_); + // Ensure that this is the correct image type + if (!isThisType(*io_, true)) { + if (io_->error() || io_->eof()) throw Error(14); + throw Error(3, "RAF"); + } + if (io_->seek(84, BasicIo::beg) != 0) throw Error(14); + byte tmp[4]; + io_->read(tmp, 4); + if (io_->error() || io_->eof()) throw Error(14); + uint32_t const pos = getULong(tmp, bigEndian) + 4; + if (io_->seek(pos, BasicIo::beg) != 0) throw Error(14); + io_->read(tmp, 2); + if (io_->error() || io_->eof()) throw Error(14); + DataBuf buf(getUShort(tmp, bigEndian) - 10); + if (io_->seek(pos + 8, BasicIo::beg) != 0) throw Error(14); + io_->read(buf.pData_, buf.size_); + if (io_->error() || io_->eof()) throw Error(14); + clearMetadata(); + TiffParser::decode(this, buf.pData_, buf.size_, + TiffCreator::create, TiffDecoder::findDecoder); + } // RafImage::readMetadata + + void RafImage::writeMetadata() + { + /* + Todo: implement me! + */ + throw(Error(31, "metadata", "RAF")); + } // RafImage::writeMetadata + + bool RafImage::isThisType(BasicIo& iIo, bool advance) const + { + return isRafType(iIo, advance); + } + + // ************************************************************************* + // free functions + + Image::AutoPtr newRafInstance(BasicIo::AutoPtr io, bool create) + { + Image::AutoPtr image(new RafImage(io, create)); + if (!image->good()) { + image.reset(); + } + return image; + } + + bool isRafType(BasicIo& iIo, bool advance) + { + const int32_t len = 8; + byte buf[len]; + iIo.read(buf, len); + if (iIo.error() || iIo.eof()) { + return false; + } + int rc = memcmp(buf, "FUJIFILM", 8); + if (!advance || rc != 0) { + iIo.seek(-len, BasicIo::cur); + } + return rc == 0; + } + +} // namespace Exiv2 diff --git a/src/rafimage.hpp b/src/rafimage.hpp new file mode 100644 index 00000000..b0b0eaab --- /dev/null +++ b/src/rafimage.hpp @@ -0,0 +1,176 @@ +// ***************************************************************** -*- C++ -*- +/* + * Copyright (C) 2007 Andreas Huggel + * + * 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., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. + */ +/*! + @file rafimage.hpp + @brief Fujifilm RAW image + @version $Rev$ + @author Andreas Huggel (ahu) + ahuggel@gmx.net + @date 05-Feb-07, ahu: created + */ +#ifndef RAFIMAGE_HPP_ +#define RAFIMAGE_HPP_ + +// ***************************************************************************** +// included header files +#include "exif.hpp" +#include "iptc.hpp" +#include "image.hpp" + +// + standard includes +#include + +// ***************************************************************************** +// namespace extensions +namespace Exiv2 { + +// ***************************************************************************** +// class definitions + + // Add RAF to the supported image formats + namespace ImageType { + const int raf = 8; //!< RAF image type (see class RafImage) + } + + /*! + @brief Class to access raw RAF images. Exif metadata is supported + directly, IPTC is read from the Exif data, if present. + */ + class RafImage : public Image { + //! @name NOT Implemented + //@{ + //! Copy constructor + RafImage(const RafImage& rhs); + //! Assignment operator + RafImage& operator=(const RafImage& rhs); + //@} + + public: + //! @name Creators + //@{ + /*! + @brief Constructor that can either open an existing RAF image or create + a new image from scratch. If a new image is to be created, any + existing data is overwritten. Since the constructor can not return + a result, callers should check the good() method after object + construction to determine success or failure. + @param io An auto-pointer that owns a BasicIo instance used for + reading and writing image metadata. \b Important: The constructor + takes ownership of the passed in BasicIo instance through the + auto-pointer. Callers should not continue to use the BasicIo + instance after it is passed to this method. Use the Image::io() + method to get a temporary reference. + @param create Specifies if an existing image should be read (false) + or if a new file should be created (true). + */ + RafImage(BasicIo::AutoPtr io, bool create); + //! Destructor + ~RafImage() {} + //@} + + //! @name Manipulators + //@{ + void readMetadata(); + /*! + @brief Todo: Write metadata back to the image. This method is not + yet implemented. Calling it will throw an Error(31). + */ + void writeMetadata(); + void setExifData(const ExifData& exifData); + void clearExifData(); + void setIptcData(const IptcData& iptcData); + void clearIptcData(); + /*! + @brief Not supported. RAF format does not contain a comment. + Calling this function will throw an Error(32). + */ + void setComment(const std::string& comment); + void clearComment(); + void setMetadata(const Image& image); + void clearMetadata(); + ExifData& exifData() { return exifData_; } + IptcData& iptcData() { return iptcData_; } + //@} + + //! @name Accessors + //@{ + bool good() const; + const ExifData& exifData() const { return exifData_; } + const IptcData& iptcData() const { return iptcData_; } + std::string comment() const { return comment_; } + BasicIo& io() const { return *io_; } + AccessMode checkMode(MetadataId metadataId) const; + //@} + + private: + //! @name Accessors + //@{ + /*! + @brief Determine if the content of the BasicIo instance is a RAF image. + + The advance flag determines if the read position in the stream is + moved (see below). This applies only if the type matches and the + function returns true. If the type does not match, the stream + position is not changed. However, if reading from the stream fails, + the stream position is undefined. Consult the stream state to obtain + more information in this case. + + @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 the type of this class;
+ false if the data does not match + */ + bool isThisType(BasicIo& iIo, bool advance) const; + /*! + @brief Todo: Write RAF header. Not implemented yet. + */ + int writeHeader(BasicIo& oIo) const; + //@} + + // DATA + BasicIo::AutoPtr io_; //!< Image data io pointer + ExifData exifData_; //!< Exif data container + IptcData iptcData_; //!< IPTC data container + std::string comment_; //!< User comment + + }; // class RafImage + +// ***************************************************************************** +// 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 RafImage 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 newRafInstance(BasicIo::AutoPtr io, bool create); + + //! Check if the file iIo is a RAF image. + bool isRafType(BasicIo& iIo, bool advance); + +} // namespace Exiv2 + +#endif // #ifndef RAFIMAGE_HPP_