libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

commit 39bca86f3e9afd58ab3adfe8ea5b4ccbed6991f9
parent 8ab5bae320cde8181b3735287a7e7042bfb3e751
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 12 Apr 2009 02:44:45 +0000

changing code to use libexiv2 directly

Diffstat:
Msrc/plugins/exiv2/Makefile.am | 52+++++++++++++++++++++++++++-------------------------
Dsrc/plugins/exiv2/README | 14--------------
Dsrc/plugins/exiv2/Todo | 40----------------------------------------
Dsrc/plugins/exiv2/basicio.cpp | 502-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/basicio.hpp | 649-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/canonmn.cpp | 931-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/canonmn.hpp | 238-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/datasets.cpp | 392-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/datasets.hpp | 358-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/error.cpp | 121-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/error.hpp | 148-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/exif.cpp | 1237-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/exif.hpp | 908-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/exifcomment.cpp | 68--------------------------------------------------------------------
Msrc/plugins/exiv2/exiv2extractor.cc | 6+++---
Dsrc/plugins/exiv2/exv_conf.h | 32--------------------------------
Dsrc/plugins/exiv2/exv_msvc.h | 32--------------------------------
Dsrc/plugins/exiv2/fujimn.cpp | 275-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/fujimn.hpp | 162-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/futils.cpp | 78------------------------------------------------------------------------------
Dsrc/plugins/exiv2/futils.hpp | 66------------------------------------------------------------------
Dsrc/plugins/exiv2/ifd.cpp | 723-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/ifd.hpp | 601-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/image.cpp | 246-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/image.hpp | 493-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/iptc.cpp | 301-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/iptc.hpp | 415-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/jpgimage.cpp | 661-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/jpgimage.hpp | 405-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/makernote.cpp | 462-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/makernote.hpp | 508-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/metadatum.cpp | 76----------------------------------------------------------------------------
Dsrc/plugins/exiv2/metadatum.hpp | 294-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/mn.hpp | 43-------------------------------------------
Dsrc/plugins/exiv2/nikonmn.cpp | 870-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/nikonmn.hpp | 309-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/olympusmn.cpp | 315-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/olympusmn.hpp | 161-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/panasonicmn.cpp | 358-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/panasonicmn.hpp | 170-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/rcsid.hpp | 62--------------------------------------------------------------
Dsrc/plugins/exiv2/sigmamn.cpp | 208-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/sigmamn.hpp | 151------------------------------------------------------------------------------
Dsrc/plugins/exiv2/sonymn.cpp | 147-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/sonymn.hpp | 139-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/tags.cpp | 1233-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/tags.hpp | 444-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/types.cpp | 344-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/types.hpp | 307-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/value.cpp | 559-------------------------------------------------------------------------------
Dsrc/plugins/exiv2/value.hpp | 1226-------------------------------------------------------------------------------
51 files changed, 30 insertions(+), 18510 deletions(-)

diff --git a/src/plugins/exiv2/Makefile.am b/src/plugins/exiv2/Makefile.am @@ -9,31 +9,33 @@ libextractor_exiv2_la_LDFLAGS = \ $(XTRA_CPPLIBS) -lpthread \ $(PLUGINFLAGS) $(retaincommand) libextractor_exiv2_la_LIBADD = \ - $(top_builddir)/src/main/libextractor.la -lpthread + $(top_builddir)/src/main/libextractor.la -lpthread -lexiv2 libextractor_exiv2_la_SOURCES = \ -exiv2extractor.cc exv_conf.h exv_msvc.h \ -basicio.cpp basicio.hpp \ -canonmn.cpp canonmn.hpp \ -datasets.cpp datasets.hpp \ -error.cpp error.hpp \ -exif.cpp exif.hpp \ -fujimn.cpp fujimn.hpp \ -futils.cpp futils.hpp \ -ifd.cpp ifd.hpp \ -image.cpp image.hpp \ -iptc.cpp iptc.hpp \ -jpgimage.cpp jpgimage.hpp \ -makernote.cpp makernote.hpp \ -metadatum.cpp metadatum.hpp \ -mn.hpp \ -nikonmn.cpp nikonmn.hpp \ -olympusmn.cpp olympusmn.hpp \ -panasonicmn.cpp panasonicmn.hpp \ -rcsid.hpp \ -sigmamn.cpp sigmamn.hpp \ -sonymn.cpp sonymn.hpp \ -tags.cpp tags.hpp \ -types.cpp types.hpp \ -value.cpp value.hpp + exiv2extractor.cc + +#exv_conf.h exv_msvc.h \ +#basicio.cpp basicio.hpp \ +#canonmn.cpp canonmn.hpp \ +#datasets.cpp datasets.hpp \ +#error.cpp error.hpp \ +#exif.cpp exif.hpp \ +#fujimn.cpp fujimn.hpp \ +#futils.cpp futils.hpp \ +#ifd.cpp ifd.hpp \ +#image.cpp image.hpp \ +#iptc.cpp iptc.hpp \ +#jpgimage.cpp jpgimage.hpp \ +#makernote.cpp makernote.hpp \ +#metadatum.cpp metadatum.hpp \ +#mn.hpp \ +#nikonmn.cpp nikonmn.hpp \ +#olympusmn.cpp olympusmn.hpp \ +#panasonicmn.cpp panasonicmn.hpp \ +#rcsid.hpp \ +#sigmamn.cpp sigmamn.hpp \ +#sonymn.cpp sonymn.hpp \ +#tags.cpp tags.hpp \ +#types.cpp types.hpp \ +#value.cpp value.hpp diff --git a/src/plugins/exiv2/README b/src/plugins/exiv2/README @@ -1,14 +0,0 @@ -This is an initial import of exiv2 (0.7, -http://home.arcor.de/ahuggel/exiv2) into libextractor. - -The current code has the following issues: - -* more memory leaks than the rest of LE combined and squared, - thus cannot be added by default -* previously generated header file is used (exv_conf.h), - should be merged with Extractor's config.h where needed; - unnecessary or bad checks should be eliminated -* lots of dead code -* possibly contains code that prints to stdout/stderr -* not sure if the parser is robust enough (needs testing) - diff --git a/src/plugins/exiv2/Todo b/src/plugins/exiv2/Todo @@ -1,40 +0,0 @@ -Library Features: -+ rename erase* methods that access a file to remove* -+ add ExifData::erase(tag) -+ Thumbnail support: set (re-calculate) -+ operator>> for Value, since we already have read()? -+ Use size_t where appropriate -+ Support TIFF type ids -+ Support for broken IFD makernotes (which have corrupted IFD offsets) -+ Support non-intrusive deletion of entries from an IFD. -+ Write an example using low level IFD classes to print summary Exif info -+ Extended JPEG support (actual resolution of the image) -+ Implement proper error handling -+ Complete support to create Exif data from scratch: - + set thumbnail, write thumbnail tags -+ Make it possible to force write from metadata (just an optional arg to write?) - -+ Make Image::doWriteMetadata do its work in a single pass - -+ Revise Image and IptcData+ExifData API (aka turn it inside out) -+ Add PSD images support (and TIFF, NEF, CRW...) -+ Add support for XML metadata files - -Exiv2 functionality -+ Add offset to value for hexdump (requires metadata to have an offset) - -Bugs: -+ Handle all Todo's -+ Cleanup and fix implementation of JpegImage (must be able to read any APP0/1), - should be able to insert exv into extracted thumbs (usually w/o APP0/1) -+ Review Image interface. Is it really necessary to have so many functions there? -+ Review the handling of type ids? What if we encounter type 27 in an IFD? -+ Rational and other output operators (see Josuttis, p653) -+ Through ExifData::iterator and Metadatum::operator= it is possible to have - multiple copies of one metadatum in the metadata container -+ Checks and non-intrusive updates must be atomic, i.e., not change anything - if the metadata is not compatible -+ Review: Exception safety -+ Review: Ifd1 only at Thumbnail, do we really need Thumbnail::update() ? -+ Is the hexdump output of exiv2 byte-swapped?? -+ Should JpegImage differ between NO Jpeg comment and an empty Jpeg comment?? diff --git a/src/plugins/exiv2/basicio.cpp b/src/plugins/exiv2/basicio.cpp @@ -1,502 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: basicio.cpp - Version: $Rev: 566 $ - Author(s): Brad Schick (brad) <brad@robotbattle.com> - History: 04-Dec-04, brad: created - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: basicio.cpp 566 2005-04-26 15:27:41Z ahuggel $"); - -// ***************************************************************************** -// included header files -#ifdef _MSC_VER -# include "exv_msvc.h" -#else -# include "exv_conf.h" -#endif - -#include "basicio.hpp" -#include "futils.hpp" -#include "types.hpp" -#include "error.hpp" - -// + standard includes -#include <string> -#include <cassert> -#include <cstdio> // for remove() -#include <sys/types.h> // for stat() -#include <sys/stat.h> // for stat() -#ifdef EXV_HAVE_PROCESS_H -# include <process.h> -#endif -#ifdef EXV_HAVE_UNISTD_H -# include <unistd.h> // for getpid, stat -#endif - -#if defined WIN32 && !defined __CYGWIN__ -# include <io.h> -#endif - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - FileIo::FileIo(const std::string& path) : - path_(path), fp_(0), opMode_(opSeek) - { - } - - FileIo::~FileIo() - { - close(); - } - - BasicIo::AutoPtr FileIo::temporary() const - { - BasicIo::AutoPtr basicIo; - - struct stat buf; - int ret = stat(path_.c_str(), &buf); - - // If file is > 1MB then use a file, otherwise use memory buffer - if (ret != 0 || buf.st_size > 1048576) { - pid_t pid = getpid(); - std::string tmpname = path_ + toString(pid); - std::auto_ptr<FileIo> fileIo(new FileIo(tmpname)); - if (fileIo->open("w+b") != 0) { - throw Error(10, path_, "w+b", strError()); - } - basicIo = fileIo; - } - else { - basicIo.reset(new MemIo); - } - - return basicIo; - } - - int FileIo::switchMode(OpMode opMode) - { - assert(fp_ != 0); - if (opMode_ == opMode) return 0; - OpMode oldOpMode = opMode_; - opMode_ = opMode; - - bool reopen = true; - std::string mode = "r+b"; - - switch(opMode) { - case opRead: - // Flush if current mode allows reading, else reopen (in mode "r+b" - // as in this case we know that we can write to the file) - if ( openMode_[0] == 'r' - || openMode_.substr(0, 2) == "w+" - || openMode_.substr(0, 2) == "a+") reopen = false; - break; - case opWrite: - // Flush if current mode allows writing, else reopen - if ( openMode_.substr(0, 2) == "r+" - || openMode_[0] == 'w' - || openMode_[0] == 'a') reopen = false; - break; - case opSeek: - reopen = false; - break; - } - - if (!reopen) { - // Don't do anything when switching _from_ opSeek mode; we - // flush when switching _to_ opSeek. - if (oldOpMode == opSeek) return 0; - - // Flush. On msvcrt fflush does not do the job - fseek(fp_, 0, SEEK_CUR); - return 0; - } - - // Reopen the file - long offset = ftell(fp_); - if (offset == -1) return -1; - if (open(mode) != 0) return 1; - return fseek(fp_, offset, SEEK_SET); - } - - long FileIo::write(const byte* data, long wcount) - { - assert(fp_ != 0); - if (switchMode(opWrite) != 0) return 0; - return (long)fwrite(data, 1, wcount, fp_); - } - - long FileIo::write(BasicIo& src) - { - assert(fp_ != 0); - if (static_cast<BasicIo*>(this) == &src) return 0; - if (!src.isopen()) return 0; - if (switchMode(opWrite) != 0) return 0; - - byte buf[4096]; - long readCount = 0; - long writeCount = 0; - long writeTotal = 0; - while ((readCount = src.read(buf, sizeof(buf)))) { - writeTotal += writeCount = (long)fwrite(buf, 1, readCount, fp_); - if (writeCount != readCount) { - // try to reset back to where write stopped - src.seek(writeCount-readCount, BasicIo::cur); - break; - } - } - - return writeTotal; - } - - void FileIo::transfer(BasicIo& src) - { - const bool wasOpen = (fp_ != 0); - const std::string lastMode(openMode_); - - FileIo *fileIo = dynamic_cast<FileIo*>(&src); - if (fileIo) { - // Optimization if this is another instance of FileIo - close(); - fileIo->close(); - // MSVCRT rename that does not overwrite existing files - if (remove(path_.c_str()) != 0) { - throw Error(2, path_, strError(), "::remove"); - } - if (rename(fileIo->path_.c_str(), path_.c_str()) == -1) { - throw Error(17, fileIo->path_, path_, strError()); - } - remove(fileIo->path_.c_str()); - } - else{ - // Generic handling, reopen both to reset to start - if (open("w+b") != 0) { - throw Error(10, path_, "w+b", strError()); - } - if (src.open() != 0) { - throw Error(9, src.path(), strError()); - } - write(src); - src.close(); - } - - if (wasOpen) { - if (open(lastMode) != 0) { - throw Error(10, path_, lastMode, strError()); - } - } - else close(); - - if (error() || src.error()) throw Error(18, path_, strError()); - } - - int FileIo::putb(byte data) - { - assert(fp_ != 0); - if (switchMode(opWrite) != 0) return EOF; - return putc(data, fp_); - } - - int FileIo::seek(long offset, Position pos) - { - assert(fp_ != 0); - int fileSeek; - if (pos == BasicIo::cur) { - fileSeek = SEEK_CUR; - } - else if (pos == BasicIo::beg) { - fileSeek = SEEK_SET; - } - else { - assert(pos == BasicIo::end); - fileSeek = SEEK_END; - } - - if (switchMode(opSeek) != 0) return 1; - return fseek(fp_, offset, fileSeek); - } - - long FileIo::tell() const - { - assert(fp_ != 0); - return ftell(fp_); - } - - - long FileIo::size() const - { - if (fp_ != 0) { - fflush(fp_); -#if defined WIN32 && !defined __CYGWIN__ - // This is required on msvcrt before stat after writing to a file - _commit(_fileno(fp_)); -#endif - } - - struct stat buf; - int ret = stat(path_.c_str(), &buf); - - if (ret != 0) return -1; - return buf.st_size; - } - - int FileIo::open() - { - // Default open is in read-only binary mode - return open("rb"); - } - - int FileIo::open(const std::string& mode) - { - if (fp_ != 0) { - fclose(fp_); - } - - openMode_ = mode; - opMode_ = opSeek; - fp_ = fopen(path_.c_str(), mode.c_str()); - if (!fp_) return 1; - return 0; - } - - bool FileIo::isopen() const - { - return fp_ != 0; - } - - int FileIo::close() - { - if (fp_ != 0) { - fclose(fp_); - fp_= 0; - } - return 0; - } - - DataBuf FileIo::read(long rcount) - { - assert(fp_ != 0); - DataBuf buf(rcount); - long readCount = read(buf.pData_, buf.size_); - buf.size_ = readCount; - return buf; - } - - long FileIo::read(byte* buf, long rcount) - { - assert(fp_ != 0); - if (switchMode(opRead) != 0) return 0; - return (long)fread(buf, 1, rcount, fp_); - } - - int FileIo::getb() - { - assert(fp_ != 0); - if (switchMode(opRead) != 0) return EOF; - return getc(fp_); - } - - int FileIo::error() const - { - return fp_ != 0 ? ferror(fp_) : 0; - } - - bool FileIo::eof() const - { - assert(fp_ != 0); - return feof(fp_) != 0; - } - - std::string FileIo::path() const - { - return path_; - } - - MemIo::MemIo(const byte* data, long size) - : data_(const_cast<byte*>(data)), - idx_(0), - size_(size), - sizeAlloced_(0), - isMalloced_(false) - { - } - - void MemIo::wrap(const byte *data, long size) - { - data_ = (byte *) data; - size_ = size; - isMalloced_ = false; - } - - BasicIo::AutoPtr MemIo::temporary() const - { - return BasicIo::AutoPtr(new MemIo); - } - - void MemIo::checkSize(long wcount) - { - long need = wcount + idx_; - if (need > size_) { - if (need > sizeAlloced_) { - // Allocate in blocks of 32kB - long want = 32768 * (1 + need / 32768); - if (size_ > 0) { - if (!isMalloced_) { - // "copy-on-expand" - byte* data = (byte*)malloc(want); - memcpy(data, data_, size_); - data_ = data; - } - else { - data_ = (byte*)realloc(data_, want); - } - } - else { - data_ = (byte*)malloc(want); - } - sizeAlloced_ = want; - isMalloced_ = true; - } - size_ = need; - } - } - - void MemIo::transfer(BasicIo& src) - { - MemIo *memIo = dynamic_cast<MemIo*>(&src); - if (memIo) { - // Optimization if this is another instance of MemIo - if (memIo->isMalloced_) - { - isMalloced_ = true; - memIo->isMalloced_ = false; - } - else - isMalloced_ = false; - - data_ = memIo->data_; - idx_ = 0; - } - else{ - // Generic reopen to reset position to start - free(data_); - idx_ = 0; - if (src.open() != 0) { - throw Error(9, src.path(), strError()); - } - write(src); - src.close(); - } - if (error() || src.error()) throw Error(19, strError()); - } - - int MemIo::seek(long offset, Position pos) - { - long newIdx; - - if (pos == BasicIo::cur ) { - newIdx = idx_ + offset; - } - else if (pos == BasicIo::beg) { - newIdx = offset; - } - else { - assert(pos == BasicIo::end); - newIdx = size_ + offset; - } - - if (newIdx < 0 || newIdx > size_) return 1; - idx_ = newIdx; - return 0; - } - - long MemIo::tell() const - { - return idx_; - } - - long MemIo::size() const - { - return size_; - } - - int MemIo::open() - { - idx_ = 0; - return 0; - } - - bool MemIo::isopen() const - { - return true; - } - - int MemIo::close() - { - return 0; - } - - DataBuf MemIo::read(long rcount) - { - DataBuf buf(rcount); - long readCount = read(buf.pData_, buf.size_); - buf.size_ = readCount; - return buf; - } - - long MemIo::read(byte* buf, long rcount) - { - long avail = size_ - idx_; - long allow = std::min(rcount, avail); - - memcpy(buf, &data_[idx_], allow); - idx_ += allow; - return allow; - } - - int MemIo::getb() - { - if (idx_ == size_) - return EOF; - return data_[idx_++]; - } - - int MemIo::error() const - { - return 0; - } - - bool MemIo::eof() const - { - return idx_ == size_; - } - - std::string MemIo::path() const - { - return "MemIo"; - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/basicio.hpp b/src/plugins/exiv2/basicio.hpp @@ -1,649 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 basicio.hpp - @brief Simple binary IO abstraction - @version $Rev: 565 $ - @author Brad Schick (brad) - <a href="mailto:brad@robotbattle.com">brad@robotbattle.com</a> - @date 04-Dec-04, brad: created - */ -#ifndef BASICIO_HPP_ -#define BASICIO_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" - -// + standard includes -#include <cstdlib> -#include <memory> -#include <string> -#include <vector> -#include <cstdio> -#include <memory> -#include <string.h> -#include <stdlib.h> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class definitions - - /*! - @brief An interface for simple binary IO. - - Designed to have semantics and names similar to those of C style FILE* - operations. Subclasses should all behave the same so that they can be - interchanged. - */ - class BasicIo - { - public: - //! BasicIo auto_ptr type - typedef std::auto_ptr<BasicIo> AutoPtr; - - //! Seek starting positions - enum Position { beg, cur, end }; - - //! @name Creators - //@{ - //! Destructor - virtual ~BasicIo() {} - //@} - - //! @name Manipulators - //@{ - /*! - @brief Open the IO source using the default access mode. The - default mode should allow for reading and writing. - - This method can also be used to "reopen" an IO source which will - flush any unwritten data and reset the IO position to the start. - Subclasses may provide custom methods to allow for - opening IO sources differently. - - @return 0 if successful;<BR> - Nonzero if failure. - */ - virtual int open() = 0; - /*! - @brief Close the IO source. After closing a BasicIo instance can not - be read or written. Closing flushes any unwritten data. It is - safe to call close on a closed instance. - @return 0 if successful;<BR> - Nonzero if failure. - */ - virtual int close() = 0; - /*! - @brief Write data to the IO source. Current IO position is advanced - by the number of bytes written. - @param data Pointer to data. Data must be at least \em wcount - bytes long - @param wcount Number of bytes to be written. - @return Number of bytes written to IO source successfully;<BR> - 0 if failure; - */ - virtual long write(const byte* data, long wcount) = 0; - /*! - @brief Write data that is read from another BasicIo instance to - the IO source. Current IO position is advanced by the number - of bytes written. - @param src Reference to another BasicIo instance. Reading start - at the source's current IO position - @return Number of bytes written to IO source successfully;<BR> - 0 if failure; - */ - virtual long write(BasicIo& src) = 0; - /*! - @brief Write one byte to the IO source. Current IO position is - advanced by one byte. - @param data The single byte to be written. - @return The value of the byte written if successful;<BR> - EOF if failure; - */ - virtual int putb(byte data) = 0; - /*! - @brief Read data from the IO source. Reading starts at the current - IO position and the position is advanced by the number of bytes - read. - @param rcount Maximum number of bytes to read. Fewer bytes may be - read if \em rcount bytes are not available. - @return DataBuf instance containing the bytes read. Use the - DataBuf::size_ member to find the number of bytes read. - DataBuf::size_ will be 0 on failure. - */ - virtual DataBuf read(long rcount) = 0; - /*! - @brief Read data from the IO source. Reading starts at the current - IO position and the position is advanced by the number of bytes - read. - @param buf Pointer to a block of memory into which the read data - is stored. The memory block must be at least \em rcount bytes - long. - @param rcount Maximum number of bytes to read. Fewer bytes may be - read if \em rcount bytes are not available. - @return Number of bytes read from IO source successfully;<BR> - 0 if failure; - */ - virtual long read(byte *buf, long rcount) = 0; - /*! - @brief Read one byte from the IO source. Current IO position is - advanced by one byte. - @return The byte read from the IO source if successful;<BR> - EOF if failure; - */ - virtual int getb() = 0; - /*! - @brief Remove all data from this object's IO source and then transfer - data from the \em src BasicIo object into this object. - - The source object is invalidated by this operation and should not be - used after this method returns. This method exists primarily to - be used with the BasicIo::temporary() method. - - @param src Reference to another BasicIo instance. The entire contents - of src are transferred to this object. The \em src object is - invalidated by the method. - @throw Error In case of failure - */ - virtual void transfer(BasicIo& src) = 0; - /*! - @brief Move the current IO position. - @param offset Number of bytes to move the position relative - to the starting position specified by \em pos - @param pos Position from which the seek should start - @return 0 if successful;<BR> - Nonzero if failure; - */ - virtual int seek(long offset, Position pos) = 0; - //@} - - //! @name Accessors - //@{ - /*! - @brief Get the current IO position. - @return Offset from the start of IO if successful;<BR> - -1 if failure; - */ - virtual long tell() const = 0; - /*! - @brief Get the current size of the IO source in bytes. - @return Size of the IO source in bytes;<BR> - -1 if failure; - */ - virtual long size() const = 0; - //!Returns true if the IO source is open, otherwise false. - virtual bool isopen() const = 0; - //!Returns 0 if the IO source is in a valid state, otherwise nonzero. - virtual int error() const = 0; - //!Returns true if the IO position has reach the end, otherwise false. - virtual bool eof() const = 0; - /*! - @brief Return the path to the IO resource. Often used to form - comprehensive error messages where only a BasicIo instance is - available. - */ - virtual std::string path() const =0; - /*! - @brief Returns a temporary data storage location. This is often - needed to rewrite an IO source. - - For example, data may be read from the original IO source, modified - in some way, and then saved to the temporary instance. After the - operation is complete, the BasicIo::transfer method can be used to - replace the original IO source with the modified version. Subclasses - are free to return any class that derives from BasicIo. - - @return An instance of BasicIo on success - @throw Error In case of failure - */ - virtual BasicIo::AutoPtr temporary() const = 0; - //@} - - protected: - //! @name Creators - //@{ - //! Default Constructor - BasicIo() {} - //@} - }; // class BasicIo - - /*! - @brief Utility class that closes a BasicIo instance upon destruction. - Meant to be used as a stack variable in functions that need to - ensure BasicIo instances get closed. Useful when functions return - errors from many locations. - */ - class IoCloser { - public: - //! @name Creators - //@{ - //! Constructor, takes a BasicIo reference - IoCloser(BasicIo &bio) : bio_(bio) {} - //! Destructor, closes the BasicIo reference - ~IoCloser() { close(); } - //@} - - //! @name Manipulators - //@{ - //! Close the BasicIo if it is open - void close() { if (bio_.isopen()) bio_.close(); } - //@} - - // DATA - //! The BasicIo reference - BasicIo &bio_; - private: - // Not implemented - //! Copy constructor - IoCloser(const IoCloser&); - //! Assignment operator - IoCloser& operator=(const IoCloser&); - }; // class IoCloser - - - /*! - @brief Provides binary file IO by implementing the BasicIo - interface. - */ - class FileIo : public BasicIo - { - public: - //! @name Creators - //@{ - /*! - @brief Constructor that accepts the file path on which IO will be - performed. The constructor does not open the file, and - therefore never failes. - @param path The full path of a file - */ - FileIo(const std::string& path); - //! Destructor. Flushes and closes an open file. - virtual ~FileIo(); - //@} - - //! @name Manipulators - //@{ - /*! - @brief Open the file using using the specified mode. - - This method can also be used to "reopen" a file which will flush any - unwritten data and reset the IO position to the start. Although - files can be opened in binary or text mode, this class has - only been tested carefully in binary mode. - - @param mode Specified that type of access allowed on the file. - Valid values match those of the C fopen command exactly. - @return 0 if successful;<BR> - Nonzero if failure. - */ - int open(const std::string& mode); - /*! - @brief Open the file using using the default access mode of "rb". - This method can also be used to "reopen" a file which will flush - any unwritten data and reset the IO position to the start. - @return 0 if successful;<BR> - Nonzero if failure. - */ - virtual int open(); - /*! - @brief Flush and unwritten data and close the file . It is - safe to call close on an already closed instance. - @return 0 if successful;<BR> - Nonzero if failure; - */ - virtual int close(); - /*! - @brief Write data to the file. The file position is advanced - by the number of bytes written. - @param data Pointer to data. Data must be at least \em wcount - bytes long - @param wcount Number of bytes to be written. - @return Number of bytes written to the file successfully;<BR> - 0 if failure; - */ - virtual long write(const byte* data, long wcount); - /*! - @brief Write data that is read from another BasicIo instance to - the file. The file position is advanced by the number - of bytes written. - @param src Reference to another BasicIo instance. Reading start - at the source's current IO position - @return Number of bytes written to the file successfully;<BR> - 0 if failure; - */ - virtual long write(BasicIo& src); - /*! - @brief Write one byte to the file. The file position is - advanced by one byte. - @param data The single byte to be written. - @return The value of the byte written if successful;<BR> - EOF if failure; - */ - virtual int putb(byte data); - /*! - @brief Read data from the file. Reading starts at the current - file position and the position is advanced by the number of - bytes read. - @param rcount Maximum number of bytes to read. Fewer bytes may be - read if \em rcount bytes are not available. - @return DataBuf instance containing the bytes read. Use the - DataBuf::size_ member to find the number of bytes read. - DataBuf::size_ will be 0 on failure. - */ - virtual DataBuf read(long rcount); - /*! - @brief Read data from the file. Reading starts at the current - file position and the position is advanced by the number of - bytes read. - @param buf Pointer to a block of memory into which the read data - is stored. The memory block must be at least \em rcount bytes - long. - @param rcount Maximum number of bytes to read. Fewer bytes may be - read if \em rcount bytes are not available. - @return Number of bytes read from the file successfully;<BR> - 0 if failure; - */ - virtual long read(byte *buf, long rcount); - /*! - @brief Read one byte from the file. The file position is - advanced by one byte. - @return The byte read from the file if successful;<BR> - EOF if failure; - */ - virtual int getb(); - /*! - @brief Remove the contents of the file and then transfer data from - the \em src BasicIo object into the empty file. - - This method is optimized to simply rename the source file if the - source object is another FileIo instance. The source BasicIo object - is invalidated by this operation and should not be used after this - method returns. This method exists primarily to be used with - the BasicIo::temporary() method. - - @param src Reference to another BasicIo instance. The entire contents - of src are transferred to this object. The \em src object is - invalidated by the method. - @throw Error In case of failure - */ - virtual void transfer(BasicIo& src); - /*! - @brief Move the current file position. - @param offset Number of bytes to move the file position - relative to the starting position specified by \em pos - @param pos Position from which the seek should start - @return 0 if successful;<BR> - Nonzero if failure; - */ - virtual int seek(long offset, Position pos); - //@} - - //! @name Accessors - //@{ - /*! - @brief Get the current file position. - @return Offset from the start of the file if successful;<BR> - -1 if failure; - */ - virtual long tell() const; - /*! - @brief Flush any buffered writes and get the current file size - in bytes. - @note On Win32 systems the file must be closed prior to calling this - function. - @return Size of the file in bytes;<BR> - -1 if failure; - */ - virtual long size() const; - //! Returns true if the file is open, otherwise false. - virtual bool isopen() const; - //! Returns 0 if the file is in a valid state, otherwise nonzero. - virtual int error() const; - //! Returns true if the file position has reach the end, otherwise false. - virtual bool eof() const; - //! Returns the path of the file - virtual std::string path() const; - /*! - @brief Returns a temporary data storage location. The actual type - returned depends upon the size of the file represented a FileIo - object. For small files, a MemIo is returned while for large files - a FileIo is returned. Callers should not rely on this behavior, - however, since it may change. - @return An instance of BasicIo on success - @throw Error If opening the temporary file fails - */ - virtual BasicIo::AutoPtr temporary() const; - //@} - - private: - // NOT IMPLEMENTED - //! Copy constructor - FileIo(FileIo& rhs); - //! Assignment operator - FileIo& operator=(const FileIo& rhs); - - // Enumeration - enum OpMode { opRead, opWrite, opSeek }; - - // DATA - std::string path_; - std::string openMode_; - FILE *fp_; - OpMode opMode_; - - // METHODS - /*! - @brief Switch to a new access mode, reopening the file if needed. - Optimized to only reopen the file when it is really necessary. - @param opMode The mode to switch to. - @return 0 if successful - */ - int switchMode(OpMode opMode); - - }; // class FileIo - - /*! - @brief Provides binary IO on blocks of memory by implementing the - BasicIo interface. The current implementation makes a copy of - any data passed to its constructors. If writes are performed, the - changed data can be retrieved using the read methods (since the - data used in construction is never modified). - - @note If read only usage of this class is common, it might be worth - creating a specialized readonly class or changing this one to - have a readonly mode. - */ - class MemIo : public BasicIo - { - public: - //! @name Creators - //@{ - //! Default constructor that results in an empty object - MemIo() : data_(0), idx_(0), size_(0), sizeAlloced_(0), isMalloced_(false) {} - /*! - @brief Constructor that accepts a block of memory to be copied. - IO operations are performed on the copied memory. - @param data Pointer to data. Data must be at least \em size - bytes long - @param size Number of bytes to copy. - */ - MemIo(const byte* data, long size); - //! Destructor. Releases all managed memory - ~MemIo() {if (isMalloced_) free(data_);} - - void wrap(const byte *data, long size); - - //@} - - //! @name Manipulators - //@{ - /*! - @brief Memory IO is always open for reading and writing. This method - therefore only resets the IO position to the start. - - @return 0 - */ - virtual int open(); - /*! - @brief Does nothing on MemIo objects. - @return 0 - */ - virtual int close(); - /*! - @brief Write data to the memory block. If needed, the size of the - internal memory block is expanded. The IO position is advanced - by the number of bytes written. - @param data Pointer to data. Data must be at least \em wcount - bytes long - @param wcount Number of bytes to be written. - @return Number of bytes written to the memory block successfully;<BR> - 0 if failure; - */ - virtual long write(const byte* data, long wcount) { return 0; } - /*! - @brief Write data that is read from another BasicIo instance to - the memory block. If needed, the size of the internal memory - block is expanded. The IO position is advanced by the number - of bytes written. - @param src Reference to another BasicIo instance. Reading start - at the source's current IO position - @return Number of bytes written to the memory block successfully;<BR> - 0 if failure; - */ - virtual long write(BasicIo& src) { return 0; } - /*! - @brief Write one byte to the memory block. The IO position is - advanced by one byte. - @param data The single byte to be written. - @return The value of the byte written if successful;<BR> - EOF if failure; - */ - virtual int putb(byte data) { return EOF; } - /*! - @brief Read data from the memory block. Reading starts at the current - IO position and the position is advanced by the number of - bytes read. - @param rcount Maximum number of bytes to read. Fewer bytes may be - read if \em rcount bytes are not available. - @return DataBuf instance containing the bytes read. Use the - DataBuf::size_ member to find the number of bytes read. - DataBuf::size_ will be 0 on failure. - */ - virtual DataBuf read(long rcount); - /*! - @brief Read data from the memory block. Reading starts at the current - IO position and the position is advanced by the number of - bytes read. - @param buf Pointer to a block of memory into which the read data - is stored. The memory block must be at least \em rcount bytes - long. - @param rcount Maximum number of bytes to read. Fewer bytes may be - read if \em rcount bytes are not available. - @return Number of bytes read from the memory block successfully;<BR> - 0 if failure; - */ - virtual long read(byte *buf, long rcount); - /*! - @brief Read one byte from the memory block. The IO position is - advanced by one byte. - @return The byte read from the memory block if successful;<BR> - EOF if failure; - */ - virtual int getb(); - /*! - @brief Clear the memory clock and then transfer data from - the \em src BasicIo object into a new block of memory. - - This method is optimized to simply swap memory block if the source - object is another MemIo instance. The source BasicIo instance - is invalidated by this operation and should not be used after this - method returns. This method exists primarily to be used with - the BasicIo::temporary() method. - - @param src Reference to another BasicIo instance. The entire contents - of src are transferred to this object. The \em src object is - invalidated by the method. - @throw Error In case of failure - */ - virtual void transfer(BasicIo& src); - /*! - @brief Move the current IO position. - @param offset Number of bytes to move the IO position - relative to the starting position specified by \em pos - @param pos Position from which the seek should start - @return 0 if successful;<BR> - Nonzero if failure; - */ - virtual int seek(long offset, Position pos); - //@} - - //! @name Accessors - //@{ - /*! - @brief Get the current IO position. - @return Offset from the start of the memory block - */ - virtual long tell() const; - /*! - @brief Get the current memory buffer size in bytes. - @return Size of the in memory data in bytes;<BR> - -1 if failure; - */ - virtual long size() const; - //!Always returns true - virtual bool isopen() const; - //!Always returns 0 - virtual int error() const; - //!Returns true if the IO position has reach the end, otherwise false. - virtual bool eof() const; - //! Returns a dummy path, indicating that memory access is used - virtual std::string path() const; - /*! - @brief Returns a temporary data storage location. Currently returns - an empty MemIo object, but callers should not rely on this - behavior since it may change. - @return An instance of BasicIo - */ - virtual BasicIo::AutoPtr temporary() const; - //@} - private: - // NOT IMPLEMENTED - //! Copy constructor - MemIo(MemIo& rhs); - //! Assignment operator - MemIo& operator=(const MemIo& rhs); - - byte *data_; - long idx_; - long size_; - long sizeAlloced_; //!< Size of the allocated buffer - bool isMalloced_; //!< Was the buffer allocated? - - // METHODS - void checkSize(long wcount); - }; // class MemIo -} // namespace Exiv2 - -#endif // #ifndef BASICIO_HPP_ diff --git a/src/plugins/exiv2/canonmn.cpp b/src/plugins/exiv2/canonmn.cpp @@ -1,931 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: canonmn.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 18-Feb-04, ahu: created - 07-Mar-04, ahu: isolated as a separate component - Credits: Canon MakerNote implemented according to the specification - "EXIF MakerNote of Canon" <http://www.burren.cx/david/canon.html> - by David Burren - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: canonmn.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "canonmn.hpp" -#include "makernote.hpp" -#include "value.hpp" -#include "ifd.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <algorithm> -#include <cassert> -#include <cstring> -#include <cmath> - -// ***************************************************************************** -// local declarations -namespace { - /* - @brief Convert Canon hex-based EV (modulo 0x20) to real number - Ported from Phil Harvey's Image::ExifTool::Canon::CanonEv - by Will Stokes - - 0x00 -> 0 - 0x0c -> 0.33333 - 0x10 -> 0.5 - 0x14 -> 0.66666 - 0x20 -> 1 - .. - 160 -> 5 - 128 -> 4 - 143 -> 4.46875 - */ - float canonEv(long val); -} - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - CanonMakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote("Canon", "*", createCanonMakerNote); - - MakerNoteFactory::registerMakerNote( - canonIfdId, MakerNote::AutoPtr(new CanonMakerNote)); - MakerNoteFactory::registerMakerNote( - canonCs1IfdId, MakerNote::AutoPtr(new CanonMakerNote)); - MakerNoteFactory::registerMakerNote( - canonCs2IfdId, MakerNote::AutoPtr(new CanonMakerNote)); - MakerNoteFactory::registerMakerNote( - canonCfIfdId, MakerNote::AutoPtr(new CanonMakerNote)); - - ExifTags::registerMakerTagInfo(canonIfdId, tagInfo_); - ExifTags::registerMakerTagInfo(canonCs1IfdId, tagInfoCs1_); - ExifTags::registerMakerTagInfo(canonCs2IfdId, tagInfoCs2_); - ExifTags::registerMakerTagInfo(canonCfIfdId, tagInfoCf_); - } - //! @endcond - - // Canon MakerNote Tag Info - const TagInfo CanonMakerNote::tagInfo_[] = { - TagInfo(0x0000, "0x0000", "Unknown", canonIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0001, "CameraSettings1", "Various camera settings (1)", canonIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0002, "0x0002", "Unknown", canonIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0003, "0x0003", "Unknown", canonIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0004, "CameraSettings2", "Various camera settings (2)", canonIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0006, "ImageType", "Image type", canonIfdId, makerTags, asciiString, printValue), - TagInfo(0x0007, "FirmwareVersion", "Firmware version", canonIfdId, makerTags, asciiString, printValue), - TagInfo(0x0008, "ImageNumber", "Image number", canonIfdId, makerTags, unsignedLong, print0x0008), - TagInfo(0x0009, "OwnerName", "Owner Name", canonIfdId, makerTags, asciiString, printValue), - TagInfo(0x000c, "SerialNumber", "Camera serial number", canonIfdId, makerTags, unsignedLong, print0x000c), - TagInfo(0x000d, "0x000d", "Unknown", canonIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000f, "CustomFunctions", "Custom Functions", canonIfdId, makerTags, unsignedShort, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownCanonMakerNoteTag)", "Unknown CanonMakerNote tag", canonIfdId, makerTags, invalidTypeId, printValue) - }; - - // Canon Camera Settings 1 Tag Info - const TagInfo CanonMakerNote::tagInfoCs1_[] = { - TagInfo(0x0001, "Macro", "Macro mode", canonCs1IfdId, makerTags, unsignedShort, printCs10x0001), - TagInfo(0x0002, "Selftimer", "Self timer", canonCs1IfdId, makerTags, unsignedShort, printCs10x0002), - TagInfo(0x0003, "Quality", "Quality", canonCs1IfdId, makerTags, unsignedShort, printCs10x0003), - TagInfo(0x0004, "FlashMode", "Flash mode setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0004), - TagInfo(0x0005, "DriveMode", "Drive mode setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0005), - TagInfo(0x0006, "0x0006", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0007, "FocusMode", "Focus mode setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0007), - TagInfo(0x0008, "0x0008", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0009, "0x0009", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000a, "ImageSize", "Image size", canonCs1IfdId, makerTags, unsignedShort, printCs10x000a), - TagInfo(0x000b, "EasyMode", "Easy shooting mode", canonCs1IfdId, makerTags, unsignedShort, printCs10x000b), - TagInfo(0x000c, "DigitalZoom", "Digital zoom", canonCs1IfdId, makerTags, unsignedShort, printCs10x000c), - TagInfo(0x000d, "Contrast", "Contrast setting", canonCs1IfdId, makerTags, unsignedShort, printCs1Lnh), - TagInfo(0x000e, "Saturation", "Saturation setting", canonCs1IfdId, makerTags, unsignedShort, printCs1Lnh), - TagInfo(0x000f, "Sharpness", "Sharpness setting", canonCs1IfdId, makerTags, unsignedShort, printCs1Lnh), - TagInfo(0x0010, "ISOSpeed", "ISO speed setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0010), - TagInfo(0x0011, "MeteringMode", "Metering mode setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0011), - TagInfo(0x0012, "FocusType", "Focus type setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0012), - TagInfo(0x0013, "AFPoint", "AF point selected", canonCs1IfdId, makerTags, unsignedShort, printCs10x0013), - TagInfo(0x0014, "ExposureProgram", "Exposure mode setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0014), - TagInfo(0x0015, "0x0015", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0016, "0x0016", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0017, "Lens", "'long' and 'short' focal length of lens (in 'focal units') and 'focal units' per mm", canonCs1IfdId, makerTags, unsignedShort, printCs1Lens), - TagInfo(0x0018, "0x0018", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0019, "0x0019", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x001a, "0x001a", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x001b, "0x001b", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x001c, "FlashActivity", "Flash activity", canonCs1IfdId, makerTags, unsignedShort, printCs10x001c), - TagInfo(0x001d, "FlashDetails", "Flash details", canonCs1IfdId, makerTags, unsignedShort, printCs10x001d), - TagInfo(0x001e, "0x001e", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x001f, "0x001f", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0020, "FocusMode", "Focus mode setting", canonCs1IfdId, makerTags, unsignedShort, printCs10x0020), - TagInfo(0x0021, "0x0021", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0022, "0x0022", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0023, "0x0023", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0024, "0x0024", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0025, "0x0025", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0026, "0x0026", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0027, "0x0027", "Unknown", canonCs1IfdId, makerTags, unsignedShort, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownCanonCs1Tag)", "Unknown Canon Camera Settings 1 tag", canonCs1IfdId, makerTags, invalidTypeId, printValue) - }; - - // Canon Camera Settings 2 Tag Info - const TagInfo CanonMakerNote::tagInfoCs2_[] = { - TagInfo(0x0001, "0x0001", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0002, "ISOSpeed", "ISO speed used", canonCs2IfdId, makerTags, unsignedShort, printCs20x0002), - TagInfo(0x0003, "0x0003", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0004, "0x0004", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0005, "0x0005", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0006, "0x0006", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0007, "WhiteBalance", "White balance setting", canonCs2IfdId, makerTags, unsignedShort, printCs20x0007), - TagInfo(0x0008, "0x0008", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0009, "Sequence", "Sequence number (if in a continuous burst)", canonCs2IfdId, makerTags, unsignedShort, printCs20x0009), - TagInfo(0x000a, "0x000a", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000b, "0x000b", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000c, "0x000c", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000d, "0x000d", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000e, "AFPointUsed", "AF point used", canonCs2IfdId, makerTags, unsignedShort, printCs20x000e), - TagInfo(0x000f, "FlashBias", "Flash bias", canonCs2IfdId, makerTags, unsignedShort, printCs20x000f), - TagInfo(0x0010, "0x0010", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0011, "0x0011", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0012, "0x0012", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0013, "SubjectDistance", "Subject distance (units are not clear)", canonCs2IfdId, makerTags, unsignedShort, printCs20x0013), - TagInfo(0x0014, "0x0014", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0015, "0x0015", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0016, "0x0016", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0017, "0x0017", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0018, "0x0018", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0019, "0x0019", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x001a, "0x001a", "Unknown", canonCs2IfdId, makerTags, unsignedShort, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownCanonCs2Tag)", "Unknown Canon Camera Settings 2 tag", canonCs2IfdId, makerTags, invalidTypeId, printValue) - }; - - // Canon Custom Function Tag Info - const TagInfo CanonMakerNote::tagInfoCf_[] = { - TagInfo(0x0001, "NoiseReduction", "Long exposure noise reduction", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0002, "ShutterAeLock", "Shutter/AE lock buttons", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0003, "MirrorLockup", "Mirror lockup", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0004, "ExposureLevelIncrements", "Tv/Av and exposure level", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0005, "AFAssist", "AF assist light", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0006, "FlashSyncSpeedAv", "Shutter speed in Av mode", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0007, "AEBSequence", "AEB sequence/auto cancellation", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0008, "ShutterCurtainSync", "Shutter curtain sync", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0009, "LensAFStopButton", "Lens AF stop button Fn. Switch", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000a, "FillFlashAutoReduction", "Auto reduction of fill flash", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000b, "MenuButtonReturn", "Menu button return position", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000c, "SetButtonFunction", "SET button func. when shooting", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000d, "SensorCleaning", "Sensor cleaning", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000e, "SuperimposedDisplay", "Superimposed display", canonCfIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x000f, "ShutterReleaseNoCFCard", "Shutter Release W/O CF Card", canonCfIfdId, makerTags, unsignedShort, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownCanonCfTag)", "Unknown Canon Custom Function tag", canonCfIfdId, makerTags, invalidTypeId, printValue) - }; - - int CanonMakerNote::read(const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - int rc = IfdMakerNote::read(buf, len, byteOrder, offset); - if (rc) return rc; - - // Decode camera settings 1 and add settings as additional entries - Entries::iterator cs = ifd_.findTag(0x0001); - if (cs != ifd_.end() && cs->type() == unsignedShort) { - for (uint16_t c = 1; cs->count() > c; ++c) { - if (c == 23 && cs->count() > 25) { - // Pack related lens info into one tag - addCsEntry(canonCs1IfdId, c, cs->offset() + c*2, - cs->data() + c*2, 3); - c += 2; - } - else { - addCsEntry(canonCs1IfdId, c, cs->offset() + c*2, - cs->data() + c*2, 1); - } - } - // Discard the original entry - ifd_.erase(cs); - } - - // Decode camera settings 2 and add settings as additional entries - cs = ifd_.findTag(0x0004); - if (cs != ifd_.end() && cs->type() == unsignedShort) { - for (uint16_t c = 1; cs->count() > c; ++c) { - addCsEntry(canonCs2IfdId, c, cs->offset() + c*2, - cs->data() + c*2, 1); - } - // Discard the original entry - ifd_.erase(cs); - } - - // Decode custom functions and add each as an additional entry - cs = ifd_.findTag(0x000f); - if (cs != ifd_.end() && cs->type() == unsignedShort) { - for (uint16_t c = 1; cs->count() > c; ++c) { - addCsEntry(canonCfIfdId, c, cs->offset() + c*2, - cs->data() + c*2, 1); - } - // Discard the original entry - ifd_.erase(cs); - } - - // Copy remaining ifd entries - entries_.insert(entries_.begin(), ifd_.begin(), ifd_.end()); - - // Set idx - int idx = 0; - Entries::iterator e = entries_.end(); - for (Entries::iterator i = entries_.begin(); i != e; ++i) { - i->setIdx(++idx); - } - - return 0; - } - - void CanonMakerNote::addCsEntry(IfdId ifdId, - uint16_t tag, - long offset, - const byte* data, - int count) - { - Entry e(false); - e.setIfdId(ifdId); - e.setTag(tag); - e.setOffset(offset); - e.setValue(unsignedShort, count, data, 2*count); - add(e); - } - - void CanonMakerNote::add(const Entry& entry) - { - assert(alloc_ == entry.alloc()); - assert( entry.ifdId() == canonIfdId - || entry.ifdId() == canonCs1IfdId - || entry.ifdId() == canonCs2IfdId - || entry.ifdId() == canonCfIfdId); - // allow duplicates - entries_.push_back(entry); - } - - long CanonMakerNote::copy(byte* buf, ByteOrder byteOrder, long offset) - { - if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder; - - assert(ifd_.alloc()); - ifd_.clear(); - - // Add all standard Canon entries to the IFD - Entries::const_iterator end = entries_.end(); - for (Entries::const_iterator i = entries_.begin(); i != end; ++i) { - if (i->ifdId() == canonIfdId) { - ifd_.add(*i); - } - } - // Collect camera settings 1 entries and add the original Canon tag - Entry cs1; - if (assemble(cs1, canonCs1IfdId, 0x0001, byteOrder_)) { - ifd_.erase(0x0001); - ifd_.add(cs1); - } - // Collect camera settings 2 entries and add the original Canon tag - Entry cs2; - if (assemble(cs2, canonCs2IfdId, 0x0004, byteOrder_)) { - ifd_.erase(0x0004); - ifd_.add(cs2); - } - // Collect custom function entries and add the original Canon tag - Entry cf; - if (assemble(cf, canonCfIfdId, 0x000f, byteOrder_)) { - ifd_.erase(0x000f); - ifd_.add(cf); - } - - return IfdMakerNote::copy(buf, byteOrder_, offset); - } // CanonMakerNote::copy - - void CanonMakerNote::updateBase(byte* pNewBase) - { - byte* pBase = ifd_.updateBase(pNewBase); - if (absOffset_ && !alloc_) { - Entries::iterator end = entries_.end(); - for (Entries::iterator pos = entries_.begin(); pos != end; ++pos) { - pos->updateBase(pBase, pNewBase); - } - } - } // CanonMakerNote::updateBase - - long CanonMakerNote::size() const - { - Ifd ifd(canonIfdId, 0, alloc_); // offset doesn't matter - - // Add all standard Canon entries to the IFD - Entries::const_iterator end = entries_.end(); - for (Entries::const_iterator i = entries_.begin(); i != end; ++i) { - if (i->ifdId() == canonIfdId) { - ifd.add(*i); - } - } - // Collect camera settings 1 entries and add the original Canon tag - Entry cs1(alloc_); - if (assemble(cs1, canonCs1IfdId, 0x0001, littleEndian)) { - ifd.erase(0x0001); - ifd.add(cs1); - } - // Collect camera settings 2 entries and add the original Canon tag - Entry cs2(alloc_); - if (assemble(cs2, canonCs2IfdId, 0x0004, littleEndian)) { - ifd.erase(0x0004); - ifd.add(cs2); - } - // Collect custom function entries and add the original Canon tag - Entry cf(alloc_); - if (assemble(cf, canonCfIfdId, 0x000f, littleEndian)) { - ifd.erase(0x000f); - ifd.add(cf); - } - - return headerSize() + ifd.size() + ifd.dataSize(); - } // CanonMakerNote::size - - long CanonMakerNote::assemble(Entry& e, - IfdId ifdId, - uint16_t tag, - ByteOrder byteOrder) const - { - DataBuf buf(1024); - memset(buf.pData_, 0x0, 1024); - uint16_t len = 0; - Entries::const_iterator end = entries_.end(); - for (Entries::const_iterator i = entries_.begin(); i != end; ++i) { - if (i->ifdId() == ifdId) { - uint16_t pos = i->tag() * 2; - uint16_t size = pos + static_cast<uint16_t>(i->size()); - assert(size <= 1024); - memcpy(buf.pData_ + pos, i->data(), i->size()); - if (len < size) len = size; - } - } - if (len > 0) { - // Number of shorts in the buffer (rounded up) - uint16_t s = (len+1) / 2; - us2Data(buf.pData_, s*2, byteOrder); - - e.setIfdId(canonIfdId); - e.setIdx(0); // don't care - e.setTag(tag); - e.setOffset(0); // will be calculated when the IFD is written - e.setValue(unsignedShort, s, buf.pData_, s*2); - } - return len; - } // CanonMakerNote::assemble - - Entries::const_iterator CanonMakerNote::findIdx(int idx) const - { - return std::find_if(entries_.begin(), entries_.end(), - FindEntryByIdx(idx)); - } - - CanonMakerNote::CanonMakerNote(bool alloc) - : IfdMakerNote(canonIfdId, alloc) - { - } - - CanonMakerNote::CanonMakerNote(const CanonMakerNote& rhs) - : IfdMakerNote(rhs) - { - entries_ = rhs.entries_; - } - - CanonMakerNote::AutoPtr CanonMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - CanonMakerNote* CanonMakerNote::create_(bool alloc) const - { - return new CanonMakerNote(alloc); - } - - CanonMakerNote::AutoPtr CanonMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - CanonMakerNote* CanonMakerNote::clone_() const - { - return new CanonMakerNote(*this); - } - - std::ostream& CanonMakerNote::print0x0008(std::ostream& os, - const Value& value) - { - std::string n = value.toString(); - return os << n.substr(0, n.length() - 4) << "-" - << n.substr(n.length() - 4); - } - - std::ostream& CanonMakerNote::print0x000c(std::ostream& os, - const Value& value) - { - std::istringstream is(value.toString()); - uint32_t l; - is >> l; - return os << std::setw(4) << std::setfill('0') << std::hex - << ((l & 0xffff0000) >> 16) - << std::setw(5) << std::setfill('0') << std::dec - << (l & 0x0000ffff); - } - - std::ostream& CanonMakerNote::printCs10x0001(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 1: os << "On"; break; - case 2: os << "Off"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0002(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - if (l == 0) { - os << "Off"; - } - else { - os << l / 10.0 << " s"; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0003(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 2: os << "Normal"; break; - case 3: os << "Fine"; break; - case 5: os << "Superfine"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0004(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Off"; break; - case 1: os << "Auto"; break; - case 2: os << "On"; break; - case 3: os << "Red-eye"; break; - case 4: os << "Slow sync"; break; - case 5: os << "Auto + red-eye"; break; - case 6: os << "On + red-eye"; break; - case 16: os << "External"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0005(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Single / timer"; break; - case 1: os << "Continuous"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0007(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "One shot"; break; - case 1: os << "AI servo"; break; - case 2: os << "AI Focus"; break; - case 3: os << "MF"; break; - case 4: os << "Single"; break; - case 5: os << "Continuous"; break; - case 6: os << "MF"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x000a(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Large"; break; - case 1: os << "Medium"; break; - case 2: os << "Small"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x000b(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Full auto"; break; - case 1: os << "Manual"; break; - case 2: os << "Landscape"; break; - case 3: os << "Fast shutter"; break; - case 4: os << "Slow shutter"; break; - case 5: os << "Night"; break; - case 6: os << "B&W"; break; - case 7: os << "Sepia"; break; - case 8: os << "Portrait"; break; - case 9: os << "Sports"; break; - case 10: os << "Macro / close-up"; break; - case 11: os << "Pan focus"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x000c(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "None"; break; - case 1: os << "2x"; break; - case 2: os << "4x"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs1Lnh(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0xffff: os << "Low"; break; - case 0x0000: os << "Normal"; break; - case 0x0001: os << "High"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0010(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "n/a"; break; - case 15: os << "Auto"; break; - case 16: os << "50"; break; - case 17: os << "100"; break; - case 18: os << "200"; break; - case 19: os << "400"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0011(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 3: os << "Evaluative"; break; - case 4: os << "Partial"; break; - case 5: os << "Center weighted"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0012(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Manual"; break; - case 1: os << "Auto"; break; - case 3: os << "Close-up (macro)"; break; - case 8: os << "Locked (pan mode)"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0013(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0x3000: os << "None (MF)"; break; - case 0x3001: os << "Auto-selected"; break; - case 0x3002: os << "Right"; break; - case 0x3003: os << "Center"; break; - case 0x3004: os << "Left"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0014(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Easy shooting"; break; - case 1: os << "Program"; break; - case 2: os << "Shutter priority"; break; - case 3: os << "Aperture priority"; break; - case 4: os << "Manual"; break; - case 5: os << "A-DEP"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x001c(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Did not fire"; break; - case 1: os << "Fired"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x001d(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - bool coma = false; - if (l & 0x4000) { - if (coma) os << ", "; - os << "External TTL"; - coma = true; - } - if (l & 0x2000) { - if (coma) os << ", "; - os << "Internal flash"; - coma = true; - } - if (l & 0x0800) { - if (coma) os << ", "; - os << "FP sync used"; - coma = true; - } - if (l & 0x0080) { - if (coma) os << ", "; - os << "Rear curtain sync used"; - coma = true; - } - if (l & 0x0010) { - if (coma) os << ", "; - os << "FP sync enabled"; - coma = true; - } - return os; - } - - std::ostream& CanonMakerNote::printCs10x0020(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Single"; break; - case 1: os << "Continuous"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs1Lens(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - if (value.count() < 3) return os << value; - - float fu = value.toFloat(2); - float len1 = value.toLong(0) / fu; - float len2 = value.toLong(1) / fu; - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(1) - << len2 << " - " << len1 << " mm"; - os.copyfmt(oss); - return os; - } - - std::ostream& CanonMakerNote::printCs20x0002(std::ostream& os, - const Value& value) - { - // Ported from Exiftool by Will Stokes - return os << exp(canonEv(value.toLong()) * log(2.0)) * 100.0 / 32.0; - } - - std::ostream& CanonMakerNote::printCs20x0007(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0: os << "Auto"; break; - case 1: os << "Sunny"; break; - case 2: os << "Cloudy"; break; - case 3: os << "Tungsten"; break; - case 4: os << "Fluorescent"; break; - case 5: os << "Flash"; break; - case 6: os << "Custom"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs20x0009(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - os << l << ""; - // Todo: determine unit - return os; - } - - std::ostream& CanonMakerNote::printCs20x000e(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - long num = (l & 0xf000) >> 12; - os << num << " focus points; "; - long used = l & 0x0fff; - if (used == 0) { - os << "none"; - } - else { - bool coma = false; - if (l & 0x0004) { - if (coma) os << ", "; - os << "left"; - coma = true; - } - if (l & 0x0002) { - if (coma) os << ", "; - os << "center"; - coma = true; - } - if (l & 0x0001) { - if (coma) os << ", "; - os << "right"; - coma = true; - } - } - os << " used"; - return os; - } - - std::ostream& CanonMakerNote::printCs20x000f(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - switch (l) { - case 0xffc0: os << "-2 EV"; break; - case 0xffcc: os << "-1.67 EV"; break; - case 0xffd0: os << "-1.50 EV"; break; - case 0xffd4: os << "-1.33 EV"; break; - case 0xffe0: os << "-1 EV"; break; - case 0xffec: os << "-0.67 EV"; break; - case 0xfff0: os << "-0.50 EV"; break; - case 0xfff4: os << "-0.33 EV"; break; - case 0x0000: os << "0 EV"; break; - case 0x000c: os << "0.33 EV"; break; - case 0x0010: os << "0.50 EV"; break; - case 0x0014: os << "0.67 EV"; break; - case 0x0020: os << "1 EV"; break; - case 0x002c: os << "1.33 EV"; break; - case 0x0030: os << "1.50 EV"; break; - case 0x0034: os << "1.67 EV"; break; - case 0x0040: os << "2 EV"; break; - default: os << "(" << l << ")"; break; - } - return os; - } - - std::ostream& CanonMakerNote::printCs20x0013(std::ostream& os, - const Value& value) - { - if (value.typeId() != unsignedShort) return os << value; - long l = value.toLong(); - if (l == 0xffff) { - os << "Infinite"; - } - else { - os << l << ""; - } - return os; - } - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createCanonMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - return MakerNote::AutoPtr(new CanonMakerNote(alloc)); - } - -} // namespace Exiv2 - -// ***************************************************************************** -// local definitions -namespace { - - float canonEv(long val) - { - // temporarily remove sign - int sign = 1; - if (val < 0) { - sign = -1; - val = -val; - } - // remove fraction - float frac = static_cast<float>(val & 0x1f); - val -= long(frac); - // convert 1/3 (0x0c) and 2/3 (0x14) codes - if (frac == 0x0c) { - frac = 32.0f / 3; - } - else if (frac == 0x14) { - frac = 64.0f / 3; - } - return sign * (val + frac) / 32.0f; - } - -} diff --git a/src/plugins/exiv2/canonmn.hpp b/src/plugins/exiv2/canonmn.hpp @@ -1,238 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 canonmn.hpp - @brief Canon MakerNote implemented according to the specification - <a href="http://www.burren.cx/david/canon.html"> - EXIF MakerNote of Canon</a> by David Burren<br> - and with reference to tag information from - <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/"> - ExifTool</a> by Phil Harvey - @version $Rev: 569 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 18-Feb-04, ahu: created<BR> - 07-Mar-04, ahu: isolated as a separate component - */ -#ifndef CANONMN_HPP_ -#define CANONMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createCanonMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! MakerNote for Canon cameras - class CanonMakerNote : public IfdMakerNote { - public: - //! Shortcut for a %CanonMakerNote auto pointer. - typedef std::auto_ptr<CanonMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - CanonMakerNote(bool alloc =true); - //! Copy constructor - CanonMakerNote(const CanonMakerNote& rhs); - //! Virtual destructor - virtual ~CanonMakerNote() {} - //@} - - //! @name Manipulators - //@{ - int read(const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - long copy(byte* buf, ByteOrder byteOrder, long offset); - void add(const Entry& entry); - Entries::iterator begin() { return entries_.begin(); } - Entries::iterator end() { return entries_.end(); } - void updateBase(byte* pNewBase); - //@} - - //! @name Accessors - //@{ - Entries::const_iterator begin() const { return entries_.begin(); } - Entries::const_iterator end() const { return entries_.end(); } - Entries::const_iterator findIdx(int idx) const; - long size() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Canon %MakerNote tags - //@{ - //! Print the image number - static std::ostream& print0x0008(std::ostream& os, const Value& value); - //! Print the serial number of the camera - static std::ostream& print0x000c(std::ostream& os, const Value& value); - - //! Macro mode - static std::ostream& printCs10x0001(std::ostream& os, const Value& value); - //! Self timer - static std::ostream& printCs10x0002(std::ostream& os, const Value& value); - //! Quality - static std::ostream& printCs10x0003(std::ostream& os, const Value& value); - //! Flash mode - static std::ostream& printCs10x0004(std::ostream& os, const Value& value); - //! Drive mode - static std::ostream& printCs10x0005(std::ostream& os, const Value& value); - //! Focus mode (G1 seems to use field 32 in preference to this) - static std::ostream& printCs10x0007(std::ostream& os, const Value& value); - //! Image size - static std::ostream& printCs10x000a(std::ostream& os, const Value& value); - //! Easy shooting - static std::ostream& printCs10x000b(std::ostream& os, const Value& value); - //! Digital zoom - static std::ostream& printCs10x000c(std::ostream& os, const Value& value); - //! ISO - static std::ostream& printCs10x0010(std::ostream& os, const Value& value); - //! Metering mode - static std::ostream& printCs10x0011(std::ostream& os, const Value& value); - //! Focus type - static std::ostream& printCs10x0012(std::ostream& os, const Value& value); - //! AF point selected - static std::ostream& printCs10x0013(std::ostream& os, const Value& value); - //! Exposure mode - static std::ostream& printCs10x0014(std::ostream& os, const Value& value); - //! Flash activity - static std::ostream& printCs10x001c(std::ostream& os, const Value& value); - //! Flash details - static std::ostream& printCs10x001d(std::ostream& os, const Value& value); - //! Focus mode (G1 seems to use this in preference to field 7) - static std::ostream& printCs10x0020(std::ostream& os, const Value& value); - //! Low, normal, high print function - static std::ostream& printCs1Lnh(std::ostream& os, const Value& value); - //! Camera lens information - static std::ostream& printCs1Lens(std::ostream& os, const Value& value); - //! ISO speed used - static std::ostream& printCs20x0002(std::ostream& os, const Value& value); - //! White balance - static std::ostream& printCs20x0007(std::ostream& os, const Value& value); - //! Sequence number - static std::ostream& printCs20x0009(std::ostream& os, const Value& value); - //! AF point used - static std::ostream& printCs20x000e(std::ostream& os, const Value& value); - //! Flash bias - static std::ostream& printCs20x000f(std::ostream& os, const Value& value); - //! Subject distance - static std::ostream& printCs20x0013(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! @name Manipulators - //@{ - //! Add a camera settings entry to the makernote entries - void addCsEntry(IfdId ifdId, - uint16_t tag, - long offset, - const byte* data, - int count); - //@} - - //! @name Accessors - //@{ - //! Assemble special Canon entries into an entry with the original tag - long assemble(Entry& e, - IfdId ifdId, - uint16_t tag, - ByteOrder byteOrder) const; - //! Internal virtual create function. - CanonMakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - CanonMakerNote* clone_() const; - //@} - - // DATA - //! Container to store Makernote entries (instead of Ifd) - Entries entries_; - - //! Tag information - static const TagInfo tagInfo_[]; - static const TagInfo tagInfoCs1_[]; - static const TagInfo tagInfoCs2_[]; - static const TagInfo tagInfoCf_[]; - - }; // class CanonMakerNote - - static CanonMakerNote::RegisterMn registerCanonMakerNote; -} // namespace Exiv2 - -#endif // #ifndef CANONMN_HPP_ diff --git a/src/plugins/exiv2/datasets.cpp b/src/plugins/exiv2/datasets.cpp @@ -1,392 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: datasets.cpp - Version: $Rev: 560 $ - Author(s): Brad Schick (brad) <brad@robotbattle.com> - History: 24-Jul-04, brad: created - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: datasets.cpp 560 2005-04-17 11:51:32Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "datasets.hpp" -#include "error.hpp" -#include "types.hpp" -#include "value.hpp" -#include "metadatum.hpp" - -#include <iostream> -#include <iomanip> -#include <sstream> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - DataSet::DataSet( - uint16_t number, - const char* name, - const char* desc, - bool mandatory, - bool repeatable, - uint32_t minbytes, - uint32_t maxbytes, - TypeId type, - uint16_t recordId, - const char* photoshop - ) - : number_(number), name_(name), desc_(desc), mandatory_(mandatory), - repeatable_(repeatable), minbytes_(minbytes), maxbytes_(maxbytes), - type_(type), recordId_(recordId), photoshop_(photoshop) - { - } - - RecordInfo::RecordInfo( - uint16_t recordId, - const char* name, - const char* desc - ) - : recordId_(recordId), name_(name), desc_(desc) - { - } - - const RecordInfo IptcDataSets::recordInfo_[] = { - RecordInfo(IptcDataSets::invalidRecord, "(invalid)", "(invalid)"), - RecordInfo(IptcDataSets::envelope, "Envelope", "IIM envelope record"), - RecordInfo(IptcDataSets::application2, "Application2", "IIM application record 2"), - }; - - static const DataSet envelopeRecord[] = { - DataSet(IptcDataSets::ModelVersion, "ModelVersion", "Version of IIM part 1", true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::Destination, "Destination", "Routing information", false, true, 0, 1024, Exiv2::string, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::FileFormat, "FileFormat", "IIM appendix A file format", true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::FileVersion, "FileVersion", "File format version", true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::ServiceId, "ServiceId", "Identifies the provider and product", true, false, 0, 10, Exiv2::string, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::EnvelopeNumber, "EnvelopeNumber", "Combined unique identification", true, false, 8, 8, Exiv2::string, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::ProductId, "ProductId", "Identifies service subset", false, true, 0, 32, Exiv2::string, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::EnvelopePriority, "EnvelopePriority", "Envelope handling priority", false, false, 1, 1, Exiv2::string, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::DateSent, "DateSent", "Date material was sent", true, false, 8, 8, Exiv2::date, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::TimeSent, "TimeSent", "Time material was sent", false, false, 11, 11, Exiv2::time, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::CharacterSet, "CharacterSet", "Specifies character sets", false, false, 0, 32, Exiv2::undefined, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::UNO, "UNO", "Unique Name of Object", false, false, 14, 80, Exiv2::string, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::ARMId, "ARMId", "Abstract Relationship Method identifier", false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), - DataSet(IptcDataSets::ARMVersion, "ARMVersion", "Abstract Relationship Method version", false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::envelope, ""), - DataSet(0xffff, "(Invalid)", "(Invalid)", false, false, 0, 0, Exiv2::unsignedShort, IptcDataSets::envelope, "") - }; - - static const DataSet application2Record[] = { - DataSet(IptcDataSets::RecordVersion, "RecordVersion", "Version of IIM part 2", true, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ObjectType, "ObjectType", "IIM appendix G object type", false, false, 3, 67, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ObjectAttribute, "ObjectAttribute", "IIM appendix G object attribute", false, true, 4, 68, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ObjectName, "ObjectName", "Shorthand reference of content", false, false, 0, 64, Exiv2::string, IptcDataSets::application2, "Document title"), - DataSet(IptcDataSets::EditStatus, "EditStatus", "Content status", false, false, 0, 64, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::EditorialUpdate, "EditorialUpdate", "Indicates the type of update", false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Urgency, "Urgency", "Editorial urgency of content", false, false, 1, 1, Exiv2::string, IptcDataSets::application2, "Urgency"), - DataSet(IptcDataSets::Subject, "Subject", "Structured definition of the subject", false, true, 13, 236, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Category, "Category", "Identifies the subject", false, false, 0, 3, Exiv2::string, IptcDataSets::application2, "Category"), - DataSet(IptcDataSets::SuppCategory, "SuppCategory", "Refines the subject", false, true, 0, 32, Exiv2::string, IptcDataSets::application2, "Supplemental Categories"), - DataSet(IptcDataSets::FixtureId, "FixtureId", "Identifies content that recurs", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Keywords, "Keywords", "Information retrieval words", false, true, 0, 64, Exiv2::string, IptcDataSets::application2, "Keywords"), - DataSet(IptcDataSets::LocationCode, "LocationCode", "ISO country code for content", false, true, 3, 3, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::LocationName, "LocationName", "Full country name for content", false, true, 0, 64, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ReleaseDate, "ReleaseDate", "Earliest intended usable date", false, false, 8, 8, Exiv2::date, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ReleaseTime, "ReleaseTime", "Earliest intended usable time", false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ExpirationDate, "ExpirationDate", "Latest intended usable date", false, false, 8, 8, Exiv2::date, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ExpirationTime, "ExpirationTime", "Latest intended usable time", false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), - DataSet(IptcDataSets::SpecialInstructions, "SpecialInstructions", "Editorial usage instructions", false, false, 0, 256, Exiv2::string, IptcDataSets::application2, "Instructions"), - DataSet(IptcDataSets::ActionAdvised, "ActionAdvised", "Action provided to previous data", false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ReferenceService, "ReferenceService", "Service Identifier of a prior envelope", false, true, 0, 10, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ReferenceDate, "ReferenceDate", "Date of a prior envelope", false, true, 8, 8, Exiv2::date, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ReferenceNumber, "ReferenceNumber", "Envelope Number of a prior envelope", false, true, 8, 8, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::DateCreated, "DateCreated", "Creation date of intellectual content", false, false, 8, 8, Exiv2::date, IptcDataSets::application2, "Date created"), - DataSet(IptcDataSets::TimeCreated, "TimeCreated", "Creation time of intellectual content", false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), - DataSet(IptcDataSets::DigitizationDate, "DigitizationDate", "Creation date of digital representation", false, false, 8, 8, Exiv2::date, IptcDataSets::application2, ""), - DataSet(IptcDataSets::DigitizationTime, "DigitizationTime", "Creation time of digital representation", false, false, 11, 11, Exiv2::time, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Program, "Program", "Content creation program", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ProgramVersion, "ProgramVersion", "Content creation program version", false, false, 0, 10, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ObjectCycle, "ObjectCycle", "Morning, evening, or both", false, false, 1, 1, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Byline, "Byline", "Name of content creator", false, true, 0, 32, Exiv2::string, IptcDataSets::application2, "Author"), - DataSet(IptcDataSets::BylineTitle, "BylineTitle", "Title of content creator", false, true, 0, 32, Exiv2::string, IptcDataSets::application2, "Authors Position"), - DataSet(IptcDataSets::City, "City", "City of content origin", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, "City"), - DataSet(IptcDataSets::SubLocation, "SubLocation", "Location within city", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ProvinceState, "ProvinceState", "Province/State of content origin", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, "State/Province"), - DataSet(IptcDataSets::CountryCode, "CountryCode", "ISO country code of content origin", false, false, 3, 3, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::CountryName, "CountryName", "Full country name of content origin", false, false, 0, 64, Exiv2::string, IptcDataSets::application2, "Country"), - DataSet(IptcDataSets::TransmissionReference, "TransmissionReference", "Location of original transmission", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, "Transmission Reference"), - DataSet(IptcDataSets::Headline, "Headline", "Content synopsis", false, false, 0, 256, Exiv2::string, IptcDataSets::application2, "Headline"), - DataSet(IptcDataSets::Credit, "Credit", "Content provider", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, "Credit"), - DataSet(IptcDataSets::Source, "Source", "Original owner of content", false, false, 0, 32, Exiv2::string, IptcDataSets::application2, "Source"), - DataSet(IptcDataSets::Copyright, "Copyright", "Necessary copyright notice", false, false, 0, 128, Exiv2::string, IptcDataSets::application2, "Copyright notice"), - DataSet(IptcDataSets::Contact, "Contact", "Person or organisation to contact", false, true, 0, 128, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Caption, "Caption", "Content description", false, false, 0, 2000, Exiv2::string, IptcDataSets::application2, "Description"), - DataSet(IptcDataSets::Writer, "Writer", "Person responsible for caption", false, true, 0, 32, Exiv2::string, IptcDataSets::application2, "Description writer"), - DataSet(IptcDataSets::RasterizedCaption, "RasterizedCaption", "Black and white caption image", false, false, 7360, 7360, Exiv2::undefined, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ImageType, "ImageType", "Color components in an image", false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::ImageOrientation, "ImageOrientation", "Indicates the layout of an image", false, false, 1, 1, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Language, "Language", "ISO 639:1988 language code", false, false, 2, 3, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::AudioType, "AudioType", "Information about audio content", false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::AudioRate, "AudioRate", "Sampling rate of audio content", false, false, 6, 6, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::AudioResolution, "AudioResolution", "Sampling resolution of audio content", false, false, 2, 2, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::AudioDuration, "AudioDuration", "Duration of audio content", false, false, 6, 6, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::AudioOutcue, "AudioOutcue", "Final words or sounds of audio content", false, false, 0, 64, Exiv2::string, IptcDataSets::application2, ""), - DataSet(IptcDataSets::PreviewFormat, "PreviewFormat", "IIM appendix A file format of preview", false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::application2, ""), - DataSet(IptcDataSets::PreviewVersion, "PreviewVersion", "File format version of preview", false, false, 2, 2, Exiv2::unsignedShort, IptcDataSets::application2, ""), - DataSet(IptcDataSets::Preview, "Preview", "Binary preview data", false, false, 0, 256000, Exiv2::undefined, IptcDataSets::application2, ""), - DataSet(0xffff, "(Invalid)", "(Invalid)", false, false, 0, 0, Exiv2::unsignedShort, IptcDataSets::application2, "") - }; - - static const DataSet unknownDataSet(0xffff, "Unknown dataset", "Unknown dataset", false, true, 0, 0xffffffff, Exiv2::string, IptcDataSets::invalidRecord, "Unknown dataset"); - - // Dataset lookup lists.This is an array with pointers to one list per IIM4 Record. - // The record id is used as the index into the array. - const DataSet* IptcDataSets::records_[] = { - 0, - envelopeRecord, application2Record, - 0 - }; - - int IptcDataSets::dataSetIdx(uint16_t number, uint16_t recordId) - { - if( recordId != envelope && recordId != application2 ) return -1; - const DataSet* dataSet = records_[recordId]; - if (dataSet == 0) return -1; - int idx; - for (idx = 0; dataSet[idx].number_ != number; ++idx) { - if (dataSet[idx].number_ == 0xffff) return -1; - } - return idx; - } - - int IptcDataSets::dataSetIdx(const std::string& dataSetName, uint16_t recordId) - { - if( recordId != envelope && recordId != application2 ) return -1; - const DataSet* dataSet = records_[recordId]; - if (dataSet == 0) return -1; - int idx; - for (idx = 0; dataSet[idx].name_ != dataSetName; ++idx) { - if (dataSet[idx].number_ == 0xffff) return -1; - } - return idx; - } - - TypeId IptcDataSets::dataSetType(uint16_t number, uint16_t recordId) - { - int idx = dataSetIdx(number, recordId); - if (idx == -1) return unknownDataSet.type_; - return records_[recordId][idx].type_; - } - - std::string IptcDataSets::dataSetName(uint16_t number, uint16_t recordId) - { - int idx = dataSetIdx(number, recordId); - if (idx != -1) return records_[recordId][idx].name_; - - std::ostringstream os; - os << "0x" << std::setw(4) << std::setfill('0') << std::right - << std::hex << number; - return os.str(); - } - - const char* IptcDataSets::dataSetDesc(uint16_t number, uint16_t recordId) - { - int idx = dataSetIdx(number, recordId); - if (idx == -1) return unknownDataSet.desc_; - return records_[recordId][idx].desc_; - } - - const char* IptcDataSets::dataSetPsName(uint16_t number, uint16_t recordId) - { - int idx = dataSetIdx(number, recordId); - if (idx == -1) return unknownDataSet.photoshop_; - return records_[recordId][idx].photoshop_; - } - - bool IptcDataSets::dataSetRepeatable(uint16_t number, uint16_t recordId) - { - int idx = dataSetIdx(number, recordId); - if (idx == -1) return unknownDataSet.repeatable_; - return records_[recordId][idx].repeatable_; - } - - uint16_t IptcDataSets::dataSet(const std::string& dataSetName, - uint16_t recordId) - { - uint16_t dataSet; - int idx = dataSetIdx(dataSetName, recordId); - if (idx != -1) { - // dataSetIdx checks the range of recordId - dataSet = records_[recordId][idx].number_; - } - else { - if (!isHex(dataSetName, 4, "0x")) throw Error(4, dataSetName); - std::istringstream is(dataSetName); - is >> std::hex >> dataSet; - } - return dataSet; - } - - std::string IptcDataSets::recordName(uint16_t recordId) - { - if (recordId == envelope || recordId == application2) { - return recordInfo_[recordId].name_; - } - - std::ostringstream os; - os << "0x" << std::setw(4) << std::setfill('0') << std::right - << std::hex << recordId; - return os.str(); - } - - const char* IptcDataSets::recordDesc(uint16_t recordId) - { - if (recordId != envelope && recordId != application2) { - return unknownDataSet.desc_; - } - return recordInfo_[recordId].desc_; - } - - uint16_t IptcDataSets::recordId(const std::string& recordName) - { - uint16_t i; - for (i = application2; i > 0; --i) { - if (recordInfo_[i].name_ == recordName) break; - } - if (i == 0) { - if (!isHex(recordName, 4, "0x")) throw Error(5, recordName); - std::istringstream is(recordName); - is >> std::hex >> i; - } - return i; - } - - void IptcDataSets::dataSetList(std::ostream& os) - { - const int count = sizeof(records_)/sizeof(records_[0]); - for (int i=0; i < count; ++i) { - const DataSet *record = records_[i]; - for (int j=0; record != 0 && record[j].number_ != 0xffff; ++j) { - os << record[j] << "\n"; - } - } - } // IptcDataSets::dataSetList - - const char* IptcKey::familyName_ = "Iptc"; - - IptcKey::IptcKey(const std::string& key) - : key_(key) - { - decomposeKey(); - } - - IptcKey::IptcKey(uint16_t tag, uint16_t record) - : tag_(tag), record_(record) - { - makeKey(); - } - - IptcKey::IptcKey(const IptcKey& rhs) - : tag_(rhs.tag_), record_(rhs.record_), key_(rhs.key_) - { - } - - IptcKey& IptcKey::operator=(const IptcKey& rhs) - { - if (this == &rhs) return *this; - Key::operator=(rhs); - tag_ = rhs.tag_; - record_ = rhs.record_; - key_ = rhs.key_; - return *this; - } - - IptcKey::AutoPtr IptcKey::clone() const - { - return AutoPtr(clone_()); - } - - IptcKey* IptcKey::clone_() const - { - return new IptcKey(*this); - } - - void IptcKey::decomposeKey() - { - // Get the family name, record name and dataSet name parts of the key - std::string::size_type pos1 = key_.find('.'); - if (pos1 == std::string::npos) throw Error(6, key_); - std::string familyName = key_.substr(0, pos1); - if (familyName != std::string(familyName_)) { - throw Error(6, key_); - } - std::string::size_type pos0 = pos1 + 1; - pos1 = key_.find('.', pos0); - if (pos1 == std::string::npos) throw Error(6, key_); - std::string recordName = key_.substr(pos0, pos1 - pos0); - if (recordName == "") throw Error(6, key_); - std::string dataSetName = key_.substr(pos1 + 1); - if (dataSetName == "") throw Error(6, key_); - - // Use the parts of the key to find dataSet and recordId - uint16_t recId = IptcDataSets::recordId(recordName); - uint16_t dataSet = IptcDataSets::dataSet(dataSetName, recId); - - // Possibly translate hex name parts (0xabcd) to real names - recordName = IptcDataSets::recordName(recId); - dataSetName = IptcDataSets::dataSetName(dataSet, recId); - - tag_ = dataSet; - record_ = recId; - key_ = familyName + "." + recordName + "." + dataSetName; - } // IptcKey::decomposeKey - - void IptcKey::makeKey() - { - key_ = std::string(familyName_) - + "." + IptcDataSets::recordName(record_) - + "." + IptcDataSets::dataSetName(tag_, record_); - } - - // ************************************************************************* - // free functions - - std::ostream& operator<<(std::ostream& os, const DataSet& dataSet) - { - IptcKey iptcKey(dataSet.number_, dataSet.recordId_); - return os << dataSet.name_ << ", " - << std::dec << dataSet.number_ << ", " - << "0x" << std::setw(4) << std::setfill('0') - << std::right << std::hex << dataSet.number_ << ", " - << IptcDataSets::recordName(dataSet.recordId_) << ", " - << std::boolalpha << dataSet.mandatory_ << ", " - << dataSet.repeatable_ << ", " - << std::dec << dataSet.minbytes_ << ", " - << dataSet.maxbytes_ << ", " - << iptcKey.key() << ", " - << TypeInfo::typeName( - IptcDataSets::dataSetType(dataSet.number_, - dataSet.recordId_)) << ", " - << dataSet.desc_; - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/datasets.hpp b/src/plugins/exiv2/datasets.hpp @@ -1,358 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 datasets.hpp - @brief Iptc dataSet and type information - @version $Rev: 560 $ - @author Brad Schick (brad) <brad@robotbattle.com> - @date 24-Jul-04, brad: created - */ -#ifndef DATASETS_HPP_ -#define DATASETS_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "metadatum.hpp" - -// + standard includes -#include <string> -#include <utility> // for std::pair -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class definitions - - //! Contains information about one record - struct RecordInfo { - //! Constructor - RecordInfo(uint16_t recordId, const char* name, const char* desc); - uint16_t recordId_; //!< Record id - const char* name_; //!< Record name (one word) - const char* desc_; //!< Record description - }; - - //! Dataset information - struct DataSet { - //! Constructor - DataSet( - uint16_t number, - const char* name, - const char* desc, - bool mandatory, - bool repeatable, - uint32_t minbytes, - uint32_t maxbytes, - TypeId type, - uint16_t recordId, - const char* photoshop - ); - uint16_t number_; //!< Dataset number - const char* name_; //!< Dataset name - const char* desc_; //!< Dataset description - bool mandatory_; //!< True if dataset is mandatory - bool repeatable_; //!< True if dataset is repeatable - uint32_t minbytes_; //!< Minimum number of bytes - uint32_t maxbytes_; //!< Maximum number of bytes - TypeId type_; //!< Exiv2 default type - uint16_t recordId_; //!< Record id - const char* photoshop_; //!< Photoshop string - }; // struct DataSet - - //! Container for Iptc dataset information. Implemented as a static class. - class IptcDataSets { - public: - /*! - @name Record identifiers - @brief Record identifiers to logically group dataSets. There are other - possible record types, but they are not standardized by the Iptc - IIM4 standard (and not commonly used in images). - */ - //@{ - static const uint16_t invalidRecord = 0; - static const uint16_t envelope = 1; - static const uint16_t application2 = 2; - //@} - - //! @name Dataset identifiers - //@{ - static const uint16_t ModelVersion = 0; - static const uint16_t Destination = 5; - static const uint16_t FileFormat = 20; - static const uint16_t FileVersion = 22; - static const uint16_t ServiceId = 30; - static const uint16_t EnvelopeNumber = 40; - static const uint16_t ProductId = 50; - static const uint16_t EnvelopePriority = 60; - static const uint16_t DateSent = 70; - static const uint16_t TimeSent = 80; - static const uint16_t CharacterSet = 90; - static const uint16_t UNO = 100; - static const uint16_t ARMId = 120; - static const uint16_t ARMVersion = 122; - static const uint16_t RecordVersion = 0; - static const uint16_t ObjectType = 3; - static const uint16_t ObjectAttribute = 4; - static const uint16_t ObjectName = 5; - static const uint16_t EditStatus = 7; - static const uint16_t EditorialUpdate = 8; - static const uint16_t Urgency = 10; - static const uint16_t Subject = 12; - static const uint16_t Category = 15; - static const uint16_t SuppCategory = 20; - static const uint16_t FixtureId = 22; - static const uint16_t Keywords = 25; - static const uint16_t LocationCode = 26; - static const uint16_t LocationName = 27; - static const uint16_t ReleaseDate = 30; - static const uint16_t ReleaseTime = 35; - static const uint16_t ExpirationDate = 37; - static const uint16_t ExpirationTime = 38; - static const uint16_t SpecialInstructions = 40; - static const uint16_t ActionAdvised = 42; - static const uint16_t ReferenceService = 45; - static const uint16_t ReferenceDate = 47; - static const uint16_t ReferenceNumber = 50; - static const uint16_t DateCreated = 55; - static const uint16_t TimeCreated = 60; - static const uint16_t DigitizationDate = 62; - static const uint16_t DigitizationTime = 63; - static const uint16_t Program = 65; - static const uint16_t ProgramVersion = 70; - static const uint16_t ObjectCycle = 75; - static const uint16_t Byline = 80; - static const uint16_t BylineTitle = 85; - static const uint16_t City = 90; - static const uint16_t SubLocation = 92; - static const uint16_t ProvinceState = 95; - static const uint16_t CountryCode = 100; - static const uint16_t CountryName = 101; - static const uint16_t TransmissionReference = 103; - static const uint16_t Headline = 105; - static const uint16_t Credit = 110; - static const uint16_t Source = 115; - static const uint16_t Copyright = 116; - static const uint16_t Contact = 118; - static const uint16_t Caption = 120; - static const uint16_t Writer = 122; - static const uint16_t RasterizedCaption = 125; - static const uint16_t ImageType = 130; - static const uint16_t ImageOrientation = 131; - static const uint16_t Language = 135; - static const uint16_t AudioType = 150; - static const uint16_t AudioRate = 151; - static const uint16_t AudioResolution = 152; - static const uint16_t AudioDuration = 153; - static const uint16_t AudioOutcue = 154; - static const uint16_t PreviewFormat = 200; - static const uint16_t PreviewVersion = 201; - static const uint16_t Preview = 202; - //@} - - private: - //! Prevent construction: not implemented. - IptcDataSets() {} - //! Prevent copy-construction: not implemented. - IptcDataSets(const IptcDataSets& rhs); - //! Prevent assignment: not implemented. - IptcDataSets& operator=(const IptcDataSets& rhs); - - public: - /*! - @brief Return the name of the dataset. - @param number The dataset number - @param recordId The Iptc record Id - @return The name of the dataset or a string containing the hexadecimal - value of the dataset in the form "0x01ff", if this is an unknown - dataset. - */ - static std::string dataSetName(uint16_t number, uint16_t recordId); - /*! - @brief Return the description of the dataset. - @param number The dataset number - @param recordId The Iptc record Id - @return The description of the dataset - */ - static const char* dataSetDesc(uint16_t number, uint16_t recordId); - /*! - @brief Return the photohsop name of a given dataset. - @param number The dataset number - @param recordId The Iptc record Id - @return The name used by photoshop for a dataset or an empty - string if photoshop does not use the dataset. - */ - static const char* dataSetPsName(uint16_t number, uint16_t recordId); - /*! - @brief Check if a given dataset is repeatable - @param number The dataset number - @param recordId The Iptc record Id - @return true if the given dataset is repeatable otherwise false - */ - static bool dataSetRepeatable(uint16_t number, uint16_t recordId); - /*! - @brief Return the dataSet number for dataset name and record id - - @param dataSetName dataSet name - @param recordId recordId - - @return dataSet number - - @throw Error if the \em dataSetName or \em recordId are invalid - */ - static uint16_t dataSet(const std::string& dataSetName, uint16_t recordId); - //! Return the type for dataSet number and Record id - static TypeId dataSetType(uint16_t number, uint16_t recordId); - /*! - @brief Return the name of the Record - @param recordId The record id - @return The name of the record or a string containing the hexadecimal - value of the record in the form "0x01ff", if this is an - unknown record. - */ - static std::string recordName(uint16_t recordId); - /*! - @brief Return the description of a record - @param recordId Record Id number - @return the description of the Record - */ - static const char* recordDesc(uint16_t recordId); - /*! - @brief Return the Id number of a record - @param recordName Name of a record type - @return the Id number of a Record - @throw Error if the record is not known; - */ - static uint16_t recordId(const std::string& recordName); - //! Print a list of all dataSets to output stream - static void dataSetList(std::ostream& os); - - private: - static int dataSetIdx(uint16_t number, uint16_t recordId); - static int dataSetIdx(const std::string& dataSetName, uint16_t recordId); - - static const DataSet* records_[]; - static const RecordInfo recordInfo_[]; - - }; // class IptcDataSets - - /*! - @brief Concrete keys for Iptc metadata. - */ - class IptcKey : public Key { - public: - //! Shortcut for an %IptcKey auto pointer. - typedef std::auto_ptr<IptcKey> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor to create an Iptc key from a key string. - - @param key The key string. - @throw Error if the first part of the key is not '<b>Iptc</b>' or - the remaining parts of the key cannot be parsed and - converted to a record name and a dataset name. - */ - explicit IptcKey(const std::string& key); - /*! - @brief Constructor to create an Iptc key from dataset and record ids. - @param tag Dataset id - @param record Record id - */ - IptcKey(uint16_t tag, uint16_t record); - //! Copy constructor - IptcKey(const IptcKey& rhs); - //@} - - //! @name Manipulators - //@{ - /*! - @brief Assignment operator. - */ - IptcKey& operator=(const IptcKey& rhs); - //@} - - //! @name Accessors - //@{ - virtual std::string key() const { return key_; } - virtual const char* familyName() const { return familyName_; } - /*! - @brief Return the name of the group (the second part of the key). - For Iptc keys, the group name is the record name. - */ - virtual std::string groupName() const { return recordName(); } - virtual std::string tagName() const - { return IptcDataSets::dataSetName(tag_, record_); } - virtual uint16_t tag() const { return tag_; } - - AutoPtr clone() const; - //! Return the name of the record - std::string recordName() const - { return IptcDataSets::recordName(record_); } - //! Return the record id - uint16_t record() const { return record_; } - //@} - - protected: - //! @name Manipulators - //@{ - /*! - @brief Set the key corresponding to the dataset and record id. - The key is of the form '<b>Iptc</b>.recordName.dataSetName'. - */ - void makeKey(); - /*! - @brief Parse and convert the key string into dataset and record id. - Updates data members if the string can be decomposed, or throws - \em Error. - - @throw Error if the key cannot be decomposed. - */ - void decomposeKey(); - //@} - - private: - //! Internal virtual copy constructor. - virtual IptcKey* clone_() const; - - // DATA - static const char* familyName_; - - uint16_t tag_; //!< Tag value - uint16_t record_; //!< Record value - std::string key_; //!< Key - - }; // class IptcKey - -// ***************************************************************************** -// free functions - - //! Output operator for dataSet - std::ostream& operator<<(std::ostream& os, const DataSet& dataSet); - -} // namespace Exiv2 - -#endif // #ifndef DATASETS_HPP_ diff --git a/src/plugins/exiv2/error.cpp b/src/plugins/exiv2/error.cpp @@ -1,121 +0,0 @@ -// ***************************************************************** -*- 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: error.cpp - Version: $Rev: 563 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 02-Apr-05, ahu: created - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: error.cpp 563 2005-04-21 07:21:53Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "error.hpp" - -// + standard includes -#include <string> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - const ErrMsg Error::errMsg_[] = { - ErrMsg( -1, "Error %0: arg1=%1, arg2=%2, arg3=%3."), - ErrMsg( 0, "Success"), - ErrMsg( 1, "%1"), // %1=error message - - ErrMsg( 2, "%1: %2 (%3)"), // %1=path, %2=strerror, %3=function that failed - // ErrMsg( 3, ""), - - ErrMsg( 4, "Invalid dataset name `%1'"), // %1=dataset name - ErrMsg( 5, "Invalid record name `%1'"), // %1=record name - ErrMsg( 6, "Invalid key `%1'"), // %1=key - ErrMsg( 7, "Invalid tag name or ifdId `%1', ifdId %2"), // %1=tag name, %2=ifdId - ErrMsg( 8, "Value not set"), - ErrMsg( 9, "%1: Failed to open the data source: %2"), // %1=path, %2=strerror - ErrMsg( 10, "%1: Failed to open file (%2): %3"), // %1=path, %2=mode, %3=strerror - ErrMsg( 11, "%1: The file contains data of an unknown image type"), // %1=path - ErrMsg( 12, "The memory contains data of an unknown image type"), - ErrMsg( 13, "Image type %1 is not supported"), // %1=image type - ErrMsg( 14, "Failed to read image data"), - ErrMsg( 15, "This does not look like a JPEG image"), - ErrMsg( 16, "MakerTagInfo registry full"), - ErrMsg( 17, "%1: Failed to rename file to %2: %3"), // %1=old path, %2=new path, %3=strerror - ErrMsg( 18, "%1: Transfer failed: %2"), // %1=path, %2=strerror - ErrMsg( 19, "Memory transfer failed: %1"), // %1=strerror - ErrMsg( 20, "Failed to read input data"), - ErrMsg( 21, "Failed to write image"), - ErrMsg( 22, "Input data does not contain a valid image"), - ErrMsg( 23, "Failed to create Makernote for ifdId %1"), // %1=ifdId - ErrMsg( 24, "Entry::setValue: Value too large (tag=%1, size=%2, requested=%3)"), // %1=tag, %2=dataSize, %3=required size - ErrMsg( 25, "Entry::setDataArea: Value too large (tag=%1, size=%2, requested=%3)"), // %1=tag, %2=dataAreaSize, %3=required size - ErrMsg( 26, "Offset out of range"), - ErrMsg( 27, "Unsupported data area offset type"), - ErrMsg( 28, "Invalid charset: `%1'"), // %1=charset name - ErrMsg( 29, "Unsupported date format"), - ErrMsg( 30, "Unsupported time format"), - - // Last error message (message is not used) - ErrMsg( -2, "(Unknown Error)") - }; - - int Error::errorIdx(int code) - { - int idx; - for (idx = 0; errMsg_[idx].code_ != code; ++idx) { - if (errMsg_[idx].code_ == -2) return 0; - } - return idx; - } - - std::string Error::what() const - { - int idx = errorIdx(code_); - std::string msg = std::string(errMsg_[idx].message_); - std::string::size_type pos; - pos = msg.find("%0"); - if (pos != std::string::npos) { - msg.replace(pos, 2, toString(code_)); - } - if (count_ > 0) { - pos = msg.find("%1"); - if (pos != std::string::npos) { - msg.replace(pos, 2, arg1_); - } - } - if (count_ > 1) { - pos = msg.find("%2"); - if (pos != std::string::npos) { - msg.replace(pos, 2, arg2_); - } - } - if (count_ > 2) { - pos = msg.find("%3"); - if (pos != std::string::npos) { - msg.replace(pos, 2, arg3_); - } - } - return msg; - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/error.hpp b/src/plugins/exiv2/error.hpp @@ -1,148 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 error.hpp - @brief Error class for exceptions - @version $Rev: 560 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 15-Jan-04, ahu: created<BR> - 11-Feb-04, ahu: isolated as a component - */ -#ifndef ERROR_HPP_ -#define ERROR_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" - -// + standard includes -#include <string> -#include <iosfwd> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class definitions - - //! Helper structure defining an error message - struct ErrMsg { - //! Constructor - ErrMsg(int code, const char* message) - : code_(code), message_(message) - { - } - int code_; //!< Error code - const char* message_; //!< Error message - }; - - /*! - @brief Error class interface. Allows the definition and use of a hierarchy - of error classes which can all be handled in one catch block. - */ - class AnyError { - public: - //! @name Creators - //@{ - //! Virtual destructor. - virtual ~AnyError() - { - } - //@} - - //! @name Accessors - //@{ - //! Return the error code. - virtual int code() const =0; - /*! - @brief Return the error message. Consider using the output operator - operator<<(std::ostream &os, const AnyError& error) instead. - @note Unlike std::exception::what(), this function returns an - std::string. - */ - virtual std::string what() const =0; - }; // AnyError - - //! %AnyBase output operator - inline std::ostream& operator<<(std::ostream& os, const AnyError& error) - { - return os << error.what(); - } - - /*! - @brief Simple error class used for exceptions. An output operator is - provided to print errors to a stream. - */ - class Error : public AnyError { - public: - //! @name Creators - //@{ - //! Constructor taking only an error code - explicit Error(int code) - : code_(code), count_(0) - { - } - //! Constructor taking an error code and one argument - template<typename A> - Error(int code, const A& arg1) - : code_(code), count_(1), arg1_(toString(arg1)) - { - } - //! Constructor taking an error code and two arguments - template<typename A, typename B> - Error(int code, const A& arg1, const B& arg2) - : code_(code), count_(2), - arg1_(toString(arg1)), arg2_(toString(arg2)) - { - } - //! Constructor taking an error code and three arguments - template<typename A, typename B, typename C> - Error(int code, const A& arg1, const B& arg2, const C& arg3) - : code_(code), count_(3), - arg1_(toString(arg1)), arg2_(toString(arg2)), arg3_(toString(arg3)) - { - } - //@} - - //! @name Accessors - //@{ - virtual int code() const { return code_; } - virtual std::string what() const; - //@} - - private: - static int errorIdx(int code); - - // DATA - int code_; //!< Error code - int count_; //!< Number of arguments - std::string arg1_; //!< First argument - std::string arg2_; //!< Second argument - std::string arg3_; //!< Third argument - - static const ErrMsg errMsg_[]; //!< List of error messages - }; // class Error - -} // namespace Exiv2 - -#endif // #ifndef ERROR_HPP_ diff --git a/src/plugins/exiv2/exif.cpp b/src/plugins/exiv2/exif.cpp @@ -1,1237 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: exif.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 26-Jan-04, ahu: created - 11-Feb-04, ahu: isolated as a component - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: exif.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// Define DEBUG_MAKERNOTE to output debug information to std::cerr, e.g, by -// calling make like this: make DEFS=-DDEBUG_MAKERNOTE exif.o -//#define DEBUG_MAKERNOTE - -// ***************************************************************************** -// included header files -#ifdef _MSC_VER -# include "exv_msvc.h" -#else -# include "exv_conf.h" -#endif - -#include "exif.hpp" -#include "types.hpp" -#include "basicio.hpp" -#include "error.hpp" -#include "value.hpp" -#include "ifd.hpp" -#include "tags.hpp" -#include "jpgimage.hpp" -#include "makernote.hpp" -#include "futils.hpp" - -// + standard includes -#include <iostream> -#include <sstream> -#include <utility> -#include <algorithm> -#include <map> -#include <cstring> -#include <cassert> -#include <cstdio> -#include <sys/types.h> // for stat() -#include <sys/stat.h> // for stat() -#ifdef EXV_HAVE_UNISTD_H -# include <unistd.h> // for stat() -#endif - -// ***************************************************************************** -// local declarations -namespace { - - /* - Set the data of the entry identified by tag in ifd to an unsigned long - with the value of offset. If no entry with this tag exists in ifd, an - entry of type unsigned long with one component is created. - */ - void setOffsetTag(Exiv2::Ifd& ifd, - int idx, - uint16_t tag, - uint32_t offset, - Exiv2::ByteOrder byteOrder); - - // Read file path into a DataBuf, which is returned. - Exiv2::DataBuf readFile(const std::string& path); - -} - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - Exifdatum::Exifdatum(const Entry& e, ByteOrder byteOrder) - : key_(ExifKey::AutoPtr(new ExifKey(e))) - { - setValue(e, byteOrder); - } - - Exifdatum::Exifdatum(const ExifKey& key, const Value* pValue) - : key_(key.clone()) - { - if (pValue) value_ = pValue->clone(); - } - - Exifdatum::~Exifdatum() - { - } - - Exifdatum::Exifdatum(const Exifdatum& rhs) - : Metadatum(rhs) - { - if (rhs.key_.get() != 0) key_ = rhs.key_->clone(); // deep copy - if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy - } - - const Value& Exifdatum::value() const - { - if (value_.get() == 0) throw Error(8); - return *value_; - } - - Exifdatum& Exifdatum::operator=(const Exifdatum& rhs) - { - if (this == &rhs) return *this; - Metadatum::operator=(rhs); - - key_.reset(); - if (rhs.key_.get() != 0) key_ = rhs.key_->clone(); // deep copy - - value_.reset(); - if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy - - return *this; - } // Exifdatum::operator= - - Exifdatum& Exifdatum::operator=(const std::string& value) - { - setValue(value); - return *this; - } - - Exifdatum& Exifdatum::operator=(const uint16_t& value) - { - return Exiv2::setValue(*this, value); - } - - Exifdatum& Exifdatum::operator=(const uint32_t& value) - { - return Exiv2::setValue(*this, value); - } - - Exifdatum& Exifdatum::operator=(const URational& value) - { - return Exiv2::setValue(*this, value); - } - - Exifdatum& Exifdatum::operator=(const int16_t& value) - { - return Exiv2::setValue(*this, value); - } - - Exifdatum& Exifdatum::operator=(const int32_t& value) - { - return Exiv2::setValue(*this, value); - } - - Exifdatum& Exifdatum::operator=(const Rational& value) - { - return Exiv2::setValue(*this, value); - } - - Exifdatum& Exifdatum::operator=(const Value& value) - { - setValue(&value); - return *this; - } - - void Exifdatum::setValue(const Value* pValue) - { - value_.reset(); - if (pValue) value_ = pValue->clone(); - } - - void Exifdatum::setValue(const Entry& e, ByteOrder byteOrder) - { - value_ = Value::create(TypeId(e.type())); - value_->read(e.data(), e.count() * e.typeSize(), byteOrder); - value_->setDataArea(e.dataArea(), e.sizeDataArea()); - } - - void Exifdatum::setValue(const std::string& value) - { - if (value_.get() == 0) { - TypeId type = ExifTags::tagType(tag(), ifdId()); - value_ = Value::create(type); - } - value_->read(value); - } - - int TiffThumbnail::setDataArea(ExifData& exifData, Ifd* pIfd1, - const byte* buf, long len) const - { - // Create a DataBuf that can hold all strips - ExifData::const_iterator sizes; - ExifKey key("Exif.Thumbnail.StripByteCounts"); - sizes = exifData.findKey(key); - if (sizes == exifData.end()) return 2; - - long totalSize = 0; - for (long i = 0; i < sizes->count(); ++i) { - totalSize += sizes->toLong(i); - } - DataBuf stripsBuf(totalSize); - - // Copy all strips into the data buffer. For each strip remember its - // offset from the start of the data buffer - ExifData::iterator stripOffsets; - key = ExifKey("Exif.Thumbnail.StripOffsets"); - stripOffsets = exifData.findKey(key); - if (stripOffsets == exifData.end()) return 2; - if (stripOffsets->count() != sizes->count()) return 2; - - std::ostringstream os; // for the strip offsets - long currentOffset = 0; - long firstOffset = stripOffsets->toLong(0); - long lastOffset = 0; - long lastSize = 0; - for (long i = 0; i < stripOffsets->count(); ++i) { - long offset = stripOffsets->toLong(i); - lastOffset = offset; - long size = sizes->toLong(i); - lastSize = size; - if (len < offset + size) return 1; - - memcpy(stripsBuf.pData_ + currentOffset, buf + offset, size); - os << currentOffset << " "; - currentOffset += size; - } - - // Set StripOffsets data area and relative offsets - stripOffsets->setDataArea(stripsBuf.pData_, stripsBuf.size_); - stripOffsets->setValue(os.str()); - - // Set corresponding data area at IFD1, if it is a contiguous area - if (pIfd1 && firstOffset + totalSize == lastOffset + lastSize) { - Ifd::iterator pos = pIfd1->findTag(0x0111); - assert(pos != pIfd1->end()); - pos->setDataArea(buf + firstOffset, totalSize); - } - - return 0; - } // TiffThumbnail::read - - const char* TiffThumbnail::format() const - { - return "TIFF"; - } - - const char* TiffThumbnail::extension() const - { - return ".tif"; - } - - DataBuf TiffThumbnail::copy(const ExifData& exifData) const - { - // Create a TIFF header and IFD1 - TiffHeader tiffHeader(exifData.byteOrder()); - Ifd ifd1(ifd1Id); - - // Populate IFD (without Exif and GPS tags) from metadata - addToIfd(ifd1, exifData.begin(), exifData.end(), exifData.byteOrder()); - ifd1.erase(0x8769); - ifd1.erase(0x8825); - ifd1.sortByTag(); - - long size = tiffHeader.size() + ifd1.size() + ifd1.dataSize(); - DataBuf buf(size); - long len = tiffHeader.copy(buf.pData_); - len += ifd1.copy(buf.pData_ + len, exifData.byteOrder(), len); - assert(len == size); - return buf; - } - - int JpegThumbnail::setDataArea(ExifData& exifData, Ifd* pIfd1, - const byte* buf, long len) const - { - ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat"); - ExifData::iterator format = exifData.findKey(key); - if (format == exifData.end()) return 1; - long offset = format->toLong(); - key = ExifKey("Exif.Thumbnail.JPEGInterchangeFormatLength"); - ExifData::const_iterator length = exifData.findKey(key); - if (length == exifData.end()) return 1; - long size = length->toLong(); - if (len < offset + size) return 2; - format->setDataArea(buf + offset, size); - format->setValue("0"); - if (pIfd1) { - Ifd::iterator pos = pIfd1->findTag(0x0201); - assert(pos != pIfd1->end()); - pos->setDataArea(buf + offset, size); - } - return 0; - } // JpegThumbnail::setDataArea - - const char* JpegThumbnail::format() const - { - return "JPEG"; - } - - const char* JpegThumbnail::extension() const - { - return ".jpg"; - } - - DataBuf JpegThumbnail::copy(const ExifData& exifData) const - { - ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat"); - ExifData::const_iterator format = exifData.findKey(key); - if (format == exifData.end()) return DataBuf(); - return format->dataArea(); - } - - ExifData::ExifData() - : pTiffHeader_(0), - pIfd0_(0), pExifIfd_(0), pIopIfd_(0), pGpsIfd_(0), pIfd1_(0), - pMakerNote_(0), size_(0), pData_(0), compatible_(true) - { - } - - ExifData::ExifData(const ExifData& rhs) - : exifMetadata_(rhs.exifMetadata_), pTiffHeader_(0), - pIfd0_(0), pExifIfd_(0), pIopIfd_(0), pGpsIfd_(0), pIfd1_(0), - pMakerNote_(0), size_(0), pData_(0), compatible_(rhs.compatible_) - { - pData_ = new byte[rhs.size_]; - size_ = rhs.size_; - memcpy(pData_, rhs.pData_, rhs.size_); - - if (rhs.pTiffHeader_) { - pTiffHeader_ = new TiffHeader(*rhs.pTiffHeader_); - } - if (rhs.pIfd0_) { - pIfd0_ = new Ifd(*rhs.pIfd0_); - pIfd0_->updateBase(pData_); - } - if (rhs.pExifIfd_) { - pExifIfd_ = new Ifd(*rhs.pExifIfd_); - pExifIfd_->updateBase(pData_); - } - if (rhs.pIopIfd_) { - pIopIfd_ = new Ifd(*rhs.pIopIfd_); - pIopIfd_->updateBase(pData_); - } - if (rhs.pGpsIfd_) { - pGpsIfd_ = new Ifd(*rhs.pGpsIfd_); - pGpsIfd_->updateBase(pData_); - } - if (rhs.pIfd1_) { - pIfd1_ = new Ifd(*rhs.pIfd1_); - pIfd1_->updateBase(pData_); - } - if (rhs.pMakerNote_) { - pMakerNote_ = rhs.pMakerNote_->clone().release(); - pMakerNote_->updateBase(pData_); - } - } - - ExifData::~ExifData() - { - delete pTiffHeader_; - delete pIfd0_; - delete pExifIfd_; - delete pIopIfd_; - delete pGpsIfd_; - delete pIfd1_; - delete pMakerNote_; - delete[] pData_; - } - - ExifData& ExifData::operator=(const ExifData& rhs) - { - if (this == &rhs) return *this; - - exifMetadata_ = rhs.exifMetadata_; - - size_ = 0; - delete[] pData_; - pData_ = new byte[rhs.size_]; - size_ = rhs.size_; - memcpy(pData_, rhs.pData_, rhs.size_); - - delete pTiffHeader_; - pTiffHeader_ = 0; - if (rhs.pTiffHeader_) { - pTiffHeader_ = new TiffHeader(*rhs.pTiffHeader_); - } - delete pIfd0_; - pIfd0_ = 0; - if (rhs.pIfd0_) { - pIfd0_ = new Ifd(*rhs.pIfd0_); - pIfd0_->updateBase(pData_); - } - delete pExifIfd_; - pExifIfd_ = 0; - if (rhs.pExifIfd_) { - pExifIfd_ = new Ifd(*rhs.pExifIfd_); - pExifIfd_->updateBase(pData_); - } - delete pIopIfd_; - pIopIfd_ = 0; - if (rhs.pIopIfd_) { - pIopIfd_ = new Ifd(*rhs.pIopIfd_); - pIopIfd_->updateBase(pData_); - } - delete pGpsIfd_; - pGpsIfd_ = 0; - if (rhs.pGpsIfd_) { - pGpsIfd_ = new Ifd(*rhs.pGpsIfd_); - pGpsIfd_->updateBase(pData_); - } - delete pIfd1_; - pIfd1_ = 0; - if (rhs.pIfd1_) { - pIfd1_ = new Ifd(*rhs.pIfd1_); - pIfd1_->updateBase(pData_); - } - delete pMakerNote_; - pMakerNote_ = 0; - if (rhs.pMakerNote_) { - pMakerNote_ = rhs.pMakerNote_->clone().release(); - pMakerNote_->updateBase(pData_); - } - - compatible_ = rhs.compatible_; - return *this; - } - - Exifdatum& ExifData::operator[](const std::string& key) - { - ExifKey exifKey(key); - iterator pos = findKey(exifKey); - if (pos == end()) { - add(Exifdatum(exifKey)); - pos = findKey(exifKey); - } - return *pos; - } - - int ExifData::load(const byte* buf, long len) - { - // Copy the data buffer - delete[] pData_; - pData_ = new byte[len]; - memcpy(pData_, buf, len); - size_ = len; - - // Read the TIFF header - delete pTiffHeader_; - pTiffHeader_ = new TiffHeader; - assert(pTiffHeader_ != 0); - int rc = pTiffHeader_->read(pData_); - if (rc) return rc; - - // Read IFD0 - delete pIfd0_; - pIfd0_ = new Ifd(ifd0Id, 0, false); - assert(pIfd0_ != 0); - rc = pIfd0_->read(pData_ + pTiffHeader_->offset(), - size_ - pTiffHeader_->offset(), - byteOrder(), - pTiffHeader_->offset()); - if (rc) return rc; - - delete pExifIfd_; - pExifIfd_ = new Ifd(exifIfdId, 0, false); - assert(pExifIfd_ != 0); - // Find and read ExifIFD sub-IFD of IFD0 - rc = pIfd0_->readSubIfd(*pExifIfd_, pData_, size_, byteOrder(), 0x8769); - if (rc) return rc; - // Find MakerNote in ExifIFD, create a MakerNote class - Ifd::iterator pos = pExifIfd_->findTag(0x927c); - Ifd::iterator make = pIfd0_->findTag(0x010f); - Ifd::iterator model = pIfd0_->findTag(0x0110); - if ( pos != pExifIfd_->end() - && make != pIfd0_->end() && model != pIfd0_->end()) { - // Todo: The conversion to string assumes that there is a \0 at the end - // Todo: How to avoid the cast (is that a MSVC thing?) - pMakerNote_ = MakerNoteFactory::create( - reinterpret_cast<const char*>(make->data()), - reinterpret_cast<const char*>(model->data()), - false, - pos->data(), - pos->size(), - byteOrder(), - pExifIfd_->offset() + pos->offset()).release(); - } - // Read the MakerNote - if (pMakerNote_) { - rc = pMakerNote_->read(pos->data(), - pos->size(), - byteOrder(), - pExifIfd_->offset() + pos->offset()); - if (rc) { -#ifndef SUPPRESS_WARNINGS - std::cerr << "Warning: Failed to read Makernote, rc = " - << rc << "\n"; -#endif - delete pMakerNote_; - pMakerNote_ = 0; - } - } - // If we successfully parsed the MakerNote, delete the raw MakerNote, - // the parsed MakerNote is the primary MakerNote from now on - if (pMakerNote_) { - pExifIfd_->erase(pos); - } - - delete pIopIfd_; - pIopIfd_ = new Ifd(iopIfdId, 0, false); - assert(pIopIfd_ != 0); - // Find and read Interoperability IFD in ExifIFD - rc = pExifIfd_->readSubIfd(*pIopIfd_, pData_, size_, byteOrder(), 0xa005); - if (rc) return rc; - - delete pGpsIfd_; - pGpsIfd_ = new Ifd(gpsIfdId, 0, false); - assert(pGpsIfd_ != 0); - // Find and read GPSInfo sub-IFD in IFD0 - rc = pIfd0_->readSubIfd(*pGpsIfd_, pData_, size_, byteOrder(), 0x8825); - if (rc) return rc; - - delete pIfd1_; - pIfd1_ = new Ifd(ifd1Id, 0, false); - assert(pIfd1_ != 0); - // Read IFD1 - if (pIfd0_->next()) { - rc = pIfd1_->read(pData_ + pIfd0_->next(), - size_ - pIfd0_->next(), - byteOrder(), - pIfd0_->next()); - if (rc) return rc; - } - // Find and delete ExifIFD sub-IFD of IFD1 - pos = pIfd1_->findTag(0x8769); - if (pos != pIfd1_->end()) { - pIfd1_->erase(pos); - rc = 7; - } - // Find and delete GPSInfo sub-IFD in IFD1 - pos = pIfd1_->findTag(0x8825); - if (pos != pIfd1_->end()) { - pIfd1_->erase(pos); - rc = 7; - } - // Copy all entries from the IFDs and the MakerNote to the metadata - exifMetadata_.clear(); - add(pIfd0_->begin(), pIfd0_->end(), byteOrder()); - add(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); - if (pMakerNote_) { - add(pMakerNote_->begin(), pMakerNote_->end(), - (pMakerNote_->byteOrder() == invalidByteOrder ? - byteOrder() : pMakerNote_->byteOrder())); - } - add(pIopIfd_->begin(), pIopIfd_->end(), byteOrder()); - add(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder()); - add(pIfd1_->begin(), pIfd1_->end(), byteOrder()); - // Read the thumbnail (but don't worry whether it was successful or not) - readThumbnail(); - - return rc; - } // ExifData::load - - - DataBuf ExifData::copy() - { - DataBuf buf; - // If we can update the internal IFDs and the underlying data buffer - // from the metadata without changing the data size, then it is enough - // to copy the data buffer. - if (compatible_ && updateEntries()) { -#ifdef DEBUG_MAKERNOTE - std::cerr << "->>>>>> using non-intrusive writing <<<<<<-\n"; -#endif - buf.alloc(size_); - memcpy(buf.pData_, pData_, size_); - } - // Else we have to do it the hard way... - else { -#ifdef DEBUG_MAKERNOTE - std::cerr << "->>>>>> writing from metadata <<<<<<-\n"; -#endif - buf = copyFromMetadata(); - } - return buf; - } - - DataBuf ExifData::copyFromMetadata() - { - // Build IFD0 - Ifd ifd0(ifd0Id); - addToIfd(ifd0, begin(), end(), byteOrder()); - - // Build Exif IFD from metadata - Ifd exifIfd(exifIfdId); - addToIfd(exifIfd, begin(), end(), byteOrder()); - MakerNote::AutoPtr makerNote; - if (pMakerNote_) { - // Build MakerNote from metadata - makerNote = pMakerNote_->create(); - addToMakerNote(makerNote.get(), - begin(), end(), - (pMakerNote_->byteOrder() == invalidByteOrder ? - byteOrder() : pMakerNote_->byteOrder())); - // Create a placeholder MakerNote entry of the correct size and - // add it to the Exif IFD (because we don't know the offset yet) - Entry e; - e.setIfdId(exifIfd.ifdId()); - e.setTag(0x927c); - DataBuf tmpBuf(makerNote->size()); - memset(tmpBuf.pData_, 0x0, tmpBuf.size_); - e.setValue(undefined, tmpBuf.size_, tmpBuf.pData_, tmpBuf.size_); - exifIfd.erase(0x927c); - exifIfd.add(e); - } - - // Build Interoperability IFD from metadata - Ifd iopIfd(iopIfdId); - addToIfd(iopIfd, begin(), end(), byteOrder()); - - // Build GPSInfo IFD from metadata - Ifd gpsIfd(gpsIfdId); - addToIfd(gpsIfd, begin(), end(), byteOrder()); - - // build IFD1 from metadata - Ifd ifd1(ifd1Id); - addToIfd(ifd1, begin(), end(), byteOrder()); - // Set a temporary dummy offset in IFD0 - if (ifd1.size() > 0) { - ifd0.setNext(1, byteOrder()); - } - - // Compute the new IFD offsets - int exifIdx = ifd0.erase(0x8769); - int gpsIdx = ifd0.erase(0x8825); - int iopIdx = exifIfd.erase(0xa005); - - TiffHeader tiffHeader(byteOrder()); - long ifd0Offset = tiffHeader.size(); - bool addOffsetTag = false; - long exifIfdOffset = ifd0Offset + ifd0.size() + ifd0.dataSize(); - if (exifIfd.size() > 0 || iopIfd.size() > 0) { - exifIfdOffset += 12; - addOffsetTag = true; - } - if (gpsIfd.size() > 0) { - exifIfdOffset += 12; - addOffsetTag = true; - } - if (ifd0.size() == 0 && addOffsetTag) { - exifIfdOffset += 6; - } - addOffsetTag = false; - long iopIfdOffset = exifIfdOffset + exifIfd.size() + exifIfd.dataSize(); - if (iopIfd.size() > 0) { - iopIfdOffset += 12; - addOffsetTag = true; - } - if (exifIfd.size() == 0 && addOffsetTag) { - iopIfdOffset += 6; - } - long gpsIfdOffset = iopIfdOffset + iopIfd.size() + iopIfd.dataSize(); - long ifd1Offset = gpsIfdOffset + gpsIfd.size() + gpsIfd.dataSize(); - - // Set the offset to IFD1 in IFD0 - if (ifd1.size() > 0) { - ifd0.setNext(ifd1Offset, byteOrder()); - } - - // Set the offset to the Exif IFD in IFD0 - if (exifIfd.size() > 0 || iopIfd.size() > 0) { - setOffsetTag(ifd0, exifIdx, 0x8769, exifIfdOffset, byteOrder()); - } - // Set the offset to the GPSInfo IFD in IFD0 - if (gpsIfd.size() > 0) { - setOffsetTag(ifd0, gpsIdx, 0x8825, gpsIfdOffset, byteOrder()); - } - // Set the offset to the Interoperability IFD in Exif IFD - if (iopIfd.size() > 0) { - setOffsetTag(exifIfd, iopIdx, 0xa005, iopIfdOffset, byteOrder()); - } - - // Allocate a data buffer big enough for all metadata - long size = tiffHeader.size(); - size += ifd0.size() + ifd0.dataSize(); - size += exifIfd.size() + exifIfd.dataSize(); - size += iopIfd.size() + iopIfd.dataSize(); - size += gpsIfd.size() + gpsIfd.dataSize(); - size += ifd1.size() + ifd1.dataSize(); - DataBuf buf(size); - - // Copy the TIFF header, all IFDs, MakerNote and thumbnail to the buffer - size = tiffHeader.copy(buf.pData_); - ifd0.sortByTag(); - size += ifd0.copy(buf.pData_ + ifd0Offset, byteOrder(), ifd0Offset); - exifIfd.sortByTag(); - size += exifIfd.copy(buf.pData_ + exifIfdOffset, byteOrder(), exifIfdOffset); - if (makerNote.get() != 0) { - // Copy the MakerNote over the placeholder data - Entries::iterator mn = exifIfd.findTag(0x927c); - // Do _not_ sort the makernote; vendors (at least Canon), don't seem - // to bother about this TIFF standard requirement, so writing the - // makernote as is might result in fewer deviations from the original - makerNote->copy(buf.pData_ + exifIfdOffset + mn->offset(), - byteOrder(), - exifIfdOffset + mn->offset()); - } - iopIfd.sortByTag(); - size += iopIfd.copy(buf.pData_ + iopIfdOffset, byteOrder(), iopIfdOffset); - gpsIfd.sortByTag(); - size += gpsIfd.copy(buf.pData_ + gpsIfdOffset, byteOrder(), gpsIfdOffset); - ifd1.sortByTag(); - size += ifd1.copy(buf.pData_ + ifd1Offset, byteOrder(), ifd1Offset); - assert(size == buf.size_); - return buf; - } // ExifData::copyFromMetadata - - void ExifData::add(Entries::const_iterator begin, - Entries::const_iterator end, - ByteOrder byteOrder) - { - Entries::const_iterator i = begin; - for (; i != end; ++i) { - add(Exifdatum(*i, byteOrder)); - } - } - - void ExifData::add(const ExifKey& key, const Value* pValue) - { - add(Exifdatum(key, pValue)); - } - - void ExifData::add(const Exifdatum& exifdatum) - { - if (ExifTags::isMakerIfd(exifdatum.ifdId())) { - if (pMakerNote_ == 0) { - pMakerNote_ = MakerNoteFactory::create(exifdatum.ifdId()).release(); - } - if (pMakerNote_ == 0) throw Error(23, exifdatum.ifdId()); - } - // allow duplicates - exifMetadata_.push_back(exifdatum); - } - - ExifData::const_iterator ExifData::findKey(const ExifKey& key) const - { - return std::find_if(exifMetadata_.begin(), exifMetadata_.end(), - FindMetadatumByKey(key.key())); - } - - ExifData::iterator ExifData::findKey(const ExifKey& key) - { - return std::find_if(exifMetadata_.begin(), exifMetadata_.end(), - FindMetadatumByKey(key.key())); - } - - ExifData::const_iterator ExifData::findIfdIdIdx(IfdId ifdId, int idx) const - { - return std::find_if(exifMetadata_.begin(), exifMetadata_.end(), - FindMetadatumByIfdIdIdx(ifdId, idx)); - } - - ExifData::iterator ExifData::findIfdIdIdx(IfdId ifdId, int idx) - { - return std::find_if(exifMetadata_.begin(), exifMetadata_.end(), - FindMetadatumByIfdIdIdx(ifdId, idx)); - } - - void ExifData::sortByKey() - { - std::sort(exifMetadata_.begin(), exifMetadata_.end(), cmpMetadataByKey); - } - - void ExifData::sortByTag() - { - std::sort(exifMetadata_.begin(), exifMetadata_.end(), cmpMetadataByTag); - } - - ExifData::iterator ExifData::erase(ExifData::iterator pos) - { - return exifMetadata_.erase(pos); - } - - void ExifData::setJpegThumbnail(const byte* buf, long size) - { - (*this)["Exif.Thumbnail.Compression"] = uint16_t(6); - Exifdatum& format = (*this)["Exif.Thumbnail.JPEGInterchangeFormat"]; - format = uint32_t(0); - format.setDataArea(buf, size); - (*this)["Exif.Thumbnail.JPEGInterchangeFormatLength"] = uint32_t(size); - } - - void ExifData::setJpegThumbnail(const byte* buf, long size, - URational xres, URational yres, uint16_t unit) - { - setJpegThumbnail(buf, size); - (*this)["Exif.Thumbnail.XResolution"] = xres; - (*this)["Exif.Thumbnail.YResolution"] = yres; - (*this)["Exif.Thumbnail.ResolutionUnit"] = unit; - } - - void ExifData::setJpegThumbnail(const std::string& path) - { - DataBuf thumb = readFile(path); // may throw - setJpegThumbnail(thumb.pData_, thumb.size_); - } - - void ExifData::setJpegThumbnail(const std::string& path, - URational xres, URational yres, uint16_t unit) - { - DataBuf thumb = readFile(path); // may throw - setJpegThumbnail(thumb.pData_, thumb.size_, xres, yres, unit); - } - - long ExifData::eraseThumbnail() - { - // First, determine if the thumbnail is at the end of the Exif data - bool stp = stdThumbPosition(); - // Delete all Exif.Thumbnail.* (IFD1) metadata - ExifMetadata::iterator i = begin(); - while (i != end()) { - if (i->ifdId() == ifd1Id) { - i = erase(i); - } - else { - ++i; - } - } - long delta = 0; - if (stp) { - delta = size_; - if (size_ > 0 && pIfd0_ && pIfd0_->next() > 0) { - // Truncate IFD1 and thumbnail data from the data buffer - size_ = pIfd0_->next(); - pIfd0_->setNext(0, byteOrder()); - if (pIfd1_) pIfd1_->clear(); - } - delta -= size_; - } - else { - // We will have to write the hard way and re-arrange the data - compatible_ = false; - if (pIfd1_) delta = pIfd1_->size() + pIfd1_->dataSize(); - } - return delta; - } // ExifData::eraseThumbnail - - bool ExifData::stdThumbPosition() const - { - if ( pIfd0_ == 0 || pExifIfd_ == 0 || pIopIfd_ == 0 - || pGpsIfd_ == 0 || pIfd1_ == 0) return true; - - // Todo: There is still an invalid assumption here: The data of an IFD - // can be stored in multiple non-contiguous blocks. In this case, - // dataOffset + dataSize does not point to the end of the IFD data. - // in particular, this is potentially the case for the remaining Exif - // data in the presence of a known Makernote. - bool rc = true; - Thumbnail::AutoPtr thumbnail = getThumbnail(); - if (thumbnail.get()) { - long maxOffset; - maxOffset = std::max(pIfd0_->offset(), pIfd0_->dataOffset()); - maxOffset = std::max(maxOffset, pExifIfd_->offset()); - maxOffset = std::max(maxOffset, pExifIfd_->dataOffset() - + pExifIfd_->dataSize()); - if (pMakerNote_) { - maxOffset = std::max(maxOffset, pMakerNote_->offset() - + pMakerNote_->size()); - } - maxOffset = std::max(maxOffset, pIopIfd_->offset()); - maxOffset = std::max(maxOffset, pIopIfd_->dataOffset() - + pIopIfd_->dataSize()); - maxOffset = std::max(maxOffset, pGpsIfd_->offset()); - maxOffset = std::max(maxOffset, pGpsIfd_->dataOffset() - + pGpsIfd_->dataSize()); - - if ( maxOffset > pIfd1_->offset() - || maxOffset > pIfd1_->dataOffset() && pIfd1_->dataOffset() > 0) - rc = false; - /* - Todo: Removed condition from the above if(). Should be re-added... - || maxOffset > pThumbnail_->offset() - */ - } - return rc; - } // ExifData::stdThumbPosition - - ByteOrder ExifData::byteOrder() const - { - if (pTiffHeader_) return pTiffHeader_->byteOrder(); - return littleEndian; - } - - int ExifData::writeThumbnail(const std::string& path) const - { - Thumbnail::AutoPtr thumbnail = getThumbnail(); - if (thumbnail.get() == 0) return 8; - - std::string name = path + thumbnail->extension(); - FileIo file(name); - if (file.open("wb") != 0) { - throw Error(10, name, "wb", strError()); - } - - DataBuf buf(thumbnail->copy(*this)); - if (file.write(buf.pData_, buf.size_) != buf.size_) { - throw Error(2, name, strError(), "FileIo::write"); - } - - return 0; - } // ExifData::writeThumbnail - - DataBuf ExifData::copyThumbnail() const - { - Thumbnail::AutoPtr thumbnail = getThumbnail(); - if (thumbnail.get() == 0) return DataBuf(); - return thumbnail->copy(*this); - } - - const char* ExifData::thumbnailFormat() const - { - Thumbnail::AutoPtr thumbnail = getThumbnail(); - if (thumbnail.get() == 0) return ""; - return thumbnail->format(); - } - - const char* ExifData::thumbnailExtension() const - { - Thumbnail::AutoPtr thumbnail = getThumbnail(); - if (thumbnail.get() == 0) return ""; - return thumbnail->extension(); - } - - Thumbnail::AutoPtr ExifData::getThumbnail() const - { - Thumbnail::AutoPtr thumbnail; - const_iterator pos = findKey(ExifKey("Exif.Thumbnail.Compression")); - if (pos != end()) { - long compression = pos->toLong(); - if (compression == 6) { - thumbnail = Thumbnail::AutoPtr(new JpegThumbnail); - } - else { - thumbnail = Thumbnail::AutoPtr(new TiffThumbnail); - } - } - return thumbnail; - - } // ExifData::getThumbnail - - int ExifData::readThumbnail() - { - int rc = -1; - Thumbnail::AutoPtr thumbnail = getThumbnail(); - if (thumbnail.get() != 0) { - rc = thumbnail->setDataArea(*this, pIfd1_, pData_, size_); - } - return rc; - - } // ExifData::readThumbnail - - bool ExifData::updateEntries() - { - if ( pIfd0_ == 0 || pExifIfd_ == 0 || pIopIfd_ == 0 - || pGpsIfd_ == 0 || pIfd1_ == 0) return false; - if (!this->compatible()) return false; - - bool compatible = true; - compatible &= updateRange(pIfd0_->begin(), pIfd0_->end(), byteOrder()); - compatible &= updateRange(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); - if (pMakerNote_) { - compatible &= updateRange(pMakerNote_->begin(), - pMakerNote_->end(), - (pMakerNote_->byteOrder() == invalidByteOrder ? - byteOrder() : pMakerNote_->byteOrder())); - } - compatible &= updateRange(pIopIfd_->begin(), pIopIfd_->end(), byteOrder()); - compatible &= updateRange(pGpsIfd_->begin(), pGpsIfd_->end(), byteOrder()); - compatible &= updateRange(pIfd1_->begin(), pIfd1_->end(), byteOrder()); - - return compatible; - } // ExifData::updateEntries - - bool ExifData::updateRange(const Entries::iterator& begin, - const Entries::iterator& end, - ByteOrder byteOrder) - { - bool compatible = true; - for (Entries::iterator entry = begin; entry != end; ++entry) { - // find the corresponding Exifdatum - const_iterator md = findIfdIdIdx(entry->ifdId(), entry->idx()); - if (md == this->end()) { - // corresponding Exifdatum was deleted: this is not (yet) a - // supported non-intrusive write operation. - compatible = false; - continue; - } - if (entry->count() == 0 && md->count() == 0) { - // Special case: don't do anything if both the entry and - // Exifdatum have no data. This is to preserve the original - // data in the offset field of an IFD entry with count 0, - // if the Exifdatum was not changed. - } - else if ( entry->size() < md->size() - || entry->sizeDataArea() < md->sizeDataArea()) { - compatible = false; - continue; - } - else { - // Hack: Set the entry's value only if there is no data area. - // This ensures that the original offsets are not overwritten - // with relative offsets from the Exifdatum (which require - // conversion to offsets relative to the start of the TIFF - // header and that is currently only done in intrusive write - // mode). On the other hand, it is thus now not possible to - // change the offsets of an entry with a data area in - // non-intrusive mode. This can be considered a bug. - // Todo: Fix me! - if (md->sizeDataArea() == 0) { - DataBuf buf(md->size()); - md->copy(buf.pData_, byteOrder); - entry->setValue(static_cast<uint16_t>(md->typeId()), - md->count(), - buf.pData_, md->size()); - } - // Always set the data area - DataBuf dataArea(md->dataArea()); - entry->setDataArea(dataArea.pData_, dataArea.size_); - } - } - return compatible; - } // ExifData::updateRange - - bool ExifData::compatible() const - { - bool compatible = true; - // For each Exifdatum, check if it is compatible with the corresponding - // IFD or MakerNote entry - for (const_iterator md = begin(); md != this->end(); ++md) { - std::pair<bool, Entries::const_iterator> rc; - rc = findEntry(md->ifdId(), md->idx()); - // Make sure that we have an entry - if (!rc.first) { - compatible = false; - break; - } - // Make sure that the size of the Exifdatum fits the available size - // of the entry - if ( md->size() > rc.second->size() - || md->sizeDataArea() > rc.second->sizeDataArea()) { - compatible = false; - break; - } - } - return compatible; - } // ExifData::compatible - - std::pair<bool, Entries::const_iterator> - ExifData::findEntry(IfdId ifdId, int idx) const - { - Entries::const_iterator entry; - std::pair<bool, Entries::const_iterator> rc(false, entry); - - if (ExifTags::isMakerIfd(ifdId) && pMakerNote_) { - entry = pMakerNote_->findIdx(idx); - if (entry != pMakerNote_->end()) { - rc.first = true; - rc.second = entry; - } - return rc; - } - const Ifd* ifd = getIfd(ifdId); - if (ifd && isExifIfd(ifdId)) { - entry = ifd->findIdx(idx); - if (entry != ifd->end()) { - rc.first = true; - rc.second = entry; - } - } - return rc; - } // ExifData::findEntry - - const Ifd* ExifData::getIfd(IfdId ifdId) const - { - const Ifd* ifd = 0; - switch (ifdId) { - case ifd0Id: - ifd = pIfd0_; - break; - case exifIfdId: - ifd = pExifIfd_; - break; - case iopIfdId: - ifd = pIopIfd_; - break; - case gpsIfdId: - ifd = pGpsIfd_; - break; - case ifd1Id: - ifd = pIfd1_; - break; - default: - ifd = 0; - break; - } - return ifd; - } // ExifData::getIfd - - // ************************************************************************* - // free functions - - void addToIfd(Ifd& ifd, - ExifMetadata::const_iterator begin, - ExifMetadata::const_iterator end, - ByteOrder byteOrder) - { - for (ExifMetadata::const_iterator i = begin; i != end; ++i) { - // add only metadata with matching IFD id - if (i->ifdId() == ifd.ifdId()) { - addToIfd(ifd, *i, byteOrder); - } - } - } // addToIfd - - void addToIfd(Ifd& ifd, const Exifdatum& md, ByteOrder byteOrder) - { - assert(ifd.alloc()); - - Entry e; - e.setIfdId(md.ifdId()); - e.setIdx(md.idx()); - e.setTag(md.tag()); - e.setOffset(0); // will be calculated when the IFD is written - - DataBuf buf(md.size()); - md.copy(buf.pData_, byteOrder); - e.setValue(static_cast<uint16_t>(md.typeId()), md.count(), - buf.pData_, buf.size_); - - DataBuf dataArea(md.dataArea()); - e.setDataArea(dataArea.pData_, dataArea.size_); - - ifd.add(e); - } // addToIfd - - void addToMakerNote(MakerNote* makerNote, - ExifMetadata::const_iterator begin, - ExifMetadata::const_iterator end, - ByteOrder byteOrder) - { - for (ExifMetadata::const_iterator i = begin; i != end; ++i) { - if (ExifTags::isMakerIfd(i->ifdId())) { - addToMakerNote(makerNote, *i, byteOrder); - } - } - } // addToMakerNote - - void addToMakerNote(MakerNote* makerNote, - const Exifdatum& md, - ByteOrder byteOrder) - { - Entry e; - e.setIfdId(md.ifdId()); - e.setIdx(md.idx()); - e.setTag(md.tag()); - e.setOffset(0); // will be calculated when the makernote is written - - DataBuf buf(md.size()); - md.copy(buf.pData_, byteOrder); - e.setValue(static_cast<uint16_t>(md.typeId()), md.count(), - buf.pData_, md.size()); - - DataBuf dataArea(md.dataArea()); - e.setDataArea(dataArea.pData_, dataArea.size_); - - makerNote->add(e); - } // addToMakerNote - - std::ostream& operator<<(std::ostream& os, const Exifdatum& md) - { - return ExifTags::printTag(os, md.tag(), md.ifdId(), md.value()); - } -} // namespace Exiv2 - -// ***************************************************************************** -// local definitions -namespace { - - void setOffsetTag(Exiv2::Ifd& ifd, - int idx, - uint16_t tag, - uint32_t offset, - Exiv2::ByteOrder byteOrder) - { - Exiv2::Ifd::iterator pos = ifd.findTag(tag); - if (pos == ifd.end()) { - Exiv2::Entry e(ifd.alloc()); - e.setIfdId(ifd.ifdId()); - e.setIdx(idx); - e.setTag(tag); - e.setOffset(0); // will be calculated when the IFD is written - ifd.add(e); - pos = ifd.findTag(tag); - } - pos->setValue(offset, byteOrder); - } - - Exiv2::DataBuf readFile(const std::string& path) - { - Exiv2::FileIo file(path); - if (file.open("rb") != 0) { - throw Exiv2::Error(10, path, "rb", Exiv2::strError()); - } - struct stat st; - if (0 != stat(path.c_str(), &st)) { - throw Exiv2::Error(2, path, Exiv2::strError(), "::stat"); - } - Exiv2::DataBuf buf(st.st_size); - long len = file.read(buf.pData_, buf.size_); - if (len != buf.size_) { - throw Exiv2::Error(2, path, Exiv2::strError(), "FileIo::read"); - } - return buf; - } - -} diff --git a/src/plugins/exiv2/exif.hpp b/src/plugins/exiv2/exif.hpp @@ -1,908 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 exif.hpp - @brief Encoding and decoding of Exif data - @version $Rev: 599 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 09-Jan-04, ahu: created - */ -#ifndef EXIF_HPP_ -#define EXIF_HPP_ - -// ***************************************************************************** -// included header files -#include "metadatum.hpp" -#include "types.hpp" -#include "error.hpp" -#include "value.hpp" -#include "ifd.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <vector> -#include <memory> - -// ***************************************************************************** -// namespace extensions -/*! - @brief Provides classes and functions to encode and decode Exif and Iptc data. - This namespace corresponds to the <b>libexiv2</b> library. - - */ -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class ExifData; - class MakerNote; - class TiffHeader; - -// ***************************************************************************** -// class definitions - - /*! - @brief Information related to one Exif tag. An Exif metadatum consists of - an ExifKey and a Value and provides methods to manipulate these. - */ - class Exifdatum : public Metadatum { - friend std::ostream& operator<<(std::ostream&, const Exifdatum&); - template<typename T> friend Exifdatum& setValue(Exifdatum&, const T&); - public: - //! @name Creators - //@{ - /*! - @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); - //! Constructor to build an %Exifdatum from an IFD entry. - Exifdatum(const Entry& e, ByteOrder byteOrder); - //! Copy constructor - Exifdatum(const Exifdatum& rhs); - //! Destructor - virtual ~Exifdatum(); - //@} - - //! @name Manipulators - //@{ - //! 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); - /*! - @brief Set the value. This method copies (clones) the value pointed - to by \em pValue. - */ - 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 value from an IFD entry. - */ - void setValue(const Entry& e, ByteOrder byteOrder); - /*! - @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(); } - //! Return the name of the group (the second part of the key) - std::string groupName() const - { return key_.get() == 0 ? "" : key_->groupName(); } - //! Return the name of the tag (which is also the third part of the key) - std::string tagName() const - { return key_.get() == 0 ? "" : key_->tagName(); } - //! Return the tag - 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); } - //! 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(); } - /*! - @brief Return the <EM>n</EM>-th component of the value converted to - long. The return value is -1 if the value of the Exifdatum is - not set and the behaviour of the method is undefined if there - is no n-th component. - */ - long toLong(long n =0) const - { return value_.get() == 0 ? -1 : value_->toLong(n); } - /*! - @brief Return the <EM>n</EM>-th component of the value converted to - float. The return value is -1 if the value of the Exifdatum is - not set and the behaviour of the method is undefined if there - is no n-th component. - */ - float toFloat(long n =0) const - { return value_.get() == 0 ? -1 : value_->toFloat(n); } - /*! - @brief Return the <EM>n</EM>-th component of the value converted to - Rational. The return value is -1/1 if the value of the - Exifdatum is not set and the behaviour of the method is - undefined if there is no n-th component. - */ - Rational toRational(long n =0) const - { return value_.get() == 0 ? Rational(-1, 1) : value_->toRational(n); } - /*! - @brief Return an auto-pointer to a copy (clone) of the value. The - caller owns this copy and the auto-pointer ensures that it will - be deleted. - - This method is provided for users who need full control over the - value. A caller may, e.g., downcast the pointer to the appropriate - subclass of Value to make use of the interface of the subclass to set - or modify its contents. - - @return An auto-pointer to a copy (clone) of the value, 0 if the value - is not set. - */ - Value::AutoPtr getValue() const - { return value_.get() == 0 ? Value::AutoPtr(0) : value_->clone(); } - /*! - @brief Return a constant reference to the value. - - This method is provided mostly for convenient and versatile output of - the value which can (to some extent) be formatted through standard - stream manipulators. Do not attempt to write to the value through - this reference. - - <b>Example:</b> <br> - @code - ExifData::const_iterator i = exifData.findKey(key); - if (i != exifData.end()) { - std::cout << i->key() << " " << std::hex << i->value() << "\n"; - } - @endcode - - @return A constant reference to the value. - @throw Error if the value is not set. - */ - 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(); } - - //@} - - private: - // DATA - ExifKey::AutoPtr key_; //!< Key - Value::AutoPtr value_; //!< Value - - }; // class Exifdatum - - /*! - @brief Output operator for Exifdatum types, prints the interpreted - tag value. - */ - std::ostream& operator<<(std::ostream& os, const Exifdatum& md); - - /*! - @brief Set the value of \em exifDatum to \em value. If the object already - has a value, it is replaced. Otherwise a new ValueType\<T\> value - is created and set to \em value. - - This is a helper function, called from Exifdatum members. It is meant to - be used with T = (u)int16_t, (u)int32_t or (U)Rational. Do not use directly. - */ - template<typename T> - Exifdatum& setValue(Exifdatum& exifDatum, const T& value); - - /*! - @brief Exif %Thumbnail image. This abstract base class provides the - interface for the thumbnail image that is optionally embedded in - the Exif data. This class is used internally by ExifData, it is - probably not useful for a client as a standalone class. Instead, - use an instance of ExifData to access the Exif thumbnail image. - */ - class Thumbnail { - public: - //! Shortcut for a %Thumbnail auto pointer. - typedef std::auto_ptr<Thumbnail> AutoPtr; - - //! @name Creators - //@{ - //! Virtual destructor - virtual ~Thumbnail() {} - //@} - - //! @name Accessors - //@{ - /*! - @brief Set the image data as data area of the appropriate Exif - metadatum. Read the thumbnail image data from data buffer - \em buf. Return 0 if successful. - - @param exifData Exif data corresponding to the data buffer. - @param pIfd1 Corresponding raw IFD1. - @param buf Data buffer containing the thumbnail data. The buffer must - start with the TIFF header. - @param len Number of bytes in the data buffer. - @return 0 if successful;<BR> - 1 in case of inconsistent thumbnail Exif data; or<BR> - 2 if the data area is outside of the data buffer - */ - virtual int setDataArea(ExifData& exifData, - Ifd* pIfd1, - const byte* buf, - long len) const =0; - /*! - @brief Return the thumbnail image in a %DataBuf. The caller owns the - data buffer and %DataBuf ensures that it will be deleted. - */ - virtual DataBuf copy(const ExifData& exifData) const =0; - /*! - @brief Return a short string for the format of the thumbnail - ("TIFF", "JPEG"). - */ - virtual const char* format() const =0; - /*! - @brief Return the file extension for the format of the thumbnail - (".tif", ".jpg"). - */ - virtual const char* extension() const =0; - //@} - - protected: - //! @name Manipulators - //@{ - /*! - @brief Assignment operator. Protected so that it can only be used - by subclasses but not directly. - */ - Thumbnail& operator=(const Thumbnail& rhs); - //@} - - }; // class Thumbnail - - //! Exif thumbnail image in TIFF format - class TiffThumbnail : public Thumbnail { - public: - //! Shortcut for a %TiffThumbnail auto pointer. - typedef std::auto_ptr<TiffThumbnail> AutoPtr; - - //! @name Manipulators - //@{ - //! Assignment operator. - TiffThumbnail& operator=(const TiffThumbnail& rhs) { return *this; } - //@} - - //! @name Accessors - //@{ - int setDataArea(ExifData& exifData, - Ifd* pIfd1, - const byte* buf, - long len) const; - DataBuf copy(const ExifData& exifData) const; - const char* format() const; - const char* extension() const; - //@} - - }; // class TiffThumbnail - - //! Exif thumbnail image in JPEG format - class JpegThumbnail : public Thumbnail { - public: - //! Shortcut for a %JpegThumbnail auto pointer. - typedef std::auto_ptr<JpegThumbnail> AutoPtr; - - //! @name Manipulators - //@{ - //! Assignment operator. - JpegThumbnail& operator=(const JpegThumbnail& rhs) { return *this; } - //@} - - //! @name Accessors - //@{ - int setDataArea(ExifData& exifData, - Ifd* pIfd1, - const byte* buf, - long len) const; - DataBuf copy(const ExifData& exifData) const; - const char* format() const; - const char* extension() const; - //@} - - }; // class JpegThumbnail - - //! Container type to hold all metadata - typedef std::vector<Exifdatum> ExifMetadata; - - //! Unary predicate that matches a Exifdatum with a given ifd id and idx - class FindMetadatumByIfdIdIdx { - public: - //! Constructor, initializes the object with the ifd id and idx to look for - FindMetadatumByIfdIdIdx(IfdId ifdId, int idx) - : ifdId_(ifdId), idx_(idx) {} - /*! - @brief Returns true if the ifd id and idx of the argument - \em exifdatum is equal to that of the object. - */ - bool operator()(const Exifdatum& exifdatum) const - { return ifdId_ == exifdatum.ifdId() && idx_ == exifdatum.idx(); } - - private: - IfdId ifdId_; - int idx_; - - }; // class FindMetadatumByIfdIdIdx - - /*! - @brief A container for Exif data. This is a top-level class of the %Exiv2 - library. The container holds Exifdatum objects. - - 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) - */ - class ExifData { - public: - //! ExifMetadata iterator type - typedef ExifMetadata::iterator iterator; - //! ExifMetadata const iterator type - typedef ExifMetadata::const_iterator const_iterator; - - //! @name Creators - //@{ - //! Default constructor - ExifData(); - //! Copy constructor (Todo: copy image data also) - ExifData(const ExifData& rhs); - //! Destructor - ~ExifData(); - //@} - - //! @name Manipulators - //@{ - //! Assignment operator (Todo: assign image data also) - ExifData& operator=(const ExifData& rhs); - /*! - @brief Load the Exif data from a byte buffer. The data buffer - must start with the TIFF header. - @param buf Pointer to the data buffer to read from - @param len Number of bytes in the data buffer - @return 0 if successful. - */ - int load(const byte* buf, long len); - /*! - @brief Write the Exif data to a data buffer, which is returned. The - caller owns this copy and %DataBuf ensures that it will be - deleted. The copied data starts with the TIFF header. - - Tries to update the original data buffer and write it back with - minimal changes, in a 'non-intrusive' fashion, if possible. In this - case, tag data that ExifData does not understand stand a good chance - to remain valid. (In particular, if the Exif data contains a - Makernote in IFD format, the offsets in its IFD will remain valid.) - <BR> - If 'non-intrusive' writing is not possible, the Exif data will be - re-built from scratch, in which case the absolute position of the - metadata entries within the data buffer may (and in most cases will) - be different from their original position. Furthermore, in this case, - the Exif data is updated with the metadata from the actual thumbnail - image (overriding existing metadata). - - @return A %DataBuf containing the Exif data. - */ - DataBuf copy(); - /*! - @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); - /*! - @brief Add all (IFD) entries in the range from iterator position begin - to iterator position end to the Exif metadata. No duplicate - checks are performed, i.e., it is possible to add multiple - metadata with the same key. - */ - void add(Entries::const_iterator begin, - Entries::const_iterator end, - ByteOrder byteOrder); - /*! - @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. - */ - 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. - - @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() { eraseThumbnail(); exifMetadata_.clear(); } - //! Sort metadata by key - void sortByKey(); - //! Sort metadata by tag - void sortByTag(); - //! Begin of the metadata - iterator begin() { return exifMetadata_.begin(); } - //! End of the metadata - iterator end() { return exifMetadata_.end(); } - /*! - @brief Find a Exifdatum with the given \em key, return an iterator to - it. If multiple metadata with the same key exist, it is - undefined which of the matching metadata is found. - */ - iterator findKey(const ExifKey& key); - /*! - @brief Find the Exifdatum with the given \em ifdId and \em idx, - return an iterator to it. - - This method can be used to uniquely identify an exifdatum that was - created from an IFD or from the makernote (with idx greater than - 0). Metadata created by an application (not read from an IFD or a - makernote) all have their idx field set to 0, i.e., they cannot be - uniquely identified with this method. If multiple metadata with the - same key exist, it is undefined which of the matching metadata is - found. - */ - iterator findIfdIdIdx(IfdId ifdId, int idx); - /*! - @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. - - 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. - - @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., IFD1 metadata. - - @return The number of bytes of thumbnail data erased from the original - Exif data. Note that the original image size may differ from - the size of the image after deleting the thumbnail by more - than this number. This is the case if the Exif data contains - extra bytes (often at the end of the Exif block) or gaps and - the thumbnail is not located at the end of the Exif block so - that non-intrusive writing of a truncated Exif block is not - possible. Instead it is in this case necessary to write the - Exif data, without the thumbnail, from the metadata and all - extra bytes and gaps are lost, resulting in a smaller image. - */ - long eraseThumbnail(); - //@} - - //! @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 an exifdatum with the given \em key, return a const - iterator to it. If multiple metadata with the same key exist, - it is undefined which of the matching metadata is found. - */ - const_iterator findKey(const ExifKey& key) const; - /*! - @brief Find the exifdatum with the given \em ifdId and \em idx, - return an iterator to it. - - This method can be used to uniquely identify a Exifdatum that was - created from an IFD or from the makernote (with idx greater than - 0). Metadata created by an application (not read from an IFD or a - makernote) all have their idx field set to 0, i.e., they cannot be - uniquely identified with this method. If multiple metadata with the - same key exist, it is undefined which of the matching metadata is - found. - */ - const_iterator findIfdIdIdx(IfdId ifdId, int idx) 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()); } - /*! - @brief Returns the byte order. Default is little endian. - */ - ByteOrder byteOrder() 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. - This will overwrite an existing file of the same name. - - @param path Path of the filename without image type extension - - @throw Error if writing to the file fails. - - @return 0 if successful;<BR> - 8 if the Exif data does not contain a thumbnail. - */ - int writeThumbnail(const std::string& path) const; - /*! - @brief Return the thumbnail image in a %DataBuf. The caller owns the - data buffer and %DataBuf ensures that it will be deleted. - */ - DataBuf copyThumbnail() const; - /*! - @brief Return a short string describing the format of the Exif - thumbnail ("TIFF", "JPEG"). - */ - const char* thumbnailFormat() const; - /*! - @brief Return the file extension for the Exif thumbnail depending - on the format (".tif", ".jpg"). - */ - const char* thumbnailExtension() const; - /*! - @brief Return a thumbnail object of the correct type, corresponding to - the current Exif data. Caller owns this object and the auto - pointer ensures that it will be deleted. - */ - Thumbnail::AutoPtr getThumbnail() const; - //@} - - private: - //! @name Manipulators - //@{ - /*! - @brief Read the thumbnail from the data buffer. Assigns the thumbnail - data area with the appropriate Exif tags. Return 0 if successful, - i.e., if there is a thumbnail. - */ - int readThumbnail(); - /*! - @brief Check if the metadata changed and update the internal IFDs and - the MakerNote if the changes are compatible with the existing - data (non-intrusive write support). - - @return True if only compatible changes were detected in the metadata - and the internal IFDs and MakerNote (and thus the data buffer) - were updated successfully. Return false, if non-intrusive - writing is not possible. The internal IFDs and the MakerNote - (and thus the data buffer) may or may not be modified in this - case. - */ - bool updateEntries(); - /*! - @brief Update the metadata for a range of entries. Called by - updateEntries() for each of the internal IFDs and the MakerNote - (if any). - */ - bool updateRange(const Entries::iterator& begin, - const Entries::iterator& end, - ByteOrder byteOrder); - /*! - @brief Write the Exif data to a data buffer the hard way, return the - data buffer. The caller owns this data buffer and %DataBuf - ensures that it will be deleted. - - Rebuilds the Exif data from scratch, using the TIFF header, metadata - container and thumbnail. In particular, the internal IFDs and the - original data buffer are not used. Furthermore, this method updates - the Exif data with the metadata from the actual thumbnail image - (overriding existing metadata). - - @return A %DataBuf containing the Exif data. - */ - DataBuf copyFromMetadata(); - //@} - - //! @name Accessors - //@{ - /*! - @brief Check if the metadata is compatible with the internal IFDs for - non-intrusive writing. Return true if compatible, false if not. - - @note This function does not detect deleted metadata as incompatible, - although the deletion of metadata is not (yet) a supported - non-intrusive write operation. - */ - bool compatible() const; - /*! - @brief Find the IFD or makernote entry corresponding to ifd id and idx. - - @return A pair of which the first part determines if a match was found - and, if true, the second contains an iterator to the entry. - */ - std::pair<bool, Entries::const_iterator> - findEntry(IfdId ifdId, int idx) const; - //! Return a pointer to the internal IFD identified by its IFD id - const Ifd* getIfd(IfdId ifdId) const; - /*! - @brief Check if IFD1, the IFD1 data and thumbnail data are located at - the end of the Exif data. Return true, if they are or if there - is no thumbnail at all, else return false. - */ - bool stdThumbPosition() const; - //@} - - // DATA - ExifMetadata exifMetadata_; - - // The pointers below are used only if Exif data is read from a - // raw data buffer - TiffHeader* pTiffHeader_; //! Pointer to the TIFF header - Ifd* pIfd0_; //! Pointer to Ifd0 - Ifd* pExifIfd_; //! Pointer to ExifIfd - Ifd* pIopIfd_; //! Pointer to IopIfd - Ifd* pGpsIfd_; //! Pointer to GpsIfd - Ifd* pIfd1_; //! Pointer to Ifd1 - MakerNote* pMakerNote_; //! Pointer to the MakerNote, if any - - long size_; //!< Size of the Exif raw data in bytes - byte* pData_; //!< Exif raw data buffer - - /*! - Can be set to false to indicate that non-intrusive writing is not - possible. If it is true (the default), then the compatibility checks - will be performed to determine which writing method to use. - */ - bool compatible_; - - }; // class ExifData - -// ***************************************************************************** -// template, inline and free functions - - template<typename T> - Exifdatum& setValue(Exifdatum& exifDatum, const T& value) - { - std::auto_ptr<ValueType<T> > v - = std::auto_ptr<ValueType<T> >(new ValueType<T>); - v->value_.push_back(value); - exifDatum.value_ = v; - return exifDatum; - } - /*! - @brief Add all metadata in the range from iterator position begin to - iterator position end, which have an IFD id matching that of the - IFD to the list of directory entries of ifd. No duplicate checks - are performed, i.e., it is possible to add multiple metadata with - the same key to an IFD. - */ - void addToIfd(Ifd& ifd, - ExifMetadata::const_iterator begin, - ExifMetadata::const_iterator end, - ByteOrder byteOrder); - /*! - @brief Add the Exifdatum to the IFD. No duplicate checks are performed, - i.e., it is possible to add multiple metadata with the same key to - an IFD. - */ - void addToIfd(Ifd& ifd, const Exifdatum& exifdatum, ByteOrder byteOrder); - /*! - @brief Add all metadata in the range from iterator position begin to - iterator position end with IFD id 'makerIfd' to the list of - makernote entries of the object pointed to be makerNote. No - duplicate checks are performed, i.e., it is possible to add - multiple metadata with the same key to a makernote. - */ - void addToMakerNote(MakerNote* makerNote, - ExifMetadata::const_iterator begin, - ExifMetadata::const_iterator end, - ByteOrder byteOrder); - /*! - @brief Add the Exifdatum to makerNote, encoded in byte order byteOrder. - No duplicate checks are performed, i.e., it is possible to add - multiple metadata with the same key to a makernote. - */ - void addToMakerNote(MakerNote* makerNote, - const Exifdatum& exifdatum, - ByteOrder byteOrder); - -} // namespace Exiv2 - -#endif // #ifndef EXIF_HPP_ diff --git a/src/plugins/exiv2/exifcomment.cpp b/src/plugins/exiv2/exifcomment.cpp @@ -1,68 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - Abstract : Sample program showing how to set the Exif comment of an image, - Exif.Photo.UserComment - - File: exifcomment.cpp - Version : $Rev: 560 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History : 10-May-04, ahu: created - 16-Jan-05, ahu: updated using CommentValue and operator trickery - */ -// ***************************************************************************** -// included header files -#include "image.hpp" -#include "exif.hpp" -#include <iostream> -#include <iomanip> -#include <cstring> -#include <cassert> - -// ***************************************************************************** -// Main -int main(int argc, char* const argv[]) -try { - - if (argc != 2) { - std::cout << "Usage: " << argv[0] << " file\n"; - return 1; - } - - Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]); - assert (image.get() != 0); - image->readMetadata(); - Exiv2::ExifData &exifData = image->exifData(); - - /* - Exiv2 uses a CommentValue for Exif user comments. The format of the - comment string includes an optional charset specification at the beginning: - - [charset=["]Ascii|Jis|Unicode|Undefined["] ]comment - - Undefined is used as a default if the comment doesn't start with a charset - definition. - - Following are a few examples of valid comments. The last one is written to - the file. - */ - exifData["Exif.Photo.UserComment"] - = "charset=\"Unicode\" An Unicode Exif comment added with Exiv2"; - exifData["Exif.Photo.UserComment"] - = "charset=\"Undefined\" An undefined Exif comment added with Exiv2"; - exifData["Exif.Photo.UserComment"] - = "Another undefined Exif comment added with Exiv2"; - exifData["Exif.Photo.UserComment"] - = "charset=Ascii An ASCII Exif comment added with Exiv2"; - - std::cout << "Writing user comment '" - << exifData["Exif.Photo.UserComment"] - << "' back to the image\n"; - - image->writeMetadata(); - - return 0; -} -catch (Exiv2::AnyError& e) { - std::cout << "Caught Exiv2 exception '" << e << "'\n"; - return -1; -} diff --git a/src/plugins/exiv2/exiv2extractor.cc b/src/plugins/exiv2/exiv2extractor.cc @@ -32,9 +32,9 @@ #include "platform.h" #include "extractor.h" -#include "exif.hpp" -#include "image.hpp" -#include "futils.hpp" +#include "exiv2/exif.hpp" +#include "exiv2/image.hpp" +#include "exiv2/futils.hpp" #define WORKAROUND_905 1 #if WORKAROUND_905 diff --git a/src/plugins/exiv2/exv_conf.h b/src/plugins/exiv2/exv_conf.h @@ -1,32 +0,0 @@ -#include "config.h" - -#define SUPPRESS_WARNINGS 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define EXV_HAVE_UNISTD_H HAVE_UNISTD_H - -#define EXV_HAVE_STDINT_H HAVE_STDINT_H - -/* Define to the address where bug reports for this package should be - sent. */ -#define EXV_PACKAGE_BUGREPORT PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#define EXV_PACKAGE_NAME PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#define EXV_PACKAGE_STRING PACKAGE_STRING - -/* Define to the version of this package. */ -#define EXV_PACKAGE_VERSION PACKAGE_VERSION - -/* File path seperator */ -#define EXV_SEPERATOR_STR DIR_SEPARATOR_STR -#define EXV_SEPERATOR_CHR DIR_SEPARATOR - -#if defined __CYGWIN32__ && !defined __CYGWIN__ - /* For backwards compatibility with Cygwin b19 and - earlier, we define __CYGWIN__ here, so that - we can rely on checking just for that macro. */ -#define __CYGWIN__ __CYGWIN32__ -#endif diff --git a/src/plugins/exiv2/exv_msvc.h b/src/plugins/exiv2/exv_msvc.h @@ -1,32 +0,0 @@ -#include "config.h" - -#define SUPPRESS_WARNINGS 1 - -/* Define to 1 if you have the <unistd.h> header file. */ -#define EXV_HAVE_UNISTD_H HAVE_UNISTD_H - -#define EXV_HAVE_STDINT_H HAVE_STDINT_H - -/* Define to the address where bug reports for this package should be - sent. */ -#define EXV_PACKAGE_BUGREPORT PACKAGE_BUGREPORT - -/* Define to the full name of this package. */ -#define EXV_PACKAGE_NAME PACKAGE_NAME - -/* Define to the full name and version of this package. */ -#define EXV_PACKAGE_STRING PACKAGE_STRING - -/* Define to the version of this package. */ -#define EXV_PACKAGE_VERSION PACKAGE_VERSION - -/* File path seperator */ -#define EXV_SEPERATOR_STR DIR_SEPARATOR_STR -#define EXV_SEPERATOR_CHR DIR_SEPARATOR - -#if defined __CYGWIN32__ && !defined __CYGWIN__ - /* For backwards compatibility with Cygwin b19 and - earlier, we define __CYGWIN__ here, so that - we can rely on checking just for that macro. */ -#define __CYGWIN__ __CYGWIN32__ -#endif diff --git a/src/plugins/exiv2/fujimn.cpp b/src/plugins/exiv2/fujimn.cpp @@ -1,275 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: fujimn.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 18-Feb-04, ahu: created - 07-Mar-04, ahu: isolated as a separate component - Credits: Fujifilm MakerNote implemented according to the specification - in "Appendix 4: Makernote of Fujifilm" of the document - "Exif file format" by TsuruZoh Tachibanaya - <http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html> - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: fujimn.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "fujimn.hpp" -#include "makernote.hpp" -#include "value.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - FujiMakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote("FUJIFILM", "*", createFujiMakerNote); - MakerNoteFactory::registerMakerNote( - fujiIfdId, MakerNote::AutoPtr(new FujiMakerNote)); - - ExifTags::registerMakerTagInfo(fujiIfdId, tagInfo_); - } - //! @endcond - - // Fujifilm MakerNote Tag Info - const TagInfo FujiMakerNote::tagInfo_[] = { - TagInfo(0x0000, "Version", "Fujifilm Makernote version", fujiIfdId, makerTags, undefined, printValue), - TagInfo(0x1000, "Quality", "Image quality setting", fujiIfdId, makerTags, asciiString, printValue), - TagInfo(0x1001, "Sharpness", "Sharpness setting", fujiIfdId, makerTags, unsignedShort, print0x1001), - TagInfo(0x1002, "WhiteBalance", "White balance setting", fujiIfdId, makerTags, unsignedShort, print0x1002), - TagInfo(0x1003, "Color", "Chroma saturation setting", fujiIfdId, makerTags, unsignedShort, print0x1003), - TagInfo(0x1004, "Tone", "Contrast setting", fujiIfdId, makerTags, unsignedShort, print0x1004), - TagInfo(0x1010, "FlashMode", "Flash firing mode setting", fujiIfdId, makerTags, unsignedShort, print0x1010), - TagInfo(0x1011, "FlashStrength", "Flash firing strength compensation setting", fujiIfdId, makerTags, signedRational, printValue), - TagInfo(0x1020, "Macro", "Macro mode setting", fujiIfdId, makerTags, unsignedShort, printOffOn), - TagInfo(0x1021, "FocusMode", "Focusing mode setting", fujiIfdId, makerTags, unsignedShort, print0x1021), - TagInfo(0x1022, "0x1022", "Unknown", fujiIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1030, "SlowSync", "Slow synchro mode setting", fujiIfdId, makerTags, unsignedShort, printOffOn), - TagInfo(0x1031, "PictureMode", "Picture mode setting", fujiIfdId, makerTags, unsignedShort, print0x1031), - TagInfo(0x1032, "0x1032", "Unknown", fujiIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1100, "Continuous", "Continuous shooting or auto bracketing setting", fujiIfdId, makerTags, unsignedShort, printOffOn), - TagInfo(0x1101, "0x1101", "Unknown", fujiIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1200, "0x1200", "Unknown", fujiIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1300, "BlurWarning", "Blur warning status", fujiIfdId, makerTags, unsignedShort, printOffOn), - TagInfo(0x1301, "FocusWarning", "Auto Focus warning status", fujiIfdId, makerTags, unsignedShort, printOffOn), - TagInfo(0x1302, "AeWarning", "Auto Exposure warning status", fujiIfdId, makerTags, unsignedShort, printOffOn), - // End of list marker - TagInfo(0xffff, "(UnknownFujiMakerNoteTag)", "Unknown FujiMakerNote tag", fujiIfdId, makerTags, invalidTypeId, printValue) - }; - - FujiMakerNote::FujiMakerNote(bool alloc) - : IfdMakerNote(fujiIfdId, alloc) - { - byteOrder_ = littleEndian; - absOffset_ = false; - byte buf[] = { - 'F', 'U', 'J', 'I', 'F', 'I', 'L', 'M', 0x0c, 0x00, 0x00, 0x00 - }; - readHeader(buf, 12, byteOrder_); - } - - FujiMakerNote::FujiMakerNote(const FujiMakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int FujiMakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 12) return 1; - - header_.alloc(12); - memcpy(header_.pData_, buf, header_.size_); - // Read the offset relative to the start of the makernote from the header - // Note: we ignore the byteOrder paramter - adjOffset_ = getUShort(header_.pData_ + 8, byteOrder_); - return 0; - } - - int FujiMakerNote::checkHeader() const - { - int rc = 0; - // Check the FUJIFILM prefix - if ( header_.size_ < 12 - || std::string(reinterpret_cast<char*>(header_.pData_), 8) - != std::string("FUJIFILM", 8)) { - rc = 2; - } - return rc; - } - - FujiMakerNote::AutoPtr FujiMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - FujiMakerNote* FujiMakerNote::create_(bool alloc) const - { - AutoPtr makerNote = AutoPtr(new FujiMakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - FujiMakerNote::AutoPtr FujiMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - FujiMakerNote* FujiMakerNote::clone_() const - { - return new FujiMakerNote(*this); - } - - std::ostream& FujiMakerNote::printOffOn(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Off"; break; - case 1: os << "On"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1001(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 1: // fallthrough - case 2: os << "Soft"; break; - case 3: os << "Normal"; break; - case 4: // fallthrough - case 5: os << "Hard"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1002(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Auto"; break; - case 256: os << "Daylight"; break; - case 512: os << "Cloudy"; break; - case 768: os << "Fluorescent (daylight)"; break; - case 769: os << "Fluorescent (warm white)"; break; - case 770: os << "Fluorescent (cool white)"; break; - case 1024: os << "Incandescent"; break; - case 3480: os << "Custom"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1003(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Standard"; break; - case 256: os << "High"; break; - case 512: os << "Original"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1004(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Standard"; break; - case 256: os << "Hard"; break; - case 512: os << "Original"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1010(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Auto"; break; - case 1: os << "On"; break; - case 2: os << "Off"; break; - case 3: os << "Red-eye"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1021(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Auto"; break; - case 1: os << "Manual"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& FujiMakerNote::print0x1031(std::ostream& os, - const Value& value) - { - switch (value.toLong()) { - case 0: os << "Auto"; break; - case 1: os << "Portrait"; break; - case 2: os << "Landscape"; break; - case 4: os << "Sports"; break; - case 5: os << "Night"; break; - case 6: os << "Program"; break; - case 256: os << "Aperture priority"; break; - case 512: os << "Shutter priority"; break; - case 768: os << "Manual"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createFujiMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - return MakerNote::AutoPtr(new FujiMakerNote(alloc)); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/fujimn.hpp b/src/plugins/exiv2/fujimn.hpp @@ -1,162 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 fujimn.hpp - @brief Fujifilm MakerNote implemented according to the specification - in Appendix 4: Makernote of Fujifilm of the document - <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html"> - Exif file format</a> by TsuruZoh Tachibanaya - @version $Rev: 569 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 11-Feb-04, ahu: created - */ -#ifndef FUJIMN_HPP_ -#define FUJIMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createFujiMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! MakerNote for Fujifilm cameras - class FujiMakerNote : public IfdMakerNote { - public: - //! Shortcut for a %FujiMakerNote auto pointer. - typedef std::auto_ptr<FujiMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - FujiMakerNote(bool alloc =true); - //! Copy constructor - FujiMakerNote(const FujiMakerNote& rhs); - //! Virtual destructor - virtual ~FujiMakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Fujifilm %MakerNote tags - //@{ - //! Print Off or On status - static std::ostream& printOffOn(std::ostream& os, const Value& value); - //! Print sharpness - static std::ostream& print0x1001(std::ostream& os, const Value& value); - //! Print white balance - static std::ostream& print0x1002(std::ostream& os, const Value& value); - //! Print color - static std::ostream& print0x1003(std::ostream& os, const Value& value); - //! Print tone - static std::ostream& print0x1004(std::ostream& os, const Value& value); - //! Print flash mode - static std::ostream& print0x1010(std::ostream& os, const Value& value); - //! Print focus mode - static std::ostream& print0x1021(std::ostream& os, const Value& value); - //! Print picture mode - static std::ostream& print0x1031(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - FujiMakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - FujiMakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class FujiMakerNote - - static FujiMakerNote::RegisterMn registerFujiMakerNote; -} // namespace Exiv2 - -#endif // #ifndef FUJIMN_HPP_ diff --git a/src/plugins/exiv2/futils.cpp b/src/plugins/exiv2/futils.cpp @@ -1,78 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: utils.cpp - Version: $Rev: 560 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 08-Dec-03, ahu: created - 02-Apr-05, ahu: moved to Exiv2 namespace - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: futils.cpp 560 2005-04-17 11:51:32Z ahuggel $"); - -// ***************************************************************************** -// included header files -#ifdef _MSC_VER -# include "exv_msvc.h" -#else -# include "exv_conf.h" -#endif - -#include "futils.hpp" - -// + standard includes -#include <sys/types.h> -#include <sys/stat.h> -#ifdef _MSC_VER -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif -#ifdef EXV_HAVE_UNISTD_H -# include <unistd.h> // for stat() -#endif - -#include <cerrno> -#include <cstring> -#include <sstream> - -namespace Exiv2 { - -// ***************************************************************************** -// free functions - - bool fileExists(const std::string& path, bool ct) - { - struct stat buf; - int ret = stat(path.c_str(), &buf); - if (0 != ret) return false; - if (ct && !S_ISREG(buf.st_mode)) return false; - return true; - } // fileExists - - std::string strError() - { - int error = errno; - std::ostringstream os; - os << strerror(error) << " (" << error << ")"; - return os.str(); - } // strError - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/futils.hpp b/src/plugins/exiv2/futils.hpp @@ -1,66 +0,0 @@ -// ********************************************************* -*- C++ -*- -/* - * Copyright (C) 2004, 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 futils.hpp - @brief Basic file utility functions required by Exiv2 - @version $Rev: 560 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 12-Dec-03, ahu: created<BR> - 02-Apr-05, ahu: moved to Exiv2 namespace - */ -#ifndef FUTILS_HPP_ -#define FUTILS_HPP_ - -// ********************************************************************* -// included header files -// + standard includes -#include <string> - -// ********************************************************************* -// namespace extensions -namespace Exiv2 { - -// ********************************************************************* -// free functions - - /*! - @brief Test if a file exists. - - @param path Name of file to verify. - @param ct Flag to check if <i>path</i> is a regular file. - @return true if <i>path</i> exists and, if <i>ct</i> is set, - is a regular file, else false. - - @note The function calls <b>stat()</b> test for <i>path</i> - and its type, see stat(2). <b>errno</b> is left unchanged - in case of an error. - */ - bool fileExists(const std::string& path, bool ct =false); - /*! - @brief Return a system error message and the error code (errno). - See %strerror(3). - */ - std::string strError(); - -} // namespace Exiv2 - -#endif // #ifndef FUTILS_HPP_ diff --git a/src/plugins/exiv2/ifd.cpp b/src/plugins/exiv2/ifd.cpp @@ -1,723 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: ifd.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 26-Jan-04, ahu: created - 11-Feb-04, ahu: isolated as a component - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: ifd.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "ifd.hpp" -#include "types.hpp" -#include "error.hpp" -#include "tags.hpp" // for ExifTags::ifdName - -// + standard includes -#include <iostream> -#include <iomanip> -#include <sstream> -#include <vector> -#include <algorithm> -#include <cstring> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - Entry::Entry(bool alloc) - : alloc_(alloc), ifdId_(ifdIdNotSet), idx_(0), - tag_(0), type_(0), count_(0), offset_(0), size_(0), pData_(0), - sizeDataArea_(0), pDataArea_(0) - { - } - - Entry::~Entry() - { - if (alloc_) { - delete[] pData_; - delete[] pDataArea_; - } - } - - Entry::Entry(const Entry& rhs) - : alloc_(rhs.alloc_), ifdId_(rhs.ifdId_), idx_(rhs.idx_), - tag_(rhs.tag_), type_(rhs.type_), - count_(rhs.count_), offset_(rhs.offset_), size_(rhs.size_), pData_(0), - sizeDataArea_(rhs.sizeDataArea_), pDataArea_(0) - { - if (alloc_) { - if (rhs.pData_) { - pData_ = new byte[rhs.size()]; - memcpy(pData_, rhs.pData_, rhs.size()); - } - if (rhs.pDataArea_) { - pDataArea_ = new byte[rhs.sizeDataArea()]; - memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea()); - } - } - else { - pData_ = rhs.pData_; - pDataArea_ = rhs.pDataArea_; - } - } - - Entry& Entry::operator=(const Entry& rhs) - { - if (this == &rhs) return *this; - alloc_ = rhs.alloc_; - ifdId_ = rhs.ifdId_; - idx_ = rhs.idx_; - tag_ = rhs.tag_; - type_ = rhs.type_; - count_ = rhs.count_; - offset_ = rhs.offset_; - size_ = rhs.size_; - sizeDataArea_ = rhs.sizeDataArea_; - if (alloc_) { - delete[] pData_; - pData_ = 0; - if (rhs.pData_) { - pData_ = new byte[rhs.size()]; - memcpy(pData_, rhs.pData_, rhs.size()); - } - delete[] pDataArea_; - pDataArea_ = 0; - if (rhs.pDataArea_) { - pDataArea_ = new byte[rhs.sizeDataArea()]; - memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea()); - } - } - else { - pData_ = rhs.pData_; - pDataArea_ = rhs.pDataArea_; - } - return *this; - } // Entry::operator= - - void Entry::setValue(uint32_t data, ByteOrder byteOrder) - { - if (pData_ == 0 || size_ < 4) { - assert(alloc_); - size_ = 4; - delete[] pData_; - pData_ = new byte[size_]; - } - ul2Data(pData_, data, byteOrder); - // do not change size_ - type_ = unsignedLong; - count_ = 1; - } - - void Entry::setValue(uint16_t type, uint32_t count, const byte* buf, long len) - { - long dataSize = count * TypeInfo::typeSize(TypeId(type)); - // No minimum size requirement, but make sure the buffer can hold the data - if (len < dataSize) throw Error(24, tag(), dataSize, len); - if (alloc_) { - delete[] pData_; - pData_ = new byte[len]; - memset(pData_, 0x0, len); - memcpy(pData_, buf, dataSize); - size_ = len; - } - else { - if (size_ == 0) { - // Set the data pointer of a virgin entry - pData_ = const_cast<byte*>(buf); - size_ = len; - } - else { - // Overwrite existing data if it fits into the buffer - if (size_ < dataSize) throw Error(24, tag(), dataSize, size_); - memset(pData_, 0x0, size_); - memcpy(pData_, buf, dataSize); - // do not change size_ - } - } - type_ = type; - count_ = count; - } // Entry::setValue - - void Entry::setDataArea(const byte* buf, long len) - { - if (alloc_) { - delete[] pDataArea_; - pDataArea_ = new byte[len]; - memcpy(pDataArea_, buf, len); - sizeDataArea_ = len; - } - else { - if (sizeDataArea_ == 0) { - // Set the data area pointer of a virgin entry - pDataArea_ = const_cast<byte*>(buf); - sizeDataArea_ = len; - } - else { - // Overwrite existing data if it fits into the buffer - if (sizeDataArea_ < len) { - throw Error(25, tag(), sizeDataArea_, len); - } - memset(pDataArea_, 0x0, sizeDataArea_); - memcpy(pDataArea_, buf, len); - // do not change sizeDataArea_ - } - } - } // Entry::setDataArea - - void Entry::setDataAreaOffsets(uint32_t offset, ByteOrder byteOrder) - { - for (uint32_t i = 0; i < count(); ++i) { - byte* buf = pData_ + i * typeSize(); - switch(TypeId(type())) { - case unsignedShort: { - uint16_t d = getUShort(buf, byteOrder); - if (d + offset > 0xffff) throw Error(26); - us2Data(buf, d + static_cast<uint16_t>(offset), byteOrder); - break; - } - case unsignedLong: { - ul2Data(buf, getULong(buf, byteOrder) + offset, byteOrder); - break; - } - case unsignedRational: { - URational d = getURational(buf, byteOrder); - d.first = d.first + offset * d.second; - ur2Data(buf, d, byteOrder); - break; - } - case signedShort: { - int16_t d = getShort(buf, byteOrder); - if (d + static_cast<int32_t>(offset) > 0xffff) throw Error(26); - s2Data(buf, d + static_cast<int16_t>(offset), byteOrder); - break; - } - case signedLong: { - int32_t d = getLong(buf, byteOrder); - l2Data(buf, d + static_cast<int32_t>(offset), byteOrder); - break; - } - case signedRational: { - Rational d = getRational(buf, byteOrder); - d.first = d.first + static_cast<int32_t>(offset) * d.second; - r2Data(buf, d, byteOrder); - break; - } - default: - throw Error(27); - break; - } - } - } // Entry::setDataAreaOffsets - - void Entry::updateBase(byte* pOldBase, byte* pNewBase) - { - if (!alloc_) { - if (pDataArea_) { - pDataArea_ = pDataArea_ - pOldBase + pNewBase; - } - if (pData_) { - pData_ = pData_ - pOldBase + pNewBase; - } - } - } // Entry::updateBase - - const byte* Entry::component(uint32_t n) const - { - if (n >= count()) return 0; - return data() + n * typeSize(); - } // Entry::component - - Ifd::Ifd(IfdId ifdId) - : alloc_(true), ifdId_(ifdId), pBase_(0), offset_(0), - dataOffset_(0), hasNext_(true), pNext_(0), next_(0) - { - pNext_ = new byte[4]; - memset(pNext_, 0x0, 4); - } - - Ifd::Ifd(IfdId ifdId, long offset) - : alloc_(true), ifdId_(ifdId), pBase_(0), offset_(offset), - dataOffset_(0), hasNext_(true), pNext_(0), next_(0) - { - pNext_ = new byte[4]; - memset(pNext_, 0x0, 4); - } - - Ifd::Ifd(IfdId ifdId, long offset, bool alloc, bool hasNext) - : alloc_(alloc), ifdId_(ifdId), pBase_(0), offset_(offset), - dataOffset_(0), hasNext_(hasNext), pNext_(0), next_(0) - { - if (alloc_ && hasNext_) { - pNext_ = new byte[4]; - memset(pNext_, 0x0, 4); - } - } - - Ifd::~Ifd() - { - // do not delete pBase_ - if (alloc_ && hasNext_) delete[] pNext_; - } - - Ifd::Ifd(const Ifd& rhs) - : alloc_(rhs.alloc_), entries_(rhs.entries_), ifdId_(rhs.ifdId_), - pBase_(rhs.pBase_), offset_(rhs.offset_), dataOffset_(rhs.dataOffset_), - hasNext_(rhs.hasNext_), pNext_(rhs.pNext_), next_(rhs.next_) - { - if (alloc_ && hasNext_) { - pNext_ = new byte[4]; - memset(pNext_, 0x0, 4); - if (rhs.pNext_) memcpy(pNext_, rhs.pNext_, 4); - } - } - - int Ifd::read(const byte* buf, long len, ByteOrder byteOrder, long offset) - { - // Todo: This is a hack to work around bug #424 - fix it properly! - if (ifdId_ == olympusIfdId) len = 65535; - - int rc = 0; - long o = 0; - Ifd::PreEntries preEntries; - - if (len < 2) rc = 6; - if (rc == 0) { - offset_ = offset; - int n = getUShort(buf, byteOrder); - o = 2; - - for (int i = 0; i < n; ++i) { - if (len < o + 12) { -#ifndef SUPPRESS_WARNINGS - std::cerr << "Error: " << ExifTags::ifdName(ifdId_) - << " entry " << i - << " lies outside of the IFD memory buffer.\n"; -#endif - rc = 6; - break; - } - Ifd::PreEntry pe; - pe.tag_ = getUShort(buf + o, byteOrder); - pe.type_ = getUShort(buf + o + 2, byteOrder); - pe.count_ = getULong(buf + o + 4, byteOrder); - pe.size_ = pe.count_ * TypeInfo::typeSize(TypeId(pe.type_)); - pe.offsetLoc_ = o + 8; - pe.offset_ = pe.size_ > 4 ? getLong(buf + o + 8, byteOrder) : 0; - preEntries.push_back(pe); - o += 12; - } - } - if (rc == 0 && hasNext_) { - if (len < o + 4) { -#ifndef SUPPRESS_WARNINGS - std::cerr << "Error: " << ExifTags::ifdName(ifdId_) - << " memory of the pointer to the next IFD" - << " lies outside of the IFD memory buffer.\n"; -#endif - rc = 6; - } - else { - if (alloc_) { - memcpy(pNext_, buf + o, 4); - } - else { - pNext_ = const_cast<byte*>(buf + o); - } - next_ = getULong(buf + o, byteOrder); - } - } - // Set the offset of the first data entry outside of the IFD. - // At the same time we guess the offset of the IFD, if it was not - // given. The guess is based on the assumption that the smallest offset - // points to a data buffer directly following the IFD. Subsequently all - // offsets of IFD entries will need to be recalculated. - if (rc == 0 && preEntries.size() > 0) { - // Find the entry with the smallest offset - Ifd::PreEntries::const_iterator i = std::min_element( - preEntries.begin(), preEntries.end(), cmpPreEntriesByOffset); - // Only do something if there is at least one entry with data - // outside the IFD directory itself. - if (i->size_ > 4) { - if (offset_ == 0) { - // Set the 'guessed' IFD offset - offset_ = i->offset_ - - (2 + 12 * static_cast<long>(preEntries.size()) - + (hasNext_ ? 4 : 0)); - } - // Set the offset of the first data entry outside of the IFD - if (i->offset_ - offset_ >= len) { -#ifndef SUPPRESS_WARNINGS - std::cerr << "Error: Offset of the 1st data entry of " - << ExifTags::ifdName(ifdId_) - << " is out of bounds:\n" - << " Offset = 0x" << std::setw(8) - << std::setfill('0') << std::hex - << i->offset_ - offset_ - << ", exceeds buffer size by " - << std::dec << i->offset_ - len - << " Bytes\n"; -#endif - rc = 6; - } - else { - dataOffset_ = i->offset_; - } - } - } - // Convert the pre-IFD entries to the actual entries, assign the data - // to each IFD entry and calculate relative offsets, relative to the - // start of the IFD - if (rc == 0) { - entries_.clear(); - int idx = 0; - const Ifd::PreEntries::iterator begin = preEntries.begin(); - const Ifd::PreEntries::iterator end = preEntries.end(); - for (Ifd::PreEntries::iterator i = begin; i != end; ++i) { - Entry e(alloc_); - e.setIfdId(ifdId_); - e.setIdx(++idx); - e.setTag(i->tag_); - long tmpOffset = - i->size_ > 4 ? i->offset_ - offset_ : i->offsetLoc_; - if (tmpOffset + i->size_ > len) { -#ifndef SUPPRESS_WARNINGS - std::cerr << "Warning: Upper boundary of data for " - << ExifTags::ifdName(ifdId_) - << " entry " << static_cast<int>(i - begin) - << " is out of bounds:\n" - << " Offset = 0x" << std::setw(8) - << std::setfill('0') << std::hex - << tmpOffset - << ", size = " << std::dec << i->size_ - << ", exceeds buffer size by " - << tmpOffset + i->size_ - len - << " Bytes; Truncating the data.\n"; -#endif - // Truncate the entry - i->size_ = 0; - i->count_ = 0; - tmpOffset = i->offsetLoc_; - } - // Set the offset to the data, relative to start of IFD - e.setOffset(tmpOffset); - // Set the size to at least for bytes to accomodate offset-data - e.setValue(i->type_, i->count_, buf + e.offset(), - std::max(long(4), i->size_)); - this->add(e); - } - } - if (!alloc_) pBase_ = const_cast<byte*>(buf) - offset_; - if (rc) this->clear(); - - return rc; - } // Ifd::read - - Ifd::const_iterator Ifd::findIdx(int idx) const - { - return std::find_if(entries_.begin(), entries_.end(), - FindEntryByIdx(idx)); - } - - Ifd::iterator Ifd::findIdx(int idx) - { - return std::find_if(entries_.begin(), entries_.end(), - FindEntryByIdx(idx)); - } - - Ifd::const_iterator Ifd::findTag(uint16_t tag) const - { - return std::find_if(entries_.begin(), entries_.end(), - FindEntryByTag(tag)); - } - - Ifd::iterator Ifd::findTag(uint16_t tag) - { - return std::find_if(entries_.begin(), entries_.end(), - FindEntryByTag(tag)); - } - - void Ifd::sortByTag() - { - std::sort(entries_.begin(), entries_.end(), cmpEntriesByTag); - } - - int Ifd::readSubIfd( - Ifd& dest, const byte* buf, long len, ByteOrder byteOrder, uint16_t tag - ) const - { - int rc = 0; - const_iterator pos = findTag(tag); - if (pos != entries_.end()) { - long offset = getULong(pos->data(), byteOrder); - if (len < offset) { - rc = 6; - } - else { - rc = dest.read(buf + offset, len - offset, byteOrder, offset); - } - } - return rc; - } // Ifd::readSubIfd - - long Ifd::copy(byte* buf, ByteOrder byteOrder, long offset) - { - if (entries_.size() == 0 && next_ == 0) return 0; - if (offset != 0) offset_ = offset; - - // Add the number of entries to the data buffer - us2Data(buf, static_cast<uint16_t>(entries_.size()), byteOrder); - long o = 2; - - // Add all directory entries to the data buffer - long dataSize = 0; - long dataAreaSize = 0; - long totalDataSize = 0; - const iterator b = entries_.begin(); - const iterator e = entries_.end(); - iterator i; - for (i = b; i != e; ++i) { - if (i->size() > 4) { - totalDataSize += i->size(); - } - } - for (i = b; i != e; ++i) { - us2Data(buf + o, i->tag(), byteOrder); - us2Data(buf + o + 2, i->type(), byteOrder); - ul2Data(buf + o + 4, i->count(), byteOrder); - if (i->sizeDataArea() > 0) { - long dataAreaOffset = offset_+size()+totalDataSize+dataAreaSize; - i->setDataAreaOffsets(dataAreaOffset, byteOrder); - dataAreaSize += i->sizeDataArea(); - } - if (i->size() > 4) { - // Set the offset of the entry, data immediately follows the IFD - i->setOffset(size() + dataSize); - l2Data(buf + o + 8, offset_ + i->offset(), byteOrder); - dataSize += i->size(); - } - else { - // Copy data into the offset field - memset(buf + o + 8, 0x0, 4); - memcpy(buf + o + 8, i->data(), i->size()); - } - o += 12; - } - - if (hasNext_) { - // Add the offset to the next IFD to the data buffer - if (pNext_) { - memcpy(buf + o, pNext_, 4); - } - else { - memset(buf + o, 0x0, 4); - } - o += 4; - } - - // 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(); - } - } - - // Add all data areas to the data buffer - for (i = b; i != e; ++i) { - if (i->sizeDataArea() > 0) { - memcpy(buf + o, i->dataArea(), i->sizeDataArea()); - o += i->sizeDataArea(); - } - } - - return o; - } // Ifd::copy - - void Ifd::clear() - { - entries_.clear(); - offset_ = 0; - dataOffset_ = 0; - if (hasNext_) { - if (alloc_) { - memset(pNext_, 0x0, 4); - } - else { - pBase_ = 0; - pNext_ = 0; - } - next_ = 0; - } - } // Ifd::clear - - void Ifd::setNext(uint32_t next, ByteOrder byteOrder) - { - if (hasNext_) { - assert(pNext_); - ul2Data(pNext_, next, byteOrder); - next_ = next; - } - } - - void Ifd::add(const Entry& entry) - { - assert(alloc_ == entry.alloc()); - assert(ifdId_ == entry.ifdId()); - // allow duplicates - entries_.push_back(entry); - } - - int Ifd::erase(uint16_t tag) - { - int idx = 0; - iterator pos = findTag(tag); - if (pos != end()) { - idx = pos->idx(); - erase(pos); - } - return idx; - } - - Ifd::iterator Ifd::erase(iterator pos) - { - return entries_.erase(pos); - } - - byte* Ifd::updateBase(byte* pNewBase) - { - byte *pOld = 0; - if (!alloc_) { - iterator end = this->end(); - for (iterator pos = begin(); pos != end; ++pos) { - pos->updateBase(pBase_, pNewBase); - } - if (hasNext_) { - pNext_ = pNext_ - pBase_ + pNewBase; - } - pOld = pBase_; - pBase_ = pNewBase; - } - return pOld; - } - - long Ifd::size() const - { - if (entries_.size() == 0 && next_ == 0) return 0; - return static_cast<long>(2 + 12 * entries_.size() + (hasNext_ ? 4 : 0)); - } - - long Ifd::dataSize() const - { - long dataSize = 0; - const_iterator end = this->end(); - for (const_iterator i = begin(); i != end; ++i) { - if (i->size() > 4) dataSize += i->size(); - dataSize += i->sizeDataArea(); - } - return dataSize; - } - - void Ifd::print(std::ostream& os, const std::string& prefix) const - { - if (entries_.size() == 0) return; - // Print a header - os << prefix << "IFD Offset: 0x" - << std::setw(8) << std::setfill('0') << std::hex << std::right - << offset_ - << ", IFD Entries: " - << std::setfill(' ') << std::dec << std::right - << static_cast<unsigned int>(entries_.size()) << "\n" - << prefix << "Entry Tag Format (Bytes each) Number Offset\n" - << prefix << "----- ------ --------------------- ------ -----------\n"; - // Print IFD entries - const const_iterator b = entries_.begin(); - const const_iterator e = entries_.end(); - const_iterator i = b; - for (; i != e; ++i) { - std::ostringstream offset; - if (i->size() > 4) { - offset << " 0x" << std::setw(8) << std::setfill('0') - << std::hex << std::right << i->offset(); - } - else { - const byte* data = i->data(); - for (int k = 0; k < i->size(); ++k) { - offset << std::setw(2) << std::setfill('0') << std::hex - << (int)data[k] << " "; - } - } - os << prefix << std::setw(5) << std::setfill(' ') << std::dec - << std::right << static_cast<int>(i - b) - << " 0x" << std::setw(4) << std::setfill('0') << std::hex - << std::right << i->tag() - << " " << std::setw(17) << std::setfill(' ') - << std::left << i->typeName() - << " (" << std::dec << i->typeSize() << ")" - << " " << std::setw(6) << std::setfill(' ') << std::dec - << std::right << i->count() - << " " << offset.str() - << "\n"; - } - if (hasNext_) { - os << prefix << "Next IFD: 0x" - << std::setw(8) << std::setfill('0') << std::hex - << std::right << next() << "\n"; - } - // Print data of IFD entries - for (i = b; i != e; ++i) { - if (i->size() > 4) { - os << "Data of entry " << static_cast<int>(i - b) << ":\n"; - hexdump(os, i->data(), i->size(), offset_ + i->offset()); - } - } - - } // Ifd::print - - // ************************************************************************* - // free functions - - bool cmpEntriesByTag(const Entry& lhs, const Entry& rhs) - { - return lhs.tag() < rhs.tag(); - } - - bool cmpPreEntriesByOffset(const Ifd::PreEntry& lhs, const Ifd::PreEntry& rhs) - { - // We need to ignore entries with size <= 4, so by definition, - // entries with size <= 4 are greater than those with size > 4 - // when compared by their offset. - if (lhs.size_ <= 4) { - return false; // lhs is greater by definition, or they are equal - } - if (rhs.size_ <= 4) { - return true; // rhs is greater by definition (they cannot be equal) - } - return lhs.offset_ < rhs.offset_; - } // cmpPreEntriesByOffset - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/ifd.hpp b/src/plugins/exiv2/ifd.hpp @@ -1,601 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 ifd.hpp - @brief Encoding and decoding of IFD (%Image File Directory) data - @version $Rev: 562 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 09-Jan-04, ahu: created<BR> - 11-Feb-04, ahu: isolated as a component - */ -#ifndef IFD_HPP_ -#define IFD_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" - -// + standard includes -#include <string> -#include <vector> -#include <iosfwd> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Ifd; - -// ***************************************************************************** -// class definitions - - /*! - @brief Data structure for one IFD directory entry. See the description of - class Ifd for an explanation of the supported modes for memory - allocation. - */ - class Entry { - public: - //! @name Creators - //@{ - /*! - @brief Default constructor. The entry allocates memory for its - data if alloc is true (the default), otherwise it remembers - just the pointers into a read and writeable data buffer which - it doesn't allocate or delete. - */ - explicit Entry(bool alloc =true); - //! Destructor - ~Entry(); - //! Copy constructor - Entry(const Entry& rhs); - //@} - - //! @name Manipulators - //@{ - //! Assignment operator - Entry& operator=(const Entry& rhs); - //! Set the tag - void setTag(uint16_t tag) { tag_ = tag; } - //! Set the IFD id - void setIfdId(IfdId ifdId) { ifdId_ = ifdId; } - //! Set the index (unique id of an entry within one IFD) - void setIdx(int idx) { idx_ = idx; } - //! Set the offset. The offset is relative to the start of the IFD. - void setOffset(long offset) { offset_ = offset; } - /*! - @brief Set the value of the entry to a single unsigned long component, - i.e., set the type of the entry to unsigned long, number of - components to one and the value according to the data provided. - - The size of the data buffer is set to at least four bytes, but is left - unchanged if it can accomodate the pointer. This method can be used - to set the value of a tag which contains a pointer (offset) to a - location in the Exif data (like e.g., ExifTag, 0x8769 in IFD0, which - contains a pointer to the Exif IFD). - <BR>This method cannot be used to set the value of a newly created - %Entry in non-alloc mode. - - @note This method is now deprecated, use data area related methods - instead. - */ - void setValue(uint32_t data, ByteOrder byteOrder); - /*! - @brief Set type, count, the data buffer and its size. - - Copies the provided buffer when called in memory allocation mode. - <BR>In non-alloc mode, use this method to initialise the data of a - newly created %Entry. In this case, only the pointer to the buffer is - copied, i.e., the buffer must remain valid throughout the life of the - %Entry. Subsequent calls in non-alloc mode will overwrite the data - pointed to by this pointer with the data provided, i.e., the buffer - provided in subsequent calls can be deleted after the call. - <BR>In either memory allocation mode, the data buffer provided must be - large enough to hold count components of type. The size of the buffer - will be as indicated in the size argument. I.e., it is possible to - allocate (set) a data buffer larger than required to hold count - components of the given type. - - @param type The type of the data. - @param count Number of components in the buffer. - @param data Pointer to the data buffer. - @param size Size of the desired data buffer in bytes. - @throw Error if no memory allocation is allowed - and the size of the data buffer is larger than the existing - data buffer of the entry or if size is not large enough to hold - count components of the given type. - */ - void setValue(uint16_t type, uint32_t count, const byte* data, long size); - /*! - @brief Set the data area. Memory management as for - setValue(uint16_t, uint32_t, const byte*, long) - - For certain tags the regular value of an IFD entry is an offset to a - data area outside of the IFD. Examples are Exif tag 0x8769 in IFD0 - (Exif.Image.ExifTag) or tag 0x0201 in IFD1 - (Exif.Thumbnail.JPEGInterchangeFormat). The offset of ExifTag points - to a data area containing the Exif IFD. That of JPEGInterchangeFormat - contains the JPEG thumbnail image. - This method sets the data area of a tag in accordance with the memory - allocation mode. - - @param buf Pointer to the data area. - @param len Size of the data area. - - @throw Error in non-alloc mode, if there already is a dataarea but the - size of the existing dataarea is not large enough for the - new buffer. - */ - void setDataArea(const byte* buf, long len); - /*! - @brief Set the offset(s) to the data area of an entry. - - Add @em offset to each data component of the entry. This is used by - Ifd::copy to convert the data components of an entry containing - offsets relative to the data area to become offsets from the start of - the TIFF header. Usually, entries with a data area have exactly one - unsigned long data component, which is 0. - - @param offset Offset - @param byteOrder Byte order - - @throw Error if the offset is out of range for the data type of the - tag or the data type is not supported. - */ - void setDataAreaOffsets(uint32_t offset, ByteOrder byteOrder); - /*! - @brief Update the base pointer of the Entry from \em pOldBase - to \em pNewBase. - - Allows to re-locate the underlying data buffer to a new location - \em pNewBase. This method only has an effect in non-alloc mode. - - @param pOldBase Base pointer of the old data buffer - @param pNewBase Base pointer of the new data buffer - */ - void updateBase(byte* pOldBase, byte* pNewBase); - //@} - - //! @name Accessors - //@{ - //! Return the tag - uint16_t tag() const { return tag_; } - //! Return the type id. - uint16_t type() const { return type_; } - //! Return the name of the type - const char* typeName() const - { return TypeInfo::typeName(TypeId(type_)); } - //! Return the size in bytes of one element of this type - long typeSize() const - { return TypeInfo::typeSize(TypeId(type_)); } - //! Return the IFD id - IfdId ifdId() const { return ifdId_; } - //! Return the index (unique id >0 of an entry within an IFD, 0 if not set) - int idx() const { return idx_; } - //! Return the number of components in the value - uint32_t count() const { return count_; } - /*! - @brief Return the size of the data buffer in bytes. - @note There is no minimum size for the data buffer, except that it - must be large enough to hold the data. - */ - long size() const { return size_; } - //! Return the offset from the start of the IFD to the data of the entry - long offset() const { return offset_; } - /*! - @brief Return a pointer to the data buffer. Do not attempt to write - to this pointer. - */ - const byte* data() const { return pData_; } - /*! - @brief Return a pointer to the n-th component, 0 if there is no - n-th component. Do not attempt to write to this pointer. - */ - const byte* component(uint32_t n) const; - //! Get the memory allocation mode - bool alloc() const { return alloc_; } - //! Return the size of the data area. - long sizeDataArea() const { return sizeDataArea_; } - /*! - @brief Return a pointer to the data area. Do not attempt to write to - this pointer. - - For certain tags the regular value of an IFD entry is an offset to a - data area outside of the IFD. Examples are Exif tag 0x8769 in IFD0 - (Exif.Image.ExifTag) or tag 0x0201 in IFD1 - (Exif.Thumbnail.JPEGInterchangeFormat). The offset of ExifTag points - to a data area containing the Exif IFD. That of JPEGInterchangeFormat - contains the JPEG thumbnail image. - Use this method to access (read-only) the data area of a tag. Use - setDataArea() to write to the data area. - - @return Return a pointer to the data area. - */ - const byte* dataArea() const { return pDataArea_; } - //@} - - private: - // DATA - /*! - True: Requires memory allocation and deallocation,<BR> - False: No memory management needed. - */ - bool alloc_; - //! Redundant IFD id (it is also at the IFD) - IfdId ifdId_; - //! Unique id of an entry within an IFD (0 if not set) - int idx_; - //! Tag - uint16_t tag_; - //! Type - uint16_t type_; - //! Number of components - uint32_t count_; - //! Offset from the start of the IFD to the data - long offset_; - /*! - Size of the data buffer holding the value in bytes, there is - no minimum size. - */ - long size_; - //! Pointer to the data buffer - byte* pData_; - //! Size of the data area - long sizeDataArea_; - //! Pointer to the data area - byte* pDataArea_; - - }; // class Entry - - //! Container type to hold all IFD directory entries - typedef std::vector<Entry> Entries; - - //! Unary predicate that matches an Entry with a given index - class FindEntryByIdx { - public: - //! Constructor, initializes the object with the index to look for - FindEntryByIdx(int idx) : idx_(idx) {} - /*! - @brief Returns true if the idx of the argument entry is equal - to that of the object. - */ - bool operator()(const Entry& entry) const - { return idx_ == entry.idx(); } - - private: - int idx_; - - }; // class FindEntryByIdx - - //! Unary predicate that matches an Entry with a given tag - class FindEntryByTag { - public: - //! Constructor, initializes the object with the tag to look for - FindEntryByTag(uint16_t tag) : tag_(tag) {} - /*! - @brief Returns true if the tag of the argument entry is equal - to that of the object. - */ - bool operator()(const Entry& entry) const - { return tag_ == entry.tag(); } - - private: - uint16_t tag_; - - }; // class FindEntryByTag - - /*! - @brief Models an IFD (%Image File Directory) - - This class models an IFD as described in the TIFF 6.0 specification. - - An instance of class %Ifd can operate in two modes, one that allocates and - deallocates the memory required to store data, and one that doesn't - perform such memory management. - <BR>An external data buffer (not managed by %Ifd) is needed for an instance - of %Ifd which operates in no memory management mode. The %Ifd will - maintain only pointers into this buffer. - <BR> The mode without memory management is used to make "non-intrusive - write support" possible. This allows writing to Exif data of an image - without changing the data layout of the Exif data, to maximize chances - that tag data, which the Exif reader may not understand (e.g., the - Makernote) remains valid. A "non-intrusive write operation" is the - modification of tag data without increasing the data size. - - @note Use the mode with memory management (the default) if you are unsure - or if these memory management considerations are of no concern to you. - - @note The two different modes imply completely different copy and - assignment behaviours, with the first resulting in entirely separate - classes and the second mode resulting in multiple classes using one - and the same data buffer. - */ - class Ifd { - //! @name Not implemented - //@{ - //! Assignment not allowed (memory management mode alloc_ is const) - Ifd& operator=(const Ifd& rhs); - //@} - - public: - //! %Entries const iterator type - typedef Entries::const_iterator const_iterator; - //! %Entries iterator type - typedef Entries::iterator iterator; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to set the IFD identifier. Memory management - is enabled, offset is set to 0. Serves as default constructor. - */ - explicit Ifd(IfdId ifdId =ifdIdNotSet); - /*! - @brief Constructor. Allows to set the IFD identifier and the offset of - the IFD from the start of TIFF header. Memory management is - enabled. - */ - Ifd(IfdId ifdId, long offset); - /*! - @brief Constructor. Allows to set the IFD identifier, offset of the - IFD from the start of TIFF header, choose whether or not - memory management is required for the Entries, and decide - whether this IFD has a next pointer. - */ - Ifd(IfdId ifdId, long offset, bool alloc, bool hasNext =true); - //! Copy constructor - Ifd(const Ifd& rhs); - //! Destructor - ~Ifd(); - //@} - - //! @name Manipulators - //@{ - /*! - @brief Read a complete IFD and its data from a data buffer - - @param buf Pointer to the data to decode. The buffer must start with the - IFD data (unlike the readSubIfd() method). - @param len Number of bytes in the data buffer - @param byteOrder Applicable byte order (little or big endian). - @param offset (Optional) offset of the IFD from the start of the TIFF - header, if known. If not given, the offset will be guessed - using the assumption that the smallest offset of all IFD - directory entries points to a data buffer immediately follwing - the IFD. - - @return 0 if successful;<BR> - 6 if the data buffer is too small, e.g., if an offset points - beyond the provided buffer. The IFD is cleared in this - case. - */ - int read(const byte* buf, long len, ByteOrder byteOrder, long offset =0); - /*! - @brief Copy the IFD to a data array, update the offsets of the IFD and - all its entries, return the number of bytes written. - - First the number of IFD entries is written (2 bytes), followed - by all directory entries: tag (2), type (2), number of data - components (4) and offset to the data or the data, if it - occupies not more than four bytes (4). The directory entries - are followed by the offset of the next IFD (4). All these - fields are encoded according to the byte order argument. Data - that doesn't fit into the offset fields follows immediately - after the IFD entries. The offsets in the IFD are set to - correctly point to the data fields, using the offset parameter - or the offset of the IFD. - - @param buf Pointer to the data buffer. The user must ensure that the - buffer has enough memory. Otherwise the call results in - undefined behaviour. - @param byteOrder Applicable byte order (little or big endian). - @param offset Target offset from the start of the TIFF header of the - 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, i.e., the offset of the IFD will be used. - @return Returns the number of characters written. - */ - long copy(byte* buf, ByteOrder byteOrder, long offset =0); - /*! - @brief Reset the IFD. Delete all IFD entries from the class and put - the object in a state where it can accept completely new - entries. - */ - void clear(); - /*! - @brief Set the offset of the next IFD. Byte order is needed to update - the underlying data buffer in non-alloc mode. This method only - has an effect if the IFD was instantiated with hasNext = true. - */ - void setNext(uint32_t next, ByteOrder byteOrder); - /*! - @brief Add the entry to the IFD. No duplicate-check is performed, - i.e., it is possible to add multiple entries with the same tag. - The memory allocation mode of the entry to be added must match - that of the IFD and the IFD ids of the IFD and entry must - match. - */ - void add(const Entry& entry); - /*! - @brief Delete the directory entry with the given tag. Return the index - of the deleted entry or 0 if no entry with tag was found. - */ - int erase(uint16_t tag); - /*! - @brief Delete the directory entry at iterator position pos, return the - position of the next entry. Note that iterators into the - directory, including pos, are potentially invalidated by this - call. - */ - iterator erase(iterator pos); - //! Sort the IFD entries by tag - void sortByTag(); - //! The first entry - iterator begin() { return entries_.begin(); } - //! End of the entries - iterator end() { return entries_.end(); } - //! Find an IFD entry by idx, return an iterator into the entries list - iterator findIdx(int idx); - //! Find an IFD entry by tag, return an iterator into the entries list - iterator findTag(uint16_t tag); - /*! - @brief Update the base pointer of the Ifd and all entries to \em pNewBase. - - Allows to re-locate the underlying data buffer to a new location - \em pNewBase. This method only has an effect in non-alloc mode. - - @param pNewBase Pointer to the new data buffer - - @return Old base pointer or 0 if called in alloc mode - */ - byte* updateBase(byte* pNewBase); - //@} - - //! @name Accessors - //@{ - /*! - @brief Read a sub-IFD from the location pointed to by the directory entry - with the given tag. - - @param dest References the destination IFD. - @param buf The data buffer to read from. The buffer must contain all Exif - data starting from the TIFF header (unlike the read() method). - @param len Number of bytes in the data buffer - @param byteOrder Applicable byte order (little or big endian). - @param tag Tag to look for. - - @return 0 if successful;<BR> - 6 if reading the sub-IFD failed (see read() above) or - the location pointed to by the directory entry with the - given tag is outside of the data buffer. - - @note It is not considered an error if the tag cannot be found in the - IFD. 0 is returned and no action is taken in this case. - */ - int readSubIfd( - Ifd& dest, const byte* buf, long len, ByteOrder byteOrder, uint16_t tag - ) const; - //! Get the memory allocation mode, see the Ifd class description for details - bool alloc() const { return alloc_; } - //! The first entry - const_iterator begin() const { return entries_.begin(); } - //! End of the entries - const_iterator end() const { return entries_.end(); } - //! Find an IFD entry by idx, return a const iterator into the entries list - const_iterator findIdx(int idx) const; - //! Find an IFD entry by tag, return a const iterator into the entries list - const_iterator findTag(uint16_t tag) const; - //! Get the IfdId of the IFD - IfdId ifdId() const { return ifdId_; } - //! Get the offset of the IFD from the start of the TIFF header - long offset() const { return offset_; } - /*! - @brief Get the offset of the first data entry outside of the IFD from - the start of the TIFF header, return 0 if there is none. The - data offset is determined when the IFD is read. - */ - long dataOffset() const { return dataOffset_; } - //! Get the offset to the next IFD from the start of the TIFF header - uint32_t next() const { return next_; } - //! Get the number of directory entries in the IFD - long count() const { return static_cast<long>(entries_.size()); } - //! Get the size of this IFD in bytes (IFD only, without data) - long size() const; - /*! - @brief Return the total size of the data of this IFD in bytes; sums - the size of all directory entries where size is greater than - four plus the size of all data areas, i.e., all data that - requires memory outside the IFD directory entries is counted. - */ - long dataSize() const; - /*! - @brief Print the IFD in human readable format to the given stream; - begin each line with prefix. - */ - void print(std::ostream& os, const std::string& prefix ="") const; - //@} - - private: - //! Helper structure to build IFD entries - struct PreEntry { - uint16_t tag_; - uint16_t type_; - uint32_t count_; - long size_; - long offsetLoc_; - long offset_; - }; - - //! cmpPreEntriesByOffset needs to know about PreEntry, that's all. - friend bool cmpPreEntriesByOffset(const PreEntry&, const PreEntry&); - - //! Container for 'pre-entries' - typedef std::vector<PreEntry> PreEntries; - - // DATA - /*! - True: requires memory allocation and deallocation, - False: no memory management needed. - */ - const bool alloc_; - //! IFD entries - Entries entries_; - //! IFD Id - IfdId ifdId_; - //! Pointer to IFD from the start of the TIFF header - byte* pBase_; - //! Offset of the IFD from the start of the TIFF header - long offset_; - //! Offset of the first data entry outside of the IFD directory - long dataOffset_; - //! Indicates whether the IFD has a next pointer - bool hasNext_; - //! Pointer to the offset of next IFD from the start of the TIFF header - byte* pNext_; - //! The offset of the next IFD as data value (always in sync with *pNext_) - uint32_t next_; - - }; // class Ifd - -// ***************************************************************************** -// free functions - - /*! - @brief Compare two IFD entries by tag. Return true if the tag of entry - lhs is less than that of rhs. - */ - bool cmpEntriesByTag(const Entry& lhs, const Entry& rhs); - - /*! - @brief Compare two 'pre-IFD entries' by offset, taking care of special - cases where one or both of the entries don't have an offset. - Return true if the offset of entry lhs is less than that of rhs, - else false. By definition, entries without an offset are greater - than those with an offset. - */ - bool cmpPreEntriesByOffset(const Ifd::PreEntry& lhs, const Ifd::PreEntry& rhs); - -} // namespace Exiv2 - -#endif // #ifndef IFD_HPP_ diff --git a/src/plugins/exiv2/image.cpp b/src/plugins/exiv2/image.cpp @@ -1,246 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: image.cpp - Version: $Rev: 598 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - Brad Schick (brad) <brad@robotbattle.com> - History: 26-Jan-04, ahu: created - 11-Feb-04, ahu: isolated as a component - 19-Jul-04, brad: revamped to be more flexible and support Iptc - 15-Jan-05, brad: inside-out design changes - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: image.cpp 598 2005-07-08 15:29:11Z ahuggel $"); - -// ***************************************************************************** -// included header files -#ifdef _MSC_VER -# include "exv_msvc.h" -#else -# include "exv_conf.h" -#endif - -#include "image.hpp" -#include "error.hpp" -#include "futils.hpp" - -// Ensure registration with factory -#include "jpgimage.hpp" - -// + standard includes -#include <cerrno> -#include <cstdio> -#include <cstring> -#include <cstdio> // for rename, remove -#include <cassert> -#include <sys/types.h> -#include <sys/stat.h> -#ifdef _MSC_VER -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif -#ifdef EXV_HAVE_UNISTD_H -# include <unistd.h> // stat -#endif - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - int ImageFactory::Init::count = 0; - - ImageFactory::Init::Init() - { - ++count; - } - - ImageFactory::Init::~Init() - { - if (--count == 0) { - Exiv2::ImageFactory::cleanup(); - } - } - - ImageFactory::Registry* ImageFactory::registry_ = 0; - - void ImageFactory::cleanup() - { - delete registry_; - registry_ = 0; - } - - void ImageFactory::init() - { - if (0 == registry_) { - registry_ = new Registry; - } - } - - 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) - { - FileIo fileIo(path); - return getType(fileIo); - } - - Image::Type ImageFactory::getType(const byte* data, long size) - { - MemIo memIo(data, size); - return getType(memIo); - } - - Image::Type ImageFactory::getType(BasicIo& io) - { - if (io.open() != 0) return Image::none; - IoCloser closer(io); - Image::Type type = Image::none; - Registry::const_iterator b = registry_->begin(); - Registry::const_iterator e = registry_->end(); - for (Registry::const_iterator i = b; i != e; ++i) - { - if (i->second.isThisType(io, false)) { - type = i->first; - break; - } - } - return type; - } // ImageFactory::getType - - Image::AutoPtr ImageFactory::open(const std::string& path) - { - BasicIo::AutoPtr io(new FileIo(path)); - Image::AutoPtr image = open(io); // may throw - if (image.get() == 0) throw Error(11, path); - return image; - } - - Image::AutoPtr ImageFactory::open(const byte* data, long size) - { - MemIo *mem = new MemIo(); - mem->wrap(data, size); - - BasicIo::AutoPtr io(mem); - Image::AutoPtr image = open(io); // may throw - if (image.get() == 0) throw Error(12); - return image; - } - - Image::AutoPtr ImageFactory::open(BasicIo::AutoPtr io) - { - if (io->open() != 0) { - throw Error(9, io->path(), strError()); - } - Image::AutoPtr image; - Registry::const_iterator b = registry_->begin(); - Registry::const_iterator e = registry_->end(); - for (Registry::const_iterator i = b; i != e; ++i) { - if (i->second.isThisType(*io, false)) { - image = i->second.newInstance(io, false); - break; - } - } - return image; - } // ImageFactory::open - - Image::AutoPtr ImageFactory::create(Image::Type type, - const std::string& path) - { - std::auto_ptr<FileIo> fileIo(new FileIo(path)); - // Create or overwrite the file, then close it - if (fileIo->open("w+b") != 0) { - throw Error(10, path, "w+b", strError()); - } - fileIo->close(); - BasicIo::AutoPtr io(fileIo); - Image::AutoPtr image = create(type, io); - if (image.get() == 0) throw Error(13, type); - return image; - } - - Image::AutoPtr ImageFactory::create(Image::Type type) - { - BasicIo::AutoPtr io(new MemIo); - Image::AutoPtr image = create(type, io); - if (image.get() == 0) throw Error(13, type); - return image; - } - - Image::AutoPtr ImageFactory::create(Image::Type type, - BasicIo::AutoPtr io) - { - // BasicIo instance does not need to be open - Registry::const_iterator i = registry_->find(type); - if (i != registry_->end()) { - return i->second.newInstance(io, true); - } - return Image::AutoPtr(); - } // ImageFactory::create - - TiffHeader::TiffHeader(ByteOrder byteOrder) - : byteOrder_(byteOrder), tag_(0x002a), offset_(0x00000008) - { - } - - int TiffHeader::read(const byte* buf) - { - if (buf[0] == 0x49 && buf[1] == 0x49) { - byteOrder_ = littleEndian; - } - else if (buf[0] == 0x4d && buf[1] == 0x4d) { - byteOrder_ = bigEndian; - } - else { - return 1; - } - tag_ = getUShort(buf+2, byteOrder_); - offset_ = getULong(buf+4, byteOrder_); - return 0; - } - - long TiffHeader::copy(byte* buf) const - { - switch (byteOrder_) { - case littleEndian: - buf[0] = 0x49; - buf[1] = 0x49; - break; - case bigEndian: - buf[0] = 0x4d; - buf[1] = 0x4d; - break; - case invalidByteOrder: - // do nothing - break; - } - us2Data(buf+2, 0x002a, byteOrder_); - ul2Data(buf+4, 0x00000008, byteOrder_); - return size(); - } // TiffHeader::copy - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/image.hpp b/src/plugins/exiv2/image.hpp @@ -1,493 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 image.hpp - @brief Class JpegImage to access JPEG images - @version $Rev: 598 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @author Brad Schick (brad) - <a href="mailto:brad@robotbattle.com">brad@robotbattle.com</a> - @date 09-Jan-04, ahu: created<BR> - 11-Feb-04, ahu: isolated as a component<BR> - 19-Jul-04, brad: revamped to be more flexible and support Iptc - 15-Jan-05, brad: inside-out design changes - */ -#ifndef IMAGE_HPP_ -#define IMAGE_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "basicio.hpp" - -// + standard includes -#include <string> -#include <map> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class ExifData; - class IptcData; - -// ***************************************************************************** -// class definitions - /*! - @brief Abstract base class defining the interface for an image. This is - the top-level interface to the Exiv2 library. - - Most client apps will obtain an Image instance by calling a static - ImageFactory method. The Image class can then be used to to - read, write, and save metadata. - */ - class Image { - public: - //! Supported image formats - enum Type { none, jpeg, exv }; - - //! Image auto_ptr type - typedef std::auto_ptr<Image> AutoPtr; - - //! @name Creators - //@{ - //! Virtual Destructor - virtual ~Image() {} - //@} - - //! @name Manipulators - //@{ - /*! - @brief Read metadata from assigned image. Before this method - is called, the various metadata types (Iptc, Exif) will be empty. - @throw Error In case of failure. - */ - virtual void readMetadata() =0; - /*! - @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 - */ - virtual void writeMetadata() =0; - /*! - @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 - */ - virtual void setExifData(const ExifData& exifData) =0; - /*! - @brief Erase any buffered Exif data. Exif data is not removed from - the actual image until the writeMetadata() method is called. - */ - virtual void clearExifData() =0; - /*! - @brief Assign new iptc data. The new iptc data is not written - to the image until the writeMetadata() method is called. - @param iptcData An IptcData instance holding iptc data to be copied - */ - virtual void setIptcData(const IptcData& iptcData) =0; - /*! - @brief Erase any buffered Iptc data. Iptc data is not removed from - the actual image until the writeMetadata() method is called. - */ - virtual void clearIptcData() =0; - /*! - @brief Set the image comment. The new comment is not written - to the image until the writeMetadata() method is called. - @param comment String containing comment. - */ - virtual void setComment(const std::string& comment) =0; - /*! - @brief Erase any buffered comment. Comment is not removed - from the actual image until the writeMetadata() method is called. - */ - virtual void clearComment() =0; - /*! - @brief Copy all existing metadata from source Image. The data is - copied into internal buffers and is not written to the image - until the writeMetadata() method is called. - @param image Metadata source. All metadata types are copied. - */ - virtual void setMetadata(const Image& image) =0; - /*! - @brief Erase all buffered metadata. Metadata is not removed - from the actual image until the writeMetadata() method is called. - */ - virtual void clearMetadata() =0; - //@} - - //! @name Accessors - //@{ - /*! - @brief Check if the Image instance is valid. Use after object - construction. - @return true if the Image is in a valid state. - */ - virtual bool good() const =0; - /*! - @brief Returns an ExifData instance containing currently buffered - exif data. - - The exif data may have been read from the image by - a previous call to readMetadata() or added directly. The exif - data in the returned instance will be written to the image when - writeMetadata() is called. - - @return read only ExifData instance containing exif values - */ - virtual const ExifData& exifData() const =0; - /*! - @brief Returns an ExifData instance containing currently buffered - exif data. - - The contained exif data may have been read from the image by - a previous call to readMetadata() or added directly. The exif - data in the returned instance will be written to the image when - writeMetadata() is called. - - @return modifiable ExifData instance containing exif values - */ - virtual ExifData& exifData() =0; - /*! - @brief Returns an IptcData instance containing currently buffered - iptc data. - - The contained iptc data may have been read from the image by - a previous call to readMetadata() or added directly. The iptc - data in the returned instance will be written to the image when - writeMetadata() is called. - - @return modifiable IptcData instance containing iptc values - */ - virtual const IptcData& iptcData() const =0; - /*! - @brief Returns an ExifData instance containing currently buffered - exif data. - - The contained iptc data may have been read from the image by - a previous call to readMetadata() or added directly. The iptc - data in the returned instance will be written to the image when - writeMetadata() is called. - - @return modifiable IptcData instance containing iptc values - */ - virtual IptcData& iptcData() =0; - /*! - @brief Return a copy of the image comment. May be an empty string. - */ - virtual std::string comment() const =0; - /*! - @brief Return a reference to the BasicIo instance being used for Io. - - This refence is particularly useful to reading the results of - operations on a MemIo instance. For example after metadata has - been modified and the writeMetadata() method has been called, - this method can be used to get access to the modified image. - - @return BasicIo instance that can be used to read or write image - data directly. - @note If the returned BasicIo is used to write to the image, the - Image class will not see those changes until the readMetadata() - method is called. - */ - virtual BasicIo& io() const = 0; - //@} - - protected: - //! @name Creators - //@{ - //! Default Constructor - Image() {} - //@} - - private: - // NOT Implemented - //! Copy constructor - Image(const Image& rhs); - //! Assignment operator - Image& operator=(const Image& rhs); - - }; // class Image - - //! Type for function pointer that creates new Image instances - typedef Image::AutoPtr (*NewInstanceFct)(BasicIo::AutoPtr io, bool create); - //! Type for function pointer that checks image types - typedef bool (*IsThisTypeFct)(BasicIo& iIo, bool advance); - - /*! - @brief Returns an Image instance of the specified type. - - The factory is implemented as a singleton, which can be accessed - through static member functions. - */ - class ImageFactory { - public: - //! @name Manipulators - //@{ - //! Destructor. - static void cleanup(); - /*! - @brief Register image type together with its function pointers. - - The image factory creates new images by calling their associated - function pointer. Additional images can be added by registering - new type and function pointers. If called for a type that already - exists in the list, the corresponding functions are replaced. - - @param type Image type. - @param newInst Function pointer for creating image instances. - @param isType Function pointer to test for matching image types. - */ - static void registerImage(Image::Type type, - NewInstanceFct newInst, - IsThisTypeFct isType); - //@} - - //! @name Accessors - //@{ - /*! - @brief Create an Image subclass of the appropriate type by reading - the specified file. %Image type is derived from the file - contents. - @param path %Image file. The contents of the file are tested to - determine the image type. File extension is ignored. - @return An auto-pointer that owns an Image instance whose type - matches that of the file. - @throw Error If opening the file fails or it contains data of an - unknown image type. - */ - static Image::AutoPtr open(const std::string& path); - /*! - @brief Create an Image subclass of the appropriate type by reading - the provided memory. %Image type is derived from the memory - contents. - @param data Pointer to a data buffer containing an image. The contents - of the memory are tested to determine the image type. - @param size Number of bytes pointed to by \em data. - @return An auto-pointer that owns an Image instance whose type - matches that of the data buffer. - @throw Error If the memory contains data of an unknown image type. - */ - static Image::AutoPtr open(const byte* data, long size); - /*! - @brief Create an Image subclass of the appropriate type by reading - the provided BasicIo instance. %Image type is derived from the - data provided by \em io. The passed in \em io instance is - (re)opened by this method. - @param io An auto-pointer that owns a BasicIo instance that provides - image data. The contents of the image data are tested to determine - the type. - @note This method 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. - @return An auto-pointer that owns an Image instance whose type - matches that of the \em io data. If no image type could be - determined, the pointer is 0. - @throw Error If opening the BasicIo fails - */ - static Image::AutoPtr open(BasicIo::AutoPtr io); - /*! - @brief Create an Image subclass of the requested type by creating a - new image file. If the file already exists, it will be overwritten. - @param type Type of the image to be created. - @param path %Image file to create. File extension is ignored. - @return An auto-pointer that owns an Image instance of the requested - type. - @throw Error If the image type is not supported. - */ - static Image::AutoPtr create(Image::Type type, const std::string& path); - /*! - @brief Create an Image subclass of the requested type by creating a - new image in memory. - @param type Type of the image to be created. - @return An auto-pointer that owns an Image instance of the requested - type. - @throw Error If the image type is not supported - */ - static Image::AutoPtr create(Image::Type type); - /*! - @brief Create an Image subclass of the requested type by writing a - new image to a BasicIo instance. If the BasicIo instance already - contains data, it will be overwritten. - @param type Type of the image to be created. - @param io An auto-pointer that owns a BasicIo instance that will - be written to when creating a new image. - @note This method 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. - @return An auto-pointer that owns an Image instance of the requested - type. If the image type is not supported, the pointer is 0. - */ - static Image::AutoPtr create(Image::Type type, BasicIo::AutoPtr io); - /*! - @brief Returns the image type of the provided file. - @param path %Image file. The contents of the file are tested to - determine the image type. File extension is ignored. - @return %Image type or Image::none if the type is not recognized. - */ - static Image::Type getType(const std::string& path); - /*! - @brief Returns the image type of the provided data buffer. - @param data Pointer to a data buffer containing an image. The contents - of the memory are tested to determine the image type. - @param size Number of bytes pointed to by \em data. - @return %Image type or Image::none if the type is not recognized. - */ - static Image::Type getType(const byte* data, long size); - /*! - @brief Returns the image type of data provided by a BasicIo instance. - The passed in \em io instance is (re)opened by this method. - @param io A BasicIo instance that provides image data. The contents - of the image data are tested to determine the type. - @return %Image type or Image::none if the type is not recognized. - */ - static Image::Type 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: - //! @name Creators - //@{ - //! Prevent construction other than through instance(). - ImageFactory(); - //! Prevent copy construction: not implemented. - ImageFactory(const ImageFactory& rhs); - //! Creates the private static instance - static void init(); - //@} - - //! Struct for storing image function pointers. - struct ImageFcts - { - NewInstanceFct newInstance; - IsThisTypeFct isThisType; - ImageFcts(NewInstanceFct newInst, IsThisTypeFct isType) - : newInstance(newInst), isThisType(isType) {} - ImageFcts() : newInstance(0), isThisType(0) {} - }; - - // DATA - //! Type used to store Image creation functions - typedef std::map<Image::Type, ImageFcts> Registry; - //! List of image types and corresponding creation functions. - static Registry* registry_; - }; // class ImageFactory - - - //! Helper class modelling the TIFF header structure. - class TiffHeader { - public: - //! @name Creators - //@{ - /*! - @brief Default constructor. Optionally sets the byte order - (default: little endian). - */ - explicit TiffHeader(ByteOrder byteOrder =littleEndian); - //@} - - //! @name Manipulators - //@{ - //! Read the TIFF header from a data buffer. Returns 0 if successful. - int read(const byte* buf); - //@} - - //! @name Accessors - //@{ - /*! - @brief Write a standard TIFF header into buf as a data string, return - number of bytes copied. - - Only the byte order of the TIFF header varies, the values written for - offset and tag are constant, i.e., independent of the values possibly - read before a call to this function. The value 0x00000008 is written - for the offset, tag is set to 0x002a. - - @param buf The data buffer to write to. - @return The number of bytes written. - */ - long copy(byte* buf) const; - //! Return the size of the TIFF header in bytes. - long size() const { return 8; } - //! Return the byte order (little or big endian). - ByteOrder byteOrder() const { return byteOrder_; } - //! Return the tag value. - uint16_t tag() const { return tag_; } - /*! - @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. - */ - uint32_t offset() const { return offset_; } - //@} - - private: - ByteOrder byteOrder_; - uint16_t tag_; - uint32_t offset_; - - }; // class TiffHeader - -} // 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_ diff --git a/src/plugins/exiv2/iptc.cpp b/src/plugins/exiv2/iptc.cpp @@ -1,301 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: iptc.cpp - Version: $Rev: 600 $ - Author(s): Brad Schick (brad) <brad@robotbattle.com> - History: 31-July-04, brad: created - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: iptc.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "iptc.hpp" -#include "types.hpp" -#include "error.hpp" -#include "value.hpp" -#include "datasets.hpp" -#include "jpgimage.hpp" - -// + standard includes -#include <iostream> -#include <algorithm> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - Iptcdatum::Iptcdatum(const IptcKey& key, - const Value* pValue) - : key_(key.clone()) - { - if (pValue) value_ = pValue->clone(); - } - - Iptcdatum::Iptcdatum(const Iptcdatum& rhs) - : Metadatum(rhs) - { - if (rhs.key_.get() != 0) key_ = rhs.key_->clone(); // deep copy - if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy - } - - Iptcdatum::~Iptcdatum() - { - } - - const Value& Iptcdatum::value() const - { - if (value_.get() == 0) throw Error(8); - return *value_; - } - - Iptcdatum& Iptcdatum::operator=(const Iptcdatum& rhs) - { - if (this == &rhs) return *this; - Metadatum::operator=(rhs); - - key_.reset(); - if (rhs.key_.get() != 0) key_ = rhs.key_->clone(); // deep copy - - value_.reset(); - if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy - - return *this; - } // Iptcdatum::operator= - - Iptcdatum& Iptcdatum::operator=(const uint16_t& value) - { - UShortValue::AutoPtr v = UShortValue::AutoPtr(new UShortValue); - v->value_.push_back(value); - value_ = v; - return *this; - } - - Iptcdatum& Iptcdatum::operator=(const std::string& value) - { - setValue(value); - return *this; - } - - Iptcdatum& Iptcdatum::operator=(const Value& value) - { - setValue(&value); - return *this; - } - - void Iptcdatum::setValue(const Value* pValue) - { - value_.reset(); - if (pValue) value_ = pValue->clone(); - } - - void Iptcdatum::setValue(const std::string& value) - { - if (value_.get() == 0) { - TypeId type = IptcDataSets::dataSetType(tag(), record()); - value_ = Value::create(type); - } - value_->read(value); - } - - const byte IptcData::marker_ = 0x1C; // Dataset marker - - Iptcdatum& IptcData::operator[](const std::string& key) - { - IptcKey iptcKey(key); - iterator pos = findKey(iptcKey); - if (pos == end()) { - add(Iptcdatum(iptcKey)); - pos = findKey(iptcKey); - } - return *pos; - } - - int IptcData::load(const byte* buf, long len) - { - const byte* pRead = buf; - iptcMetadata_.clear(); - - int rc = 0; - uint16_t record = 0; - uint16_t dataSet = 0; - uint32_t sizeData = 0; - byte extTest = 0; - - while (pRead + 3 < buf + len) { - if (*pRead++ != marker_) return 5; - record = *pRead++; - dataSet = *pRead++; - - extTest = *pRead; - if (extTest & 0x80) { - // extended dataset - uint16_t sizeOfSize = (getUShort(pRead, bigEndian) & 0x7FFF); - if (sizeOfSize > 4) return 5; - pRead += 2; - sizeData = 0; - for (; sizeOfSize > 0; --sizeOfSize) { - sizeData |= *pRead++ << (8 *(sizeOfSize-1)); - } - } - else { - // standard dataset - sizeData = getUShort(pRead, bigEndian); - pRead += 2; - } - rc = readData(dataSet, record, pRead, sizeData); - if( rc ) return rc; - pRead += sizeData; - } - - return rc; - } // IptcData::read - - int IptcData::readData(uint16_t dataSet, uint16_t record, - const byte* data, uint32_t sizeData) - { - Value::AutoPtr value; - TypeId type = IptcDataSets::dataSetType(dataSet, record); - value = Value::create(type); - value->read(data, sizeData, bigEndian); - IptcKey key(dataSet, record); - add(key, value.get()); - return 0; - } - - DataBuf IptcData::copy() - { - DataBuf buf(size()); - byte *pWrite = buf.pData_; - - const_iterator iter = iptcMetadata_.begin(); - const_iterator end = iptcMetadata_.end(); - for ( ; iter != end; ++iter) { - // marker, record Id, dataset num - *pWrite++ = marker_; - *pWrite++ = static_cast<byte>(iter->record()); - *pWrite++ = static_cast<byte>(iter->tag()); - - // extended or standard dataset? - long dataSize = iter->size(); - if (dataSize > 32767) { - // always use 4 bytes for extended length - uint16_t sizeOfSize = 4 | 0x8000; - us2Data(pWrite, sizeOfSize, bigEndian); - pWrite += 2; - ul2Data(pWrite, dataSize, bigEndian); - pWrite += 4; - } - else { - us2Data(pWrite, static_cast<uint16_t>(dataSize), bigEndian); - pWrite += 2; - } - - pWrite += iter->value().copy(pWrite, bigEndian); - } - - return buf; - } // IptcData::updateBuffer - - long IptcData::size() const - { - long newSize = 0; - const_iterator iter = iptcMetadata_.begin(); - const_iterator end = iptcMetadata_.end(); - for ( ; iter != end; ++iter) { - // marker, record Id, dataset num, first 2 bytes of size - newSize += 5; - long dataSize = iter->size(); - newSize += dataSize; - if (dataSize > 32767) { - // extended dataset (we always use 4 bytes) - newSize += 4; - } - } - return newSize; - } // IptcData::size - - int IptcData::add(const IptcKey& key, Value* value) - { - return add(Iptcdatum(key, value)); - } - - int IptcData::add(const Iptcdatum& iptcDatum) - { - if (!IptcDataSets::dataSetRepeatable( - iptcDatum.tag(), iptcDatum.record()) && - findId(iptcDatum.tag(), iptcDatum.record()) != end()) { - return 6; - } - // allow duplicates - iptcMetadata_.push_back(iptcDatum); - return 0; - } - - IptcData::const_iterator IptcData::findKey(const IptcKey& key) const - { - return std::find_if(iptcMetadata_.begin(), iptcMetadata_.end(), - FindMetadatumById(key.tag(), key.record())); - } - - IptcData::iterator IptcData::findKey(const IptcKey& key) - { - return std::find_if(iptcMetadata_.begin(), iptcMetadata_.end(), - FindMetadatumById(key.tag(), key.record())); - } - - IptcData::const_iterator IptcData::findId(uint16_t dataset, uint16_t record) const - { - return std::find_if(iptcMetadata_.begin(), iptcMetadata_.end(), - FindMetadatumById(dataset, record)); - } - - IptcData::iterator IptcData::findId(uint16_t dataset, uint16_t record) - { - return std::find_if(iptcMetadata_.begin(), iptcMetadata_.end(), - FindMetadatumById(dataset, record)); - } - - void IptcData::sortByKey() - { - std::sort(iptcMetadata_.begin(), iptcMetadata_.end(), cmpMetadataByKey); - } - - void IptcData::sortByTag() - { - std::sort(iptcMetadata_.begin(), iptcMetadata_.end(), cmpMetadataByTag); - } - - IptcData::iterator IptcData::erase(IptcData::iterator pos) - { - return iptcMetadata_.erase(pos); - } - - // ************************************************************************* - // free functions - std::ostream& operator<<(std::ostream& os, const Iptcdatum& md) - { - return os << md.value(); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/iptc.hpp b/src/plugins/exiv2/iptc.hpp @@ -1,415 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 iptc.hpp - @brief Encoding and decoding of Iptc data - @version $Rev: 599 $ - @author Brad Schick (brad) - <a href="mailto:brad@robotbattle.com">brad@robotbattle.com</a> - @date 31-Jul-04, brad: created - */ -#ifndef IPTC_HPP_ -#define IPTC_HPP_ - -// ***************************************************************************** -// included header files -#include "metadatum.hpp" -#include "types.hpp" -#include "error.hpp" -#include "value.hpp" -#include "datasets.hpp" - -// + standard includes -#include <string> -#include <vector> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class definitions - - /*! - @brief Information related to one Iptc dataset. An Iptc metadatum consists - of an IptcKey and a Value and provides methods to manipulate these. - */ - class Iptcdatum : public Metadatum { - public: - //! @name Creators - //@{ - /*! - @brief Constructor for new tags created by an application. The - %Iptcdatum is created from a key / value pair. %Iptcdatum - copies (clones) the value if one is provided. Alternatively, a - program can create an 'empty' %Iptcdatum with only a key and - set the value using setValue(). - - @param key The key of the %Iptcdatum. - @param pValue Pointer to a %Iptcdatum value. - @throw Error if the key cannot be parsed and converted - to a tag number and record id. - */ - explicit Iptcdatum(const IptcKey& key, - const Value* pValue =0); - //! Copy constructor - Iptcdatum(const Iptcdatum& rhs); - //! Destructor - virtual ~Iptcdatum(); - //@} - - //! @name Manipulators - //@{ - //! Assignment operator - Iptcdatum& operator=(const Iptcdatum& rhs); - /*! - @brief Assign \em value to the %Iptcdatum. The type of the new Value - is set to UShortValue. - */ - Iptcdatum& operator=(const uint16_t& value); - /*! - @brief Assign \em value to the %Iptcdatum. - Calls setValue(const std::string&). - */ - Iptcdatum& operator=(const std::string& value); - /*! - @brief Assign \em value to the %Iptcdatum. - Calls setValue(const Value*). - */ - Iptcdatum& operator=(const Value& value); - /*! - @brief Set the Value. This method copies (clones) the %Value pointed - to by \em pValue. - */ - void setValue(const Value* pValue); - /*! - @brief Set the value to the string \em value, using - Value::read(const std::string&). - If the %Iptcdatum does not have a Value yet, then a %Value of - the correct type for this %Iptcdatum is created. If that - fails (because of an unknown dataset), a StringValue is - created. - */ - void setValue(const std::string& value); - //@} - - //! @name Accessors - //@{ - /*! - @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); } - /*! - @brief Return the key of the Iptcdatum. The key is of the form - '<b>Iptc</b>.recordName.datasetName'. Note however that the key - is not necessarily unique, i.e., an IptcData may contain - multiple metadata with the same key. - */ - std::string key() const { return key_.get() == 0 ? "" : key_->key(); } - /*! - @brief Return the name of the record - @return record name - */ - std::string recordName() const - { return key_.get() == 0 ? "" : key_->recordName(); } - /*! - @brief Return the record id - @return record id - */ - uint16_t record() const - { return key_.get() == 0 ? 0 : key_->record(); } - /*! - @brief Return the name of the tag (aka dataset) - @return tag name - */ - std::string tagName() const - { return key_.get() == 0 ? "" : key_->tagName(); } - //! Return the tag (aka dataset) number - uint16_t tag() const - { return key_.get() == 0 ? 0 : key_->tag(); } - //! 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(); } - /*! - @brief Return the n-th component of the value converted to long. The - return value is -1 if the value of the Iptcdatum is not set and - the behaviour of the method is undefined if there is no n-th - component. - */ - long toLong(long n =0) const - { return value_.get() == 0 ? -1 : value_->toLong(n); } - /*! - @brief Return the n-th component of the value converted to float. The - return value is -1 if the value of the Iptcdatum is not set and - the behaviour of the method is undefined if there is no n-th - component. - */ - float toFloat(long n =0) const - { return value_.get() == 0 ? -1 : value_->toFloat(n); } - /*! - @brief Return the n-th component of the value converted to - Rational. The return value is -1/1 if the value of the - Iptcdatum is not set and the behaviour of the method is - undefined if there is no n-th component. - */ - Rational toRational(long n =0) const - { return value_.get() == 0 ? Rational(-1, 1) : value_->toRational(n); } - /*! - @brief Return an auto-pointer to a copy (clone) of the value. The - caller owns this copy and the auto-pointer ensures that it will - be deleted. - - This method is provided for users who need full control over the - value. A caller may, e.g., downcast the pointer to the appropriate - subclass of Value to make use of the interface of the subclass to set - or modify its contents. - - @return An auto-pointer to a copy (clone) of the value, 0 if the value - is not set. - */ - Value::AutoPtr getValue() const - { return value_.get() == 0 ? Value::AutoPtr(0) : value_->clone(); } - /*! - @brief Return a constant reference to the value. - - This method is provided mostly for convenient and versatile output of - the value which can (to some extent) be formatted through standard - stream manipulators. Do not attempt to write to the value through - this reference. - - <b>Example:</b> <br> - @code - IptcData::const_iterator i = iptcData.findKey(key); - if (i != iptcData.end()) { - std::cout << i->key() << " " << std::hex << i->value() << "\n"; - } - @endcode - - @return A constant reference to the value. - @throw Error If the value is not set. - */ - const Value& value() const; - //@} - - private: - // DATA - IptcKey::AutoPtr key_; //!< Key - Value::AutoPtr value_; //!< Value - - }; // class Iptcdatum - - /*! - @brief Output operator for Iptcdatum types, printing the interpreted - tag value. - */ - std::ostream& operator<<(std::ostream& os, const Iptcdatum& md); - - //! Container type to hold all metadata - typedef std::vector<Iptcdatum> IptcMetadata; - - //! Unary predicate that matches an Iptcdatum with given record and dataset - class FindMetadatumById { - public: - //! Constructor, initializes the object with the record and dataset id - FindMetadatumById(uint16_t dataset, uint16_t record) - : dataset_(dataset), record_(record) {} - /*! - @brief Returns true if the record and dataset id of the argument - Iptcdatum is equal to that of the object. - */ - bool operator()(const Iptcdatum& iptcdatum) const - { return dataset_ == iptcdatum.tag() && record_ == iptcdatum.record(); } - - private: - uint16_t dataset_; - uint16_t record_; - - }; // class FindMetadatumById - - /*! - @brief A container for Iptc data. This is a top-level class of - the %Exiv2 library. - - Provide high-level access to the Iptc data of an image: - - read Iptc information from JPEG files - - access metadata through keys and standard C++ iterators - - add, modify and delete metadata - - write Iptc data to JPEG files - - extract Iptc metadata to files, insert from these files - */ - class IptcData { - public: - //! IptcMetadata iterator type - typedef IptcMetadata::iterator iterator; - //! IptcMetadata const iterator type - typedef IptcMetadata::const_iterator const_iterator; - - // Use the compiler generated constructors and assignment operator - - //! @name Manipulators - //@{ - /*! - @brief Load the Iptc data from a byte buffer. The format must follow - the IPTC IIM4 standard. - @param buf Pointer to the data buffer to read from - @param len Number of bytes in the data buffer - @return 0 if successful;<BR> - 5 if Iptc data is invalid or corrupt;<BR> - */ - int load(const byte* buf, long len); - /*! - @brief Write the Iptc data to a data buffer and return the data buffer. - Caller owns this buffer. The copied data follows the IPTC IIM4 - standard. - @return Data buffer containing the Iptc data. - */ - DataBuf copy(); - /*! - @brief Returns a reference to the %Iptcdatum that is associated with a - particular \em key. If %IptcData does not already contain such - an %Iptcdatum, operator[] adds object \em Iptcdatum(key). - - @note Since operator[] might insert a new element, it can't be a const - member function. - */ - Iptcdatum& operator[](const std::string& key); - /*! - @brief Add an %Iptcdatum from the supplied key and value pair. This - method copies (clones) the value. A check for non-repeatable - datasets is performed. - @return 0 if successful;<BR> - 6 if the dataset already exists and is not repeatable - */ - int add(const IptcKey& key, Value* value); - /*! - @brief Add a copy of the Iptcdatum to the Iptc metadata. A check - for non-repeatable datasets is performed. - @return 0 if successful;<BR> - 6 if the dataset already exists and is not repeatable;<BR> - */ - int add(const Iptcdatum& iptcdatum); - /*! - @brief Delete the Iptcdatum at iterator position pos, return the - position of the next Iptcdatum. Note that iterators into - the metadata, including pos, are potentially invalidated - by this call. - */ - iterator erase(iterator pos); - /*! - @brief Delete all Iptcdatum instances resulting in an empty container. - */ - void clear() { iptcMetadata_.clear(); } - //! Sort metadata by key - void sortByKey(); - //! Sort metadata by tag (aka dataset) - void sortByTag(); - //! Begin of the metadata - iterator begin() { return iptcMetadata_.begin(); } - //! End of the metadata - iterator end() { return iptcMetadata_.end(); } - /*! - @brief Find a Iptcdatum with the given key, return an iterator to it. - If multiple entries with the same key exist, it is undefined - which of the matching metadata is found. - */ - iterator findKey(const IptcKey& key); - /*! - @brief Find a Iptcdatum with the given record and dataset it, - return a const iterator to it. If multiple entries with the - same Ids exists, it is undefined which of the matching - metadata is found. - */ - iterator findId(uint16_t dataset, - uint16_t record = IptcDataSets::application2); - //@} - - //! @name Accessors - //@{ - //! Begin of the metadata - const_iterator begin() const { return iptcMetadata_.begin(); } - //! End of the metadata - const_iterator end() const { return iptcMetadata_.end(); } - /*! - @brief Find an Iptcdatum with the given key, return a const iterator - to it. If multiple metadata with the same key exist it is - undefined which of the matching metadata is found. - */ - const_iterator findKey(const IptcKey& key) const; - /*! - @brief Find a Iptcdatum with the given record and dataset number, - return a const iterator to it. If multiple metadata with the - same Ids exist it is undefined which of the matching - metadata is found. - */ - const_iterator findId(uint16_t dataset, - uint16_t record = IptcDataSets::application2) const; - //! Return true if there is no Iptc metadata - bool empty() const { return count() == 0; } - //! Get the number of metadata entries - long count() const { return static_cast<long>(iptcMetadata_.size()); } - /*! - @brief Return the exact size of all contained Iptc metadata - */ - long size() const; - //@} - - private: - /*! - @brief Read a single dataset payload and create a new metadata entry - @param dataSet DataSet number - @param record Record Id - @param data Pointer to the first byte of dataset payload - @param sizeData Length in bytes of dataset payload - @return 0 if successful. - */ - int readData(uint16_t dataSet, uint16_t record, - const byte* data, uint32_t sizeData); - - // Constant data - static const byte marker_; // Dataset marker - - // DATA - IptcMetadata iptcMetadata_; - }; // class IptcData - -} // namespace Exiv2 - -#endif // #ifndef IPTC_HPP_ diff --git a/src/plugins/exiv2/jpgimage.cpp b/src/plugins/exiv2/jpgimage.cpp @@ -1,661 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: jpgimage.cpp - Version: $Rev: 563 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - Brad Schick (brad) <brad@robotbattle.com> - History: 15-Jan-05, brad: split out from image.cpp - - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: jpgimage.cpp 563 2005-04-21 07:21:53Z ahuggel $"); - -// ***************************************************************************** -// included header files -#ifdef _MSC_VER -# include "exv_msvc.h" -#else -# include "exv_conf.h" -#endif - -#include "jpgimage.hpp" -#include "error.hpp" -#include "futils.hpp" - -// + standard includes -#include <cstring> -#include <cassert> - -// ***************************************************************************** -// class member definitions -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::eoi_ = 0xd9; - const byte JpegBase::app0_ = 0xe0; - const byte JpegBase::app1_ = 0xe1; - const byte JpegBase::app13_ = 0xed; - const byte JpegBase::com_ = 0xfe; - const uint16_t JpegBase::iptc_ = 0x0404; - const char JpegBase::exifId_[] = "Exif\0\0"; - const char JpegBase::jfifId_[] = "JFIF\0"; - const char JpegBase::ps3Id_[] = "Photoshop 3.0\0"; - const char JpegBase::bimId_[] = "8BIM"; - - JpegBase::JpegBase(BasicIo::AutoPtr io, bool create, - const byte initData[], long dataSize) - : io_(io) - { - if (create) { - initImage(initData, dataSize); - } - } - - int JpegBase::initImage(const byte initData[], long dataSize) - { - if (io_->open() != 0) { - return 4; - } - IoCloser closer(*io_); - if (io_->write(initData, dataSize) != dataSize) { - return 4; - } - return 0; - } - - bool JpegBase::good() const - { - if (io_->open() != 0) return false; - IoCloser closer(*io_); - return isThisType(*io_, false); - } - - void JpegBase::clearMetadata() - { - clearIptcData(); - clearExifData(); - clearComment(); - } - - void JpegBase::clearIptcData() - { - iptcData_.clear(); - } - - void JpegBase::clearExifData() - { - exifData_.clear(); - } - - void JpegBase::clearComment() - { - comment_.erase(); - } - - void JpegBase::setExifData(const ExifData& exifData) - { - exifData_ = exifData; - } - - void JpegBase::setIptcData(const IptcData& iptcData) - { - iptcData_ = iptcData; - } - - void JpegBase::setComment(const std::string& comment) - { - comment_ = comment; - } - - void JpegBase::setMetadata(const Image& image) - { - setIptcData(image.iptcData()); - setExifData(image.exifData()); - setComment(image.comment()); - } - - int JpegBase::advanceToMarker() const - { - int c = -1; - // Skips potential padding between markers - while ((c=io_->getb()) != 0xff) { - if (c == EOF) return -1; - } - - // Markers can start with any number of 0xff - while ((c=io_->getb()) == 0xff) { - if (c == EOF) return -1; - } - return c; - } - - void JpegBase::readMetadata() - { - 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(15); - } - clearMetadata(); - int search = 3; - const long bufMinSize = 16; - long bufRead = 0; - DataBuf buf(bufMinSize); - - // Read section marker - int marker = advanceToMarker(); - if (marker < 0) throw Error(15); - - while (marker != sos_ && marker != eoi_ && search > 0) { - // Read size and signature (ok if this hits EOF) - bufRead = io_->read(buf.pData_, bufMinSize); - if (io_->error()) throw Error(14); - uint16_t size = getUShort(buf.pData_, bigEndian); - - if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) { - if (size < 8) throw Error(15); - // Seek to begining and read the Exif data - io_->seek(8-bufRead, BasicIo::cur); - long sizeExifData = size - 8; - DataBuf rawExif(sizeExifData); - io_->read(rawExif.pData_, sizeExifData); - if (io_->error() || io_->eof()) throw Error(14); - if (exifData_.load(rawExif.pData_, sizeExifData)) throw Error(15); - --search; - } - else if (marker == app13_ && memcmp(buf.pData_ + 2, ps3Id_, 14) == 0) { - if (size < 16) throw Error(15); - // Read the rest of the APP13 segment - // needed if bufMinSize!=16: io_->seek(16-bufRead, BasicIo::cur); - DataBuf psData(size - 16); - io_->read(psData.pData_, psData.size_); - if (io_->error() || io_->eof()) throw Error(14); - const byte *record = 0; - uint16_t sizeIptc = 0; - uint16_t sizeHdr = 0; - // Find actual Iptc data within the APP13 segment - if (!locateIptcData(psData.pData_, psData.size_, &record, - &sizeHdr, &sizeIptc)) { - assert(sizeIptc); - if (iptcData_.load(record + sizeHdr, sizeIptc)) throw Error(15); - } - --search; - } - else if (marker == com_ && comment_.empty()) - { - if (size < 2) throw Error(15); - // Jpegs can have multiple comments, but for now only read - // the first one (most jpegs only have one anyway). Comments - // are simple single byte ISO-8859-1 strings. - io_->seek(2-bufRead, BasicIo::cur); - buf.alloc(size-2); - io_->read(buf.pData_, size-2); - if (io_->error() || io_->eof()) throw Error(14); - comment_.assign(reinterpret_cast<char*>(buf.pData_), size-2); - while ( comment_.length() - && comment_.at(comment_.length()-1) == '\0') { - comment_.erase(comment_.length()-1); - } - --search; - } - else { - if (size < 2) throw Error(15); - // Skip the remainder of the unknown segment - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(15); - } - // Read the beginning of the next segment - marker = advanceToMarker(); - if (marker < 0) throw Error(15); - } - } // JpegBase::readMetadata - - - // Operates on raw data (rather than file streams) to simplify reuse - int JpegBase::locateIptcData(const byte *pPsData, - long sizePsData, - const byte **record, - uint16_t *const sizeHdr, - uint16_t *const sizeIptc) const - { - assert(record); - assert(sizeHdr); - assert(sizeIptc); - // Used for error checking - long position = 0; - - // Data should follow Photoshop format, if not exit - while (position <= (sizePsData - 14) && - memcmp(pPsData + position, bimId_, 4)==0) { - const byte *hrd = pPsData + position; - position += 4; - uint16_t type = getUShort(pPsData+ position, bigEndian); - position += 2; - - // Pascal string is padded to have an even size (including size byte) - byte psSize = pPsData[position] + 1; - psSize += (psSize & 1); - position += psSize; - if (position >= sizePsData) return -2; - - // Data is also padded to be even - long dataSize = getULong(pPsData + position, bigEndian); - position += 4; - if (dataSize > sizePsData - position) return -2; - - if (type == iptc_) { - *sizeIptc = static_cast<uint16_t>(dataSize); - *sizeHdr = psSize + 10; - *record = hrd; - return 0; - } - position += dataSize + (dataSize & 1); - } - return 3; - } // JpegBase::locateIptcData - - void JpegBase::writeMetadata() - { - if (io_->open() != 0) { - throw Error(9, io_->path(), strError()); - } - IoCloser closer(*io_); - BasicIo::AutoPtr tempIo(io_->temporary()); // may throw - assert (tempIo.get() != 0); - - doWriteMetadata(*tempIo); // may throw - io_->close(); - io_->transfer(*tempIo); // may throw - } // JpegBase::writeMetadata - - void JpegBase::doWriteMetadata(BasicIo& outIo) - { - if (!io_->isopen()) throw Error(20); - if (!outIo.isopen()) throw Error(21); - - // Ensure that this is the correct image type - if (!isThisType(*io_, true)) { - if (io_->error() || io_->eof()) throw Error(20); - throw Error(22); - } - - const long bufMinSize = 16; - long bufRead = 0; - DataBuf buf(bufMinSize); - const long seek = io_->tell(); - int count = 0; - int search = 0; - int insertPos = 0; - int skipApp1Exif = -1; - int skipApp13Ps3 = -1; - int skipCom = -1; - DataBuf psData; - - // Write image header - if (writeHeader(outIo)) throw Error(21); - - // Read section marker - int marker = advanceToMarker(); - if (marker < 0) throw Error(22); - - // First find segments of interest. Normally app0 is first and we want - // to insert after it. But if app0 comes after com, app1 and app13 then - // don't bother. - while (marker != sos_ && marker != eoi_ && search < 3) { - // Read size and signature (ok if this hits EOF) - bufRead = io_->read(buf.pData_, bufMinSize); - if (io_->error()) throw Error(20); - uint16_t size = getUShort(buf.pData_, bigEndian); - - if (marker == app0_) { - if (size < 2) throw Error(22); - insertPos = count + 1; - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); - } - else if (marker == app1_ && memcmp(buf.pData_ + 2, exifId_, 6) == 0) { - if (size < 8) throw Error(22); - skipApp1Exif = count; - ++search; - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); - } - else if (marker == app13_ && memcmp(buf.pData_ + 2, ps3Id_, 14) == 0) { - if (size < 16) throw Error(22); - skipApp13Ps3 = count; - ++search; - // needed if bufMinSize!=16: io_->seek(16-bufRead, BasicIo::cur); - psData.alloc(size - 16); - // Load PS data now to allow reinsertion at any point - io_->read(psData.pData_, psData.size_); - if (io_->error() || io_->eof()) throw Error(20); - } - else if (marker == com_ && skipCom == -1) { - if (size < 2) throw Error(22); - // Jpegs can have multiple comments, but for now only handle - // the first one (most jpegs only have one anyway). - skipCom = count; - ++search; - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); - } - else { - if (size < 2) throw Error(22); - if (io_->seek(size-bufRead, BasicIo::cur)) throw Error(22); - } - marker = advanceToMarker(); - if (marker < 0) throw Error(22); - ++count; - } - - if (exifData_.count() > 0) ++search; - if (iptcData_.count() > 0) ++search; - if (!comment_.empty()) ++search; - - io_->seek(seek, BasicIo::beg); - count = 0; - marker = advanceToMarker(); - if (marker < 0) throw Error(22); - - // To simplify this a bit, new segments are inserts at either the start - // or right after app0. This is standard in most jpegs, but has the - // potential to change segment ordering (which is allowed). - // Segments are erased if there is no assigned metadata. - while (marker != sos_ && search > 0) { - // Read size and signature (ok if this hits EOF) - bufRead = io_->read(buf.pData_, bufMinSize); - if (io_->error()) throw Error(20); - // Careful, this can be a meaningless number for empty - // images with only an eoi_ marker - uint16_t size = getUShort(buf.pData_, bigEndian); - - if (insertPos == count) { - byte tmpBuf[18]; - if (!comment_.empty()) { - // Write COM marker, size of comment, and string - tmpBuf[0] = 0xff; - tmpBuf[1] = com_; - us2Data(tmpBuf + 2, - static_cast<uint16_t>(comment_.length()+3), bigEndian); - if (outIo.write(tmpBuf, 4) != 4) throw Error(21); - if (outIo.write((byte*)comment_.data(), (long)comment_.length()) - != (long)comment_.length()) throw Error(21); - if (outIo.putb(0)==EOF) throw Error(21); - if (outIo.error()) throw Error(21); - --search; - } - if (exifData_.count() > 0) { - // Write APP1 marker, size of APP1 field, Exif id and Exif data - DataBuf rawExif(exifData_.copy()); - tmpBuf[0] = 0xff; - tmpBuf[1] = app1_; - us2Data(tmpBuf + 2, - static_cast<uint16_t>(rawExif.size_+8), - bigEndian); - memcpy(tmpBuf + 4, exifId_, 6); - if (outIo.write(tmpBuf, 10) != 10) throw Error(21); - if (outIo.write(rawExif.pData_, rawExif.size_) - != rawExif.size_) throw Error(21); - if (outIo.error()) throw Error(21); - --search; - } - - const byte *record = psData.pData_; - uint16_t sizeIptc = 0; - uint16_t sizeHdr = 0; - // Safe to call with zero psData.size_ - locateIptcData(psData.pData_, psData.size_, &record, &sizeHdr, &sizeIptc); - - // Data is rounded to be even - const int sizeOldData = sizeHdr + sizeIptc + (sizeIptc & 1); - if (psData.size_ > sizeOldData || iptcData_.count() > 0) { - // rawIptc may have size of zero. - DataBuf rawIptc(iptcData_.copy()); - // write app13 marker, new size, and ps3Id - tmpBuf[0] = 0xff; - tmpBuf[1] = app13_; - const int sizeNewData = rawIptc.size_ ? - rawIptc.size_ + (rawIptc.size_ & 1) + 12 : 0; - us2Data(tmpBuf + 2, - static_cast<uint16_t>(psData.size_-sizeOldData+sizeNewData+16), - bigEndian); - memcpy(tmpBuf + 4, ps3Id_, 14); - if (outIo.write(tmpBuf, 18) != 18) throw Error(21); - if (outIo.error()) throw Error(21); - - const long sizeFront = (long)(record - psData.pData_); - const long sizeEnd = psData.size_ - sizeFront - sizeOldData; - // write data before old record. - if (outIo.write(psData.pData_, sizeFront) != sizeFront) throw Error(21); - - // write new iptc record if we have it - if (iptcData_.count() > 0) { - memcpy(tmpBuf, bimId_, 4); - us2Data(tmpBuf+4, iptc_, bigEndian); - tmpBuf[6] = 0; - tmpBuf[7] = 0; - ul2Data(tmpBuf + 8, rawIptc.size_, bigEndian); - if (outIo.write(tmpBuf, 12) != 12) throw Error(21); - if (outIo.write(rawIptc.pData_, rawIptc.size_) - != rawIptc.size_) throw Error(21); - // data is padded to be even (but not included in size) - if (rawIptc.size_ & 1) { - if (outIo.putb(0)==EOF) throw Error(21); - } - if (outIo.error()) throw Error(21); - --search; - } - - // write existing stuff after record - if (outIo.write(record+sizeOldData, sizeEnd) - != sizeEnd) throw Error(21); - if (outIo.error()) throw Error(21); - } - } - if (marker == eoi_) { - break; - } - else if (skipApp1Exif==count || skipApp13Ps3==count || skipCom==count) { - --search; - io_->seek(size-bufRead, BasicIo::cur); - } - else { - if (size < 2) throw Error(22); - buf.alloc(size+2); - io_->seek(-bufRead-2, BasicIo::cur); - io_->read(buf.pData_, size+2); - if (io_->error() || io_->eof()) throw Error(20); - if (outIo.write(buf.pData_, size+2) != size+2) throw Error(21); - if (outIo.error()) throw Error(21); - } - - // Next marker - marker = advanceToMarker(); - if (marker < 0) throw Error(22); - ++count; - } - - // Copy rest of the Io - io_->seek(-2, BasicIo::cur); - buf.alloc(4096); - long readSize = 0; - while ((readSize=io_->read(buf.pData_, buf.size_))) { - if (outIo.write(buf.pData_, readSize) != readSize) throw Error(21); - } - if (outIo.error()) throw Error(21); - - } // JpegBase::doWriteMetadata - - - const byte JpegImage::soi_ = 0xd8; - const byte JpegImage::blank_[] = { - 0xFF,0xD8,0xFF,0xDB,0x00,0x84,0x00,0x10,0x0B,0x0B,0x0B,0x0C,0x0B,0x10,0x0C,0x0C, - 0x10,0x17,0x0F,0x0D,0x0F,0x17,0x1B,0x14,0x10,0x10,0x14,0x1B,0x1F,0x17,0x17,0x17, - 0x17,0x17,0x1F,0x1E,0x17,0x1A,0x1A,0x1A,0x1A,0x17,0x1E,0x1E,0x23,0x25,0x27,0x25, - 0x23,0x1E,0x2F,0x2F,0x33,0x33,0x2F,0x2F,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40, - 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x01,0x11,0x0F,0x0F,0x11,0x13,0x11,0x15,0x12, - 0x12,0x15,0x14,0x11,0x14,0x11,0x14,0x1A,0x14,0x16,0x16,0x14,0x1A,0x26,0x1A,0x1A, - 0x1C,0x1A,0x1A,0x26,0x30,0x23,0x1E,0x1E,0x1E,0x1E,0x23,0x30,0x2B,0x2E,0x27,0x27, - 0x27,0x2E,0x2B,0x35,0x35,0x30,0x30,0x35,0x35,0x40,0x40,0x3F,0x40,0x40,0x40,0x40, - 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0xFF,0xC0,0x00,0x11,0x08,0x00,0x01,0x00, - 0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xFF,0xC4,0x00,0x4B,0x00, - 0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x07,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xDA,0x00,0x0C,0x03,0x01,0x00,0x02, - 0x11,0x03,0x11,0x00,0x3F,0x00,0xA0,0x00,0x0F,0xFF,0xD9 }; - - JpegImage::JpegImage(BasicIo::AutoPtr io, bool create) - : JpegBase(io, create, blank_, sizeof(blank_)) - { - } - - //! @cond IGNORE - JpegImage::JpegRegister::JpegRegister() - { - ImageFactory::registerImage( - Image::jpeg, newJpegInstance, isJpegType); - } - //! @endcond - - int JpegImage::writeHeader(BasicIo& outIo) const - { - // Jpeg header - byte tmpBuf[2]; - tmpBuf[0] = 0xff; - tmpBuf[1] = soi_; - if (outIo.write(tmpBuf, 2) != 2) return 4; - if (outIo.error()) return 4; - return 0; - } - - bool JpegImage::isThisType(BasicIo& iIo, bool advance) const - { - return isJpegType(iIo, advance); - } - - Image::AutoPtr newJpegInstance(BasicIo::AutoPtr io, bool create) - { - Image::AutoPtr image = Image::AutoPtr(new JpegImage(io, create)); - if (!image->good()) { - image.reset(); - } - return image; - } - - bool isJpegType(BasicIo& iIo, bool advance) - { - bool result = true; - byte tmpBuf[2]; - iIo.read(tmpBuf, 2); - if (iIo.error() || iIo.eof()) return false; - - if (0xff!=tmpBuf[0] || JpegImage::soi_!=tmpBuf[1]) { - result = false; - } - if (!advance || !result ) iIo.seek(-2, BasicIo::cur); - return result; - } - - const char ExvImage::exiv2Id_[] = "Exiv2"; - const byte ExvImage::blank_[] = { 0xff,0x01,'E','x','i','v','2',0xff,0xd9 }; - - ExvImage::ExvImage(BasicIo::AutoPtr io, bool create) - : JpegBase(io, create, blank_, sizeof(blank_)) - { - } - - //! @cond IGNORE - ExvImage::ExvRegister::ExvRegister() - { - ImageFactory::registerImage( - Image::exv, newExvInstance, isExvType); - } - //! @endcond - - int ExvImage::writeHeader(BasicIo& outIo) const - { - // Exv header - byte tmpBuf[7]; - tmpBuf[0] = 0xff; - tmpBuf[1] = 0x01; - memcpy(tmpBuf + 2, exiv2Id_, 5); - if (outIo.write(tmpBuf, 7) != 7) return 4; - if (outIo.error()) return 4; - return 0; - } - - bool ExvImage::isThisType(BasicIo& iIo, bool advance) const - { - return isExvType(iIo, advance); - } - - Image::AutoPtr newExvInstance(BasicIo::AutoPtr io, bool create) - { - Image::AutoPtr image; - if (create) { - image = Image::AutoPtr(new ExvImage(io, true)); - } - else { - image = Image::AutoPtr(new ExvImage(io, false)); - } - if (!image->good()) image.reset(); - return image; - } - - bool isExvType(BasicIo& iIo, bool advance) - { - bool result = true; - byte tmpBuf[7]; - iIo.read(tmpBuf, 7); - if (iIo.error() || iIo.eof()) return false; - - if ( 0xff != tmpBuf[0] || 0x01 != tmpBuf[1] - || memcmp(tmpBuf + 2, ExvImage::exiv2Id_, 5) != 0) { - result = false; - } - if (!advance || !result ) iIo.seek(-7, BasicIo::cur); - return result; - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/jpgimage.hpp b/src/plugins/exiv2/jpgimage.hpp @@ -1,405 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 jpgimage.hpp - @brief Class JpegImage to access JPEG images - @version $Rev: 563 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @author Brad Schick (brad) - <a href="mailto:brad@robotbattle.com">brad@robotbattle.com</a> - @date 15-Jan-05, brad: split out from image.cpp - */ -#ifndef JPGIMAGE_HPP_ -#define JPGIMAGE_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "image.hpp" -#include "basicio.hpp" -#include "exif.hpp" -#include "iptc.hpp" - -// + standard includes -#include <string> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - - -// ***************************************************************************** -// class definitions - - /*! - @brief Abstract helper base class to access JPEG images. - */ - class JpegBase : public Image { - public: - //! @name Creators - //@{ - //! Virtual destructor. - virtual ~JpegBase() {} - //@} - //! @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(); - /*! - @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(); - /*! - @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 clearExifData(); - void setIptcData(const IptcData& iptcData); - void clearIptcData(); - void setComment(const std::string& comment); - void clearComment(); - void setMetadata(const Image& image); - void clearMetadata(); - //@} - - //! @name Accessors - //@{ - bool good() const; - const ExifData& exifData() const { return exifData_; } - ExifData& exifData() { return exifData_; } - const IptcData& iptcData() const { return iptcData_; } - IptcData& iptcData() { return iptcData_; } - std::string comment() const { return comment_; } - BasicIo& io() const { return *io_; } - //@} - protected: - //! @name Creators - //@{ - /*! - @brief Constructor that can either open an existing image or create - a new image from scratch. If a new image is to be created, any - existing data is overwritten. - @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 image should be created (true). - @param initData Data to initialize newly created images. Only used - when \em create is true. Should contain data for the smallest - valid image of the calling subclass. - @param dataSize Size of initData in bytes. - */ - JpegBase(BasicIo::AutoPtr io, bool create, - const byte initData[], long dataSize); - //@} - //! @name Manipulators - //@{ - /*! - @brief Writes the image 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> - */ - virtual int writeHeader(BasicIo& oIo) const =0; - //@} - //! @name Accessors - //@{ - /*! - @brief Determine if the content of the BasicIo instance is of the - type supported by this class. - - 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;<BR> - false if the data does not match;<BR> - */ - virtual bool isThisType(BasicIo& iIo, bool advance) const =0; - //@} - - // Constant Data - static const byte sos_; //!< JPEG SOS marker - static const byte eoi_; //!< JPEG EOI marker - static const byte app0_; //!< JPEG APP0 marker - static const byte app1_; //!< JPEG APP1 marker - static const byte app13_; //!< JPEG APP13 marker - static const byte com_; //!< JPEG Comment marker - static const char exifId_[]; //!< Exif identifier - static const char jfifId_[]; //!< JFIF identifier - static const char ps3Id_[]; //!< Photoshop marker - static const char bimId_[]; //!< Photoshop marker - static const uint16_t iptc_; //!< Photoshop Iptc marker - - private: - // DATA - BasicIo::AutoPtr io_; //!< Image data io pointer - ExifData exifData_; //!< Exif data container - IptcData iptcData_; //!< Iptc data container - std::string comment_; //!< JPEG comment - - // METHODS - /*! - @brief Advances associated io instance to one byte past the next - Jpeg marker and returns the marker. This method should be called - when the BasicIo instance is positioned one byte past the end of a - Jpeg segment. - @return the next Jpeg segment marker if successful;<BR> - -1 if a maker was not found before EOF;<BR> - */ - int advanceToMarker() const; - /*! - @brief Locates Photoshop formated Iptc data in a memory buffer. - Operates on raw data to simplify reuse. - @param pPsData Pointer to buffer containing entire payload of - Photoshop formated APP13 Jpeg segment. - @param sizePsData Size in bytes of pPsData. - @param record Output value that is set to the start of the Iptc - data block within pPsData (may not be null). - @param sizeHdr Output value that is set to the size of the header - within the Iptc data block pointed to by record (may not - be null). - @param sizeIptc Output value that is set to the size of the actual - Iptc data within the Iptc data block pointed to by record - (may not be null). - @return 0 if successful;<BR> - 3 if no Iptc data was found in pPsData;<BR> - -2 if the pPsData buffer does not contain valid data. - */ - int locateIptcData(const byte *pPsData, - long sizePsData, - const byte **record, - uint16_t *const sizeHdr, - uint16_t *const sizeIptc) const; - /*! - @brief Initialize the image with the provided data. - @param initData Data to be written to the associated BasicIo - @param dataSize Size in bytes of data to be written - @return 0 if successful;<BR> - 4 if the image can not be written to. - */ - int initImage(const byte initData[], long dataSize); - /*! - @brief Provides the main implementation of writeMetadata() by - writing all buffered metadata to the provided BasicIo. - @param oIo BasicIo instance to write to (a temporary location). - - @return 4 if opening or writing to the associated BasicIo fails - */ - void doWriteMetadata(BasicIo& oIo); - - // NOT Implemented - //! Default constructor. - JpegBase(); - //! Copy constructor - JpegBase(const JpegBase& rhs); - //! Assignment operator - JpegBase& operator=(const JpegBase& rhs); - }; // class JpegBase - - /*! - @brief Class to access JPEG images - */ - class JpegImage : public JpegBase { - friend bool isJpegType(BasicIo& iIo, bool advance); - public: - //! @name Creators - //@{ - /*! - @brief Constructor that can either open an existing Jpeg 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). - */ - JpegImage(BasicIo::AutoPtr io, bool create); - //! Destructor - ~JpegImage() {} - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct JpegRegister{ - JpegRegister(); - }; - //! @endcond - protected: - //! @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; - //@} - //! @name Manipulators - //@{ - /*! - @brief Writes a Jpeg header (aka signature) to the BasicIo instance. - @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; - //@} - private: - // Constant data - static const byte soi_; // SOI marker - static const byte blank_[]; // Minimal Jpeg image - - // NOT Implemented - //! Default constructor - JpegImage(); - //! Copy constructor - JpegImage(const JpegImage& rhs); - //! Assignment operator - JpegImage& operator=(const JpegImage& rhs); - }; // class JpegImage - - static JpegImage::JpegRegister jpegReg; - - //! Helper class to access %Exiv2 files - class ExvImage : public JpegBase { - friend bool isExvType(BasicIo& iIo, bool advance); - public: - //! @name Creators - //@{ - /*! - @brief Constructor that can either open an existing Exv 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). - */ - ExvImage(BasicIo::AutoPtr io, bool create); - //! Destructor - ~ExvImage() {} - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct ExvRegister{ - ExvRegister(); - }; - //! @endcond - protected: - //! @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; - //@} - //! @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; - //@} - private: - // Constant data - static const char exiv2Id_[]; // Exv identifier - static const byte blank_[]; // Minimal exiv file - - // NOT Implemented - //! Default constructor - ExvImage(); - //! Copy constructor - ExvImage(const ExvImage& rhs); - //! Assignment operator - ExvImage& operator=(const ExvImage& rhs); - }; // class ExvImage - - static ExvImage::ExvRegister exvReg; -} // namespace Exiv2 - - -#endif // #ifndef JPGIMAGE_HPP_ diff --git a/src/plugins/exiv2/makernote.cpp b/src/plugins/exiv2/makernote.cpp @@ -1,462 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: makernote.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 18-Feb-04, ahu: created - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: makernote.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// Define DEBUG_* to output debug information to std::cerr, e.g, by calling -// make like this: make DEFS=-DDEBUG_MAKERNOTE makernote.o -//#define DEBUG_MAKERNOTE -//#define DEBUG_REGISTRY - -// ***************************************************************************** -// included header files -#include "makernote.hpp" -#include "error.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <iostream> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - MakerNote::MakerNote(bool alloc) - : alloc_(alloc), offset_(0), byteOrder_(invalidByteOrder) - { - } - - MakerNote::AutoPtr MakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - MakerNote::AutoPtr MakerNote::clone() const - { - return AutoPtr(clone_()); - } - - IfdMakerNote::IfdMakerNote(IfdId ifdId, bool alloc, bool hasNext) - : MakerNote(alloc), - absOffset_(true), adjOffset_(0), ifd_(ifdId, 0, alloc, hasNext) - { - } - - IfdMakerNote::IfdMakerNote(const IfdMakerNote& rhs) - : MakerNote(rhs), absOffset_(rhs.absOffset_), adjOffset_(rhs.adjOffset_), - header_(rhs.header_.size_), ifd_(rhs.ifd_) - { - memcpy(header_.pData_, rhs.header_.pData_, header_.size_); - } - - int IfdMakerNote::read(const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - // Remember the offset - offset_ = offset; - // Set byte order if none is set yet - if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder; - // Read and check the header (and set offset adjustment) - int rc = readHeader(buf, len, byteOrder); - if (rc == 0) { - rc = checkHeader(); - } - // Adjust the offset - offset = absOffset_ ? offset + adjOffset_ : adjOffset_; - // Read the makernote IFD - if (rc == 0) { - rc = ifd_.read(buf + headerSize(), - len - headerSize(), - byteOrder_, - offset); - } - if (rc == 0) { - // IfdMakerNote currently does not support multiple IFDs - if (ifd_.next() != 0) { -#ifndef SUPPRESS_WARNINGS - std::cerr << "Warning: Makernote IFD has a next pointer != 0 (" - << ifd_.next() - << "). Ignored.\n"; -#endif - } - } -#ifdef DEBUG_MAKERNOTE - hexdump(std::cerr, buf, len, offset); - if (rc == 0) ifd_.print(std::cerr); -#endif - - return rc; - } // IfdMakerNote::read - - long IfdMakerNote::copy(byte* buf, ByteOrder byteOrder, long offset) - { - // Remember the new offset - offset_ = offset; - // Set byte order if none is set yet - if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder; - // Adjust the offset - offset = absOffset_ ? offset + adjOffset_ : adjOffset_; - - long len = 0; - len += copyHeader(buf); - len += ifd_.copy(buf + len, byteOrder_, offset); - - return len; - } // IfdMakerNote::copy - - int IfdMakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - // Default implementation does nothing, assuming there is no header - return 0; - } - - void IfdMakerNote::updateBase(byte* pNewBase) - { - if (absOffset_) { - ifd_.updateBase(pNewBase); - } - } - - int IfdMakerNote::checkHeader() const - { - // Default implementation does nothing, assuming there is no header - return 0; - } - - long IfdMakerNote::copyHeader(byte* buf) const - { - if (header_.size_ != 0) memcpy(buf, header_.pData_, header_.size_); - return header_.size_; - } - - long IfdMakerNote::headerSize() const - { - return header_.size_; - } - - Entries::const_iterator IfdMakerNote::findIdx(int idx) const - { - return ifd_.findIdx(idx); - } - - long IfdMakerNote::size() const - { - return headerSize() + ifd_.size() + ifd_.dataSize(); - } - - IfdMakerNote::AutoPtr IfdMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - IfdMakerNote::AutoPtr IfdMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - int MakerNoteFactory::Init::count = 0; - - MakerNoteFactory::Init::Init() - { - ++count; - } - - MakerNoteFactory::Init::~Init() - { - if (--count == 0) { - Exiv2::MakerNoteFactory::cleanup(); - } - } - - MakerNoteFactory::Registry* MakerNoteFactory::pRegistry_ = 0; - MakerNoteFactory::IfdIdRegistry* MakerNoteFactory::pIfdIdRegistry_ = 0; - - void MakerNoteFactory::cleanup() - { - if (pRegistry_ != 0) { - Registry::iterator e = pRegistry_->end(); - for (Registry::iterator i = pRegistry_->begin(); i != e; ++i) { - delete i->second; - } - delete pRegistry_; - } - - if (pIfdIdRegistry_ != 0) { - IfdIdRegistry::iterator e = pIfdIdRegistry_->end(); - for (IfdIdRegistry::iterator i = pIfdIdRegistry_->begin(); i != e; ++i) { - delete i->second; - } - delete pIfdIdRegistry_; - } - } - - void MakerNoteFactory::init() - { - if (0 == pRegistry_) { - pRegistry_ = new Registry; - } - if (0 == pIfdIdRegistry_) { - pIfdIdRegistry_ = new IfdIdRegistry; - } - } // MakerNoteFactory::init - - void MakerNoteFactory::registerMakerNote(IfdId ifdId, - MakerNote::AutoPtr makerNote) - { - init(); - MakerNote* pMakerNote = makerNote.release(); - assert(pMakerNote); - IfdIdRegistry::iterator pos = pIfdIdRegistry_->find(ifdId); - if (pos != pIfdIdRegistry_->end()) { - delete pos->second; - pos->second = 0; - } - (*pIfdIdRegistry_)[ifdId] = pMakerNote; - } // MakerNoteFactory::registerMakerNote - - MakerNote::AutoPtr MakerNoteFactory::create(IfdId ifdId, bool alloc) - { - assert(pIfdIdRegistry_ != 0); - IfdIdRegistry::const_iterator i = pIfdIdRegistry_->find(ifdId); - if (i == pIfdIdRegistry_->end()) return MakerNote::AutoPtr(0); - assert(i->second); - return i->second->create(alloc); - } // MakerNoteFactory::create - - void MakerNoteFactory::registerMakerNote(const std::string& make, - const std::string& model, - CreateFct createMakerNote) - { -#ifdef DEBUG_REGISTRY - std::cerr << "Registering MakerNote create function for \"" - << make << "\" and \"" << model << "\".\n"; -#endif - init(); - // Todo: use case insensitive make and model comparisons - - // Find or create a registry entry for make - ModelRegistry* pModelRegistry = 0; - assert(pRegistry_ != 0); - Registry::const_iterator end1 = pRegistry_->end(); - Registry::const_iterator pos1; - for (pos1 = pRegistry_->begin(); pos1 != end1; ++pos1) { - if (pos1->first == make) break; - } - if (pos1 != end1) { - pModelRegistry = pos1->second; - } - else { - pModelRegistry = new ModelRegistry; - pRegistry_->push_back(std::make_pair(make, pModelRegistry)); - } - // Find or create a registry entry for model - ModelRegistry::iterator end2 = pModelRegistry->end(); - ModelRegistry::iterator pos2; - for (pos2 = pModelRegistry->begin(); pos2 != end2; ++pos2) { - if (pos2->first == model) break; - } - if (pos2 != end2) { - pos2->second = createMakerNote; - } - else { - pModelRegistry->push_back(std::make_pair(model, createMakerNote)); - } - } // MakerNoteFactory::registerMakerNote - - MakerNote::AutoPtr MakerNoteFactory::create(const std::string& make, - const std::string& model, - bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { -#ifdef DEBUG_REGISTRY - std::cerr << "Entering MakerNoteFactory::create(\"" - << make << "\", \"" << model << "\", " - << (alloc == true ? "true" : "false") << ")\n"; -#endif - // loop through each make of the registry to find the best matching make - int score = 0; - ModelRegistry* pModelRegistry = 0; -#ifdef DEBUG_REGISTRY - std::string makeMatch; - std::cerr << "Searching make registry...\n"; -#endif - assert(pRegistry_ != 0); - Registry::const_iterator end1 = pRegistry_->end(); - Registry::const_iterator pos1; - for (pos1 = pRegistry_->begin(); pos1 != end1; ++pos1) { - int rc = match(pos1->first, make); - if (rc > score) { - score = rc; -#ifdef DEBUG_REGISTRY - makeMatch = pos1->first; -#endif - pModelRegistry = pos1->second; - } - } - if (pModelRegistry == 0) return MakerNote::AutoPtr(0); -#ifdef DEBUG_REGISTRY - std::cerr << "Best match is \"" << makeMatch << "\".\n"; -#endif - - // loop through each model of the model registry to find the best match - score = 0; - CreateFct createMakerNote = 0; -#ifdef DEBUG_REGISTRY - std::string modelMatch; - std::cerr << "Searching model registry...\n"; -#endif - ModelRegistry::const_iterator end2 = pModelRegistry->end(); - ModelRegistry::const_iterator pos2; - for (pos2 = pModelRegistry->begin(); pos2 != end2; ++pos2) { - int rc = match(pos2->first, model); - if (rc > score) { - score = rc; -#ifdef DEBUG_REGISTRY - modelMatch = pos2->first; -#endif - createMakerNote = pos2->second; - } - } - if (createMakerNote == 0) return MakerNote::AutoPtr(0); -#ifdef DEBUG_REGISTRY - std::cerr << "Best match is \"" << modelMatch << "\".\n"; -#endif - - return createMakerNote(alloc, buf, len, byteOrder, offset); - } // MakerNoteFactory::create - - int MakerNoteFactory::match(const std::string& regEntry, - const std::string& key) - { -#ifdef DEBUG_REGISTRY - std::cerr << " Matching registry entry \"" << regEntry << "\" (" - << (int)regEntry.size() << ") with key \"" << key << "\" (" - << (int)key.size() << "): "; -#endif - // Todo: make the comparisons case insensitive - - // Handle exact match (this is only necessary because of the different - // return value - the following algorithm also finds exact matches) - if (regEntry == key) { -#ifdef DEBUG_REGISTRY - std::cerr << "Exact match (score: " << (int)key.size() + 2 << ")\n"; -#endif - return static_cast<int>(key.size()) + 2; - } - std::string uKey = key; - std::string uReg = regEntry; - - int count = 0; // number of matching characters - std::string::size_type ei = 0; // index in the registry entry - std::string::size_type ki = 0; // index in the key - - while (ei != std::string::npos) { - - std::string::size_type pos = uReg.find('*', ei); - if (pos != ei) { - std::string ss = pos == std::string::npos ? - uReg.substr(ei) : uReg.substr(ei, pos - ei); - - if (ki == std::string::npos) { -#ifdef DEBUG_REGISTRY - std::cerr << "Not a match.\n"; -#endif - return 0; - } - - bool found = false; - // Find the substr ss in the key starting from index ki. - // Take care of the special cases - // + where the substr must match the key from beg to end, - // + from beg, - // + to end - // + and where it can be anywhere in the key. - // If found, ki is adjusted to the position in the key after ss. - if (ei == 0 && pos == std::string::npos) { // ei == 0 => ki == 0 - if (0 == uKey.compare(ss)) { - found = true; - ki = std::string::npos; - } - } - else if (ei == 0) { // ei == 0 => ki == 0 - if (0 == uKey.compare(0, ss.size(), ss)) { - found = true; - ki = ss.size(); - } - } - else if (pos == std::string::npos) { - if ( ss.size() <= uKey.size() - && ki <= uKey.size() - ss.size()) { - if (0 == uKey.compare( - uKey.size() - ss.size(), ss.size(), ss)) { - found = true; - ki = std::string::npos; - } - } - } - else { - std::string::size_type idx = uKey.find(ss, ki); - if (idx != std::string::npos) { - found = true; - ki = idx + ss.size(); - } - } - - if (found) { - count += static_cast<int>(ss.size()); - } - else { -#ifdef DEBUG_REGISTRY - std::cerr << "Not a match.\n"; -#endif - return 0; - } - } // if the substr is not empty - - ei = pos == std::string::npos ? std::string::npos : pos + 1; - - } // while ei doesn't point to the end of the registry entry - -#ifdef DEBUG_REGISTRY - std::cerr << "Match (score: " << count + 1 << ")\n"; -#endif - return count + 1; - - } // MakerNoteFactory::match - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/makernote.hpp b/src/plugins/exiv2/makernote.hpp @@ -1,508 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 makernote.hpp - @brief Contains the Exif %MakerNote interface, IFD %MakerNote and a - MakerNote factory - @version $Rev: 598 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 18-Feb-04, ahu: created - */ -#ifndef MAKERNOTE_HPP_ -#define MAKERNOTE_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "ifd.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <utility> -#include <vector> -#include <map> -#include <memory> -#include <string.h> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// class definitions - - /*! - @brief Exif makernote interface - - %MakerNote is a low-level container for makernote entries. The ExifData - container uses makernote entries just like the other Exif metadata. Thus, - clients can access Exif and makernote tags and their values uniformly - through the ExifData interface. The role of %MakerNote is very similar to - that of class Ifd (but makernotes do not need to be in IFD format, see - below). In addition, it provides %MakerNote specific tag descriptions and - print functions to interpret the makernote values. - - MakerNote holds methods and functionality to - - read the makernote from a character buffer - - copy the makernote to a character buffer - - maintain a list of makernote entries (similar to IFD entries) - - interpret (print) the values of makernote tags - - Makernotes can be added to the system by subclassing %MakerNote and - registering a create function for the new subclass together with the - camera make and model (which may contain wildcards) in the - MakerNoteFactory. Since the majority of makernotes are in IFD format, - subclass IfdMakerNote is provided. It contains an IFD container and - implements all interface methods related to the makernote entries. <BR> - - To implement a new IFD makernote, all that you need to do is - - subclass %IfdMakerNote, - - implement methods to read and check the header (if any) as well as - clone and create functions, - - add a list of tag descriptions and appropriate print functions and - - register the camera make/model and create function in the makernote factory. - . - See existing makernote implementations for examples, e.g., CanonMakerNote - or FujiMakerNote. - - Finally, the header file which defines the static variable - \em register*MakerNote needs to be included from mn.hpp, to ensure that - the makernote is automatically registered in the factory. - */ - class MakerNote { - //! @name Not implemented - //@{ - //! Assignment not allowed (memory management mode alloc_ is const) - MakerNote& operator=(const MakerNote& rhs); - //@} - - public: - //! Shortcut for a %MakerNote auto pointer. - typedef std::auto_ptr<MakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the Entries. - */ - explicit MakerNote(bool alloc =true); - //! Virtual destructor. - virtual ~MakerNote() {} - //@} - - //! @name Manipulators - //@{ - /*! - @brief Read the makernote, including the makernote header, from - character buffer buf of length len at position offset (from the - start of the TIFF header) and encoded in byte order byteOrder. - Return 0 if successful. - */ - virtual int read(const byte* buf, - long len, - ByteOrder byteOrder, - long offset) =0; - /*! - @brief Copy (write) the makerNote to the character buffer buf at - position offset (from the start of the TIFF header), encoded - in byte order byteOrder. Update internal offsets if necessary. - Return the number of bytes written. - */ - virtual long copy(byte* buf, ByteOrder byteOrder, long offset) =0; - /*! - @brief Add the entry to the makernote. No duplicate-check is performed, - i.e., it is possible to add multiple entries with the same tag. - The memory allocation mode of the entry to be added must be the - same as that of the makernote and the IFD id of the entry must - be set to 'makerIfd'. - */ - virtual void add(const Entry& entry) =0; - //! The first makernote entry - virtual Entries::iterator begin() =0; - //! End of the makernote entries - virtual Entries::iterator end() =0; - /*! - @brief Update the base pointer of the %MakerNote and all its entries - to \em pNewBase. - - Allows to re-locate the underlying data buffer to a new location - \em pNewBase. This method only has an effect in non-alloc mode. - */ - virtual void updateBase(byte* pNewBase) =0; - //@} - - //! @name Accessors - //@{ - //! Return the byte order (little or big endian). - ByteOrder byteOrder() const { return byteOrder_; } - //! Return the offset of the makernote from the start of the TIFF header - long offset() const { return offset_; } - /*! - @brief Return an auto-pointer to an newly created, empty instance of - the same type as this. The makernote entries are <B>not</B> - copied. The caller owns the new object and the auto-pointer - ensures that it will be deleted. - - @param alloc Memory management model for the newly created object. - Indicates if memory required to store data should be allocated - and deallocated (true) or not (false). If false, only pointers - to the buffer provided to read() will be kept. See Ifd for more - background on this concept. - */ - AutoPtr create(bool alloc =true) const; - /*! - @brief Return an auto-pointer to a clone of this object. The caller - owns the new object and the auto-pointer ensures that it will - be deleted. - - @note In non-alloc mode the clone potentially contains pointers to - the same data buffer as the original. - Use updateBase(byte* pNewBase) to adjust them. - */ - AutoPtr clone() const; - //! The first makernote entry - virtual Entries::const_iterator begin() const =0; - //! End of the makernote entries - virtual Entries::const_iterator end() const =0; - //! Find an entry by idx, return a const iterator to the record - virtual Entries::const_iterator findIdx(int idx) const =0; - //! Return the size of the makernote in bytes - virtual long size() const =0; - //@} - - protected: - // DATA - /*! - @brief Flag to control the memory management: <BR> - True: requires memory allocation and deallocation, <BR> - False: no memory management needed. - */ - const bool alloc_; - /*! - @brief Offset of the makernote from the start of the TIFF header - (for offset()). - */ - long offset_; - /*! - @brief Alternative byte order to use, invalid if the byte order of the - Exif block can be used - */ - ByteOrder byteOrder_; - - private: - //! Internal virtual create function. - virtual MakerNote* create_(bool alloc =true) const =0; - //! Internal virtual copy constructor. - virtual MakerNote* clone_() const =0; - - }; // class MakerNote - - //! Type for a pointer to a function creating a makernote - typedef MakerNote::AutoPtr (*CreateFct)(bool, const byte*, long, ByteOrder, long); - - /*! - @brief Interface for MakerNotes in IFD format. See MakerNote. - */ - class IfdMakerNote : public MakerNote { - //! @name Not implemented - //@{ - //! Assignment not allowed (Ifd does not have an assignment operator) - IfdMakerNote& operator=(const IfdMakerNote& rhs); - //@} - - public: - //! Shortcut for an %IfdMakerNote auto pointer. - typedef std::auto_ptr<IfdMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Requires an %Ifd id and allows to choose whether - or not memory management is needed for the Entries and whether - the IFD has a next pointer. - */ - explicit IfdMakerNote(IfdId ifdId, bool alloc =true, bool hasNext =true); - //! Copy constructor - IfdMakerNote(const IfdMakerNote& rhs); - //! Virtual destructor - virtual ~IfdMakerNote() {} - //@} - - //! @name Manipulators - //@{ - virtual int read(const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - /*! - @brief Read the makernote header from the makernote databuffer. This - method must set the offset adjustment (adjOffset_), if needed - (assuming that the required information is in the header). - Return 0 if successful. - @note The default implementation does nothing, assuming there is no - header - */ - virtual int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - virtual long copy(byte* buf, ByteOrder byteOrder, long offset); - virtual void add(const Entry& entry) { ifd_.add(entry); } - virtual Entries::iterator begin() { return ifd_.begin(); } - virtual Entries::iterator end() { return ifd_.end(); } - virtual void updateBase(byte* pNewBase); - //@} - - //! @name Accessors - //@{ - virtual Entries::const_iterator begin() const { return ifd_.begin(); } - virtual Entries::const_iterator end() const { return ifd_.end(); } - virtual Entries::const_iterator findIdx(int idx) const; - virtual long size() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - /*! - @brief Check the makernote header. This will typically check if a - required prefix string is present in the header. Return 0 if - successful. - @note The default implementation does nothing, assuming there is no - header - */ - virtual int checkHeader() const; - /*! - @brief Write the makernote header to a character buffer, return the - number of characters written. - @note The default implementation copies the header_ buffer. - */ - virtual long copyHeader(byte* buf) const; - /*! - @brief Return the size of the makernote header in bytes. - @note The default implementation returns the size of the header_ - buffer. - */ - virtual long headerSize() const; - //@} - - protected: - // DATA - /*! - @brief True: Adjustment of the IFD offsets is to be added to the - offset from the start of the TIFF header (i.e., the - start of the Exif data section), - False: Adjustment of the IFD offsets is a suitable absolute - value. Ignore the offset from the start of the TIFF - header. - */ - bool absOffset_; - /*! - @brief Adjustment of the IFD offsets relative to the start of the - TIFF header or to the start of the makernote, depending on - the setting of absOffset_. - */ - long adjOffset_; - //! Data buffer for the makernote header - DataBuf header_; - //! The makernote IFD - Ifd ifd_; - - private: - virtual IfdMakerNote* create_(bool alloc =true) const =0; - virtual IfdMakerNote* clone_() const =0; - - }; // class IfdMakerNote - - /*! - @brief Factory for MakerNote objects. - - Maintains an associative list (tree) of camera makes/models and - corresponding %MakerNote create functions. Creates an instance of the - %MakerNote for one camera make/model. The factory is implemented as a - static class. - */ - class MakerNoteFactory { - public: - //! Destructor. - static void cleanup(); - /*! - @brief Register a %MakerNote create function for a camera make and - model. - - Registers a create function for a %MakerNote for a given make and - model combination with the factory. Both the make and model strings - may contain wildcards ('*', e.g., "Canon*"). If the make already - exists in the registry, then a new branch for the model is added. If - the model also already exists, then the new create function replaces - the old one. - - @param make Camera manufacturer. (Typically the string from the Exif - make tag.) - @param model Camera model. (Typically the string from the Exif - model tag.) - @param createMakerNote Pointer to a function to create a new - %MakerNote of a particular type. - */ - static void registerMakerNote(const std::string& make, - const std::string& model, - CreateFct createMakerNote); - - //! Register a %MakerNote prototype in the IFD id registry. - static void registerMakerNote(IfdId ifdId, MakerNote::AutoPtr makerNote); - - /*! - @brief Create the appropriate %MakerNote based on camera make and - model and possibly the contents of the makernote itself, return - an auto-pointer to the newly created MakerNote instance. Return - 0 if no %MakerNote is defined for the camera model. - - The method searches the make-model tree for a make and model - combination in the registry that matches the search key. The search is - case insensitive (Todo: implement case-insensitive comparisons) and - wildcards in the registry entries are supported. First the best - matching make is searched, then the best matching model for this make - is searched. If there is no matching make or no matching model within - the models registered for the best matching make, then no makernote - is created and the function returns 0. If a match is found, the - function invokes the registered create function and returns an - auto-pointer to the newly created MakerNote. The makernote pointed to - is owned by the caller of the function and the auto-pointer ensures - that it is deleted. The best match is an exact match, then a match is - rated according to the number of matching characters. The makernote - buffer is passed on to the create function, which can based on its - content, automatically determine the correct version or flavour of the - makernote required. This is used, e.g., to determine which of the - three Nikon makernotes to create. - - @param make Camera manufacturer. (Typically the string from the Exif - make tag.) - @param model Camera model. (Typically the string from the Exif - model tag.) - @param alloc Memory management model for the new MakerNote. Determines - if memory required to store data should be allocated and - deallocated (true) or not (false). If false, only pointers to - the buffer provided to read() will be kept. See Ifd for more - background on this concept. - @param buf Pointer to the makernote character buffer. - @param len Length of the makernote character buffer. - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded. - @param offset Offset from the start of the TIFF header of the makernote - buffer. - - @return An auto-pointer that owns a %MakerNote for the camera model. - If the camera is not supported, the pointer is 0. - */ - static MakerNote::AutoPtr create(const std::string& make, - const std::string& model, - bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - - //! Create a %MakerNote for an IFD id. - static MakerNote::AutoPtr create(IfdId ifdId, bool alloc =true); - - /*! - @brief Match a registry entry with a key (used for make and model). - - The matching algorithm is case insensitive and wildcards ('*') in the - registry entry are supported. The best match is an exact match, then - a match is rated according to the number of matching characters. - - @return A score value indicating how good the key and registry entry - match. 0 means no match, values greater than 0 indicate a - match, larger values are better matches:<BR> - 0: key and registry entry do not match<BR> - 1: a pure wildcard match, i.e., the registry entry is just - a wildcard.<BR> - Score values greater than 1 are computed by adding 1 to the - number of matching characters, except for an exact match, - which scores 2 plus the number of matching characters. - */ - static int match(const std::string& regEntry, const std::string& key); - - /*! - @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: - //! @name Creators - //@{ - //! Prevent construction: not implemented. - MakerNoteFactory() {} - //! Prevent copy construction: not implemented. - MakerNoteFactory(const MakerNoteFactory& rhs); - //@} - - //! Creates the private static instance - static void init(); - - //! Type used to store model labels and %MakerNote create functions - typedef std::vector<std::pair<std::string, CreateFct> > ModelRegistry; - //! Type used to store a list of make labels and model registries - typedef std::vector<std::pair<std::string, ModelRegistry*> > Registry; - //! Type used to store a list of IFD ids and %MakerNote prototypes - typedef std::map<IfdId, MakerNote*> IfdIdRegistry; - - // DATA - //! List of makernote types and corresponding makernote create functions. - static Registry* pRegistry_; - //! List of makernote IFD ids and corresponding create functions. - static IfdIdRegistry* pIfdIdRegistry_; - - }; // class MakerNoteFactory - -} // namespace Exiv2 - -namespace { - /*! - Each translation unit that includes makernote.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::MakerNoteFactory::Init makerNoteFactoryInit; -} - -#endif // #ifndef MAKERNOTE_HPP_ diff --git a/src/plugins/exiv2/metadatum.cpp b/src/plugins/exiv2/metadatum.cpp @@ -1,76 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: metadatum.cpp - Version: $Rev: 538 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - Brad Schick (brad) <brad@robotbattle.com> - History: 26-Jan-04, ahu: created - 31-Jul-04, brad: isolated as a component - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: metadatum.cpp 538 2005-03-12 16:43:06Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "metadatum.hpp" - -// + standard includes -#include <iostream> -#include <iomanip> - - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - Key::AutoPtr Key::clone() const - { - return AutoPtr(clone_()); - } - - std::ostream& operator<<(std::ostream& os, const Metadatum& md) - { - os << "0x" << std::setw(4) << std::setfill('0') << std::right - << std::hex << md.tag() << " " - << std::setw(40) << std::setfill(' ') << std::left - << md.key() << " " - << std::setw(9) << std::setfill(' ') << std::left - << md.typeName() << " " - << std::dec << md.value() - << "\n"; - return os; - } - - bool cmpMetadataByTag(const Metadatum& lhs, const Metadatum& rhs) - { - return lhs.tag() < rhs.tag(); - } - - - bool cmpMetadataByKey(const Metadatum& lhs, const Metadatum& rhs) - { - return lhs.key() < rhs.key(); - } - -} // namespace Exiv2 - diff --git a/src/plugins/exiv2/metadatum.hpp b/src/plugins/exiv2/metadatum.hpp @@ -1,294 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 metadatum.hpp - @brief Provides abstract base classes Metadatum and Key - @version $Rev: 560 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @author Brad Schick (brad) - <a href="mailto:brad@robotbattle.com">brad@robotbattle.com</a> - @date 09-Jan-04, ahu: created<BR> - 31-Jul-04, brad: isolated as a component<BR> - 23-Aug-04, ahu: added Key - */ -#ifndef METADATUM_HPP_ -#define METADATUM_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "value.hpp" - -// + standard includes -#include <string> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class definitions - - /*! - @brief Abstract base class defining the %Key of a metadatum. - Keys are used to identify and group metadata. - */ - class Key { - public: - //! Shortcut for a %Key auto pointer. - typedef std::auto_ptr<Key> AutoPtr; - - //! @name Creators - //@{ - //! Destructor - virtual ~Key() {} - //@} - - //! @name Accessors - //@{ - /*! - @brief Return the key of the metadatum as a string. The key is of the - form 'familyName.groupName.tagName'. Note however that the - key is not necessarily unique, e.g., an ExifData may contain - multiple metadata with the same key. - */ - virtual std::string key() const =0; - //! Return an identifier for the type of metadata (the first part of the key) - virtual const char* familyName() const =0; - //! Return the name of the group (the second part of the key) - virtual std::string groupName() const =0; - //! Return the name of the tag (which is also the third part of the key) - virtual std::string tagName() const =0; - //! Return the tag number - virtual uint16_t tag() const =0; - /*! - @brief Return an auto-pointer to a copy of itself (deep copy). - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - */ - AutoPtr clone() const; - /*! - @brief Write the key to an output stream. You do not usually have - to use this function; it is used for the implementation of - the output operator for %Key, - operator<<(std::ostream &os, const Key &key). - */ - std::ostream& write(std::ostream& os) const { return os << key(); } - //@} - - protected: - //! @name Manipulators - //@{ - /*! - @brief Assignment operator. Protected so that it can only be used - by subclasses but not directly. - */ - Key& operator=(const Key& rhs) { return *this; } - //@} - - private: - //! Internal virtual copy constructor. - virtual Key* clone_() const =0; - - }; // class Key - - //! Output operator for Key types - inline std::ostream& operator<<(std::ostream& os, const Key& key) - { - return key.write(os); - } - - /*! - @brief Abstract base class defining the interface to access information - related to one metadata tag. - */ - class Metadatum { - public: - //! @name Creators - //@{ - //! Default Constructor - Metadatum() {} - //! Copy constructor - Metadatum(const Metadatum& rhs) {} - //! Destructor - virtual ~Metadatum() {} - //@} - - //! @name Manipulators - //@{ - /*! - @brief Set the value. This method copies (clones) the value pointed - to by pValue. - */ - virtual void setValue(const Value* pValue) =0; - /*! - @brief Set the value to the string buf. - Uses Value::read(const std::string& buf). If the metadatum does - not have a value yet, then an AsciiValue is created. - */ - virtual void setValue(const std::string& buf) =0; - //@} - - //! @name Accessors - //@{ - /*! - @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. - */ - virtual long copy(byte* buf, ByteOrder byteOrder) const =0; - /*! - @brief Return the key of the metadatum. The key is of the form - 'familyName.ifdItem.tagName'. Note however that the key - is not necessarily unique, i.e., an ExifData may contain - multiple metadata with the same key. - */ - virtual std::string key() const =0; - //! Return the name of the tag (which is also the third part of the key) - virtual std::string tagName() const =0; - //! Return the tag - virtual uint16_t tag() const =0; - //! Return the type id of the value - virtual TypeId typeId() const =0; - //! Return the name of the type - virtual const char* typeName() const =0; - //! Return the size in bytes of one component of this type - virtual long typeSize() const =0; - //! Return the number of components in the value - virtual long count() const =0; - //! Return the size of the value in bytes - virtual long size() const =0; - //! Return the value as a string. - virtual std::string toString() const =0; - /*! - @brief Return the n-th component of the value converted to long. The - return value is -1 if the value of the Metadatum is not set and - the behaviour of the method is undefined if there is no n-th - component. - */ - virtual long toLong(long n =0) const =0; - /*! - @brief Return the n-th component of the value converted to float. The - return value is -1 if the value of the Metadatum is not set and - the behaviour of the method is undefined if there is no n-th - component. - */ - virtual float toFloat(long n =0) const =0; - /*! - @brief Return the n-th component of the value converted to - Rational. The return value is -1/1 if the value of the - Metadatum is not set and the behaviour of the method is - undefined if there is no n-th component. - */ - virtual Rational toRational(long n =0) const =0; - /*! - @brief Return an auto-pointer to a copy (clone) of the value. The - caller owns this copy and the auto-poiner ensures that it will - be deleted. - - This method is provided for users who need full control over the - value. A caller may, e.g., downcast the pointer to the appropriate - subclass of Value to make use of the interface of the subclass to set - or modify its contents. - - @return An auto-pointer containing a pointer to a copy (clone) of the - value, 0 if the value is not set. - */ - virtual Value::AutoPtr getValue() const =0; - /*! - @brief Return a constant reference to the value. - - This method is provided mostly for convenient and versatile output of - the value which can (to some extent) be formatted through standard - stream manipulators. Do not attempt to write to the value through - this reference. - - <b>Example:</b> <br> - @code - ExifData::const_iterator i = exifData.findKey(key); - if (i != exifData.end()) { - std::cout << i->key() << " " << std::hex << i->value() << "\n"; - } - @endcode - - @return A constant reference to the value. - @throw Error if the value is not set. - */ - virtual const Value& value() const =0; - //@} - - protected: - //! @name Manipulators - //@{ - /*! - @brief Assignment operator. Protected so that it can only be used - by subclasses but not directly. - */ - Metadatum& operator=(const Metadatum& rhs) { return *this; } - //@} - - }; // class Metadatum - - //! Unary predicate that matches a Exifdatum with a given key - class FindMetadatumByKey { - public: - //! Constructor, initializes the object with the tag to look for - FindMetadatumByKey(const std::string& key) : key_(key) {} - /*! - @brief Returns true if the key of the argument metadatum is equal - to that of the object. - */ - bool operator()(const Metadatum& metadatum) const - { return key_ == metadatum.key(); } - - private: - std::string key_; - - }; // class FindMetadatumByTag - - - /*! - @brief Output operator for Metadatum types, printing the interpreted - tag value. - */ - std::ostream& operator<<(std::ostream& os, const Metadatum& md); - /*! - @brief Compare two metadata by tag. Return true if the tag of metadatum - lhs is less than that of rhs. - */ - bool cmpMetadataByTag(const Metadatum& lhs, const Metadatum& rhs); - /*! - @brief Compare two metadata by key. Return true if the key of metadatum - lhs is less than that of rhs. - */ - bool cmpMetadataByKey(const Metadatum& lhs, const Metadatum& rhs); - -} // namespace Exiv2 - -#endif // #ifndef METADATUM_HPP_ diff --git a/src/plugins/exiv2/mn.hpp b/src/plugins/exiv2/mn.hpp @@ -1,43 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 mn.hpp - @brief Include all makernote header files. Makes sure that the static - variable used to register makernotes is instantiated. - @version $Rev: 581 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 28-May-05, ahu: created - */ -#ifndef MN_HPP_ -#define MN_HPP_ - -// ***************************************************************************** -// included header files -#include "canonmn.hpp" -#include "fujimn.hpp" -#include "nikonmn.hpp" -#include "olympusmn.hpp" -#include "panasonicmn.hpp" -#include "sigmamn.hpp" -#include "sonymn.hpp" - -#endif // #ifndef MN_HPP_ diff --git a/src/plugins/exiv2/nikonmn.cpp b/src/plugins/exiv2/nikonmn.cpp @@ -1,870 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 2005 Andreas Huggel <ahuggel@gmx.net> - * - * Lens database to decode Exif.Nikon3.LensData - * Copyright (C) 2005 Robert Rottmerhusen <email@rottmerhusen.com> - * - * 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: nikonmn.cpp - Version: $Rev: 588 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 17-May-04, ahu: created - 25-May-04, ahu: combined all Nikon formats in one component - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: nikonmn.cpp 588 2005-06-14 13:57:39Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "nikonmn.hpp" -#include "makernote.hpp" -#include "value.hpp" -#include "image.hpp" -#include "tags.hpp" -#include "error.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> -#include <cstring> - -#define EXV_HAVE_LENSDATA - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - Nikon1MakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote("NIKON*", "*", createNikonMakerNote); - MakerNoteFactory::registerMakerNote( - nikon1IfdId, MakerNote::AutoPtr(new Nikon1MakerNote)); - - ExifTags::registerMakerTagInfo(nikon1IfdId, tagInfo_); - } - //! @endcond - - // Nikon1 MakerNote Tag Info - const TagInfo Nikon1MakerNote::tagInfo_[] = { - TagInfo(0x0001, "Version", "Nikon Makernote version", nikon1IfdId, makerTags, undefined, printValue), - TagInfo(0x0002, "ISOSpeed", "ISO speed setting", nikon1IfdId, makerTags, unsignedShort, print0x0002), - TagInfo(0x0003, "ColorMode", "Color mode", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0004, "Quality", "Image quality setting", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0005, "WhiteBalance", "White balance", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0006, "Sharpening", "Image sharpening setting", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0007, "Focus", "Focus mode", nikon1IfdId, makerTags, asciiString, print0x0007), - TagInfo(0x0008, "Flash", "Flash mode", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x000a, "0x000a", "Unknown", nikon1IfdId, makerTags, unsignedRational, printValue), - TagInfo(0x000f, "ISOSelection", "ISO selection", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0010, "DataDump", "Data dump", nikon1IfdId, makerTags, undefined, printValue), - TagInfo(0x0080, "ImageAdjustment", "Image adjustment setting", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0082, "Adapter", "Adapter used", nikon1IfdId, makerTags, asciiString, printValue), - TagInfo(0x0085, "FocusDistance", "Manual focus distance", nikon1IfdId, makerTags, unsignedRational, print0x0085), - TagInfo(0x0086, "DigitalZoom", "Digital zoom setting", nikon1IfdId, makerTags, unsignedRational, print0x0086), - TagInfo(0x0088, "AFFocusPos", "AF focus position", nikon1IfdId, makerTags, undefined, print0x0088), - // End of list marker - TagInfo(0xffff, "(UnknownNikon1MnTag)", "Unknown Nikon1MakerNote tag", nikon1IfdId, makerTags, invalidTypeId, printValue) - }; - - Nikon1MakerNote::Nikon1MakerNote(bool alloc) - : IfdMakerNote(nikon1IfdId, alloc) - { - } - - Nikon1MakerNote::Nikon1MakerNote(const Nikon1MakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - Nikon1MakerNote::AutoPtr Nikon1MakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - Nikon1MakerNote* Nikon1MakerNote::create_(bool alloc) const - { - return new Nikon1MakerNote(alloc); - } - - Nikon1MakerNote::AutoPtr Nikon1MakerNote::clone() const - { - return AutoPtr(clone_()); - } - - Nikon1MakerNote* Nikon1MakerNote::clone_() const - { - return new Nikon1MakerNote(*this); - } - - std::ostream& Nikon1MakerNote::print0x0002(std::ostream& os, - const Value& value) - { - if (value.count() > 1) { - os << value.toLong(1); - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& Nikon1MakerNote::print0x0007(std::ostream& os, - const Value& value) - { - std::string focus = value.toString(); - if (focus == "AF-C ") os << "Continuous autofocus"; - else if (focus == "AF-S ") os << "Single autofocus"; - else os << "(" << value << ")"; - return os; - } - - std::ostream& Nikon1MakerNote::print0x0085(std::ostream& os, - const Value& value) - { - Rational distance = value.toRational(); - if (distance.first == 0) { - os << "Unknown"; - } - else if (distance.second != 0) { - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(2) - << (float)distance.first / distance.second - << " m"; - os.copyfmt(oss); - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& Nikon1MakerNote::print0x0086(std::ostream& os, - const Value& value) - { - Rational zoom = value.toRational(); - if (zoom.first == 0) { - os << "Not used"; - } - else if (zoom.second != 0) { - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(1) - << (float)zoom.first / zoom.second - << "x"; - os.copyfmt(oss); - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& Nikon1MakerNote::print0x0088(std::ostream& os, - const Value& value) - { - if (value.count() > 1) { - switch (value.toLong(1)) { - case 0: os << "Center"; break; - case 1: os << "Top"; break; - case 2: os << "Bottom"; break; - case 3: os << "Left"; break; - case 4: os << "Right"; break; - default: os << "(" << value << ")"; break; - } - } - else { - os << "(" << value << ")"; - } - return os; - } - - //! @cond IGNORE - Nikon2MakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote( - nikon2IfdId, MakerNote::AutoPtr(new Nikon2MakerNote)); - - ExifTags::registerMakerTagInfo(nikon2IfdId, tagInfo_); - } - //! @endcond - - // Nikon2 MakerNote Tag Info - const TagInfo Nikon2MakerNote::tagInfo_[] = { - TagInfo(0x0002, "0x0002", "Unknown", nikon2IfdId, makerTags, asciiString, printValue), - TagInfo(0x0003, "Quality", "Image quality setting", nikon2IfdId, makerTags, unsignedShort, print0x0003), - TagInfo(0x0004, "ColorMode", "Color mode", nikon2IfdId, makerTags, unsignedShort, print0x0004), - TagInfo(0x0005, "ImageAdjustment", "Image adjustment setting", nikon2IfdId, makerTags, unsignedShort, print0x0005), - TagInfo(0x0006, "ISOSpeed", "ISO speed setting", nikon2IfdId, makerTags, unsignedShort, print0x0006), - TagInfo(0x0007, "WhiteBalance", "White balance", nikon2IfdId, makerTags, unsignedShort, print0x0007), - TagInfo(0x0008, "Focus", "Focus mode", nikon2IfdId, makerTags, unsignedRational, printValue), - TagInfo(0x0009, "0x0009", "Unknown", nikon2IfdId, makerTags, asciiString, printValue), - TagInfo(0x000a, "DigitalZoom", "Digital zoom setting", nikon2IfdId, makerTags, unsignedRational, print0x000a), - TagInfo(0x000b, "Adapter", "Adapter used", nikon2IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0f00, "0x0f00", "Unknown", nikon2IfdId, makerTags, unsignedLong, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownNikon2MnTag)", "Unknown Nikon2MakerNote tag", nikon2IfdId, makerTags, invalidTypeId, printValue) - }; - - Nikon2MakerNote::Nikon2MakerNote(bool alloc) - : IfdMakerNote(nikon2IfdId, alloc) - { - byte buf[] = { - 'N', 'i', 'k', 'o', 'n', '\0', 0x00, 0x01 - }; - readHeader(buf, 8, byteOrder_); - } - - Nikon2MakerNote::Nikon2MakerNote(const Nikon2MakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int Nikon2MakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 8) return 1; - - header_.alloc(8); - memcpy(header_.pData_, buf, header_.size_); - adjOffset_ = 8; - return 0; - } - - int Nikon2MakerNote::checkHeader() const - { - int rc = 0; - // Check the Nikon prefix - if ( header_.size_ < 8 - || std::string(reinterpret_cast<char*>(header_.pData_), 6) - != std::string("Nikon\0", 6)) { - rc = 2; - } - return rc; - } - - Nikon2MakerNote::AutoPtr Nikon2MakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - Nikon2MakerNote* Nikon2MakerNote::create_(bool alloc) const - { - AutoPtr makerNote(new Nikon2MakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - Nikon2MakerNote::AutoPtr Nikon2MakerNote::clone() const - { - return AutoPtr(clone_()); - } - - Nikon2MakerNote* Nikon2MakerNote::clone_() const - { - return new Nikon2MakerNote(*this); - } - - std::ostream& Nikon2MakerNote::print0x0003(std::ostream& os, - const Value& value) - { - long quality = value.toLong(); - switch (quality) { - case 1: os << "VGA Basic"; break; - case 2: os << "VGA Normal"; break; - case 3: os << "VGA Fine"; break; - case 4: os << "SXGA Basic"; break; - case 5: os << "SXGA Normal"; break; - case 6: os << "SXGA Fine"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon2MakerNote::print0x0004(std::ostream& os, - const Value& value) - { - long color = value.toLong(); - switch (color) { - case 1: os << "Color"; break; - case 2: os << "Monochrome"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon2MakerNote::print0x0005(std::ostream& os, - const Value& value) - { - long adjustment = value.toLong(); - switch (adjustment) { - case 0: os << "Normal"; break; - case 1: os << "Bright+"; break; - case 2: os << "Bright-"; break; - case 3: os << "Contrast+"; break; - case 4: os << "Contrast-"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon2MakerNote::print0x0006(std::ostream& os, - const Value& value) - { - long iso = value.toLong(); - switch (iso) { - case 0: os << "80"; break; - case 2: os << "160"; break; - case 4: os << "320"; break; - case 5: os << "100"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon2MakerNote::print0x0007(std::ostream& os, - const Value& value) - { - long wb = value.toLong(); - switch (wb) { - case 0: os << "Auto"; break; - case 1: os << "Preset"; break; - case 2: os << "Daylight"; break; - case 3: os << "Incandescent"; break; - case 4: os << "Fluorescent"; break; - case 5: os << "Cloudy"; break; - case 6: os << "Speedlight"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon2MakerNote::print0x000a(std::ostream& os, - const Value& value) - { - Rational zoom = value.toRational(); - if (zoom.first == 0) { - os << "Not used"; - } - else if (zoom.second != 0) { - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(1) - << (float)zoom.first / zoom.second - << "x"; - os.copyfmt(oss); - } - else { - os << "(" << value << ")"; - } - return os; - } - - //! @cond IGNORE - Nikon3MakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote( - nikon3IfdId, MakerNote::AutoPtr(new Nikon3MakerNote)); - - ExifTags::registerMakerTagInfo(nikon3IfdId, tagInfo_); - } - //! @endcond - - // Nikon3 MakerNote Tag Info - const TagInfo Nikon3MakerNote::tagInfo_[] = { - TagInfo(0x0001, "Version", "Nikon Makernote version", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x0002, "ISOSpeed", "ISO speed used", nikon3IfdId, makerTags, unsignedShort, print0x0002), - TagInfo(0x0003, "ColorMode", "Color mode", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0004, "Quality", "Image quality setting", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0005, "WhiteBalance", "White balance", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0006, "Sharpening", "Image sharpening setting", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0007, "Focus", "Focus mode", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0008, "FlashSetting", "Flash setting", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0009, "FlashMode", "Flash mode", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x000b, "WhiteBalanceBias", "White balance bias", nikon3IfdId, makerTags, signedShort, printValue), -// TagInfo(0x000c, "ColorBalance1", "Color balance 1", nikon3IfdId, makerTags, xxx, printValue), - TagInfo(0x000d, "0x000d", "Unknown", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x000e, "ExposureDiff", "Exposure difference", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x000f, "ISOSelection", "ISO selection", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0010, "DataDump", "Data dump", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x0011, "ThumbOffset", "Thumbnail IFD offset", nikon3IfdId, makerTags, unsignedLong, printValue), - TagInfo(0x0012, "FlashComp", "Flash compensation setting", nikon3IfdId, makerTags, undefined, print0x0012), - TagInfo(0x0013, "ISOSetting", "ISO speed setting", nikon3IfdId, makerTags, unsignedShort, print0x0002), // use 0x0002 print fct - TagInfo(0x0016, "ImageBoundry", "Image boundry", nikon3IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0017, "0x0017", "Unknown", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x0018, "FlashBracketComp", "Flash bracket compensation applied", nikon3IfdId, makerTags, undefined, print0x0012), // use 0x0012 print fct - TagInfo(0x0019, "ExposureBracketComp", "AE bracket compensation applied", nikon3IfdId, makerTags, signedRational, printValue), - TagInfo(0x0080, "ImageAdjustment", "Image adjustment setting", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0081, "ToneComp", "Tone compensation setting (contrast)", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0082, "AuxiliaryLens", "Auxiliary lens (adapter)", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0083, "LensType", "Lens type", nikon3IfdId, makerTags, unsignedByte, printValue), - TagInfo(0x0084, "Lens", "Lens", nikon3IfdId, makerTags, unsignedRational, print0x0084), - TagInfo(0x0085, "FocusDistance", "Manual focus distance", nikon3IfdId, makerTags, unsignedRational, printValue), - TagInfo(0x0086, "DigitalZoom", "Digital zoom setting", nikon3IfdId, makerTags, unsignedRational, printValue), - TagInfo(0x0087, "FlashType", "Type of flash used", nikon3IfdId, makerTags, unsignedByte, print0x0087), - TagInfo(0x0088, "AFFocusPos", "AF focus position", nikon3IfdId, makerTags, undefined, print0x0088), - TagInfo(0x0089, "Bracketing", "Bracketing", nikon3IfdId, makerTags, unsignedShort, print0x0089), - TagInfo(0x008a, "0x008a", "Unknown", nikon3IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x008b, "LensFStops", "Number of lens stops", nikon3IfdId, makerTags, undefined, print0x008b), -// TagInfo(0x008c, "NEFCurve1", "NEF curve 1", nikon3IfdId, makerTags, xxx, printValue), - TagInfo(0x008d, "ColorMode", "Color mode", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x008f, "SceneMode", "Scene mode", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0090, "LightingType", "Lighting type", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x0091, "0x0091", "Unknown", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x0092, "HueAdjustment", "Hue adjustment", nikon3IfdId, makerTags, signedShort, printValue), - TagInfo(0x0094, "Saturation", "Saturation adjustment", nikon3IfdId, makerTags, signedShort, printValue), - TagInfo(0x0095, "NoiseReduction", "Noise reduction", nikon3IfdId, makerTags, asciiString, printValue), -// TagInfo(0x0096, "NEFCurve2", "NEF curve 2", nikon3IfdId, makerTags, xxx, printValue), - TagInfo(0x0097, "ColorBalance2", "Color balance 2", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x0098, "LensData", "Lens data", nikon3IfdId, makerTags, undefined, print0x0098), - TagInfo(0x0099, "NEFThumbnailSize", "NEF thumbnail size", nikon3IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x009a, "0x009a", "Unknown", nikon3IfdId, makerTags, unsignedRational, printValue), - TagInfo(0x009b, "0x009b", "Unknown", nikon3IfdId, makerTags, unsignedShort, printValue), - TagInfo(0x009f, "0x009f", "Unknown", nikon3IfdId, makerTags, signedShort, printValue), - TagInfo(0x00a0, "SerialNumber", "Camera serial number", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x00a2, "0x00a2", "Unknown", nikon3IfdId, makerTags, unsignedLong, printValue), - TagInfo(0x00a3, "0x00a3", "Unknown", nikon3IfdId, makerTags, unsignedByte, printValue), - TagInfo(0x00a5, "0x00a5", "Unknown", nikon3IfdId, makerTags, unsignedLong, printValue), - TagInfo(0x00a6, "0x00a6", "Unknown", nikon3IfdId, makerTags, unsignedLong, printValue), - TagInfo(0x00a7, "ShutterCount", "Number of shots taken by camera", nikon3IfdId, makerTags, unsignedLong, printValue), - TagInfo(0x00a8, "0x00a8", "Unknown", nikon3IfdId, makerTags, undefined, printValue), - TagInfo(0x00a9, "ImageOptimization", "Image optimization", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x00aa, "Saturation", "Saturation", nikon3IfdId, makerTags, asciiString, printValue), - TagInfo(0x00ab, "VariProgram", "Vari program", nikon3IfdId, makerTags, asciiString, printValue), -// TagInfo(0x0e00, "PrintIM", "Print image matching", nikon3IfdId, makerTags, xxx, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownNikon3MnTag)", "Unknown Nikon3MakerNote tag", nikon3IfdId, makerTags, invalidTypeId, printValue) - }; - - Nikon3MakerNote::Nikon3MakerNote(bool alloc) - : IfdMakerNote(nikon3IfdId, alloc) - { - absOffset_ = false; - byte buf[] = { - 'N', 'i', 'k', 'o', 'n', '\0', - 0x02, 0x10, 0x00, 0x00, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08 - }; - readHeader(buf, 18, byteOrder_); - } - - Nikon3MakerNote::Nikon3MakerNote(const Nikon3MakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int Nikon3MakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 18) return 1; - - header_.alloc(18); - memcpy(header_.pData_, buf, header_.size_); - TiffHeader tiffHeader; - tiffHeader.read(header_.pData_ + 10); - byteOrder_ = tiffHeader.byteOrder(); - adjOffset_ = tiffHeader.offset(); - return 0; - } - - int Nikon3MakerNote::checkHeader() const - { - int rc = 0; - // Check the Nikon prefix - if ( header_.size_ < 18 - || std::string(reinterpret_cast<char*>(header_.pData_), 6) - != std::string("Nikon\0", 6)) { - rc = 2; - } - return rc; - } - - Nikon3MakerNote::AutoPtr Nikon3MakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - Nikon3MakerNote* Nikon3MakerNote::create_(bool alloc) const - { - AutoPtr makerNote(new Nikon3MakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - Nikon3MakerNote::AutoPtr Nikon3MakerNote::clone() const - { - return AutoPtr(clone_()); - } - - Nikon3MakerNote* Nikon3MakerNote::clone_() const - { - return new Nikon3MakerNote(*this); - } - - std::ostream& Nikon3MakerNote::print0x0002(std::ostream& os, - const Value& value) - { - if (value.count() > 1) { - os << value.toLong(1); - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& Nikon3MakerNote::print0x0012(std::ostream& os, - const Value& value) - { - // From the PHP JPEG Metadata Toolkit - long fec = value.toLong(); - switch (fec) { - case 0x06: os << "+1.0 EV"; break; - case 0x04: os << "+0.7 EV"; break; - case 0x03: os << "+0.5 EV"; break; - case 0x02: os << "+0.3 EV"; break; - case 0x00: os << "0.0 EV"; break; - case 0xfe: os << "-0.3 EV"; break; - case 0xfd: os << "-0.5 EV"; break; - case 0xfc: os << "-0.7 EV"; break; - case 0xfa: os << "-1.0 EV"; break; - case 0xf8: os << "-1.3 EV"; break; - case 0xf7: os << "-1.5 EV"; break; - case 0xf6: os << "-1.7 EV"; break; - case 0xf4: os << "-2.0 EV"; break; - case 0xf2: os << "-2.3 EV"; break; - case 0xf1: os << "-2.5 EV"; break; - case 0xf0: os << "-2.7 EV"; break; - case 0xee: os << "-3.0 EV"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon3MakerNote::print0x0084(std::ostream& os, - const Value& value) - { - if (value.count() == 4) { - long len1 = value.toLong(0); - long len2 = value.toLong(1); - Rational fno1 = value.toRational(2); - Rational fno2 = value.toRational(3); - os << len1; - if (len2 != len1) { - os << "-" << len2; - } - os << "mm " - << "F" << (float)fno1.first / fno1.second; - if (fno2 != fno1) { - os << "-" << (float)fno2.first / fno2.second; - } - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& Nikon3MakerNote::print0x0087(std::ostream& os, - const Value& value) - { - // From Exiftool - long flash = value.toLong(); - switch (flash) { - case 0: os << "Not used"; break; - case 8: os << "Fired, commander mode"; break; - case 9: os << "Fired, TTL mode"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon3MakerNote::print0x0088(std::ostream& os, - const Value& value) - { - // Mappings taken from Exiftool - long afpos = value.toLong(); - switch (afpos) { - case 0x0000: os << "Center"; break; - case 0x0100: os << "Top"; break; - case 0x0200: os << "Bottom"; break; - case 0x0300: os << "Left"; break; - case 0x0400: os << "Right"; break; - - // D70 - case 0x00001: os << "Single area, center"; break; - case 0x10002: os << "Single area, top"; break; - case 0x20004: os << "Single area, bottom"; break; - case 0x30008: os << "Single area, left"; break; - case 0x40010: os << "Single area, right"; break; - - case 0x1000001: os << "Dynamic area, center"; break; - case 0x1010002: os << "Dynamic area, top"; break; - case 0x1020004: os << "Dynamic area, bottom"; break; - case 0x1030008: os << "Dynamic area, left"; break; - case 0x1040010: os << "Dynamic area, right"; break; - - case 0x2000001: os << "Closest subject, center"; break; - case 0x2010002: os << "Closest subject, top"; break; - case 0x2020004: os << "Closest subject, bottom"; break; - case 0x2030008: os << "Closest subject, left"; break; - case 0x2040010: os << "Closest subject, right"; break; - - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon3MakerNote::print0x0089(std::ostream& os, - const Value& value) - { - // From Exiftool - long b = value.toLong(); - switch (b) { - case 0x00: os << "Single"; break; - case 0x01: os << "Continuous"; break; - case 0x02: os << "Delay"; break; - case 0x03: os << "Remote with delay"; break; - case 0x04: os << "Remote"; break; - case 0x16: os << "Exposure bracketing"; break; - case 0x64: os << "White balance bracketing"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& Nikon3MakerNote::print0x008b(std::ostream& os, - const Value& value) - { - // Decoded by Robert Rottmerhusen <email@rottmerhusen.com> - if (value.size() != 4) return os << "(" << value << ")"; - float a = value.toFloat(0); - long b = value.toLong(1); - long c = value.toLong(2); - if (c == 0) return os << "(" << value << ")"; - return os << a * b / c; - } - - std::ostream& Nikon3MakerNote::print0x0098(std::ostream& os, - const Value& value) - { -#ifdef EXV_HAVE_LENSDATA - //# List of AF F-Mount lenses - version 1.12 - //#----------------------------------------- - //# created by Robert Rottmerhusen 2005 - //# for use in non-commercial, GPL or open source software only! - //# please contact me for adding lenses or use in commercial software. - //# - //#"data from TAG 0x98" "ltyp""manuf" "lens name from manuf"; - //# - struct {unsigned char lid,stps,focs,focl,aps,apl,lfw, ltype; const char *manuf, *lensname;} - fmountlens[] = { - {0x01,0x58,0x50,0x50,0x14,0x14,0x02,0x00, "Nikon", "AF Nikkor 50mm f/1.8"}, - {0x02,0x42,0x44,0x5C,0x2A,0x34,0x08,0x00, "Nikon", "AF Zoom-Nikkor 35-70mm f/3.3-4.5"}, - {0x04,0x48,0x3C,0x3C,0x24,0x24,0x03,0x00, "Nikon", "AF Nikkor 28mm f/2.8"}, - {0x05,0x54,0x50,0x50,0x0C,0x0C,0x04,0x00, "Nikon", "AF Nikkor 50mm f/1.4"}, - {0x07,0x40,0x3C,0x62,0x2C,0x34,0x03,0x00, "Nikon", "AF Zoom-Nikkor 28-85mm f/3.5-4.5"}, - {0x08,0x40,0x44,0x6A,0x2C,0x34,0x04,0x00, "Nikon", "AF Zoom-Nikkor 35-105mm f/3.5-4.5"}, - {0x09,0x48,0x37,0x37,0x24,0x24,0x04,0x00, "Nikon", "AF Nikkor 24mm f/2.8"}, - {0x0A,0x48,0x8E,0x8E,0x24,0x24,0x03,0x00, "Nikon", "AF Nikkor 300mm f/2.8 IF-ED"}, - {0x0B,0x48,0x7C,0x7C,0x24,0x24,0x05,0x00, "Nikon", "AF Nikkor 180mm f/2.8 IF-ED"}, - {0x0E,0x48,0x5C,0x81,0x30,0x30,0x05,0x00, "Nikon", "AF Zoom-Nikkor 70-210mm f/4"}, - {0x0F,0x58,0x50,0x50,0x14,0x14,0x05,0x00, "Nikon", "AF Nikkor 50mm f/1.8 N"}, - {0x10,0x48,0x8E,0x8E,0x30,0x30,0x08,0x00, "Nikon", "AF Nikkor 300mm f/4 IF-ED"}, - {0x12,0x48,0x5C,0x81,0x30,0x3C,0x09,0x00, "Nikon", "AF Nikkor 70-210mm f/4-5.6"}, - {0x13,0x42,0x37,0x50,0x2A,0x34,0x0B,0x00, "Nikon", "AF Zoom-Nikkor 24-50mm f/3.3-4.5"}, - {0x14,0x48,0x60,0x80,0x24,0x24,0x0B,0x00, "Nikon", "AF Zoom-Nikkor 80-200mm f/2.8 ED"}, - {0x15,0x4C,0x62,0x62,0x14,0x14,0x0C,0x00, "Nikon", "AF Nikkor 85mm f/1.8"}, - {0x1B,0x44,0x5E,0x8E,0x34,0x3C,0x10,0x00, "Nikon", "AF Zoom-Nikkor 75-300mm f/4.5-5.6"}, - {0x1C,0x48,0x30,0x30,0x24,0x24,0x12,0x00, "Nikon", "AF Nikkor 20mm f/2.8"}, - {0x1D,0x42,0x44,0x5C,0x2A,0x34,0x12,0x00, "Nikon", "AF Zoom-Nikkor 35-70mm f/3.3-4.5 N"}, - {0x1E,0x54,0x56,0x56,0x24,0x24,0x13,0x00, "Nikon", "AF Micro-Nikkor 60mm f/2.8"}, - {0x25,0x48,0x44,0x5c,0x24,0x24,0x1B,0x02, "Nikon", "AF Zoom-Nikkor 35-70mm f/2.8D"}, - {0x25,0x48,0x44,0x5c,0x24,0x24,0x52,0x02, "Nikon", "AF Zoom-Nikkor 35-70mm f/2.8D N"}, - {0x27,0x48,0x8E,0x8E,0x24,0x24,0xF2,0x02, "Nikon", "AF-I Nikkor 300mm f/2.8D IF-ED"}, - {0x2A,0x54,0x3C,0x3C,0x0C,0x0C,0x26,0x02, "Nikon", "AF Nikkor 28mm f/1.4D"}, - {0x2C,0x48,0x6A,0x6A,0x18,0x18,0x27,0x02, "Nikon", "AF DC-Nikkor 105mm f/2D"}, - {0x2D,0x48,0x80,0x80,0x30,0x30,0x21,0x02, "Nikon", "AF Micro-Nikkor 200mm f/4D IF-ED"}, - {0x31,0x54,0x56,0x56,0x24,0x24,0x25,0x02, "Nikon", "AF Micro-Nikkor 60mm f/2.8D"}, - {0x32,0x54,0x6A,0x6A,0x24,0x24,0x35,0x02, "Nikon", "AF Micro-Nikkor 105mm f/2.8D"}, - {0x33,0x48,0x2D,0x2D,0x24,0x24,0x31,0x02, "Nikon", "AF Nikkor 18mm f/2.8D"}, - {0x36,0x48,0x37,0x37,0x24,0x24,0x34,0x02, "Nikon", "AF Nikkor 24mm f/2.8D"}, - {0x37,0x48,0x30,0x30,0x24,0x24,0x36,0x02, "Nikon", "AF Nikkor 20mm f/2.8D"}, - {0x38,0x4C,0x62,0x62,0x14,0x14,0x37,0x02, "Nikon", "AF Nikkor 85mm f/1.8D"}, - {0x3B,0x48,0x44,0x5C,0x24,0x24,0x3A,0x02, "Nikon", "AF Zoom-Nikkor 35-70mm f/2.8D N"}, - {0x3E,0x48,0x3C,0x3C,0x24,0x24,0x3D,0x02, "Nikon", "AF Nikkor 28mm f/2.8D"}, - {0x41,0x48,0x7c,0x7c,0x24,0x24,0x43,0x02, "Nikon", "AF Nikkor 180mm f/2.8D IF-ED"}, - {0x42,0x54,0x44,0x44,0x18,0x18,0x44,0x02, "Nikon", "AF Nikkor 35mm f/2D"}, - {0x43,0x54,0x50,0x50,0x0C,0x0C,0x46,0x02, "Nikon", "AF Nikkor 50mm f/1.4D"}, - {0x46,0x3C,0x44,0x60,0x30,0x3C,0x49,0x02, "Nikon", "AF Zoom-Nikkor 35-80mm f/4-5.6D"}, - {0x48,0x48,0x8E,0x8E,0x24,0x24,0x4B,0x02, "Nikon", "AF-S Nikkor 300mm f/2.8D IF-ED"}, - {0x4A,0x54,0x62,0x62,0x0C,0x0C,0x4D,0x02, "Nikon", "AF Nikkor 85mm f/1.4D IF"}, - {0x4C,0x40,0x37,0x6E,0x2C,0x3C,0x4F,0x02, "Nikon", "AF Zoom-Nikkor 24-120mm f/3.5-5.6D IF"}, - {0x4D,0x40,0x3C,0x80,0x2C,0x3C,0x62,0x02, "Nikon", "AF Zoom-Nikkor 28-200mm f/3.5-5.6D IF"}, - {0x4E,0x48,0x72,0x72,0x18,0x18,0x51,0x02, "Nikon", "AF DC-Nikkor 135mm f/2D"}, - {0x53,0x48,0x60,0x80,0x24,0x24,0x60,0x02, "Nikon", "AF Zoom-Nikkor 80-200mm f/2.8D ED"}, - {0x54,0x44,0x5C,0x7C,0x34,0x3C,0x58,0x02, "Nikon", "AF Zoom-Micro Nikkor 70-180mm f/4.5-5.6D ED"}, - {0x56,0x48,0x5C,0x8E,0x30,0x3C,0x5A,0x02, "Nikon", "AF Zoom-Nikkor 70-300mm f/4-5.6D ED"}, - {0x59,0x48,0x98,0x98,0x24,0x24,0x5D,0x02, "Nikon", "AF-S Nikkor 400mm f/2.8D IF-ED"}, - {0x5A,0x3C,0x3E,0x56,0x30,0x3C,0x5E,0x06, "Nikon", "IX-Nikkor 30-60mm f/4-5.6"}, - {0x5D,0x48,0x3C,0x5C,0x24,0x24,0x63,0x02, "Nikon", "AF-S Zoom-Nikkor 28-70mm f/2.8D IF-ED"}, - {0x5E,0x48,0x60,0x80,0x24,0x24,0x64,0x02, "Nikon", "AF-S Zoom-Nikkor 80-200mm f/2.8D IF-ED"}, - {0x5F,0x40,0x3C,0x6A,0x2C,0x34,0x65,0x02, "Nikon", "AF Zoom-Nikkor 28-105mm f/3.5-4.5D IF"}, - {0x63,0x48,0x2B,0x44,0x24,0x24,0x68,0x02, "Nikon", "AF-S Nikkor 17-35mm f/2.8D IF-ED"}, - {0x64,0x00,0x62,0x62,0x24,0x24,0x6A,0x02, "Nikon", "PC Micro-Nikkor 85mm f/2.8D"}, - {0x65,0x44,0x60,0x98,0x34,0x3C,0x6B,0x0A, "Nikon", "AF VR Zoom-Nikkor 80-400mm f/4.5-5.6D ED"}, - {0x66,0x40,0x2D,0x44,0x2C,0x34,0x6C,0x02, "Nikon", "AF Zoom-Nikkor 18-35mm f/3.5-4.5D IF-ED"}, - {0x67,0x48,0x37,0x62,0x24,0x30,0x6D,0x02, "Nikon", "AF Zoom-Nikkor 24-85mm f/2.8-4D IF"}, - {0x68,0x42,0x3C,0x60,0x2A,0x3C,0x6E,0x06, "Nikon", "AF Zoom-Nikkor 28-80mm f/3.3-5.6G"}, - {0x69,0x48,0x5C,0x8E,0x30,0x3C,0x6F,0x06, "Nikon", "AF Zoom-Nikkor 70-300mm f/4-5.6G"}, - {0x6A,0x48,0x8E,0x8E,0x30,0x30,0x70,0x02, "Nikon", "AF-S Nikkor 300mm f/4D IF-ED"}, - {0x6D,0x48,0x8E,0x8E,0x24,0x24,0x73,0x02, "Nikon", "AF-S Nikkor 300mm f/2.8D IF-ED II"}, - {0x6E,0x48,0x98,0x98,0x24,0x24,0x74,0x02, "Nikon", "AF-S Nikkor 400mm f/2.8D IF-ED II"}, - {0x70,0x3C,0xA6,0xA6,0x30,0x30,0x76,0x02, "Nikon", "AF-S Nikkor 600mm f/4D IF-ED"}, - {0x72,0x48,0x4C,0x4C,0x24,0x24,0x77,0x00, "Nikon", "Nikkor 45mm f/2.8 P"}, - {0x74,0x40,0x37,0x62,0x2C,0x34,0x78,0x06, "Nikon", "AF-S Zoom-Nikkor 24-85mm f/3.5-4.5G IF-ED"}, - {0x75,0x40,0x3C,0x68,0x2C,0x3C,0x79,0x06, "Nikon", "AF Zoom-Nikkor 28-100mm f/3.5-5.6G"}, - {0x76,0x58,0x50,0x50,0x14,0x14,0x7A,0x02, "Nikon", "AF Nikkor 50mm f/1.8D"}, - {0x77,0x48,0x5C,0x80,0x24,0x24,0x7B,0x0E, "Nikon", "AF-S VR Zoom-Nikkor 70-200mm f/2.8G IF-ED"}, - {0x78,0x40,0x37,0x6E,0x2C,0x3C,0x7C,0x0E, "Nikon", "AF-S VR Zoom-Nikkor 24-120mm f/3.5-5.6G IF-ED"}, - {0x79,0x40,0x3C,0x80,0x2C,0x3C,0x7F,0x06, "Nikon", "AF Zoom-Nikkor 28-200mm f/3.5-5.6G IF-ED"}, - {0x7A,0x3C,0x1F,0x37,0x30,0x30,0x7E,0x06, "Nikon", "AF-S DX Zoom-Nikkor 12-24mm f/4G IF-ED"}, - {0x7B,0x48,0x80,0x98,0x30,0x30,0x80,0x0E, "Nikon", "AF-S VR Zoom-Nikkor 200-400mm f/4G IF-ED"}, - {0x7D,0x48,0x2B,0x53,0x24,0x24,0x82,0x06, "Nikon", "AF-S DX Zoom-Nikkor 17-55mm f/2.8G IF-ED"}, - {0x7F,0x40,0x2D,0x5C,0x2C,0x34,0x84,0x06, "Nikon", "AF-S DX Zoom-Nikkor 18-70mm f/3.5-4.5G IF-ED"}, - {0x80,0x48,0x1A,0x1A,0x24,0x24,0x85,0x06, "Nikon", "AF DX Fisheye-Nikkor 10.5mm f/2.8G ED"}, - {0x81,0x54,0x80,0x80,0x18,0x18,0x86,0x0E, "Nikon", "AF-S VR Nikkor 200mm f/2G IF-ED"}, - {0x82,0x48,0x8E,0x8E,0x24,0x24,0x87,0x0E, "Nikon", "AF-S VR Nikkor 300mm f/2.8G IF-ED"}, - {0x89,0x3C,0x53,0x80,0x30,0x3C,0x8B,0x06, "Nikon", "AF-S DX Zoom-Nikkor 55-200mm f/4-5.6G ED"}, - {0x8C,0x40,0x2D,0x53,0x2C,0x3C,0x8E,0x06, "Nikon", "AF-S DX Zoom-Nikkor 18-55mm f/3.5-5.6G ED"}, - {0x06,0x3F,0x68,0x68,0x2C,0x2C,0x06,0x00, "Cosina", "100mm F/3.5 Macro"}, - {0x02,0x3F,0x24,0x24,0x2C,0x2C,0x02,0x00, "Sigma", "14mm F3.5"}, - {0x02,0x46,0x37,0x37,0x25,0x25,0x02,0x00, "Sigma", "24mm F2.8 Macro"}, - {0x02,0x3F,0x3C,0x5C,0x2D,0x35,0x02,0x00, "Sigma", "28-70mm F3.5-4.5 UC"}, - {0x02,0x40,0x44,0x73,0x2B,0x36,0x02,0x00, "Sigma", "35-135mm F3.5-4.5 a"}, - {0x02,0x37,0x5E,0x8E,0x35,0x3D,0x02,0x00, "Sigma", "75-300mm F4.5-5.6 APO"}, - {0x02,0x48,0x65,0x65,0x24,0x24,0x02,0x00, "Sigma", "90mm F2.8 Macro"}, - {0x02,0x2F,0x98,0x98,0x3D,0x3D,0x02,0x00, "Sigma", "400mm F5.6 APO"}, - {0x26,0x40,0x3C,0x8E,0x2C,0x40,0x1C,0x02, "Sigma", "28-300mm F3.5-6.3 Macro D"}, - {0x26,0x40,0x3C,0x80,0x2B,0x3C,0x1C,0x02, "Sigma", "28-200mm F3.5-5.6 Compact Aspherical Hyperzoom Macro D"}, - {0x26,0x40,0x3C,0x60,0x2C,0x3C,0x1C,0x02, "Sigma", "28-80mm F3.5-5.6 Mini Zoom Macro II Aspherical D"}, - {0x26,0x54,0x37,0x5C,0x24,0x24,0x1C,0x02, "Sigma", "24-70mm F2.8 EX DG Macro D"}, - {0x26,0x40,0x2D,0x70,0x2B,0x3C,0x1C,0x06, "Sigma", "18-125mm F3.5-5.6 DC G"}, - {0x26,0x48,0x2D,0x50,0x24,0x24,0x1C,0x06, "Sigma", "18-50mm F2.8 EX DC G"}, - {0x26,0x40,0x2D,0x50,0x2C,0x3C,0x1C,0x06, "Sigma", "18-50mm F3.5-5.6 DC G"}, - {0x48,0x38,0x1F,0x37,0x34,0x3C,0x4B,0x06, "Sigma", "12-24mm F4.5-5.6 EX Aspherical DG HSM G"}, - {0x48,0x48,0x2B,0x44,0x24,0x30,0x4B,0x06, "Sigma", "17-35mm F2.8-4 EX DG Aspherical HSM G"}, - {0x48,0x3C,0x50,0xA0,0x30,0x40,0x4B,0x02, "Sigma", "50-500mmF4-6.3 EX APO RF HSM D"}, - {0x48,0x54,0x5C,0x80,0x24,0x24,0x4B,0x02, "Sigma", "70-200mm F2.8 EX APO IF HSM D"}, - {0x48,0x48,0x68,0x8E,0x30,0x30,0x4B,0x02, "Sigma", "100-300mm F4 EX IF HSM D"}, - {0x48,0x48,0x76,0x76,0x24,0x24,0x4B,0x06, "Sigma", "150mm F2.8 EX DG APO Macro HSM G"}, - {0x77,0x44,0x61,0x98,0x34,0x3C,0x7B,0x0E, "Sigma", "80-400mm f4.5-5.6 EX OS G"}, - {0x03,0x43,0x5C,0x81,0x35,0x35,0x02,0x00, "Soligor", "AF C/D ZOOM UMCS 70-210mm 1:4.5"}, - {0x00,0x3C,0x1F,0x37,0x30,0x30,0x00,0x06, "Tokina", "AT-X 124 AF PRO DX - AF 12-24mm f/4"}, - {0x00,0x40,0x2B,0x2B,0x2C,0x2C,0x00,0x02, "Tokina", "AT-X 17 AF PRO - AF 17mm f/3.5"}, - {0x00,0x54,0x68,0x68,0x24,0x24,0x00,0x02, "Tokina", "AT-X M100 PRO D - 100mm F2.8"}, - {0x4D,0x41,0x3C,0x8E,0x2B,0x40,0x62,0x02, "Tamron", "AF28-300mm F/3.5-6.3 XR Di LD Aspherical (IF)"}, - {0x00,0x3F,0x2D,0x80,0x2B,0x40,0x00,0x06, "Tamron", "AF18-200mm F/3.5-6.3 XR Di II LD Aspherical (IF)"}, - {0x32,0x53,0x64,0x64,0x24,0x24,0x35,0x02, "Tamron", "SP AF90mm F/2.8 Di 1:1 Macro"}, - {0x00,0x48,0x3C,0x6A,0x24,0x24,0x00,0x02, "Unknown", "28-105mm F/2.8D"}, - {0x00,0x49,0x30,0x48,0x22,0x2B,0x00,0x02, "Unknown", "20-40mm F/2.7-3.3D"}, - {0x07,0x46,0x2B,0x44,0x24,0x30,0x03,0x02, "Unknown", "AF17-35mm D"}, - {0x1E,0x5D,0x64,0x64,0x20,0x20,0x13,0x00, "Unknown", "90mm F/2.5"}, - {0x20,0x3C,0x80,0x98,0x3D,0x3D,0x1E,0x02, "Unknown", "200-400mm F/5.6D"}, - {0x2F,0x40,0x30,0x44,0x2C,0x34,0x29,0x02, "Unknown", "20-35mm F/3.5-4.5D"}, - {0,0,0,0,0,0,0,0, NULL, NULL} - }; - - if (value.typeId() != undefined) return os << value; - - DataBuf lens(value.size()); - // ByteOrder is only to satisfy the interface - value.copy(lens.pData_, invalidByteOrder); - - int idx = 0; - if (0 == memcmp(lens.pData_, "0100", 4)) { - idx = 6; - } - else if (0 == memcmp(lens.pData_, "0101", 4)) { - idx = 11; - } - else if (0 == memcmp(lens.pData_, "0201", 4)) { - // Here we should decrypt(lens.pData_ + 4, lens.size_ - 4); - // however, the decrypt algorithm requires access to serial number - // and shutter count tags but print functions are static... - idx = 11; - } - if (idx == 0 || lens.size_ < idx + 7) { - // Unknown version or not enough data - return os << value; - } - for (int i = 0; fmountlens[i].lensname != NULL; ++i) { - if ( lens.pData_[idx] == fmountlens[i].lid - && lens.pData_[idx+1] == fmountlens[i].stps - && lens.pData_[idx+2] == fmountlens[i].focs - && lens.pData_[idx+3] == fmountlens[i].focl - && lens.pData_[idx+4] == fmountlens[i].aps - && lens.pData_[idx+5] == fmountlens[i].apl - && lens.pData_[idx+6] == fmountlens[i].lfw) { - // Lens found in database - return os << fmountlens[i].manuf << " " << fmountlens[i].lensname; - } - } - // Lens not found in database - return os << value; -#else - return os << value; -#endif // EXV_HAVE_LENSDATA - } - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createNikonMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - // If there is no "Nikon" string it must be Nikon1 format - if (len < 6 || std::string(reinterpret_cast<const char*>(buf), 6) - != std::string("Nikon\0", 6)) { - return MakerNote::AutoPtr(new Nikon1MakerNote(alloc)); - } - // If the "Nikon" string is not followed by a TIFF header, we assume - // Nikon2 format - TiffHeader tiffHeader; - if ( len < 18 - || tiffHeader.read(buf + 10) != 0 || tiffHeader.tag() != 0x002a) { - return MakerNote::AutoPtr(new Nikon2MakerNote(alloc)); - } - // Else we have a Nikon3 makernote - return MakerNote::AutoPtr(new Nikon3MakerNote(alloc)); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/nikonmn.hpp b/src/plugins/exiv2/nikonmn.hpp @@ -1,309 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 nikonmn.hpp - @brief Nikon MakerNote formats. - - The Nikon MakerNote formats are implemented according to the following references<BR> - Format 1: - <ul> - <li><a href="http://www.tawbaware.com/990exif.htm">MakerNote EXIF Tag of the Nikon 990</a> by Max Lyons</li></ul> - Format 2: - <ul><li>"Appendix 2: Makernote of Nikon" of the document - <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html"> - Exif file format</a> by TsuruZoh Tachibanaya</li></ul> - Format 3: - <ul><li>"EXIFutils Field Reference Guide"</li> - <li><a href="http://www.ozhiker.com/electronics/pjmt/jpeg_info/nikon_mn.html#Nikon_Type_3_Tags">Nikon Type 3 Makernote Tags Definition</a> - of the PHP JPEG Metadata Toolkit by Evan Hunter</li> - <li>Nikon tag information from <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/">ExifTool</a> by Phil Harvey</li> - <li>Email communication with Robert Rottmerhusen</li> - </ul> - - @version $Rev: 588 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 17-May-04, ahu: created<BR> - 25-May-04, ahu: combined all Nikon formats in one component - */ -#ifndef NIKONMN_HPP_ -#define NIKONMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createNikonMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! A MakerNote format used by Nikon cameras, such as the E990 and D1. - class Nikon1MakerNote : public IfdMakerNote { - public: - //! Shortcut for a %Nikon1MakerNote auto pointer. - typedef std::auto_ptr<Nikon1MakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - Nikon1MakerNote(bool alloc =true); - //! Copy constructor - Nikon1MakerNote(const Nikon1MakerNote& rhs); - //! Virtual destructor - virtual ~Nikon1MakerNote() {} - //@} - - //! @name Accessors - //@{ - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Nikon1 %MakerNote tags - //@{ - //! Print ISO setting - static std::ostream& print0x0002(std::ostream& os, const Value& value); - //! Print autofocus mode - static std::ostream& print0x0007(std::ostream& os, const Value& value); - //! Print manual focus distance - static std::ostream& print0x0085(std::ostream& os, const Value& value); - //! Print digital zoom setting - static std::ostream& print0x0086(std::ostream& os, const Value& value); - //! Print AF focus position - static std::ostream& print0x0088(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - Nikon1MakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - Nikon1MakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class Nikon1MakerNote - - static Nikon1MakerNote::RegisterMn registerNikon1MakerNote; - - /*! - @brief A second MakerNote format used by Nikon cameras, including the - E700, E800, E900, E900S, E910, E950 - */ - class Nikon2MakerNote : public IfdMakerNote { - public: - //! Shortcut for a %Nikon2MakerNote auto pointer. - typedef std::auto_ptr<Nikon2MakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - Nikon2MakerNote(bool alloc =true); - //! Copy constructor - Nikon2MakerNote(const Nikon2MakerNote& rhs); - //! Virtual destructor - virtual ~Nikon2MakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Nikon2 %MakerNote tags - //@{ - //! Print quality setting - static std::ostream& print0x0003(std::ostream& os, const Value& value); - //! Print color mode setting - static std::ostream& print0x0004(std::ostream& os, const Value& value); - //! Print image adjustment setting - static std::ostream& print0x0005(std::ostream& os, const Value& value); - //! Print ISO speed setting - static std::ostream& print0x0006(std::ostream& os, const Value& value); - //! Print white balance setting - static std::ostream& print0x0007(std::ostream& os, const Value& value); - //! Print digital zoom setting - static std::ostream& print0x000a(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - Nikon2MakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - Nikon2MakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class Nikon2MakerNote - - static Nikon2MakerNote::RegisterMn registerNikon2MakerNote; - - //! A third MakerNote format used by Nikon cameras, e.g., E5400, SQ, D2H, D70 - class Nikon3MakerNote : public IfdMakerNote { - public: - //! Shortcut for a %Nikon3MakerNote auto pointer. - typedef std::auto_ptr<Nikon3MakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - Nikon3MakerNote(bool alloc =true); - //! Copy constructor - Nikon3MakerNote(const Nikon3MakerNote& rhs); - //! Virtual destructor - virtual ~Nikon3MakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Nikon3 %MakerNote tags - //@{ - //! Print ISO setting - static std::ostream& print0x0002(std::ostream& os, const Value& value); - //! Print flash compensation - static std::ostream& print0x0012(std::ostream& os, const Value& value); - //! Print lens information - static std::ostream& print0x0084(std::ostream& os, const Value& value); - //! Print flash used information - static std::ostream& print0x0087(std::ostream& os, const Value& value); - //! Print AF point - static std::ostream& print0x0088(std::ostream& os, const Value& value); - //! Print bracketing information - static std::ostream& print0x0089(std::ostream& os, const Value& value); - //! Print number of lens stops - static std::ostream& print0x008b(std::ostream& os, const Value& value); - //! Print number of lens data - static std::ostream& print0x0098(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - Nikon3MakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - Nikon3MakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class Nikon3MakerNote - - static Nikon3MakerNote::RegisterMn registerNikon3MakerNote; - -} // namespace Exiv2 - -#endif // #ifndef NIKONMN_HPP_ diff --git a/src/plugins/exiv2/olympusmn.cpp b/src/plugins/exiv2/olympusmn.cpp @@ -1,315 +0,0 @@ -// ***************************************************************** -*- 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: olympusmn.cpp - Version: $Rev: 600 $ - Author(s): Will Stokes (wuz) <wstokes@gmail.com> - Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 10-Mar-05, wuz: created - Credits: See header file. - */ - -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: olympusmn.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "olympusmn.hpp" -#include "makernote.hpp" -#include "value.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - OlympusMakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote( - "OLYMPUS*", "*", createOlympusMakerNote); - MakerNoteFactory::registerMakerNote( - olympusIfdId, MakerNote::AutoPtr(new OlympusMakerNote)); - - ExifTags::registerMakerTagInfo(olympusIfdId, tagInfo_); - } - //! @endcond - - // Olympus Tag Info - const TagInfo OlympusMakerNote::tagInfo_[] = { - TagInfo(0x0200, "SpecialMode", "Picture taking mode", olympusIfdId, makerTags, unsignedLong, print0x0200), - TagInfo(0x0201, "Quality", "Image quality setting", olympusIfdId, makerTags, unsignedShort, print0x0201), - TagInfo(0x0202, "Macro", "Macro mode", olympusIfdId, makerTags, unsignedShort, print0x0202), - TagInfo(0x0203, "BWMode", "Black and White Mode", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0204, "DigitalZoom", "Digital zoom ratio", olympusIfdId, makerTags, unsignedRational, print0x0204), - TagInfo(0x0205, "FocalPlaneDiagonal", "Focal plane diagonal", olympusIfdId, makerTags, unsignedRational, printValue), - TagInfo(0x0206, "0x0206", "Unknown", olympusIfdId, makerTags, signedShort, printValue), - TagInfo(0x0207, "FirmwareVersion", "Software firmware version", olympusIfdId, makerTags, asciiString, printValue), - TagInfo(0x0208, "PictureInfo", "ASCII format data such as [PictureInfo]", olympusIfdId, makerTags, asciiString, printValue), - TagInfo(0x0209, "CameraID", "CameraID data", olympusIfdId, makerTags, undefined, printValue), - TagInfo(0x0300, "PreCaptureFrames", "Pre-capture frames", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0301, "0x0301", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0302, "OneTouchWB", "OneTouchWB", olympusIfdId, makerTags, unsignedShort, print0x0302), - TagInfo(0x0303, "0x0303", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0304, "0x0304", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0f00, "DataDump", "Various camera settings", olympusIfdId, makerTags, undefined, printValue), - TagInfo(0x1000, "0x1000", "Unknown", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1001, "0x1001", "Unknown", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1002, "0x1002", "Unknown", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1003, "0x1003", "Unknown", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1004, "FlashMode", "Flash mode", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1005, "FlashDevice", "Flash device", olympusIfdId, makerTags, unsignedShort, print0x1005), - TagInfo(0x1006, "Bracket", "Bracket", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1007, "0x1007", "Unknown", olympusIfdId, makerTags, signedShort, printValue), - TagInfo(0x1008, "0x1008", "Unknown", olympusIfdId, makerTags, signedShort, printValue), - TagInfo(0x1009, "0x1009", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x100a, "0x100a", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x100b, "FocusMode", "Focus mode", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x100c, "FocusDistance", "Focus distance", olympusIfdId, makerTags, unsignedRational, printValue), - TagInfo(0x100d, "Zoom", "Zoom", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x100e, "MacroFocus", "Macro focus", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x100f, "SharpnessFactor", "Sharpness factor", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1010, "0x1010", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1011, "ColorMatrix", "Color matrix", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1012, "BlackLevel", "Black level", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1013, "0x1013", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1014, "0x1014", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1015, "WhiteBalance", "White balance", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1016, "0x1016", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1017, "RedBalance", "Red balance", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1018, "BlueBalance", "Blue balance", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1019, "0x1019", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x101a, "SerialNumber", "Serial number", olympusIfdId, makerTags, asciiString, printValue), - TagInfo(0x101b, "0x101b", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x101c, "0x101c", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x101d, "0x101d", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x101e, "0x101e", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x101f, "0x101f", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x1020, "0x1020", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x1021, "0x1021", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x1022, "0x1022", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x1023, "FlashBias", "Flash bias", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1024, "0x1024", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1025, "0x1025", "Unknown", olympusIfdId, makerTags, signedRational, printValue), - TagInfo(0x1026, "0x1026", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1027, "0x1027", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1028, "0x1028", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1029, "Contrast", "Contrast setting", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x102a, "SharpnessFactor", "Sharpness factor", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x102b, "ColorControl", "Color control", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x102c, "ValidBits", "Valid bits", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x102d, "Coring Filter", "Coring filter", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x102e, "ImageWidth", "Image width", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x102f, "ImageHeight", "Image height", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x1030, "0x1030", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1031, "0x1031", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x1032, "0x1032", "Unknown", olympusIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x1033, "0x1033", "Unknown", olympusIfdId, makerTags, unsignedLong, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownOlympusMakerNoteTag)", "Unknown OlympusMakerNote tag", olympusIfdId, makerTags, invalidTypeId, printValue) - }; - - OlympusMakerNote::OlympusMakerNote(bool alloc) - : IfdMakerNote(olympusIfdId, alloc) - { - byte buf[] = { - 'O', 'L', 'Y', 'M', 'P', 0x00, 0x01, 0x00 - }; - readHeader(buf, 8, byteOrder_); - } - - OlympusMakerNote::OlympusMakerNote(const OlympusMakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int OlympusMakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 8) return 1; - - // Copy the header - header_.alloc(8); - memcpy(header_.pData_, buf, header_.size_); - // Adjust the offset of the IFD for the prefix - adjOffset_ = 8; - - return 0; - } - - int OlympusMakerNote::checkHeader() const - { - int rc = 0; - // Check the OLYMPUS prefix - if ( header_.size_ < 8 - || std::string(reinterpret_cast<char*>(header_.pData_), 5) - != std::string("OLYMP", 5)) { - rc = 2; - } - return rc; - } - - OlympusMakerNote::AutoPtr OlympusMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - OlympusMakerNote* OlympusMakerNote::create_(bool alloc) const - { - AutoPtr makerNote = AutoPtr(new OlympusMakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - OlympusMakerNote::AutoPtr OlympusMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - OlympusMakerNote* OlympusMakerNote::clone_() const - { - return new OlympusMakerNote(*this); - } - - std::ostream& OlympusMakerNote::print0x0200(std::ostream& os, - const Value& value) - { - if (value.count() != 3 || value.typeId() != unsignedLong) { - return os << value; - } - long l0 = value.toLong(0); - switch (l0) { - case 0: os << "Normal"; break; - case 2: os << "Fast"; break; - case 3: os << "Panorama"; break; - default: os << "(" << l0 << ")"; break; - } - if (l0 != 0) { - os << ", "; - long l1 = value.toLong(1); - os << "Sequence number " << l1; - } - if (l0 != 0 && l0 != 2) { - os << ", "; - long l2 = value.toLong(2); - switch (l2) { - case 1: os << "Left to Right"; break; - case 2: os << "Right to Left"; break; - case 3: os << "Bottom to Top"; break; - case 4: os << "Top to Bottom"; break; - default: os << "(" << l2 << ")"; break; - } - } - return os; - } // OlympusMakerNote::print0x0200 - - //! Quality - const TagDetails quality[] = { - { 0, "(start)" }, - { 1, "Standard Quality (SQ)" }, - { 2, "High Quality (HQ)" }, - { 3, "Super High Quality (SHQ)" }, - { 6, "Raw" }, - { 0, "(end)" } - }; - - std::ostream& OlympusMakerNote::print0x0201(std::ostream& os, - const Value& value) - { - return TagTranslator(quality).print(os, value); - } // OlympusMakerNote::print0x0201 - - //! Macro - const TagDetails macro[] = { - { -1, "(start)" }, - { 0, "Off" }, - { 1, "On" }, - { 2, "Super Macro" }, - { -1, "(end)" } - }; - - std::ostream& OlympusMakerNote::print0x0202(std::ostream& os, - const Value& value) - { - return TagTranslator(macro).print(os, value); - } // OlympusMakerNote::print0x0202 - - std::ostream& OlympusMakerNote::print0x0204(std::ostream& os, - const Value& value) - { - float f = value.toFloat(); - if (f == 0.0 || f == 1.0) return os << "None"; - return os << std::fixed << std::setprecision(1) << f << "x"; - } // OlympusMakerNote::print0x0204 - - //! OneTouchWB - const TagDetails oneTouchWb[] = { - { -1, "(start)" }, - { 0, "Off" }, - { 1, "On" }, - { 2, "On (Preset)" }, - { -1, "(end)" } - }; - - std::ostream& OlympusMakerNote::print0x0302(std::ostream& os, - const Value& value) - { - return TagTranslator(oneTouchWb).print(os, value); - } // OlympusMakerNote::print0x0302 - - //! FlashDevice - const TagDetails flashDevice[] = { - { -1, "(start)" }, - { 0, "None" }, - { 1, "Internal" }, - { 4, "External" }, - { 4, "Internal + External" }, - { -1, "(end)" } - }; - - std::ostream& OlympusMakerNote::print0x1005(std::ostream& os, - const Value& value) - { - return TagTranslator(flashDevice).print(os, value); - } // OlympusMakerNote::print0x1005 - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createOlympusMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - return MakerNote::AutoPtr(new OlympusMakerNote(alloc)); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/olympusmn.hpp b/src/plugins/exiv2/olympusmn.hpp @@ -1,161 +0,0 @@ -// ***************************************************************** -*- 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 olympusmn.hpp - @brief Olympus MakerNote implemented using the following references: - <a href="http://park2.wakwak.com/%7Etsuruzoh/Computer/Digicams/exif-e.html#APP1">Exif file format, Appendix 1: MakerNote of Olympus Digicams</a> by TsuruZoh Tachibanaya, - Olympus.pm of <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/">ExifTool</a> by Phil Harvey, - <a href="http://www.ozhiker.com/electronics/pjmt/jpeg_info/olympus_mn.html">Olympus Makernote Format Specification</a> by Evan Hunter, - email communication with <a href="mailto:wstokes@gmail.com">Will Stokes</a> - @version $Rev: 580 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @author Will Stokes (wuz) - <a href="mailto:wstokes@gmail.com">wstokes@gmail.com</a> - @date 10-Mar-05, wuz: created - */ -#ifndef OLYMPUSMN_HPP_ -#define OLYMPUSMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createOlympusMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! MakerNote for Olympus cameras - class OlympusMakerNote : public IfdMakerNote { - public: - //! Shortcut for a %OlympusMakerNote auto pointer. - typedef std::auto_ptr<OlympusMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - OlympusMakerNote(bool alloc =true); - //! Copy constructor - OlympusMakerNote(const OlympusMakerNote& rhs); - //! Virtual destructor - virtual ~OlympusMakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Olympus %MakerNote tags - //@{ - //! Print 'Special Mode' - static std::ostream& print0x0200(std::ostream& os, const Value& value); - //! Print Jpeg quality - static std::ostream& print0x0201(std::ostream& os, const Value& value); - //! Print Macro mode - static std::ostream& print0x0202(std::ostream& os, const Value& value); - //! Print Digital Zoom Factor - static std::ostream& print0x0204(std::ostream& os, const Value& value); - //! Print OneTouchWB - static std::ostream& print0x0302(std::ostream& os, const Value& value); - //! Print FlashDevice - static std::ostream& print0x1005(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - OlympusMakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - OlympusMakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class OlympusMakerNote - - static OlympusMakerNote::RegisterMn registerOlympusMakerNote; -} // namespace Exiv2 - -#endif // #ifndef OLYMPUSMN_HPP_ diff --git a/src/plugins/exiv2/panasonicmn.cpp b/src/plugins/exiv2/panasonicmn.cpp @@ -1,358 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: panasonicmn.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 11-Jun-04, ahu: created - Credits: See header file - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: panasonicmn.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "panasonicmn.hpp" -#include "makernote.hpp" -#include "value.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - PanasonicMakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote("Panasonic", "*", createPanasonicMakerNote); - MakerNoteFactory::registerMakerNote( - panasonicIfdId, MakerNote::AutoPtr(new PanasonicMakerNote)); - - ExifTags::registerMakerTagInfo(panasonicIfdId, tagInfo_); - } - //! @endcond - - // Panasonic MakerNote Tag Info - const TagInfo PanasonicMakerNote::tagInfo_[] = { - TagInfo(0x0001, "Quality", "Image Quality", panasonicIfdId, makerTags, unsignedShort, print0x0001), - TagInfo(0x0002, "FirmwareVersion", "Firmware version", panasonicIfdId, makerTags, undefined, printValue), - TagInfo(0x0003, "WhiteBalance", "White balance setting", panasonicIfdId, makerTags, unsignedShort, print0x0003), - TagInfo(0x0004, "0x0004", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0007, "FocusMode", "Focus mode", panasonicIfdId, makerTags, unsignedShort, print0x0007), - TagInfo(0x000f, "SpotMode", "Spot mode", panasonicIfdId, makerTags, unsignedByte, print0x000f), - TagInfo(0x001a, "ImageStabilizer", "Image stabilizer", panasonicIfdId, makerTags, unsignedShort, print0x001a), - TagInfo(0x001c, "Macro", "Macro mode", panasonicIfdId, makerTags, unsignedShort, print0x001c), - TagInfo(0x001f, "ShootingMode", "Shooting mode", panasonicIfdId, makerTags, unsignedShort, print0x001f), - TagInfo(0x0020, "Audio", "Audio", panasonicIfdId, makerTags, unsignedShort, print0x0020), - TagInfo(0x0021, "DataDump", "Data dump", panasonicIfdId, makerTags, undefined, printValue), - TagInfo(0x0022, "0x0022", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0023, "WhiteBalanceBias", "White balance adjustment", panasonicIfdId, makerTags, unsignedShort, print0x0023), - TagInfo(0x0024, "FlashBias", "Flash bias", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0025, "SerialNumber", "Serial number", panasonicIfdId, makerTags, undefined, printValue), - TagInfo(0x0026, "0x0026", "Unknown", panasonicIfdId, makerTags, undefined, printValue), - TagInfo(0x0027, "0x0027", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0028, "ColorEffect", "Color effect", panasonicIfdId, makerTags, unsignedShort, print0x0028), - TagInfo(0x0029, "0x0029", "Unknown", panasonicIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x002a, "0x002a", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x002b, "0x002b", "Unknown", panasonicIfdId, makerTags, unsignedLong, printValue), - TagInfo(0x002c, "Contrast", "Contrast setting", panasonicIfdId, makerTags, unsignedShort, print0x002c), - TagInfo(0x002d, "NoiseReduction", "Noise reduction", panasonicIfdId, makerTags, unsignedShort, print0x002d), - TagInfo(0x002e, "0x002e", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x002f, "0x002f", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0030, "0x0030", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0031, "0x0031", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x0032, "0x0032", "Unknown", panasonicIfdId, makerTags, unsignedShort, printValue), - TagInfo(0x4449, "0x4449", "Unknown", panasonicIfdId, makerTags, undefined, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownPanasonicMakerNoteTag)", "Unknown PanasonicMakerNote tag", panasonicIfdId, makerTags, invalidTypeId, printValue) - }; - - PanasonicMakerNote::PanasonicMakerNote(bool alloc) - : IfdMakerNote(panasonicIfdId, alloc, false) - { - byte buf[] = { - 'P', 'a', 'n', 'a', 's', 'o', 'n', 'i', 'c', 0x00, 0x00, 0x00 - }; - readHeader(buf, 12, byteOrder_); - } - - PanasonicMakerNote::PanasonicMakerNote(const PanasonicMakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int PanasonicMakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 12) return 1; - - header_.alloc(12); - memcpy(header_.pData_, buf, header_.size_); - // Adjust the offset of the IFD for the prefix - adjOffset_ = 12; - return 0; - } - - int PanasonicMakerNote::checkHeader() const - { - int rc = 0; - // Check the Panasonic prefix - if ( header_.size_ < 12 - || std::string(reinterpret_cast<char*>(header_.pData_), 9) - != std::string("Panasonic", 9)) { - rc = 2; - } - return rc; - } - - PanasonicMakerNote::AutoPtr PanasonicMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - PanasonicMakerNote* PanasonicMakerNote::create_(bool alloc) const - { - AutoPtr makerNote = AutoPtr(new PanasonicMakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - PanasonicMakerNote::AutoPtr PanasonicMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - PanasonicMakerNote* PanasonicMakerNote::clone_() const - { - return new PanasonicMakerNote(*this); - } - - //! Quality - const TagDetails quality[] = { - { 0, "(start)" }, - { 2, "High" }, - { 3, "Standard" }, - { 6, "Very High" }, - { 7, "Raw" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x0001(std::ostream& os, - const Value& value) - { - return TagTranslator(quality).print(os, value); - } // PanasonicMakerNote::print0x0001 - - //! WhiteBalance - const TagDetails whiteBalance[] = { - { 0, "(start)" }, - { 1, "Auto" }, - { 2, "Daylight" }, - { 3, "Cloudy" }, - { 4, "Halogen" }, - { 5, "Manual" }, - { 8, "Flash" }, - { 10, "Black and White" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x0003(std::ostream& os, - const Value& value) - { - return TagTranslator(whiteBalance).print(os, value); - } // PanasonicMakerNote::print0x0003 - - //! FocusMode - const TagDetails focusMode[] = { - { 0, "(start)" }, - { 1, "Auto" }, - { 2, "Manual" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x0007(std::ostream& os, - const Value& value) - { - return TagTranslator(focusMode).print(os, value); - } // PanasonicMakerNote::print0x0007 - - std::ostream& PanasonicMakerNote::print0x000f(std::ostream& os, - const Value& value) - { - if (value.count() < 2 || value.typeId() != unsignedByte) { - return os << value; - } - long l0 = value.toLong(0); - if (l0 == 1) os << "On"; - else if (l0 == 16) os << "Off"; - else os << value; - return os; - } // PanasonicMakerNote::print0x000f - - //! ImageStabilizer - const TagDetails imageStabilizer[] = { - { 0, "(start)" }, - { 2, "On, Mode 1" }, - { 3, "Off" }, - { 4, "On, Mode 2" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x001a(std::ostream& os, - const Value& value) - { - return TagTranslator(imageStabilizer).print(os, value); - } // PanasonicMakerNote::print0x001a - - //! Macro - const TagDetails macro[] = { - { 0, "(start)" }, - { 1, "On" }, - { 2, "Off" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x001c(std::ostream& os, - const Value& value) - { - return TagTranslator(macro).print(os, value); - } // PanasonicMakerNote::print0x001c - - //! ShootingMode - const TagDetails shootingMode[] = { - { 0, "(start)" }, - { 1, "Normal" }, - { 2, "Portrait" }, - { 3, "Scenery" }, - { 4, "Sports" }, - { 5, "Night Portrait" }, - { 6, "Program" }, - { 7, "Aperture Priority" }, - { 8, "Shutter Priority" }, - { 9, "Macro" }, - { 11, "Manual" }, - { 13, "Panning" }, - { 18, "Fireworks" }, - { 19, "Party" }, - { 20, "Snow" }, - { 21, "Night Scenery" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x001f(std::ostream& os, - const Value& value) - { - return TagTranslator(shootingMode).print(os, value); - } // PanasonicMakerNote::print0x001f - - //! Audio - const TagDetails Audio[] = { - { 0, "(start)" }, - { 1, "Yes" }, - { 2, "No" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x0020(std::ostream& os, - const Value& value) - { - return TagTranslator(Audio).print(os, value); - } // PanasonicMakerNote::print0x0020 - - std::ostream& PanasonicMakerNote::print0x0023(std::ostream& os, - const Value& value) - { - return os << std::fixed << std::setprecision(1) - << value.toLong() / 3 << " EV"; - } // PanasonicMakerNote::print0x0023 - - //! ColorEffect - const TagDetails colorEffect[] = { - { 0, "(start)" }, - { 1, "Off" }, - { 2, "Warm" }, - { 3, "Cool" }, - { 4, "Black and White" }, - { 5, "Sepia" }, - { 0, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x0028(std::ostream& os, - const Value& value) - { - return TagTranslator(colorEffect).print(os, value); - } // PanasonicMakerNote::print0x0028 - - //! Contrast - const TagDetails contrast[] = { - { -1, "(start)" }, - { 0, "Standard" }, - { 1, "Low" }, - { 2, "High" }, - { 0x100, "Low" }, - { 0x110, "Standard" }, - { 0x120, "High" }, - { -1, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x002c(std::ostream& os, - const Value& value) - { - return TagTranslator(contrast).print(os, value); - } // PanasonicMakerNote::print0x002c - - //! NoiseReduction - const TagDetails noiseReduction[] = { - { -1, "(start)" }, - { 0, "Standard" }, - { 1, "Low" }, - { 2, "High" }, - { -1, "(end)" } - }; - - std::ostream& PanasonicMakerNote::print0x002d(std::ostream& os, - const Value& value) - { - return TagTranslator(noiseReduction).print(os, value); - } // PanasonicMakerNote::print0x002d - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createPanasonicMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - return MakerNote::AutoPtr(new PanasonicMakerNote(alloc)); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/panasonicmn.hpp b/src/plugins/exiv2/panasonicmn.hpp @@ -1,170 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 panasonicmn.hpp - @brief Panasonic MakerNote implemented using the following references: - <a href="http://www.compton.nu/panasonic.html">Panasonic MakerNote Information</a> by Tom Hughes, - Panasonic.pm of <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/">ExifTool</a> by Phil Harvey, - <a href="http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html">Panasonic Makernote Format Specification</a> by Evan Hunter. - @version $Rev: 581 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 11-Jun-05, ahu: created - */ -#ifndef PANASONICMN_HPP_ -#define PANASONICMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createPanasonicMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! MakerNote for Panasonic cameras - class PanasonicMakerNote : public IfdMakerNote { - public: - //! Shortcut for a %PanasonicMakerNote auto pointer. - typedef std::auto_ptr<PanasonicMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - PanasonicMakerNote(bool alloc =true); - //! Copy constructor - PanasonicMakerNote(const PanasonicMakerNote& rhs); - //! Virtual destructor - virtual ~PanasonicMakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Panasonic %MakerNote tags - //@{ - //! Print Quality - static std::ostream& print0x0001(std::ostream& os, const Value& value); - //! Print WhiteBalance - static std::ostream& print0x0003(std::ostream& os, const Value& value); - //! Print FocusMode - static std::ostream& print0x0007(std::ostream& os, const Value& value); - //! Print SpotMode - static std::ostream& print0x000f(std::ostream& os, const Value& value); - //! Print ImageStabilizer - static std::ostream& print0x001a(std::ostream& os, const Value& value); - //! Print Macro - static std::ostream& print0x001c(std::ostream& os, const Value& value); - //! Print ShootingMode - static std::ostream& print0x001f(std::ostream& os, const Value& value); - //! Print Audio - static std::ostream& print0x0020(std::ostream& os, const Value& value); - //! Print WhiteBalanceBias - static std::ostream& print0x0023(std::ostream& os, const Value& value); - //! Print ColorEffect - static std::ostream& print0x0028(std::ostream& os, const Value& value); - //! Print Contrast - static std::ostream& print0x002c(std::ostream& os, const Value& value); - //! Print NoiseReduction - static std::ostream& print0x002d(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - PanasonicMakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - PanasonicMakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class PanasonicMakerNote - - static PanasonicMakerNote::RegisterMn registerPanasonicMakerNote; -} // namespace Exiv2 - -#endif // #ifndef PANASONICMN_HPP_ diff --git a/src/plugins/exiv2/rcsid.hpp b/src/plugins/exiv2/rcsid.hpp @@ -1,62 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 rcsid.hpp - @brief Define an RCS id string in every object file compiled from a source - file that includes rcsid.hpp. - - This is a simplified version of the ACE_RCSID macro that is used in the - <a href="http://www.cs.wustl.edu/~schmidt/ACE.html">ACE(TM)</a> distribution. - - @version $Rev: 538 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 02-Feb-04, ahu: created - */ -#ifndef RCSID_HPP_ -#define RCSID_HPP_ - -#if !defined (EXIV2_RCSID) -/*! - @brief Macro to store version information in each object file. - - Use this macro by including the following two lines at the beginning of - each *.cpp file. See the ident(1) manual pages for more information. - - @code - #include "rcsid.hpp" - EXIV2_RCSID("@(#) $Id$"); - @endcode - - The macro hack itself has the following purposes: - -# To define the RCS id string variable in the local namespace, so - that there won't be any duplicate extern symbols at link time. - -# To avoid warnings of the type "variable declared and never used". - - */ -#define EXIV2_RCSID(id) \ - namespace { \ - inline const char* getRcsId(const char*) { return id ; } \ - const char* rcsId = getRcsId(rcsId); \ - } - -#endif // #if !defined (EXIV2_RCSID) -#endif // #ifndef RCSID_HPP_ diff --git a/src/plugins/exiv2/sigmamn.cpp b/src/plugins/exiv2/sigmamn.cpp @@ -1,208 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: sigmamn.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 02-Apr-04, ahu: created - Credits: Sigma and Foveon MakerNote implemented according to the specification - in "SIGMA and FOVEON EXIF MakerNote Documentation" by Foveon. - <http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html> - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: sigmamn.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "sigmamn.hpp" -#include "makernote.hpp" -#include "value.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - SigmaMakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote("SIGMA", "*", createSigmaMakerNote); - MakerNoteFactory::registerMakerNote("FOVEON", "*", createSigmaMakerNote); - MakerNoteFactory::registerMakerNote( - sigmaIfdId, MakerNote::AutoPtr(new SigmaMakerNote)); - - ExifTags::registerMakerTagInfo(sigmaIfdId, tagInfo_); - } - //! @endcond - - // Sigma (Foveon) MakerNote Tag Info - const TagInfo SigmaMakerNote::tagInfo_[] = { - TagInfo(0x0002, "SerialNumber", "Camera serial number", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0003, "DriveMode", "Drive Mode", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0004, "ResolutionMode", "Resolution Mode", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0005, "AutofocusMode", "Autofocus mode", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0006, "FocusSetting", "Focus setting", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0007, "WhiteBalance", "White balance", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0008, "ExposureMode", "Exposure mode", sigmaIfdId, makerTags, asciiString, print0x0008), - TagInfo(0x0009, "MeteringMode", "Metering mode", sigmaIfdId, makerTags, asciiString, print0x0009), - TagInfo(0x000a, "LensRange", "Lens focal length range", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x000b, "ColorSpace", "Color space", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x000c, "Exposure", "Exposure", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x000d, "Contrast", "Contrast", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x000e, "Shadow", "Shadow", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x000f, "Highlight", "Highlight", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x0010, "Saturation", "Saturation", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x0011, "Sharpness", "Sharpness", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x0012, "FillLight", "X3 Fill light", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x0014, "ColorAdjustment", "Color adjustment", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x0015, "AdjustmentMode", "Adjustment mode", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0016, "Quality", "Quality", sigmaIfdId, makerTags, asciiString, printStripLabel), - TagInfo(0x0017, "Firmware", "Firmware", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0018, "Software", "Software", sigmaIfdId, makerTags, asciiString, printValue), - TagInfo(0x0019, "AutoBracket", "Auto bracket", sigmaIfdId, makerTags, asciiString, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownSigmaMakerNoteTag)", "Unknown SigmaMakerNote tag", sigmaIfdId, makerTags, invalidTypeId, printValue) - }; - - SigmaMakerNote::SigmaMakerNote(bool alloc) - : IfdMakerNote(sigmaIfdId, alloc) - { - byte buf[] = { - 'S', 'I', 'G', 'M', 'A', '\0', '\0', '\0', 0x01, 0x00 - }; - readHeader(buf, 10, byteOrder_); - } - - SigmaMakerNote::SigmaMakerNote(const SigmaMakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int SigmaMakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 10) return 1; - - // Copy the header. My one and only Sigma sample has two undocumented - // extra bytes (0x01, 0x00) between the ID string and the start of the - // Makernote IFD. So we copy 10 bytes into the header. - header_.alloc(10); - memcpy(header_.pData_, buf, header_.size_); - // Adjust the offset of the IFD for the prefix - adjOffset_ = 10; - return 0; - } - - int SigmaMakerNote::checkHeader() const - { - int rc = 0; - // Check the SIGMA or FOVEON prefix - if ( header_.size_ < 10 - || std::string(reinterpret_cast<char*>(header_.pData_), 8) - != std::string("SIGMA\0\0\0", 8) - && std::string(reinterpret_cast<char*>(header_.pData_), 8) - != std::string("FOVEON\0\0", 8)) { - rc = 2; - } - return rc; - } - - SigmaMakerNote::AutoPtr SigmaMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - SigmaMakerNote* SigmaMakerNote::create_(bool alloc) const - { - AutoPtr makerNote = AutoPtr(new SigmaMakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - SigmaMakerNote::AutoPtr SigmaMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - SigmaMakerNote* SigmaMakerNote::clone_() const - { - return new SigmaMakerNote(*this); - } - - std::ostream& SigmaMakerNote::printStripLabel(std::ostream& os, - const Value& value) - { - std::string v = value.toString(); - std::string::size_type pos = v.find(':'); - if (pos != std::string::npos) { - if (v[pos + 1] == ' ') ++pos; - v = v.substr(pos + 1); - } - return os << v; - } - - std::ostream& SigmaMakerNote::print0x0008(std::ostream& os, - const Value& value) - { - switch (value.toString()[0]) { - case 'P': os << "Program"; break; - case 'A': os << "Aperture priority"; break; - case 'S': os << "Shutter priority"; break; - case 'M': os << "Manual"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - - std::ostream& SigmaMakerNote::print0x0009(std::ostream& os, - const Value& value) - { - switch (value.toString()[0]) { - case 'A': os << "Average"; break; - case 'C': os << "Center"; break; - case '8': os << "8-Segment"; break; - default: os << "(" << value << ")"; break; - } - return os; - } - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createSigmaMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - return MakerNote::AutoPtr(new SigmaMakerNote(alloc)); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/sigmamn.hpp b/src/plugins/exiv2/sigmamn.hpp @@ -1,151 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 sigmamn.hpp - @brief Sigma and Foveon MakerNote implemented according to the specification - <a href="http://www.x3f.info/technotes/FileDocs/MakerNoteDoc.html"> - SIGMA and FOVEON EXIF MakerNote Documentation</a> by Foveon. - @version $Rev: 569 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 02-Apr-04, ahu: created - */ -#ifndef SIGMAMN_HPP_ -#define SIGMAMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createSigmaMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! MakerNote for Sigma (Foveon) cameras - class SigmaMakerNote : public IfdMakerNote { - public: - //! Shortcut for a %SigmaMakerNote auto pointer. - typedef std::auto_ptr<SigmaMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - SigmaMakerNote(bool alloc =true); - //! Copy constructor - SigmaMakerNote(const SigmaMakerNote& rhs); - //! Virtual destructor - virtual ~SigmaMakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @name Print functions for Sigma (Foveon) %MakerNote tags - //@{ - //! Strip the label from the value and print the remainder - static std::ostream& printStripLabel(std::ostream& os, const Value& value); - //! Print exposure mode - static std::ostream& print0x0008(std::ostream& os, const Value& value); - //! Print metering mode - static std::ostream& print0x0009(std::ostream& os, const Value& value); - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - SigmaMakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - SigmaMakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class SigmaMakerNote - - static SigmaMakerNote::RegisterMn registerSigmaMakerNote; -} // namespace Exiv2 - -#endif // #ifndef SIGMAMN_HPP_ diff --git a/src/plugins/exiv2/sonymn.cpp b/src/plugins/exiv2/sonymn.cpp @@ -1,147 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: sonymn.cpp - Version: $Rev: 600 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 18-Apr-05, ahu: created - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: sonymn.cpp 600 2005-07-09 10:38:09Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "sonymn.hpp" -#include "makernote.hpp" -#include "value.hpp" - -// + standard includes -#include <string> -#include <sstream> -#include <iomanip> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - //! @cond IGNORE - SonyMakerNote::RegisterMn::RegisterMn() - { - MakerNoteFactory::registerMakerNote("SONY", "*", createSonyMakerNote); - MakerNoteFactory::registerMakerNote( - sonyIfdId, MakerNote::AutoPtr(new SonyMakerNote)); - - ExifTags::registerMakerTagInfo(sonyIfdId, tagInfo_); - } - //! @endcond - - // Sony MakerNote Tag Info - const TagInfo SonyMakerNote::tagInfo_[] = { - TagInfo(0x2000, "0x2000", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9001, "0x9001", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9002, "0x9002", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9003, "0x9003", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9004, "0x9004", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9005, "0x9005", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9006, "0x9006", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9007, "0x9007", "Unknown", sonyIfdId, makerTags, undefined, printValue), - TagInfo(0x9008, "0x9008", "Unknown", sonyIfdId, makerTags, undefined, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownSonyMakerNoteTag)", "Unknown SonyMakerNote tag", sonyIfdId, makerTags, invalidTypeId, printValue) - }; - - SonyMakerNote::SonyMakerNote(bool alloc) - : IfdMakerNote(sonyIfdId, alloc, false) - { - byte buf[] = { - 'S', 'O', 'N', 'Y', ' ', 'D', 'S', 'C', ' ', '\0', '\0', '\0' - }; - readHeader(buf, 12, byteOrder_); - } - - SonyMakerNote::SonyMakerNote(const SonyMakerNote& rhs) - : IfdMakerNote(rhs) - { - } - - int SonyMakerNote::readHeader(const byte* buf, - long len, - ByteOrder byteOrder) - { - if (len < 12) return 1; - header_.alloc(12); - memcpy(header_.pData_, buf, header_.size_); - // Adjust the offset of the IFD for the prefix - adjOffset_ = 12; - return 0; - } - - int SonyMakerNote::checkHeader() const - { - int rc = 0; - // Check the SONY prefix - if ( header_.size_ < 12 - || std::string(reinterpret_cast<char*>(header_.pData_), 12) - != std::string("SONY DSC \0\0\0", 12)) { - rc = 2; - } - return rc; - } - - SonyMakerNote::AutoPtr SonyMakerNote::create(bool alloc) const - { - return AutoPtr(create_(alloc)); - } - - SonyMakerNote* SonyMakerNote::create_(bool alloc) const - { - AutoPtr makerNote = AutoPtr(new SonyMakerNote(alloc)); - assert(makerNote.get() != 0); - makerNote->readHeader(header_.pData_, header_.size_, byteOrder_); - return makerNote.release(); - } - - SonyMakerNote::AutoPtr SonyMakerNote::clone() const - { - return AutoPtr(clone_()); - } - - SonyMakerNote* SonyMakerNote::clone_() const - { - return new SonyMakerNote(*this); - } - -// ***************************************************************************** -// free functions - - MakerNote::AutoPtr createSonyMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset) - { - return MakerNote::AutoPtr(new SonyMakerNote(alloc)); - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/sonymn.hpp b/src/plugins/exiv2/sonymn.hpp @@ -1,139 +0,0 @@ -// ***************************************************************** -*- 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 sonymn.hpp - @brief Basic Sony MakerNote implementation - @version $Rev: 569 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 18-Apr-05, ahu: created - */ -#ifndef SONYMN_HPP_ -#define SONYMN_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" -#include "makernote.hpp" -#include "tags.hpp" - -// + standard includes -#include <string> -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - -// ***************************************************************************** -// free functions - - /*! - @brief Return an auto-pointer to a newly created empty MakerNote - initialized to operate in the memory management model indicated. - The caller owns this copy and the auto-pointer ensures that it - will be deleted. - - @param alloc Memory management model for the new MakerNote. Determines if - memory required to store data should be allocated and deallocated - (true) or not (false). If false, only pointers to the buffer - provided to read() will be kept. See Ifd for more background on - this concept. - @param buf Pointer to the makernote character buffer (not used). - @param len Length of the makernote character buffer (not used). - @param byteOrder Byte order in which the Exif data (and possibly the - makernote) is encoded (not used). - @param offset Offset from the start of the TIFF header of the makernote - buffer (not used). - - @return An auto-pointer to a newly created empty MakerNote. The caller - owns this copy and the auto-pointer ensures that it will be - deleted. - */ - MakerNote::AutoPtr createSonyMakerNote(bool alloc, - const byte* buf, - long len, - ByteOrder byteOrder, - long offset); - -// ***************************************************************************** -// class definitions - - //! MakerNote for Sony cameras - class SonyMakerNote : public IfdMakerNote { - public: - //! Shortcut for a %SonyMakerNote auto pointer. - typedef std::auto_ptr<SonyMakerNote> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor. Allows to choose whether or not memory management - is required for the makernote entries. - */ - SonyMakerNote(bool alloc =true); - //! Copy constructor - SonyMakerNote(const SonyMakerNote& rhs); - //! Virtual destructor - virtual ~SonyMakerNote() {} - //@} - - //! @name Manipulators - //@{ - int readHeader(const byte* buf, - long len, - ByteOrder byteOrder); - //@} - - //! @name Accessors - //@{ - int checkHeader() const; - AutoPtr create(bool alloc =true) const; - AutoPtr clone() const; - //@} - - //! @cond IGNORE - // Public only so that we can create a static instance - struct RegisterMn { - RegisterMn(); - }; - //! @endcond - - private: - //! Internal virtual create function. - SonyMakerNote* create_(bool alloc =true) const; - //! Internal virtual copy constructor. - SonyMakerNote* clone_() const; - - //! Tag information - static const TagInfo tagInfo_[]; - - }; // class SonyMakerNote - - static SonyMakerNote::RegisterMn registerSonyMakerNote; -} // namespace Exiv2 - -#endif // #ifndef SONYMN_HPP_ diff --git a/src/plugins/exiv2/tags.cpp b/src/plugins/exiv2/tags.cpp @@ -1,1233 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: tags.cpp - Version: $Rev: 596 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 15-Jan-04, ahu: created - 21-Jan-05, ahu: added MakerNote TagInfo registry and related code - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: tags.cpp 596 2005-06-26 11:04:27Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "tags.hpp" -#include "error.hpp" -#include "types.hpp" -#include "ifd.hpp" -#include "value.hpp" -#include "makernote.hpp" -#include "mn.hpp" // To ensure that all makernotes are registered - -#include <iostream> -#include <iomanip> -#include <sstream> -#include <utility> -#include <cstdlib> -#include <cassert> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - IfdInfo::IfdInfo(IfdId ifdId, const char* name, const char* item) - : ifdId_(ifdId), name_(name), item_(item) - { - } - - // Todo: Allow to register new IfdInfo entries from elsewhere (the makernotes) - // Important: IFD item must be unique! - const IfdInfo ExifTags::ifdInfo_[] = { - IfdInfo(ifdIdNotSet, "(Unknown IFD)", "(Unknown item)"), - IfdInfo(ifd0Id, "IFD0", "Image"), - IfdInfo(exifIfdId, "Exif", "Photo"), // just to avoid 'Exif.Exif.*' keys - IfdInfo(gpsIfdId, "GPSInfo", "GPSInfo"), - IfdInfo(iopIfdId, "Iop", "Iop"), - IfdInfo(ifd1Id, "IFD1", "Thumbnail"), - IfdInfo(canonIfdId, "Makernote", "Canon"), - IfdInfo(canonCs1IfdId, "Makernote", "CanonCs1"), - IfdInfo(canonCs2IfdId, "Makernote", "CanonCs2"), - IfdInfo(canonCfIfdId, "Makernote", "CanonCf"), - IfdInfo(fujiIfdId, "Makernote", "Fujifilm"), - IfdInfo(nikon1IfdId, "Makernote", "Nikon1"), - IfdInfo(nikon2IfdId, "Makernote", "Nikon2"), - IfdInfo(nikon3IfdId, "Makernote", "Nikon3"), - IfdInfo(olympusIfdId, "Makernote", "Olympus"), - IfdInfo(panasonicIfdId, "Makernote", "Panasonic"), - IfdInfo(sigmaIfdId, "Makernote", "Sigma"), - IfdInfo(sonyIfdId, "Makernote", "Sony"), - IfdInfo(lastIfdId, "(Last IFD info)", "(Last IFD item)") - }; - - SectionInfo::SectionInfo( - SectionId sectionId, - const char* name, - const char* desc - ) - : sectionId_(sectionId), name_(name), desc_(desc) - { - } - - const SectionInfo ExifTags::sectionInfo_[] = { - SectionInfo(sectionIdNotSet, "(UnknownSection)", "Unknown section"), - SectionInfo(imgStruct, "ImageStructure", "Image data structure"), - SectionInfo(recOffset, "RecordingOffset", "Recording offset"), - SectionInfo(imgCharacter, "ImageCharacteristics", "Image data characteristics"), - SectionInfo(otherTags, "OtherTags", "Other data"), - SectionInfo(exifFormat, "ExifFormat", "Exif data structure"), - SectionInfo(exifVersion, "ExifVersion", "Exif Version"), - SectionInfo(imgConfig, "ImageConfig", "Image configuration"), - SectionInfo(userInfo, "UserInfo", "User information"), - SectionInfo(relatedFile, "RelatedFile", "Related file"), - SectionInfo(dateTime, "DateTime", "Date and time"), - SectionInfo(captureCond, "CaptureConditions", "Picture taking conditions"), - SectionInfo(gpsTags, "GPS", "GPS information"), - SectionInfo(iopTags, "Interoperability", "Interoperability information"), - SectionInfo(makerTags, "Makernote", "Vendor specific information"), - SectionInfo(lastSectionId, "(LastSection)", "Last section") - }; - - TagInfo::TagInfo( - uint16_t tag, - const char* name, - const char* desc, - IfdId ifdId, - SectionId sectionId, - TypeId typeId, - PrintFct printFct - ) - : tag_(tag), name_(name), desc_(desc), ifdId_(ifdId), - sectionId_(sectionId), typeId_(typeId), printFct_(printFct) - { - } - - // Base IFD Tags (IFD0 and IFD1) - static const TagInfo ifdTagInfo[] = { - TagInfo(0x0100, "ImageWidth", "Image width", ifd0Id, imgStruct, unsignedLong, printValue), - TagInfo(0x0101, "ImageLength", "Image height", ifd0Id, imgStruct, unsignedLong, printValue), - TagInfo(0x0102, "BitsPerSample", "Number of bits per component", ifd0Id, imgStruct, unsignedShort, printValue), - TagInfo(0x0103, "Compression", "Compression scheme", ifd0Id, imgStruct, unsignedShort, print0x0103), - TagInfo(0x0106, "PhotometricInterpretation", "Pixel composition", ifd0Id, imgStruct, unsignedShort, print0x0106), - TagInfo(0x010e, "ImageDescription", "Image title", ifd0Id, otherTags, asciiString, printValue), - TagInfo(0x010f, "Make", "Manufacturer of image input equipment", ifd0Id, otherTags, asciiString, printValue), - TagInfo(0x0110, "Model", "Model of image input equipment", ifd0Id, otherTags, asciiString, printValue), - TagInfo(0x0111, "StripOffsets", "Image data location", ifd0Id, recOffset, unsignedLong, printValue), - TagInfo(0x0112, "Orientation", "Orientation of image", ifd0Id, imgStruct, unsignedShort, print0x0112), - TagInfo(0x0115, "SamplesPerPixel", "Number of components", ifd0Id, imgStruct, unsignedShort, printValue), - TagInfo(0x0116, "RowsPerStrip", "Number of rows per strip", ifd0Id, recOffset, unsignedLong, printValue), - TagInfo(0x0117, "StripByteCounts", "Bytes per compressed strip", ifd0Id, recOffset, unsignedLong, printValue), - TagInfo(0x011a, "XResolution", "Image resolution in width direction", ifd0Id, imgStruct, unsignedRational, printLong), - TagInfo(0x011b, "YResolution", "Image resolution in height direction", ifd0Id, imgStruct, unsignedRational, printLong), - TagInfo(0x011c, "PlanarConfiguration", "Image data arrangement", ifd0Id, imgStruct, unsignedShort, printValue), - TagInfo(0x0128, "ResolutionUnit", "Unit of X and Y resolution", ifd0Id, imgStruct, unsignedShort, printUnit), - TagInfo(0x012d, "TransferFunction", "Transfer function", ifd0Id, imgCharacter, unsignedShort, printValue), - TagInfo(0x0131, "Software", "Software used", ifd0Id, otherTags, asciiString, printValue), - TagInfo(0x0132, "DateTime", "File change date and time", ifd0Id, otherTags, asciiString, printValue), - TagInfo(0x013b, "Artist", "Person who created the image", ifd0Id, otherTags, asciiString, printValue), - TagInfo(0x013e, "WhitePoint", "White point chromaticity", ifd0Id, imgCharacter, unsignedRational, printValue), - TagInfo(0x013f, "PrimaryChromaticities", "Chromaticities of primaries", ifd0Id, imgCharacter, unsignedRational, printValue), - TagInfo(0x0201, "JPEGInterchangeFormat", "Offset to JPEG SOI", ifd0Id, recOffset, unsignedLong, printValue), - TagInfo(0x0202, "JPEGInterchangeFormatLength", "Bytes of JPEG data", ifd0Id, recOffset, unsignedLong, printValue), - TagInfo(0x0211, "YCbCrCoefficients", "Color space transformation matrix coefficients", ifd0Id, imgCharacter, unsignedRational, printValue), - TagInfo(0x0212, "YCbCrSubSampling", "Subsampling ratio of Y to C", ifd0Id, imgStruct, unsignedShort, printValue), - TagInfo(0x0213, "YCbCrPositioning", "Y and C positioning", ifd0Id, imgStruct, unsignedShort, print0x0213), - TagInfo(0x0214, "ReferenceBlackWhite", "Pair of black and white reference values", ifd0Id, imgCharacter, unsignedRational, printValue), - TagInfo(0x8298, "Copyright", "Copyright holder", ifd0Id, otherTags, asciiString, print0x8298), - TagInfo(0x8769, "ExifTag", "Exif IFD Pointer", ifd0Id, exifFormat, unsignedLong, printValue), - TagInfo(0x8825, "GPSTag", "GPSInfo IFD Pointer", ifd0Id, exifFormat, unsignedLong, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownIfdTag)", "Unknown IFD tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue) - }; - - // Exif IFD Tags - static const TagInfo exifTagInfo[] = { - TagInfo(0x829a, "ExposureTime", "Exposure time", exifIfdId, captureCond, unsignedRational, print0x829a), - TagInfo(0x829d, "FNumber", "F number", exifIfdId, captureCond, unsignedRational, print0x829d), - TagInfo(0x8822, "ExposureProgram", "Exposure program", exifIfdId, captureCond, unsignedShort, print0x8822), - TagInfo(0x8824, "SpectralSensitivity", "Spectral sensitivity", exifIfdId, captureCond, asciiString, printValue), - TagInfo(0x8827, "ISOSpeedRatings", "ISO speed ratings", exifIfdId, captureCond, unsignedShort, print0x8827), - TagInfo(0x8828, "OECF", "Optoelectric coefficient", exifIfdId, captureCond, undefined, printValue), - TagInfo(0x9000, "ExifVersion", "Exif Version", exifIfdId, exifVersion, undefined, printValue), - TagInfo(0x9003, "DateTimeOriginal", "Date and time original image was generated", exifIfdId, dateTime, asciiString, printValue), - TagInfo(0x9004, "DateTimeDigitized", "Date and time image was made digital data", exifIfdId, dateTime, asciiString, printValue), - TagInfo(0x9101, "ComponentsConfiguration", "Meaning of each component", exifIfdId, imgConfig, undefined, print0x9101), - TagInfo(0x9102, "CompressedBitsPerPixel", "Image compression mode", exifIfdId, imgConfig, unsignedRational, printFloat), - TagInfo(0x9201, "ShutterSpeedValue", "Shutter speed", exifIfdId, captureCond, signedRational, printFloat), - TagInfo(0x9202, "ApertureValue", "Aperture", exifIfdId, captureCond, unsignedRational, printFloat), - TagInfo(0x9203, "BrightnessValue", "Brightness", exifIfdId, captureCond, signedRational, printFloat), - TagInfo(0x9204, "ExposureBiasValue", "Exposure bias", exifIfdId, captureCond, signedRational, print0x9204), - TagInfo(0x9205, "MaxApertureValue", "Maximum lens aperture", exifIfdId, captureCond, unsignedRational, printFloat), - TagInfo(0x9206, "SubjectDistance", "Subject distance", exifIfdId, captureCond, unsignedRational, print0x9206), - TagInfo(0x9207, "MeteringMode", "Metering mode", exifIfdId, captureCond, unsignedShort, print0x9207), - TagInfo(0x9208, "LightSource", "Light source", exifIfdId, captureCond, unsignedShort, print0x9208), - TagInfo(0x9209, "Flash", "Flash", exifIfdId, captureCond, unsignedShort, print0x9209), - TagInfo(0x920a, "FocalLength", "Lens focal length", exifIfdId, captureCond, unsignedRational, print0x920a), - TagInfo(0x9214, "SubjectArea", "Subject area", exifIfdId, captureCond, unsignedShort, printValue), - TagInfo(0x927c, "MakerNote", "Manufacturer notes", exifIfdId, userInfo, undefined, printValue), - TagInfo(0x9286, "UserComment", "User comments", exifIfdId, userInfo, comment, print0x9286), - TagInfo(0x9290, "SubSecTime", "DateTime subseconds", exifIfdId, dateTime, asciiString, printValue), - TagInfo(0x9291, "SubSecTimeOriginal", "DateTimeOriginal subseconds", exifIfdId, dateTime, asciiString, printValue), - TagInfo(0x9292, "SubSecTimeDigitized", "DateTimeDigitized subseconds", exifIfdId, dateTime, asciiString, printValue), - TagInfo(0xa000, "FlashpixVersion", "Supported Flashpix version", exifIfdId, exifVersion, undefined, printValue), - TagInfo(0xa001, "ColorSpace", "Color space information", exifIfdId, imgCharacter, unsignedShort, print0xa001), - TagInfo(0xa002, "PixelXDimension", "Valid image width", exifIfdId, imgConfig, unsignedLong, printValue), - TagInfo(0xa003, "PixelYDimension", "Valid image height", exifIfdId, imgConfig, unsignedLong, printValue), - TagInfo(0xa004, "RelatedSoundFile", "Related audio file", exifIfdId, relatedFile, asciiString, printValue), - TagInfo(0xa005, "InteroperabilityTag", "Interoperability IFD Pointer", exifIfdId, exifFormat, unsignedLong, printValue), - TagInfo(0xa20b, "FlashEnergy", "Flash energy", exifIfdId, captureCond, unsignedRational, printValue), - TagInfo(0xa20c, "SpatialFrequencyResponse", "Spatial frequency response", exifIfdId, captureCond, undefined, printValue), - TagInfo(0xa20e, "FocalPlaneXResolution", "Focal plane X resolution", exifIfdId, captureCond, unsignedRational, printFloat), - TagInfo(0xa20f, "FocalPlaneYResolution", "Focal plane Y resolution", exifIfdId, captureCond, unsignedRational, printFloat), - TagInfo(0xa210, "FocalPlaneResolutionUnit", "Focal plane resolution unit", exifIfdId, captureCond, unsignedShort, printUnit), - TagInfo(0xa214, "SubjectLocation", "Subject location", exifIfdId, captureCond, unsignedShort, printValue), - TagInfo(0xa215, "ExposureIndex", "Exposure index", exifIfdId, captureCond, unsignedRational, printValue), - TagInfo(0xa217, "SensingMethod", "Sensing method", exifIfdId, captureCond, unsignedShort, print0xa217), - TagInfo(0xa300, "FileSource", "File source", exifIfdId, captureCond, undefined, print0xa300), - TagInfo(0xa301, "SceneType", "Scene type", exifIfdId, captureCond, undefined, print0xa301), - TagInfo(0xa302, "CFAPattern", "CFA pattern", exifIfdId, captureCond, undefined, printValue), - TagInfo(0xa401, "CustomRendered", "Custom image processing", exifIfdId, captureCond, unsignedShort, printValue), - TagInfo(0xa402, "ExposureMode", "Exposure mode", exifIfdId, captureCond, unsignedShort, print0xa402), - TagInfo(0xa403, "WhiteBalance", "White balance", exifIfdId, captureCond, unsignedShort, print0xa403), - TagInfo(0xa404, "DigitalZoomRatio", "Digital zoom ratio", exifIfdId, captureCond, unsignedRational, print0xa404), - TagInfo(0xa405, "FocalLengthIn35mmFilm", "Focal length in 35 mm film", exifIfdId, captureCond, unsignedShort, print0xa405), - TagInfo(0xa406, "SceneCaptureType", "Scene capture type", exifIfdId, captureCond, unsignedShort, print0xa406), - TagInfo(0xa407, "GainControl", "Gain control", exifIfdId, captureCond, unsignedRational, print0xa407), - TagInfo(0xa408, "Contrast", "Contrast", exifIfdId, captureCond, unsignedShort, print0xa408), - TagInfo(0xa409, "Saturation", "Saturation", exifIfdId, captureCond, unsignedShort, print0xa409), - TagInfo(0xa40a, "Sharpness", "Sharpness", exifIfdId, captureCond, unsignedShort, print0xa40a), - TagInfo(0xa40b, "DeviceSettingDescription", "Device settings description", exifIfdId, captureCond, undefined, printValue), - TagInfo(0xa40c, "SubjectDistanceRange", "Subject distance range", exifIfdId, captureCond, unsignedShort, print0xa40c), - TagInfo(0xa420, "ImageUniqueID", "Unique image ID", exifIfdId, otherTags, asciiString, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownExifTag)", "Unknown Exif tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue) - }; - - // GPS Info Tags - static const TagInfo gpsTagInfo[] = { - TagInfo(0x0000, "GPSVersionID", "GPS tag version", gpsIfdId, gpsTags, unsignedByte, printValue), - TagInfo(0x0001, "GPSLatitudeRef", "North or South Latitude", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0002, "GPSLatitude", "Latitude", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0003, "GPSLongitudeRef", "East or West Longitude", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0004, "GPSLongitude", "Longitude", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0005, "GPSAltitudeRef", "Altitude reference", gpsIfdId, gpsTags, unsignedByte, printValue), - TagInfo(0x0006, "GPSAltitude", "Altitude", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0007, "GPSTimeStamp", "GPS time (atomic clock)", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0008, "GPSSatellites", "GPS satellites used for measurement", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0009, "GPSStatus", "GPS receiver status", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x000a, "GPSMeasureMode", "GPS measurement mode", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x000b, "GPSDOP", "Measurement precision", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x000c, "GPSSpeedRef", "Speed unit", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x000d, "GPSSpeed", "Speed of GPS receiver", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x000e, "GPSTrackRef", "Reference for direction of movement", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x000f, "GPSTrack", "Direction of movement", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0010, "GPSImgDirectionRef", "Reference for direction of image", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0011, "GPSImgDirection", "Direction of image", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0012, "GPSMapDatum", "Geodetic survey data used", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0013, "GPSDestLatitudeRef", "Reference for latitude of destination", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0014, "GPSDestLatitude", "Latitude of destination", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0015, "GPSDestLongitudeRef", "Reference for longitude of destination", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0016, "GPSDestLongitude", "Longitude of destination", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0017, "GPSDestBearingRef", "Reference for bearing of destination", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x0018, "GPSDestBearing", "Bearing of destination", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x0019, "GPSDestDistanceRef", "Reference for distance to destination", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x001a, "GPSDestDistance", "Distance to destination", gpsIfdId, gpsTags, unsignedRational, printValue), - TagInfo(0x001b, "GPSProcessingMethod", "Name of GPS processing method", gpsIfdId, gpsTags, undefined, printValue), - TagInfo(0x001c, "GPSAreaInformation", "Name of GPS area", gpsIfdId, gpsTags, undefined, printValue), - TagInfo(0x001d, "GPSDateStamp", "GPS date", gpsIfdId, gpsTags, asciiString, printValue), - TagInfo(0x001e, "GPSDifferential", "GPS differential correction", gpsIfdId, gpsTags, unsignedShort, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownGpsTag)", "Unknown GPSInfo tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue) - }; - - // Exif Interoperability IFD Tags - static const TagInfo iopTagInfo[] = { - TagInfo(0x0001, "InteroperabilityIndex", "Interoperability Identification", iopIfdId, iopTags, asciiString, printValue), - TagInfo(0x0002, "InteroperabilityVersion", "Interoperability version", iopIfdId, iopTags, undefined, printValue), - TagInfo(0x1000, "RelatedImageFileFormat", "File format of image file", iopIfdId, iopTags, asciiString, printValue), - TagInfo(0x1001, "RelatedImageWidth", "Image width", iopIfdId, iopTags, unsignedLong, printValue), - TagInfo(0x1002, "RelatedImageLength", "Image height", iopIfdId, iopTags, unsignedLong, printValue), - // End of list marker - TagInfo(0xffff, "(UnknownIopTag)", "Unknown Exif Interoperability tag", ifdIdNotSet, sectionIdNotSet, invalidTypeId, printValue) - }; - - // Unknown Tag - static const TagInfo unknownTag(0xffff, "Unknown tag", "Unknown tag", ifdIdNotSet, sectionIdNotSet, asciiString, printValue); - - std::ostream& TagTranslator::print(std::ostream& os, const Value& value) const - { - if (!pTagDetails_) return os << value; - - long l = value.toLong(); - - long e = pTagDetails_[0].val_; - int i = 1; - for (; pTagDetails_[i].val_ != l && pTagDetails_[i].val_ != e; ++i) {} - if (pTagDetails_[i].val_ == l) { - os << pTagDetails_[i].label_; - } - else { - os << "(" << l << ")"; - } - return os; - } // TagTranslator::print - - // Tag lookup lists with tag names, desc and where they (preferably) belong to; - // this is an array with pointers to one list per IFD. The IfdId is used as the - // index into the array. - const TagInfo* ExifTags::tagInfos_[] = { - 0, - ifdTagInfo, exifTagInfo, gpsTagInfo, iopTagInfo, ifdTagInfo, - 0 - }; - - // Lookup list for registered makernote tag info tables - const TagInfo* ExifTags::makerTagInfos_[]; - - // All makernote ifd ids, in the same order as the tag infos in makerTagInfos_ - IfdId ExifTags::makerIfdIds_[]; - - void ExifTags::registerBaseTagInfo(IfdId ifdId) - { - registerMakerTagInfo(ifdId, ifdTagInfo); - } - - void ExifTags::registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo) - { - int i = 0; - for (; i < MAX_MAKER_TAG_INFOS; ++i) { - if (makerIfdIds_[i] == 0) { - makerIfdIds_[i] = ifdId; - makerTagInfos_[i] = tagInfo; - break; - } - } - if (i == MAX_MAKER_TAG_INFOS) throw Error(16); - } // ExifTags::registerMakerTagInfo - - int ExifTags::tagInfoIdx(uint16_t tag, IfdId ifdId) - { - const TagInfo* tagInfo = tagInfos_[ifdId]; - if (tagInfo == 0) return -1; - int idx; - for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) { - if (tagInfo[idx].tag_ == tag) return idx; - } - return -1; - } // ExifTags::tagInfoIdx - - const TagInfo* ExifTags::makerTagInfo(uint16_t tag, IfdId ifdId) - { - int i = 0; - for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i); - if (i == MAX_MAKER_TAG_INFOS) return 0; - - for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) { - if (makerTagInfos_[i][k].tag_ == tag) return &makerTagInfos_[i][k]; - } - - return 0; - } // ExifTags::makerTagInfo - - const TagInfo* ExifTags::makerTagInfo(const std::string& tagName, - IfdId ifdId) - { - int i = 0; - for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i); - if (i == MAX_MAKER_TAG_INFOS) return 0; - - for (int k = 0; makerTagInfos_[i][k].tag_ != 0xffff; ++k) { - if (makerTagInfos_[i][k].name_ == tagName) { - return &makerTagInfos_[i][k]; - } - } - - return 0; - } // ExifTags::makerTagInfo - - bool ExifTags::isMakerIfd(IfdId ifdId) - { - int i = 0; - for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i); - return i != MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != IfdId(0); - } - - std::string ExifTags::tagName(uint16_t tag, IfdId ifdId) - { - if (isExifIfd(ifdId)) { - int idx = tagInfoIdx(tag, ifdId); - if (idx != -1) return tagInfos_[ifdId][idx].name_; - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tag, ifdId); - if (tagInfo != 0) return tagInfo->name_; - } - std::ostringstream os; - os << "0x" << std::setw(4) << std::setfill('0') << std::right - << std::hex << tag; - return os.str(); - } // ExifTags::tagName - - const char* ExifTags::tagDesc(uint16_t tag, IfdId ifdId) - { - if (isExifIfd(ifdId)) { - int idx = tagInfoIdx(tag, ifdId); - if (idx == -1) return unknownTag.desc_; - return tagInfos_[ifdId][idx].desc_; - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tag, ifdId); - if (tagInfo != 0) return tagInfo->desc_; - } - return ""; - } // ExifTags::tagDesc - - const char* ExifTags::sectionName(uint16_t tag, IfdId ifdId) - { - if (isExifIfd(ifdId)) { - int idx = tagInfoIdx(tag, ifdId); - if (idx == -1) return sectionInfo_[unknownTag.sectionId_].name_; - const TagInfo* tagInfo = tagInfos_[ifdId]; - return sectionInfo_[tagInfo[idx].sectionId_].name_; - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tag, ifdId); - if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].name_; - } - return ""; - } // ExifTags::sectionName - - const char* ExifTags::sectionDesc(uint16_t tag, IfdId ifdId) - { - if (isExifIfd(ifdId)) { - int idx = tagInfoIdx(tag, ifdId); - if (idx == -1) return sectionInfo_[unknownTag.sectionId_].desc_; - const TagInfo* tagInfo = tagInfos_[ifdId]; - return sectionInfo_[tagInfo[idx].sectionId_].desc_; - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tag, ifdId); - if (tagInfo != 0) return sectionInfo_[tagInfo->sectionId_].desc_; - } - return ""; - } // ExifTags::sectionDesc - - uint16_t ExifTags::tag(const std::string& tagName, IfdId ifdId) - { - uint16_t tag = 0xffff; - if (isExifIfd(ifdId)) { - const TagInfo* tagInfo = tagInfos_[ifdId]; - if (tagInfo) { - int idx; - for (idx = 0; tagInfo[idx].tag_ != 0xffff; ++idx) { - if (tagInfo[idx].name_ == tagName) break; - } - tag = tagInfo[idx].tag_; - } - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tagName, ifdId); - if (tagInfo != 0) tag = tagInfo->tag_; - } - if (tag == 0xffff) { - if (!isHex(tagName, 4, "0x")) throw Error(7, tagName, ifdId); - std::istringstream is(tagName); - is >> std::hex >> tag; - } - return tag; - } // ExifTags::tag - - IfdId ExifTags::ifdIdByIfdItem(const std::string& ifdItem) - { - int i; - for (i = int(lastIfdId) - 1; i > 0; --i) { - if (ifdInfo_[i].item_ == ifdItem) break; - } - return IfdId(i); - } - - const char* ExifTags::ifdName(IfdId ifdId) - { - return ifdInfo_[ifdId].name_; - } - - const char* ExifTags::ifdItem(IfdId ifdId) - { - return ifdInfo_[ifdId].item_; - } - - const char* ExifTags::sectionName(SectionId sectionId) - { - return sectionInfo_[sectionId].name_; - } - - SectionId ExifTags::sectionId(const std::string& sectionName) - { - int i; - for (i = int(lastSectionId) - 1; i > 0; --i) { - if (sectionInfo_[i].name_ == sectionName) break; - } - return SectionId(i); - } - - TypeId ExifTags::tagType(uint16_t tag, IfdId ifdId) - { - if (isExifIfd(ifdId)) { - int idx = tagInfoIdx(tag, ifdId); - if (idx != -1) return tagInfos_[ifdId][idx].typeId_; - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tag, ifdId); - if (tagInfo != 0) return tagInfo->typeId_; - } - return unknownTag.typeId_; - } - - std::ostream& ExifTags::printTag(std::ostream& os, - uint16_t tag, - IfdId ifdId, - const Value& value) - { - if (value.count() == 0) return os; - PrintFct fct = printValue; - if (isExifIfd(ifdId)) { - int idx = tagInfoIdx(tag, ifdId); - if (idx != -1) { - fct = tagInfos_[ifdId][idx].printFct_; - } - } - if (isMakerIfd(ifdId)) { - const TagInfo* tagInfo = makerTagInfo(tag, ifdId); - if (tagInfo != 0) fct = tagInfo->printFct_; - } - return fct(os, value); - } // ExifTags::printTag - - void ExifTags::taglist(std::ostream& os) - { - for (int i=0; ifdTagInfo[i].tag_ != 0xffff; ++i) { - os << ifdTagInfo[i] << "\n"; - } - for (int i=0; exifTagInfo[i].tag_ != 0xffff; ++i) { - os << exifTagInfo[i] << "\n"; - } - for (int i=0; iopTagInfo[i].tag_ != 0xffff; ++i) { - os << iopTagInfo[i] << "\n"; - } - for (int i=0; gpsTagInfo[i].tag_ != 0xffff; ++i) { - os << gpsTagInfo[i] << "\n"; - } - } // ExifTags::taglist - - void ExifTags::makerTaglist(std::ostream& os, IfdId ifdId) - { - int i = 0; - for (; i < MAX_MAKER_TAG_INFOS && makerIfdIds_[i] != ifdId; ++i); - if (i != MAX_MAKER_TAG_INFOS) { - const TagInfo* mnTagInfo = makerTagInfos_[i]; - for (int k=0; mnTagInfo[k].tag_ != 0xffff; ++k) { - os << mnTagInfo[k] << "\n"; - } - } - } // ExifTags::makerTaglist - - const char* ExifKey::familyName_ = "Exif"; - - ExifKey::ExifKey(const std::string& key) - : tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""), - idx_(0), key_(key) - { - decomposeKey(); - } - - ExifKey::ExifKey(uint16_t tag, const std::string& ifdItem) - : tag_(0), ifdId_(ifdIdNotSet), ifdItem_(""), - idx_(0), key_("") - { - IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem); - if (ExifTags::isMakerIfd(ifdId)) { - MakerNote::AutoPtr makerNote = MakerNoteFactory::create(ifdId); - if (makerNote.get() == 0) throw Error(23, ifdId); - } - tag_ = tag; - ifdId_ = ifdId; - ifdItem_ = ifdItem; - makeKey(); - } - - ExifKey::ExifKey(const Entry& e) - : tag_(e.tag()), ifdId_(e.ifdId()), - ifdItem_(ExifTags::ifdItem(e.ifdId())), - idx_(e.idx()), key_("") - { - makeKey(); - } - - ExifKey::ExifKey(const ExifKey& rhs) - : tag_(rhs.tag_), ifdId_(rhs.ifdId_), ifdItem_(rhs.ifdItem_), - idx_(rhs.idx_), key_(rhs.key_) - { - } - - ExifKey::~ExifKey() - { - } - - ExifKey& ExifKey::operator=(const ExifKey& rhs) - { - if (this == &rhs) return *this; - Key::operator=(rhs); - tag_ = rhs.tag_; - ifdId_ = rhs.ifdId_; - ifdItem_ = rhs.ifdItem_; - idx_ = rhs.idx_; - key_ = rhs.key_; - return *this; - } - - std::string ExifKey::tagName() const - { - return ExifTags::tagName(tag_, ifdId_); - } - - ExifKey::AutoPtr ExifKey::clone() const - { - return AutoPtr(clone_()); - } - - ExifKey* ExifKey::clone_() const - { - return new ExifKey(*this); - } - - std::string ExifKey::sectionName() const - { - return ExifTags::sectionName(tag(), ifdId()); - } - - void ExifKey::decomposeKey() - { - // Get the family name, IFD name and tag name parts of the key - std::string::size_type pos1 = key_.find('.'); - if (pos1 == std::string::npos) throw Error(6, key_); - std::string familyName = key_.substr(0, pos1); - if (familyName != std::string(familyName_)) { - throw Error(6, key_); - } - std::string::size_type pos0 = pos1 + 1; - pos1 = key_.find('.', pos0); - if (pos1 == std::string::npos) throw Error(6, key_); - std::string ifdItem = key_.substr(pos0, pos1 - pos0); - if (ifdItem == "") throw Error(6, key_); - std::string tagName = key_.substr(pos1 + 1); - if (tagName == "") throw Error(6, key_); - - // Find IfdId - IfdId ifdId = ExifTags::ifdIdByIfdItem(ifdItem); - if (ifdId == ifdIdNotSet) throw Error(6, key_); - if (ExifTags::isMakerIfd(ifdId)) { - MakerNote::AutoPtr makerNote = MakerNoteFactory::create(ifdId); - if (makerNote.get() == 0) throw Error(6, key_); - } - // Convert tag - uint16_t tag = ExifTags::tag(tagName, ifdId); - - // Translate hex tag name (0xabcd) to a real tag name if there is one - tagName = ExifTags::tagName(tag, ifdId); - - tag_ = tag; - ifdId_ = ifdId; - ifdItem_ = ifdItem; - key_ = familyName + "." + ifdItem + "." + tagName; - } - - void ExifKey::makeKey() - { - key_ = std::string(familyName_) - + "." + ifdItem_ - + "." + ExifTags::tagName(tag_, ifdId_); - } - - // ************************************************************************* - // free functions - - bool isExifIfd(IfdId ifdId) - { - bool rc; - switch (ifdId) { - case ifd0Id: rc = true; break; - case exifIfdId: rc = true; break; - case gpsIfdId: rc = true; break; - case iopIfdId: rc = true; break; - case ifd1Id: rc = true; break; - default: rc = false; break; - } - return rc; - } // isExifIfd - - std::ostream& operator<<(std::ostream& os, const TagInfo& ti) - { - ExifKey exifKey(ti.tag_, ExifTags::ifdItem(ti.ifdId_)); - return os << ExifTags::tagName(ti.tag_, ti.ifdId_) << ", " - << std::dec << ti.tag_ << ", " - << "0x" << std::setw(4) << std::setfill('0') - << std::right << std::hex << ti.tag_ << ", " - << ExifTags::ifdName(ti.ifdId_) << ", " - << exifKey.key() << ", " - << TypeInfo::typeName( - ExifTags::tagType(ti.tag_, ti.ifdId_)) << ", " - << ExifTags::tagDesc(ti.tag_, ti.ifdId_); - } - - std::ostream& operator<<(std::ostream& os, const Rational& r) - { - return os << r.first << "/" << r.second; - } - - std::istream& operator>>(std::istream& is, Rational& r) - { - int32_t nominator; - int32_t denominator; - char c; - is >> nominator >> c >> denominator; - if (is && c == '/') r = std::make_pair(nominator, denominator); - return is; - } - - std::ostream& operator<<(std::ostream& os, const URational& r) - { - return os << r.first << "/" << r.second; - } - - std::istream& operator>>(std::istream& is, URational& r) - { - uint32_t nominator; - uint32_t denominator; - char c; - is >> nominator >> c >> denominator; - if (is && c == '/') r = std::make_pair(nominator, denominator); - return is; - } - - std::ostream& printValue(std::ostream& os, const Value& value) - { - return os << value; - } - - std::ostream& printLong(std::ostream& os, const Value& value) - { - Rational r = value.toRational(); - if (r.second != 0) return os << static_cast<long>(r.first) / r.second; - return os << "(" << value << ")"; - } // printLong - - std::ostream& printFloat(std::ostream& os, const Value& value) - { - Rational r = value.toRational(); - if (r.second != 0) return os << static_cast<float>(r.first) / r.second; - return os << "(" << value << ")"; - } // printFloat - - std::ostream& printUnit(std::ostream& os, const Value& value) - { - long unit = value.toLong(); - switch (unit) { - case 2: os << "inch"; break; - case 3: os << "cm"; break; - default: os << "(" << unit << ")"; break; - } - return os; - } - - std::ostream& print0x0103(std::ostream& os, const Value& value) - { - long compression = value.toLong(); - switch (compression) { - case 1: os << "TIFF"; break; - case 6: os << "JPEG"; break; - default: os << "(" << compression << ")"; break; - } - return os; - } - - std::ostream& print0x0106(std::ostream& os, const Value& value) - { - long photo = value.toLong(); - switch (photo) { - case 2: os << "RGB"; break; - case 6: os << "YCbCr"; break; - default: os << "(" << photo << ")"; break; - } - return os; - } - - std::ostream& print0x0112(std::ostream& os, const Value& value) - { - long orientation = value.toLong(); - switch (orientation) { - case 1: os << "top, left"; break; - case 2: os << "top, right"; break; - case 3: os << "bottom, right"; break; - case 4: os << "bottom, left"; break; - case 5: os << "left, top"; break; - case 6: os << "right, top"; break; - case 7: os << "right, bottom"; break; - case 8: os << "left, bottom"; break; - default: os << "(" << orientation << ")"; break; - } - return os; - } - - std::ostream& print0x0213(std::ostream& os, const Value& value) - { - long position = value.toLong(); - switch (position) { - case 1: os << "Centered"; break; - case 2: os << "Co-sited"; break; - default: os << "(" << position << ")"; break; - } - return os; - } - - std::ostream& print0x8298(std::ostream& os, const Value& value) - { - // Print the copyright information in the format Photographer, Editor - std::string val = value.toString(); - std::string::size_type pos = val.find('\0'); - if (pos != std::string::npos) { - std::string photographer(val, 0, pos); - if (photographer != " ") os << photographer; - std::string editor(val, pos + 1); - if (editor != "") { - if (photographer != " ") os << ", "; - os << editor; - } - } - else { - os << val; - } - return os; - } - - std::ostream& print0x829a(std::ostream& os, const Value& value) - { - Rational t = value.toRational(); - if (t.first > 1 && t.second > 1 && t.second >= t.first) { - t.second = static_cast<uint32_t>( - static_cast<float>(t.second) / t.first + 0.5); - t.first = 1; - } - if (t.second > 1 && t.second < t.first) { - t.first = static_cast<uint32_t>( - static_cast<float>(t.first) / t.second + 0.5); - t.second = 1; - } - if (t.second == 1) { - os << t.first << " s"; - } - else { - os << t.first << "/" << t.second << " s"; - } - return os; - } - - std::ostream& print0x829d(std::ostream& os, const Value& value) - { - Rational fnumber = value.toRational(); - if (fnumber.second != 0) { - os << "F" << (float)fnumber.first / fnumber.second; - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& print0x8822(std::ostream& os, const Value& value) - { - long program = value.toLong(); - switch (program) { - case 0: os << "Not defined"; break; - case 1: os << "Manual"; break; - case 2: os << "Auto"; break; - case 3: os << "Aperture priority"; break; - case 4: os << "Shutter priority"; break; - case 5: os << "Creative program"; break; - case 6: os << "Action program"; break; - case 7: os << "Portrait mode"; break; - case 8: os << "Landscape mode"; break; - default: os << "(" << program << ")"; break; - } - return os; - } - - std::ostream& print0x8827(std::ostream& os, const Value& value) - { - return os << value.toLong(); - } - - std::ostream& print0x9101(std::ostream& os, const Value& value) - { - for (long i = 0; i < value.count(); ++i) { - long l = value.toLong(i); - switch (l) { - case 0: break; - case 1: os << "Y"; break; - case 2: os << "Cb"; break; - case 3: os << "Cr"; break; - case 4: os << "R"; break; - case 5: os << "G"; break; - case 6: os << "B"; break; - default: os << "(" << l << ")"; break; - } - } - return os; - } - - std::ostream& print0x9204(std::ostream& os, const Value& value) - { - Rational bias = value.toRational(); - if (bias.second <= 0) { - os << "(" << bias.first << "/" << bias.second << ")"; - } - else if (bias.first == 0) { - os << "0"; - } - else { - long d = lgcd(labs(bias.first), bias.second); - long num = labs(bias.first) / d; - long den = bias.second / d; - os << (bias.first < 0 ? "-" : "+") << num; - if (den != 1) { - os << "/" << den; - } - } - return os; - } - - std::ostream& print0x9206(std::ostream& os, const Value& value) - { - Rational distance = value.toRational(); - if (distance.first == 0) { - os << "Unknown"; - } - else if (static_cast<uint32_t>(distance.first) == 0xffffffff) { - os << "Infinity"; - } - else if (distance.second != 0) { - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(2) - << (float)distance.first / distance.second - << " m"; - os.copyfmt(oss); - } - else { - os << "(" << value << ")"; - } - return os; - } - - std::ostream& print0x9207(std::ostream& os, const Value& value) - { - long mode = value.toLong(); - switch (mode) { - case 0: os << "Unknown"; break; - case 1: os << "Average"; break; - case 2: os << "Center weighted"; break; - case 3: os << "Spot"; break; - case 4: os << "Multispot"; break; - case 5: os << "Matrix"; break; - case 6: os << "Partial"; break; - default: os << "(" << mode << ")"; break; - } - return os; - } - - std::ostream& print0x9208(std::ostream& os, const Value& value) - { - long source = value.toLong(); - switch (source) { - case 0: os << "Unknown"; break; - case 1: os << "Daylight"; break; - case 2: os << "Fluorescent"; break; - case 3: os << "Tungsten (incandescent light)"; break; - case 4: os << "Flash"; break; - case 9: os << "Fine weather"; break; - case 10: os << "Cloudy weather"; break; - case 11: os << "Shade"; break; - case 12: os << "Daylight fluorescent (D 5700 - 7100K)"; break; - case 13: os << "Day white fluorescent (N 4600 - 5400K)"; break; - case 14: os << "Cool white fluorescent (W 3900 - 4500K)"; break; - case 15: os << "White fluorescent (WW 3200 - 3700K)"; break; - case 17: os << "Standard light A"; break; - case 18: os << "Standard light B"; break; - case 19: os << "Standard light C"; break; - case 20: os << "D55"; break; - case 21: os << "D65"; break; - case 22: os << "D75"; break; - case 23: os << "D50"; break; - case 24: os << "ISO studio tungsten"; break; - case 255: os << "other light source"; break; - default: os << "(" << source << ")"; break; - } - return os; - } - - std::ostream& print0x9209(std::ostream& os, const Value& value) - { - long flash = value.toLong(); - switch (flash) { - case 0x00: os << "No"; break; - case 0x01: os << "Yes"; break; - case 0x05: os << "Strobe return light not detected"; break; - case 0x07: os << "Strobe return light detected"; break; - case 0x09: os << "Yes, compulsory"; break; - case 0x0d: os << "Yes, compulsory, return light not detected"; break; - case 0x0f: os << "Yes, compulsory, return light detected"; break; - case 0x10: os << "No, compulsory"; break; - case 0x18: os << "No, auto"; break; - case 0x19: os << "Yes, auto"; break; - case 0x1d: os << "Yes, auto, return light not detected"; break; - case 0x1f: os << "Yes, auto, return light detected"; break; - case 0x20: os << "No flash function"; break; - case 0x41: os << "Yes, red-eye reduction"; break; - case 0x45: os << "Yes, red-eye reduction, return light not detected"; break; - case 0x47: os << "Yes, red-eye reduction, return light detected"; break; - case 0x49: os << "Yes, compulsory, red-eye reduction"; break; - case 0x4d: os << "Yes, compulsory, red-eye reduction, return light not detected"; break; - case 0x4f: os << "Yes, compulsory, red-eye reduction, return light detected"; break; - case 0x59: os << "Yes, auto, red-eye reduction"; break; - case 0x5d: os << "Yes, auto, red-eye reduction, return light not detected"; break; - case 0x5f: os << "Yes, auto, red-eye reduction, return light detected"; break; - default: os << "(" << flash << ")"; break; - } - return os; - } - - std::ostream& print0x920a(std::ostream& os, const Value& value) - { - Rational length = value.toRational(); - if (length.second != 0) { - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(1) - << (float)length.first / length.second - << " mm"; - os.copyfmt(oss); - } - else { - os << "(" << value << ")"; - } - return os; - } - - // Todo: Implement this properly - std::ostream& print0x9286(std::ostream& os, const Value& value) - { - if (value.size() > 8) { - DataBuf buf(value.size()); - value.copy(buf.pData_, bigEndian); - // Hack: Skip the leading 8-Byte character code, truncate - // trailing '\0's and let the stream take care of the remainder - std::string userComment(reinterpret_cast<char*>(buf.pData_) + 8, buf.size_ - 8); - std::string::size_type pos = userComment.find_last_not_of('\0'); - os << userComment.substr(0, pos + 1); - } - return os; - } - - std::ostream& print0xa001(std::ostream& os, const Value& value) - { - long space = value.toLong(); - switch (space) { - case 1: os << "sRGB"; break; - case 0xffff: os << "Uncalibrated"; break; - default: os << "(" << space << ")"; break; - } - return os; - } - - std::ostream& print0xa217(std::ostream& os, const Value& value) - { - long method = value.toLong(); - switch (method) { - case 1: os << "Not defined"; break; - case 2: os << "One-chip color area"; break; - case 3: os << "Two-chip color area"; break; - case 4: os << "Three-chip color area"; break; - case 5: os << "Color sequential area"; break; - case 7: os << "Trilinear sensor"; break; - case 8: os << "Color sequential linear"; break; - default: os << "(" << method << ")"; break; - } - return os; - } - - std::ostream& print0xa300(std::ostream& os, const Value& value) - { - long source = value.toLong(); - switch (source) { - case 3: os << "Digital still camera"; break; - default: os << "(" << source << ")"; break; - } - return os; - } - - std::ostream& print0xa301(std::ostream& os, const Value& value) - { - long scene = value.toLong(); - switch (scene) { - case 1: os << "Directly photographed"; break; - default: os << "(" << scene << ")"; break; - } - return os; - } - - std::ostream& print0xa402(std::ostream& os, const Value& value) - { - long mode = value.toLong(); - switch (mode) { - case 0: os << "Auto"; break; - case 1: os << "Manual"; break; - case 2: os << "Auto bracket"; break; - default: os << "(" << mode << ")"; break; - } - return os; - } - - std::ostream& print0xa403(std::ostream& os, const Value& value) - { - long wb = value.toLong(); - switch (wb) { - case 0: os << "Auto"; break; - case 1: os << "Manual"; break; - default: os << "(" << wb << ")"; break; - } - return os; - } - - std::ostream& print0xa404(std::ostream& os, const Value& value) - { - Rational zoom = value.toRational(); - if (zoom.second == 0) { - os << "Digital zoom not used"; - } - else { - std::ostringstream oss; - oss.copyfmt(os); - os << std::fixed << std::setprecision(1) - << (float)zoom.first / zoom.second; - os.copyfmt(oss); - } - return os; - } - - std::ostream& print0xa405(std::ostream& os, const Value& value) - { - long length = value.toLong(); - if (length == 0) { - os << "Unknown"; - } - else { - os << length << ".0 mm"; - } - return os; - } - - std::ostream& print0xa406(std::ostream& os, const Value& value) - { - long scene = value.toLong(); - switch (scene) { - case 0: os << "Standard"; break; - case 1: os << "Landscape"; break; - case 2: os << "Portrait"; break; - case 3: os << "Night scene"; break; - default: os << "(" << scene << ")"; break; - } - return os; - } - - std::ostream& print0xa407(std::ostream& os, const Value& value) - { - long gain = value.toLong(); - switch (gain) { - case 0: os << "None"; break; - case 1: os << "Low gain up"; break; - case 2: os << "High gain up"; break; - case 3: os << "Low gain down"; break; - case 4: os << "High gain down"; break; - default: os << "(" << gain << ")"; break; - } - return os; - } - - std::ostream& print0xa408(std::ostream& os, const Value& value) - { - long contrast = value.toLong(); - switch (contrast) { - case 0: os << "Normal"; break; - case 1: os << "Soft"; break; - case 2: os << "Hard"; break; - default: os << "(" << contrast << ")"; break; - } - return os; - } - - std::ostream& print0xa409(std::ostream& os, const Value& value) - { - long saturation = value.toLong(); - switch (saturation) { - case 0: os << "Normal"; break; - case 1: os << "Low"; break; - case 2: os << "High"; break; - default: os << "(" << saturation << ")"; break; - } - return os; - } - - std::ostream& print0xa40a(std::ostream& os, const Value& value) - { - long sharpness = value.toLong(); - switch (sharpness) { - case 0: os << "Normal"; break; - case 1: os << "Soft"; break; - case 2: os << "Hard"; break; - default: os << "(" << sharpness << ")"; break; - } - return os; - } - - std::ostream& print0xa40c(std::ostream& os, const Value& value) - { - long distance = value.toLong(); - switch (distance) { - case 0: os << "Unknown"; break; - case 1: os << "Macro"; break; - case 2: os << "Close view"; break; - case 3: os << "Distant view"; break; - default: os << "(" << distance << ")"; break; - } - return os; - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/tags.hpp b/src/plugins/exiv2/tags.hpp @@ -1,444 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 tags.hpp - @brief Exif tag and type information - @version $Rev: 580 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 15-Jan-04, ahu: created<BR> - 11-Feb-04, ahu: isolated as a component - */ -#ifndef TAGS_HPP_ -#define TAGS_HPP_ - -// ***************************************************************************** -// included header files -#include "metadatum.hpp" -#include "types.hpp" - -// + standard includes -#include <string> -#include <utility> // for std::pair -#include <iosfwd> -#include <memory> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class declarations - class Value; - class Entry; - -// ***************************************************************************** -// type definitions - - //! Type for a function pointer for functions interpreting the tag value - typedef std::ostream& (*PrintFct)(std::ostream&, const Value&); - - /*! - @brief Section identifiers to logically group tags. A section consists - of nothing more than a name, based on the Exif standard. - */ - enum SectionId { sectionIdNotSet, - imgStruct, recOffset, imgCharacter, otherTags, exifFormat, - exifVersion, imgConfig, userInfo, relatedFile, dateTime, - captureCond, gpsTags, iopTags, makerTags, - lastSectionId }; - -// ***************************************************************************** -// class definitions - - //! Contains information pertaining to one IFD - struct IfdInfo { - //! Constructor - IfdInfo(IfdId ifdId, const char* name, const char* item); - IfdId ifdId_; //!< IFD id - const char* name_; //!< IFD name - //! Related IFD item. This is also an IFD name, unique for each IFD. - const char* item_; - }; - - //! Contains information pertaining to one section - struct SectionInfo { - //! Constructor - SectionInfo(SectionId sectionId, const char* name, const char* desc); - SectionId sectionId_; //!< Section id - const char* name_; //!< Section name (one word) - const char* desc_; //!< Section description - }; - - //! Tag information - struct TagInfo { - //! Constructor - TagInfo( - uint16_t tag, - const char* name, - const char* desc, - IfdId ifdId, - SectionId sectionId, - TypeId typeId, - PrintFct printFct - ); - uint16_t tag_; //!< Tag - const char* name_; //!< One word tag label - const char* desc_; //!< Short tag description - IfdId ifdId_; //!< Link to the (prefered) IFD - SectionId sectionId_; //!< Section id - TypeId typeId_; //!< Type id - PrintFct printFct_; //!< Pointer to tag print function - }; // struct TagInfo - - /*! - @brief Helper structure for lookup tables for translations of numeric - tag values to human readable labels. - */ - struct TagDetails { - long val_; //!< Tag value - const char* label_; //!< Translation of the tag value - }; // struct TagDetails - - /*! - @brief Translation from numeric values from a lookup list to human - readable labels - */ - class TagTranslator { - public: - //! @name Creators - //@{ - //! Default constructor. - explicit TagTranslator(const TagDetails* pTagDetails) - : pTagDetails_(pTagDetails) {} - // No d'tor: Do not delete the list. - //@} - - //! @name Accessors - //@{ - //! Translate the tag value and write it out to the provided stream - std::ostream& print(std::ostream& os, const Value& value) const; - //@} - private: - const TagDetails* pTagDetails_; - }; // class TagTranslator - - //! Container for Exif tag information. Implemented as a static class. - class ExifTags { - //! Prevent construction: not implemented. - ExifTags() {} - //! Prevent copy-construction: not implemented. - ExifTags(const ExifTags& rhs); - //! Prevent assignment: not implemented. - ExifTags& operator=(const ExifTags& rhs); - - public: - /*! - @brief Return the name of the tag or a string with the hexadecimal - value of the tag in the form "0x01ff", if the tag is not - a known Exif tag. - - @param tag The tag - @param ifdId IFD id - @return The name of the tag or a string containing the hexadecimal - value of the tag in the form "0x01ff", if this is an unknown - tag. - */ - static std::string tagName(uint16_t tag, IfdId ifdId); - /*! - @brief Return the description of the tag. - @param tag The tag - @param ifdId IFD id - @return The description of the tag or a string indicating that - the tag is unknown. - */ - static const char* tagDesc(uint16_t tag, IfdId ifdId); - /*! - @brief Return the tag for one combination of IFD id and tagName. - If the tagName is not known, it expects tag names in the - form "0x01ff" and converts them to unsigned integer. - - @throw Error if the tagname or ifdId is invalid - */ - static uint16_t tag(const std::string& tagName, IfdId ifdId); - //! Return the IFD id for an IFD item - static IfdId ifdIdByIfdItem(const std::string& ifdItem); - //! Return the name of the IFD - static const char* ifdName(IfdId ifdId); - //! Return the related image item (image or thumbnail) - static const char* ifdItem(IfdId ifdId); - //! Return the name of the section - static const char* sectionName(SectionId sectionId); - /*! - @brief Return the name of the section for a combination of - tag and IFD id. - @param tag The tag - @param ifdId IFD id - @return The name of the section or a string indicating that the - section or the tag is unknown. - */ - static const char* sectionName(uint16_t tag, IfdId ifdId); - /*! - @brief Return the description of the section for a combination of - tag and IFD id. - @param tag The tag - @param ifdId IFD id - @return The description of the section or a string indicating that - the section or the tag is unknown. - */ - static const char* sectionDesc(uint16_t tag, IfdId ifdId); - //! Return the section id for a section name - static SectionId sectionId(const std::string& sectionName); - //! Return the type for tag and IFD id - static TypeId tagType(uint16_t tag, IfdId ifdId); - //! Interpret and print the value of an Exif tag - static std::ostream& printTag(std::ostream& os, - uint16_t tag, - IfdId ifdId, - const Value& value); - //! Print a list of all standard Exif tags to output stream - static void taglist(std::ostream& os); - //! Print a list of all tags related to one makernote %IfdId - static void makerTaglist(std::ostream& os, IfdId ifdId); - //! Register an %IfdId with the base IFD %TagInfo list for a makernote - static void registerBaseTagInfo(IfdId ifdId); - /*! - @brief Register an %IfdId and %TagInfo list for a makernote - - @throw Error if the MakerTagInfo registry is full - */ - static void registerMakerTagInfo(IfdId ifdId, const TagInfo* tagInfo); - /*! - @brief Return true if \em ifdId is an %Ifd Id which is registered - as a makernote %Ifd id. Note: Calling this function with - makerIfd returns false. - */ - static bool isMakerIfd(IfdId ifdId); - - private: - static int tagInfoIdx(uint16_t tag, IfdId ifdId); - static const TagInfo* makerTagInfo(uint16_t tag, IfdId ifdId); - static const TagInfo* makerTagInfo(const std::string& tagName, - IfdId ifdId); - - static const IfdInfo ifdInfo_[]; - static const SectionInfo sectionInfo_[]; - - static const TagInfo* tagInfos_[]; - - static const int MAX_MAKER_TAG_INFOS = 64; - static const TagInfo* makerTagInfos_[MAX_MAKER_TAG_INFOS]; - static IfdId makerIfdIds_[MAX_MAKER_TAG_INFOS]; - - }; // class ExifTags - - /*! - @brief Concrete keys for Exif metadata. - */ - class ExifKey : public Key { - public: - //! Shortcut for an %ExifKey auto pointer. - typedef std::auto_ptr<ExifKey> AutoPtr; - - //! @name Creators - //@{ - /*! - @brief Constructor to create an Exif key from a key string. - - @param key The key string. - @throw Error if the first part of the key is not '<b>Exif</b>' or - the remainin parts of the key cannot be parsed and - converted to an ifd-item and tag name. - */ - explicit ExifKey(const std::string& key); - /*! - @brief Constructor to create an Exif key from a tag and IFD item - string. - @param tag The tag value - @param ifdItem The IFD string. For MakerNote tags, this must be the - IFD item of the specific MakerNote. "MakerNote" is not allowed. - @throw Error if the key cannot be constructed from the tag and IFD - item parameters. - */ - ExifKey(uint16_t tag, const std::string& ifdItem); - //! Constructor to build an ExifKey from an IFD entry. - explicit ExifKey(const Entry& e); - //! Copy constructor - ExifKey(const ExifKey& rhs); - virtual ~ExifKey(); - //@} - - //! @name Manipulators - //@{ - /*! - @brief Assignment operator. - */ - ExifKey& operator=(const ExifKey& rhs); - //@} - - //! @name Accessors - //@{ - virtual std::string key() const { return key_; } - virtual const char* familyName() const { return familyName_; } - /*! - @brief Return the name of the group (the second part of the key). - For Exif keys, the group name is the IFD item. - */ - virtual std::string groupName() const { return ifdItem(); } - virtual std::string tagName() const; - virtual uint16_t tag() const { return tag_; } - - AutoPtr clone() const; - //! Return the IFD id - IfdId ifdId() const { return ifdId_; } - //! Return the name of the IFD - const char* ifdName() const { return ExifTags::ifdName(ifdId()); } - //! Return the related image item - std::string ifdItem() const { return ifdItem_; } - //! Return the name of the Exif section (deprecated) - std::string sectionName() const; - //! Return the index (unique id of this key within the original IFD) - int idx() const { return idx_; } - //@} - - protected: - //! @name Manipulators - //@{ - /*! - @brief Set the key corresponding to the tag and IFD id. - The key is of the form '<b>Exif</b>.ifdItem.tagName'. - */ - void makeKey(); - /*! - @brief Parse and convert the key string into tag and IFD Id. - Updates data members if the string can be decomposed, - or throws \em Error . - - @throw Error if the key cannot be decomposed. - */ - void decomposeKey(); - //@} - - private: - //! Internal virtual copy constructor. - virtual ExifKey* clone_() const; - - // DATA - static const char* familyName_; - - uint16_t tag_; //!< Tag value - IfdId ifdId_; //!< The IFD associated with this tag - std::string ifdItem_; //!< The IFD item - int idx_; //!< Unique id of an entry within one IFD - std::string key_; //!< Key - }; // class ExifKey - -// ***************************************************************************** -// free functions - - /*! - @brief Return true if \em ifdId is an Exif %Ifd Id, i.e., one of - ifd0Id, exifIfdId, gpsIfdId, iopIfdId or ifd1Id, else false. - This is used to differentiate between standard Exif %Ifds - and %Ifds associated with the makernote. - */ - bool isExifIfd(IfdId ifdId); - - //! Output operator for TagInfo - std::ostream& operator<<(std::ostream& os, const TagInfo& ti); - - //! @name Functions printing interpreted tag values - //@{ - //! Default print function, using the Value output operator - std::ostream& printValue(std::ostream& os, const Value& value); - //! Print the value converted to a long - std::ostream& printLong(std::ostream& os, const Value& value); - //! Print a Rational or URational value in floating point format - std::ostream& printFloat(std::ostream& os, const Value& value); - //! Print the unit for measuring X and Y resolution - std::ostream& printUnit(std::ostream& os, const Value& value); - - //! Print the compression scheme used for the image data - std::ostream& print0x0103(std::ostream& os, const Value& value); - //! Print the pixel composition - std::ostream& print0x0106(std::ostream& os, const Value& value); - //! Print the orientation - std::ostream& print0x0112(std::ostream& os, const Value& value); - //! Print the YCbCrPositioning - std::ostream& print0x0213(std::ostream& os, const Value& value); - //! Print the Copyright - std::ostream& print0x8298(std::ostream& os, const Value& value); - //! Print the Exposure time - std::ostream& print0x829a(std::ostream& os, const Value& value); - //! Print the F number - std::ostream& print0x829d(std::ostream& os, const Value& value); - //! Print the Exposure mode - std::ostream& print0x8822(std::ostream& os, const Value& value); - //! Print ISO speed ratings - std::ostream& print0x8827(std::ostream& os, const Value& value); - //! Print components configuration specific to compressed data - std::ostream& print0x9101(std::ostream& os, const Value& value); - //! Print the exposure bias value - std::ostream& print0x9204(std::ostream& os, const Value& value); - //! Print the subject distance - std::ostream& print0x9206(std::ostream& os, const Value& value); - //! Print the metering mode - std::ostream& print0x9207(std::ostream& os, const Value& value); - //! Print the light source - std::ostream& print0x9208(std::ostream& os, const Value& value); - //! Print the flash status - std::ostream& print0x9209(std::ostream& os, const Value& value); - //! Print the actual focal length of the lens - std::ostream& print0x920a(std::ostream& os, const Value& value); - //! Print the user comment - std::ostream& print0x9286(std::ostream& os, const Value& value); - //! Print color space information - std::ostream& print0xa001(std::ostream& os, const Value& value); - //! Print info on image sensor type on the camera or input device - std::ostream& print0xa217(std::ostream& os, const Value& value); - //! Print file source - std::ostream& print0xa300(std::ostream& os, const Value& value); - //! Print scene type - std::ostream& print0xa301(std::ostream& os, const Value& value); - //! Print the exposure mode - std::ostream& print0xa402(std::ostream& os, const Value& value); - //! Print white balance information - std::ostream& print0xa403(std::ostream& os, const Value& value); - //! Print digital zoom ratio - std::ostream& print0xa404(std::ostream& os, const Value& value); - //! Print 35mm equivalent focal length - std::ostream& print0xa405(std::ostream& os, const Value& value); - //! Print scene capture type - std::ostream& print0xa406(std::ostream& os, const Value& value); - //! Print overall image gain adjustment - std::ostream& print0xa407(std::ostream& os, const Value& value); - //! Print contract adjustment - std::ostream& print0xa408(std::ostream& os, const Value& value); - //! Print saturation adjustment - std::ostream& print0xa409(std::ostream& os, const Value& value); - //! Print sharpness adjustment - std::ostream& print0xa40a(std::ostream& os, const Value& value); - //! Print subject distance range - std::ostream& print0xa40c(std::ostream& os, const Value& value); - //@} -} // namespace Exiv2 - -#endif // #ifndef TAGS_HPP_ diff --git a/src/plugins/exiv2/types.cpp b/src/plugins/exiv2/types.cpp @@ -1,344 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: types.cpp - Version: $Rev: 578 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 26-Jan-04, ahu: created - 11-Feb-04, ahu: isolated as a component - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: types.cpp 578 2005-06-07 15:01:11Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "types.hpp" - -// + standard includes -#include <string> -#include <iostream> -#include <iomanip> -#include <sstream> -#include <utility> -#include <cctype> -#include <string.h> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - TypeInfoTable::TypeInfoTable(TypeId typeId, const char* name, long size) - : typeId_(typeId), name_(name), size_(size) - { - } - - //! Lookup list of supported IFD type information - const TypeInfoTable TypeInfo::typeInfoTable_[] = { - TypeInfoTable(invalidTypeId, "Invalid", 0), - TypeInfoTable(unsignedByte, "Byte", 1), - TypeInfoTable(asciiString, "Ascii", 1), - TypeInfoTable(unsignedShort, "Short", 2), - TypeInfoTable(unsignedLong, "Long", 4), - TypeInfoTable(unsignedRational, "Rational", 8), - TypeInfoTable(invalid6, "Invalid(6)", 1), - TypeInfoTable(undefined, "Undefined", 1), - TypeInfoTable(signedShort, "SShort", 2), - TypeInfoTable(signedLong, "SLong", 4), - TypeInfoTable(signedRational, "SRational", 8), - TypeInfoTable(string, "String", 1), - TypeInfoTable(date, "Date", 8), - TypeInfoTable(time, "Time", 11), - TypeInfoTable(comment, "Comment", 1), - // End of list marker - TypeInfoTable(lastTypeId, "(Unknown)", 0) - }; - - const char* TypeInfo::typeName(TypeId typeId) - { - return typeInfoTable_[ typeId < lastTypeId ? typeId : 0 ].name_; - } - - TypeId TypeInfo::typeId(const std::string& typeName) - { - int i = 0; - for (; typeInfoTable_[i].typeId_ != lastTypeId - && typeInfoTable_[i].name_ != typeName; ++i) {} - return typeInfoTable_[i].typeId_ == lastTypeId ? - invalidTypeId : typeInfoTable_[i].typeId_; - } - - long TypeInfo::typeSize(TypeId typeId) - { - return typeInfoTable_[ typeId < lastTypeId ? typeId : 0 ].size_; - } - - DataBuf::DataBuf(DataBuf& rhs) - : pData_(rhs.pData_), size_(rhs.size_) - { - rhs.release(); - } - - DataBuf::DataBuf(byte* pData, long size) - : pData_(0), size_(0) - { - if (size > 0) { - pData_ = new byte[size]; - memcpy(pData_, pData, size); - size_ = size; - } - } - - DataBuf& DataBuf::operator=(DataBuf& rhs) - { - if (this == &rhs) return *this; - reset(rhs.release()); - return *this; - } - - void DataBuf::alloc(long size) - { - if (size > size_) { - delete[] pData_; - size_ = size; - pData_ = new byte[size]; - } - } - - std::pair<byte*, long> DataBuf::release() - { - std::pair<byte*, long> p = std::make_pair(pData_, size_); - pData_ = 0; - size_ = 0; - return p; - } - - void DataBuf::reset(std::pair<byte*, long> p) - { - if (pData_ != p.first) { - delete[] pData_; - pData_ = p.first; - } - size_ = p.second; - } - - // ************************************************************************* - // free functions - - uint16_t getUShort(const byte* buf, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - return (byte)buf[1] << 8 | (byte)buf[0]; - } - else { - return (byte)buf[0] << 8 | (byte)buf[1]; - } - } - - uint32_t getULong(const byte* buf, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - return (byte)buf[3] << 24 | (byte)buf[2] << 16 - | (byte)buf[1] << 8 | (byte)buf[0]; - } - else { - return (byte)buf[0] << 24 | (byte)buf[1] << 16 - | (byte)buf[2] << 8 | (byte)buf[3]; - } - } - - URational getURational(const byte* buf, ByteOrder byteOrder) - { - uint32_t nominator = getULong(buf, byteOrder); - uint32_t denominator = getULong(buf + 4, byteOrder); - return std::make_pair(nominator, denominator); - } - - int16_t getShort(const byte* buf, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - return (byte)buf[1] << 8 | (byte)buf[0]; - } - else { - return (byte)buf[0] << 8 | (byte)buf[1]; - } - } - - int32_t getLong(const byte* buf, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - return (byte)buf[3] << 24 | (byte)buf[2] << 16 - | (byte)buf[1] << 8 | (byte)buf[0]; - } - else { - return (byte)buf[0] << 24 | (byte)buf[1] << 16 - | (byte)buf[2] << 8 | (byte)buf[3]; - } - } - - Rational getRational(const byte* buf, ByteOrder byteOrder) - { - int32_t nominator = getLong(buf, byteOrder); - int32_t denominator = getLong(buf + 4, byteOrder); - return std::make_pair(nominator, denominator); - } - - long us2Data(byte* buf, uint16_t s, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - buf[0] = (byte)(s & 0x00ff); - buf[1] = (byte)((s & 0xff00) >> 8); - } - else { - buf[0] = (byte)((s & 0xff00) >> 8); - buf[1] = (byte)(s & 0x00ff); - } - return 2; - } - - long ul2Data(byte* buf, uint32_t l, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - buf[0] = (byte)(l & 0x000000ff); - buf[1] = (byte)((l & 0x0000ff00) >> 8); - buf[2] = (byte)((l & 0x00ff0000) >> 16); - buf[3] = (byte)((l & 0xff000000) >> 24); - } - else { - buf[0] = (byte)((l & 0xff000000) >> 24); - buf[1] = (byte)((l & 0x00ff0000) >> 16); - buf[2] = (byte)((l & 0x0000ff00) >> 8); - buf[3] = (byte)(l & 0x000000ff); - } - return 4; - } - - long ur2Data(byte* buf, URational l, ByteOrder byteOrder) - { - long o = ul2Data(buf, l.first, byteOrder); - o += ul2Data(buf+o, l.second, byteOrder); - return o; - } - - long s2Data(byte* buf, int16_t s, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - buf[0] = (byte)(s & 0x00ff); - buf[1] = (byte)((s & 0xff00) >> 8); - } - else { - buf[0] = (byte)((s & 0xff00) >> 8); - buf[1] = (byte)(s & 0x00ff); - } - return 2; - } - - long l2Data(byte* buf, int32_t l, ByteOrder byteOrder) - { - if (byteOrder == littleEndian) { - buf[0] = (byte)(l & 0x000000ff); - buf[1] = (byte)((l & 0x0000ff00) >> 8); - buf[2] = (byte)((l & 0x00ff0000) >> 16); - buf[3] = (byte)((l & 0xff000000) >> 24); - } - else { - buf[0] = (byte)((l & 0xff000000) >> 24); - buf[1] = (byte)((l & 0x00ff0000) >> 16); - buf[2] = (byte)((l & 0x0000ff00) >> 8); - buf[3] = (byte)(l & 0x000000ff); - } - return 4; - } - - long r2Data(byte* buf, Rational l, ByteOrder byteOrder) - { - long o = l2Data(buf, l.first, byteOrder); - o += l2Data(buf+o, l.second, byteOrder); - return o; - } - - void hexdump(std::ostream& os, const byte* buf, long len, long offset) - { - const std::string::size_type pos = 8 + 16 * 3 + 2; - const std::string align(pos, ' '); - - long i = 0; - while (i < len) { - os << " " - << std::setw(4) << std::setfill('0') << std::hex - << i + offset << " "; - std::ostringstream ss; - do { - byte c = buf[i]; - os << std::setw(2) << std::setfill('0') << std::right - << std::hex << (int)c << " "; - ss << ((int)c >= 31 && (int)c < 127 ? char(buf[i]) : '.'); - } while (++i < len && i%16 != 0); - std::string::size_type width = 9 + ((i-1)%16 + 1) * 3; - os << (width > pos ? "" : align.substr(width)) << ss.str() << "\n"; - } - os << std::dec << std::setfill(' '); - } // hexdump - - int gcd(int a, int b) - { - int temp; - if (a < b) { - temp = a; - a = b; - b = temp; - } - while ((temp = a % b) != 0) { - a = b; - b = temp; - } - return b; - } // gcd - - long lgcd(long a, long b) - { - long temp; - if (a < b) { - temp = a; - a = b; - b = temp; - } - while ((temp = a % b) != 0) { - a = b; - b = temp; - } - return b; - } // lgcd - - bool isHex(const std::string& str, size_t size, const std::string& prefix) - { - if ( str.size() <= prefix.size() - || str.substr(0, prefix.size()) != prefix) return false; - if ( size > 0 - && str.size() != size + prefix.size()) return false; - - for (size_t i = prefix.size(); i < str.size(); ++i) { - if (!isxdigit(str[i])) return false; - } - return true; - } // isHex - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/types.hpp b/src/plugins/exiv2/types.hpp @@ -1,307 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 types.hpp - @brief Type definitions for %Exiv2 and related functionality - @version $Rev: 581 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 09-Jan-04, ahu: created<BR> - 11-Feb-04, ahu: isolated as a component - 31-Jul-04, brad: added Time, Data and String values - */ -#ifndef TYPES_HPP_ -#define TYPES_HPP_ - -// ***************************************************************************** -// included header files -#if _MSC_VER -# include "exv_msvc.h" -#else -# include "exv_conf.h" -#endif - -// + standard includes -#include <string> -#include <iosfwd> -#include <utility> -#include <sstream> -#include <cstdio> -#if EXV_HAVE_STDINT_H -# include <stdint.h> -#endif - -// MSVC doesn't provide C99 types, but it has MS specific variants -#if _MSC_VER -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -#endif - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// type definitions - - //! 1 byte unsigned integer type. - typedef uint8_t byte; - - //! 8 byte unsigned rational type. - typedef std::pair<uint32_t, uint32_t> URational; - //! 8 byte signed rational type. - typedef std::pair<int32_t, int32_t> Rational; - - //! Type to express the byte order (little or big endian) - enum ByteOrder { invalidByteOrder, littleEndian, bigEndian }; - - //! Type identifiers for IFD format types - enum TypeId { invalidTypeId, unsignedByte, asciiString, unsignedShort, - unsignedLong, unsignedRational, invalid6, undefined, - signedShort, signedLong, signedRational, - string, date, time, - comment, - lastTypeId }; - - // Todo: decentralize IfdId, so that new ids can be defined elsewhere - //! Type to specify the IFD to which a metadata belongs - enum IfdId { ifdIdNotSet, - ifd0Id, exifIfdId, gpsIfdId, iopIfdId, ifd1Id, - canonIfdId, canonCs1IfdId, canonCs2IfdId, canonCfIfdId, - fujiIfdId, nikon1IfdId, nikon2IfdId, nikon3IfdId, - olympusIfdId, panasonicIfdId, sigmaIfdId, sonyIfdId, - lastIfdId }; - -// ***************************************************************************** -// class definitions - - //! Information pertaining to the defined types - struct TypeInfoTable { - //! Constructor - TypeInfoTable(TypeId typeId, const char* name, long size); - TypeId typeId_; //!< Type id - const char* name_; //!< Name of the type - long size_; //!< Bytes per data entry - }; // struct TypeInfoTable - - //! Type information lookup functions. Implemented as a static class. - class TypeInfo { - //! Prevent construction: not implemented. - TypeInfo() {} - //! Prevent copy-construction: not implemented. - TypeInfo(const TypeInfo& rhs); - //! Prevent assignment: not implemented. - TypeInfo& operator=(const TypeInfo& rhs); - - public: - //! Return the name of the type - static const char* typeName(TypeId typeId); - //! Return the type id for a type name - static TypeId typeId(const std::string& typeName); - //! Return the size in bytes of one element of this type - static long typeSize(TypeId typeId); - - private: - static const TypeInfoTable typeInfoTable_[]; - }; - - /*! - @brief Auxiliary type to enable copies and assignments, similar to - std::auto_ptr_ref. See http://www.josuttis.com/libbook/auto_ptr.html - for a discussion. - */ - struct DataBufRef { - //! Constructor - DataBufRef(std::pair<byte*, long> rhs) : p(rhs) {} - //! Pointer to a byte array and its size - std::pair<byte*, long> p; - }; - - /*! - @brief Utility class containing a character array. All it does is to take - care of memory allocation and deletion. Its primary use is meant to - be as a stack variable in functions that need a temporary data - buffer. Todo: this should be some sort of smart pointer, - essentially an std::auto_ptr for a character array. But it isn't... - */ - class DataBuf { - public: - //! @name Creators - //@{ - //! Default constructor - DataBuf() : pData_(0), size_(0) {} - //! Constructor with an initial buffer size - explicit DataBuf(long size) : pData_(new byte[size]), size_(size) {} - //! Constructor, copies an existing buffer - DataBuf(byte* pData, long size); - /*! - @brief Copy constructor. Transfers the buffer to the newly created - object similar to std::auto_ptr, i.e., the original object is - modified. - */ - DataBuf(DataBuf& rhs); - //! Destructor, deletes the allocated buffer - ~DataBuf() { delete[] pData_; } - //@} - - //! @name Manipulators - //@{ - /*! - @brief Assignment operator. Transfers the buffer and releases the - buffer at the original object similar to std::auto_ptr, i.e., - the original object is modified. - */ - DataBuf& operator=(DataBuf& rhs); - //! Allocate a data buffer of the given size - void alloc(long size); - /*! - @brief Release ownership of the buffer to the caller. Returns the - buffer as a data pointer and size pair, resets the internal - buffer. - */ - std::pair<byte*, long> release(); - //! Reset value - void reset(std::pair<byte*, long> =std::make_pair(0,0)); - //@} - - /*! - @name Conversions - - Special conversions with auxiliary type to enable copies - and assignments, similar to those used for std::auto_ptr. - See http://www.josuttis.com/libbook/auto_ptr.html for a discussion. - */ - //@{ - DataBuf(DataBufRef rhs) : pData_(rhs.p.first), size_(rhs.p.second) {} - DataBuf& operator=(DataBufRef rhs) { reset(rhs.p); return *this; } - operator DataBufRef() { return DataBufRef(release()); } - //@} - - // DATA - //! Pointer to the buffer, 0 if none has been allocated - byte* pData_; - //! The current size of the buffer - long size_; - }; // class DataBuf - - -// ***************************************************************************** -// free functions - - //! Read a 2 byte unsigned short value from the data buffer - uint16_t getUShort(const byte* buf, ByteOrder byteOrder); - //! Read a 4 byte unsigned long value from the data buffer - uint32_t getULong(const byte* buf, ByteOrder byteOrder); - //! Read an 8 byte unsigned rational value from the data buffer - URational getURational(const byte* buf, ByteOrder byteOrder); - //! Read a 2 byte signed short value from the data buffer - int16_t getShort(const byte* buf, ByteOrder byteOrder); - //! Read a 4 byte signed long value from the data buffer - int32_t getLong(const byte* buf, ByteOrder byteOrder); - //! Read an 8 byte signed rational value from the data buffer - Rational getRational(const byte* buf, ByteOrder byteOrder); - - //! Output operator for our fake rational - std::ostream& operator<<(std::ostream& os, const Rational& r); - //! Input operator for our fake rational - std::istream& operator>>(std::istream& is, Rational& r); - //! Output operator for our fake unsigned rational - std::ostream& operator<<(std::ostream& os, const URational& r); - //! Input operator for our fake unsigned rational - std::istream& operator>>(std::istream& is, URational& r); - - /*! - @brief Convert an unsigned short to data, write the data to the buffer, - return number of bytes written. - */ - long us2Data(byte* buf, uint16_t s, ByteOrder byteOrder); - /*! - @brief Convert an unsigned long to data, write the data to the buffer, - return number of bytes written. - */ - long ul2Data(byte* buf, uint32_t l, ByteOrder byteOrder); - /*! - @brief Convert an unsigned rational to data, write the data to the buffer, - return number of bytes written. - */ - long ur2Data(byte* buf, URational l, ByteOrder byteOrder); - /*! - @brief Convert a signed short to data, write the data to the buffer, - return number of bytes written. - */ - long s2Data(byte* buf, int16_t s, ByteOrder byteOrder); - /*! - @brief Convert a signed long to data, write the data to the buffer, - return number of bytes written. - */ - long l2Data(byte* buf, int32_t l, ByteOrder byteOrder); - /*! - @brief Convert a signed rational to data, write the data to the buffer, - return number of bytes written. - */ - long r2Data(byte* buf, Rational l, ByteOrder byteOrder); - - /*! - @brief Print len bytes from buf in hex and ASCII format to the given - stream, prefixed with the position in the buffer adjusted by - offset. - */ - void hexdump(std::ostream& os, const byte* buf, long len, long offset =0); - - /*! - @brief Return the greatest common denominator of integers a and b. - Both parameters must be greater than 0. - */ - int gcd(int a, int b); - - /*! - @brief Return the greatest common denominator of long values a and b. - Both parameters must be greater than 0. - */ - long lgcd(long a, long b); - - /*! - @brief Return true if str is a hex number starting with prefix followed - by size hex digits, false otherwise. If size is 0, any number of - digits is allowed and all are checked. - */ - bool isHex(const std::string& str, - size_t size =0, - const std::string& prefix =""); - -// ***************************************************************************** -// template and inline definitions - - //! Utility function to convert the argument of any type to a string - template<typename T> - std::string toString(const T& arg) - { - std::ostringstream os; - os << arg; - return os.str(); - } - -} // namespace Exiv2 - -#endif // #ifndef TYPES_HPP_ diff --git a/src/plugins/exiv2/value.cpp b/src/plugins/exiv2/value.cpp @@ -1,559 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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: value.cpp - Version: $Rev: 560 $ - Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net> - History: 26-Jan-04, ahu: created - 11-Feb-04, ahu: isolated as a component - 31-Jul-04, brad: added Time, Date and String values - */ -// ***************************************************************************** -#include "rcsid.hpp" -EXIV2_RCSID("@(#) $Id: value.cpp 560 2005-04-17 11:51:32Z ahuggel $"); - -// ***************************************************************************** -// included header files -#include "value.hpp" -#include "types.hpp" -#include "error.hpp" - -// + standard includes -#include <cstdlib> -#include <iostream> -#include <iomanip> -#include <sstream> -#include <cassert> -#include <ctime> -#include <stdlib.h> - -// ***************************************************************************** -// class member definitions -namespace Exiv2 { - - Value& Value::operator=(const Value& rhs) - { - if (this == &rhs) return *this; - type_ = rhs.type_; - return *this; - } - - Value::AutoPtr Value::create(TypeId typeId) - { - AutoPtr value; - switch (typeId) { - case invalidTypeId: - value = AutoPtr(new DataValue(invalidTypeId)); - break; - case unsignedByte: - value = AutoPtr(new DataValue(unsignedByte)); - break; - case asciiString: - value = AutoPtr(new AsciiValue); - break; - case unsignedShort: - value = AutoPtr(new ValueType<uint16_t>); - break; - case unsignedLong: - value = AutoPtr(new ValueType<uint32_t>); - break; - case unsignedRational: - value = AutoPtr(new ValueType<URational>); - break; - case invalid6: - value = AutoPtr(new DataValue(invalid6)); - break; - case undefined: - value = AutoPtr(new DataValue); - break; - case signedShort: - value = AutoPtr(new ValueType<int16_t>); - break; - case signedLong: - value = AutoPtr(new ValueType<int32_t>); - break; - case signedRational: - value = AutoPtr(new ValueType<Rational>); - break; - case string: - value = AutoPtr(new StringValue); - break; - case date: - value = AutoPtr(new DateValue); - break; - case time: - value = AutoPtr(new TimeValue); - break; - case comment: - value = AutoPtr(new CommentValue); - break; - default: - value = AutoPtr(new DataValue(typeId)); - break; - } - return value; - } // Value::create - - std::string Value::toString() const - { - std::ostringstream os; - write(os); - return os.str(); - } - - DataValue& DataValue::operator=(const DataValue& rhs) - { - if (this == &rhs) return *this; - Value::operator=(rhs); - value_ = rhs.value_; - return *this; - } - - void DataValue::read(const byte* buf, long len, ByteOrder byteOrder) - { - // byteOrder not needed - value_.assign(buf, buf + len); - } - - void DataValue::read(const std::string& buf) - { - std::istringstream is(buf); - int tmp; - value_.clear(); - while (is >> tmp) { - value_.push_back(static_cast<byte>(tmp)); - } - } - - long DataValue::copy(byte* buf, ByteOrder byteOrder) const - { - // byteOrder not needed - return static_cast<long>( - std::copy(value_.begin(), value_.end(), buf) - buf - ); - } - - long DataValue::size() const - { - return static_cast<long>(value_.size()); - } - - DataValue* DataValue::clone_() const - { - return new DataValue(*this); - } - - std::ostream& DataValue::write(std::ostream& os) const - { - std::vector<byte>::size_type end = value_.size(); - for (std::vector<byte>::size_type i = 0; i != end; ++i) { - os << static_cast<int>(value_[i]) << " "; - } - return os; - } - - StringValueBase& StringValueBase::operator=(const StringValueBase& rhs) - { - if (this == &rhs) return *this; - Value::operator=(rhs); - value_ = rhs.value_; - return *this; - } - - void StringValueBase::read(const std::string& buf) - { - value_ = buf; - } - - void StringValueBase::read(const byte* buf, long len, ByteOrder byteOrder) - { - // byteOrder not needed - value_ = std::string(reinterpret_cast<const char*>(buf), len); - } - - long StringValueBase::copy(byte* buf, ByteOrder byteOrder) const - { - // byteOrder not needed - return static_cast<long>( - value_.copy(reinterpret_cast<char*>(buf), value_.size()) - ); - } - - long StringValueBase::size() const - { - return static_cast<long>(value_.size()); - } - - std::ostream& StringValueBase::write(std::ostream& os) const - { - return os << value_; - } - - StringValue& StringValue::operator=(const StringValue& rhs) - { - if (this == &rhs) return *this; - StringValueBase::operator=(rhs); - return *this; - } - - StringValue* StringValue::clone_() const - { - return new StringValue(*this); - } - - AsciiValue& AsciiValue::operator=(const AsciiValue& rhs) - { - if (this == &rhs) return *this; - StringValueBase::operator=(rhs); - return *this; - } - - void AsciiValue::read(const std::string& buf) - { - value_ = buf; - if (value_[value_.size()-1] != '\0') value_ += '\0'; - } - - AsciiValue* AsciiValue::clone_() const - { - return new AsciiValue(*this); - } - - std::ostream& AsciiValue::write(std::ostream& os) const - { - // Strip all trailing '\0's (if any) - std::string::size_type pos = value_.find_last_not_of('\0'); - return os << value_.substr(0, pos + 1); - } - - CommentValue::CharsetTable::CharsetTable(CharsetId charsetId, - const char* name, - const char* code) - : charsetId_(charsetId), name_(name), code_(code) - { - } - - //! Lookup list of supported IFD type information - const CommentValue::CharsetTable CommentValue::CharsetInfo::charsetTable_[] = { - CharsetTable(ascii, "Ascii", "ASCII\0\0\0"), - CharsetTable(jis, "Jis", "JIS\0\0\0\0\0"), - CharsetTable(unicode, "Unicode", "UNICODE\0"), - CharsetTable(undefined, "Undefined", "\0\0\0\0\0\0\0\0"), - CharsetTable(invalidCharsetId, "InvalidCharsetId", "\0\0\0\0\0\0\0\0"), - CharsetTable(lastCharsetId, "InvalidCharsetId", "\0\0\0\0\0\0\0\0") - }; - - const char* CommentValue::CharsetInfo::name(CharsetId charsetId) - { - return charsetTable_[ charsetId < lastCharsetId ? charsetId : undefined ].name_; - } - - const char* CommentValue::CharsetInfo::code(CharsetId charsetId) - { - return charsetTable_[ charsetId < lastCharsetId ? charsetId : undefined ].code_; - } - - CommentValue::CharsetId CommentValue::CharsetInfo::charsetIdByName( - const std::string& name) - { - int i = 0; - for (; charsetTable_[i].charsetId_ != lastCharsetId - && charsetTable_[i].name_ != name; ++i) {} - return charsetTable_[i].charsetId_ == lastCharsetId ? - invalidCharsetId : charsetTable_[i].charsetId_; - } - - CommentValue::CharsetId CommentValue::CharsetInfo::charsetIdByCode( - const std::string& code) - { - int i = 0; - for (; charsetTable_[i].charsetId_ != lastCharsetId - && std::string(charsetTable_[i].code_, 8) != code; ++i) {} - return charsetTable_[i].charsetId_ == lastCharsetId ? - invalidCharsetId : charsetTable_[i].charsetId_; - } - - CommentValue::CommentValue(const std::string& comment) - : StringValueBase(Exiv2::undefined) - { - read(comment); - } - - CommentValue& CommentValue::operator=(const CommentValue& rhs) - { - if (this == &rhs) return *this; - StringValueBase::operator=(rhs); - return *this; - } - - void CommentValue::read(const std::string& comment) - { - std::string c = comment; - CharsetId charsetId = undefined; - if (comment.length() > 8 && comment.substr(0, 8) == "charset=") { - std::string::size_type pos = comment.find_first_of(' '); - std::string name = comment.substr(8, pos-8); - // Strip quotes (so you can also to specify the charset without quotes) - if (name[0] == '"') name = name.substr(1); - if (name[name.length()-1] == '"') name = name.substr(0, name.length()-1); - charsetId = CharsetInfo::charsetIdByName(name); - if (charsetId == invalidCharsetId) throw Error(28, name); - c.clear(); - if (pos != std::string::npos) c = comment.substr(pos+1); - } - const std::string code(CharsetInfo::code(charsetId), 8); - StringValueBase::read(code + c); - } - - std::ostream& CommentValue::write(std::ostream& os) const - { - CharsetId charsetId = this->charsetId(); - if (charsetId != undefined) { - os << "charset=\"" << CharsetInfo::name(charsetId) << "\" "; - } - return os << comment(); - } - - std::string CommentValue::comment() const - { - if (value_.length() >= 8) return value_.substr(8); - return ""; - } - - CommentValue::CharsetId CommentValue::charsetId() const - { - CharsetId charsetId = undefined; - if (value_.length() >= 8) { - const std::string code = value_.substr(0, 8); - charsetId = CharsetInfo::charsetIdByCode(code); - } - return charsetId; - } - - CommentValue* CommentValue::clone_() const - { - return new CommentValue(*this); - } - - DateValue::DateValue(int year, int month, int day) - : Value(date) - { - date_.year = year; - date_.month = month; - date_.day = day; - } - - DateValue& DateValue::operator=(const DateValue& rhs) - { - if (this == &rhs) return *this; - Value::operator=(rhs); - date_.year = rhs.date_.year; - date_.month = rhs.date_.month; - date_.day = rhs.date_.day; - return *this; - } - - void DateValue::read(const byte* buf, long len, ByteOrder byteOrder) - { - // byteOrder not needed - // Hard coded to read Iptc style dates - if (len != 8) throw Error(29); - int scanned = sscanf(reinterpret_cast<const char*>(buf), - "%4d%2d%2d", - &date_.year, &date_.month, &date_.day); - if (scanned != 3) throw Error(29); - } - - void DateValue::read(const std::string& buf) - { - // byteOrder not needed - // Hard coded to read Iptc style dates - if (buf.length() < 8) throw Error(29); - int scanned = sscanf(buf.data(), - "%4d-%d-%d", - &date_.year, &date_.month, &date_.day); - if (scanned != 3) throw Error(29); - } - - void DateValue::setDate( const Date& src ) - { - date_.year = src.year; - date_.month = src.month; - date_.day = src.day; - } - - long DateValue::copy(byte* buf, ByteOrder byteOrder) const - { - // byteOrder not needed - // sprintf wants to add the null terminator, so use oversized buffer - char temp[9]; - - int wrote = sprintf( temp, "%04d%02d%02d", - date_.year, date_.month, date_.day); - assert(wrote == 8); - memcpy(buf, temp, 8); - return 8; - } - - long DateValue::size() const - { - return 8; - } - - DateValue* DateValue::clone_() const - { - return new DateValue(*this); - } - - std::ostream& DateValue::write(std::ostream& os) const - { - return os << date_.year << '-' << std::right - << std::setw(2) << std::setfill('0') << date_.month << '-' - << std::setw(2) << std::setfill('0') << date_.day; - } - - long DateValue::toLong(long n) const - { - // Range of tm struct is limited to about 1970 to 2038 - // This will return -1 if outside that range - std::tm tms; - memset(&tms, 0, sizeof(tms)); - tms.tm_mday = date_.day; - tms.tm_mon = date_.month - 1; - tms.tm_year = date_.year - 1900; - return static_cast<long>(std::mktime(&tms)); - } - - TimeValue::TimeValue(int hour, int minute, - int second, int tzHour, - int tzMinute) - : Value(date) - { - time_.hour=hour; - time_.minute=minute; - time_.second=second; - time_.tzHour=tzHour; - time_.tzMinute=tzMinute; - } - - TimeValue& TimeValue::operator=(const TimeValue& rhs) - { - if (this == &rhs) return *this; - Value::operator=(rhs); - memcpy(&time_, &rhs.time_, sizeof(time_)); - return *this; - } - - void TimeValue::read(const byte* buf, long len, ByteOrder byteOrder) - { - // byteOrder not needed - // Hard coded to read Iptc style times - if (len != 11) throw Error(30); - char plusMinus; - int scanned = sscanf(reinterpret_cast<const char*>(buf), - "%2d%2d%2d%1c%2d%2d", - &time_.hour, &time_.minute, &time_.second, - &plusMinus, &time_.tzHour, &time_.tzMinute ); - - if (scanned != 6) throw Error(30); - if (plusMinus == '-') { - time_.tzHour *= -1; - time_.tzMinute *= -1; - } - } - - void TimeValue::read(const std::string& buf) - { - // byteOrder not needed - // Hard coded to read Iptc style times - if (buf.length() < 9) throw Error(30); - char plusMinus; - int scanned = sscanf(buf.data(), - "%d:%d:%d%1c%d:%d", - &time_.hour, &time_.minute, &time_.second, - &plusMinus, &time_.tzHour, &time_.tzMinute ); - - if (scanned != 6) throw Error(30); - if (plusMinus == '-') { - time_.tzHour *= -1; - time_.tzMinute *= -1; - } - } - - void TimeValue::setTime( const Time& src ) - { - memcpy(&time_, &src, sizeof(time_)); - } - - long TimeValue::copy(byte* buf, ByteOrder byteOrder) const - { - // byteOrder not needed - // sprintf wants to add the null terminator, so use oversized buffer - char temp[12]; - char plusMinus = '+'; - if (time_.tzHour < 0 || time_.tzMinute < 0) plusMinus = '-'; - - int wrote = sprintf(temp, - "%02d%02d%02d%1c%02d%02d", - time_.hour, time_.minute, time_.second, - plusMinus, abs(time_.tzHour), abs(time_.tzMinute)); - - assert(wrote == 11); - memcpy(buf, temp, 11); - return 11; - } - - long TimeValue::size() const - { - return 11; - } - - TimeValue* TimeValue::clone_() const - { - return new TimeValue(*this); - } - - std::ostream& TimeValue::write(std::ostream& os) const - { - char plusMinus = '+'; - if (time_.tzHour < 0 || time_.tzMinute < 0) plusMinus = '-'; - - return os << std::right - << std::setw(2) << std::setfill('0') << time_.hour << ':' - << std::setw(2) << std::setfill('0') << time_.minute << ':' - << std::setw(2) << std::setfill('0') << time_.second << plusMinus - << std::setw(2) << std::setfill('0') << abs(time_.tzHour) << ':' - << std::setw(2) << std::setfill('0') << abs(time_.tzMinute); - } - - long TimeValue::toLong(long n) const - { - // Returns number of seconds in the day in UTC. - long result = (time_.hour - time_.tzHour) * 60 * 60; - result += (time_.minute - time_.tzMinute) * 60; - result += time_.second; - if (result < 0) { - result += 86400; - } - return result; - } - -} // namespace Exiv2 diff --git a/src/plugins/exiv2/value.hpp b/src/plugins/exiv2/value.hpp @@ -1,1226 +0,0 @@ -// ***************************************************************** -*- C++ -*- -/* - * Copyright (C) 2004, 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 value.hpp - @brief Value interface and concrete subclasses - @version $Rev: 560 $ - @author Andreas Huggel (ahu) - <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a> - @date 09-Jan-04, ahu: created - 11-Feb-04, ahu: isolated as a component - 31-Jul-04, brad: added Time, Data and String values - */ -#ifndef VALUE_HPP_ -#define VALUE_HPP_ - -// ***************************************************************************** -// included header files -#include "types.hpp" - -// + standard includes -#include <string> -#include <vector> -#include <iostream> -#include <sstream> -#include <memory> -#include <string.h> - -// ***************************************************************************** -// namespace extensions -namespace Exiv2 { - -// ***************************************************************************** -// class definitions - - /*! - @brief Common interface for all types of values used with metadata. - - The interface provides a uniform way to access values independent from - their actual C++ type for simple tasks like reading the values from a - string or data buffer. For other tasks, like modifying values you may - need to downcast it to the actual subclass of %Value so that you can - access the subclass specific interface. - */ - class Value { - public: - //! Shortcut for a %Value auto pointer. - typedef std::auto_ptr<Value> AutoPtr; - - //! @name Creators - //@{ - //! Constructor, taking a type id to initialize the base class with - explicit Value(TypeId typeId) - : type_(typeId) {} - //! Copy constructor - Value(const Value& rhs) - : type_(rhs.type_) {} - //! Virtual destructor. - virtual ~Value() {} - //@} - - //! @name Manipulators - //@{ - /*! - @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 - @param byteOrder Applicable byte order (little or big endian). - */ - virtual void read(const byte* buf, long len, ByteOrder byteOrder) =0; - /*! - @brief Set the value from a string buffer. The format of the string - corresponds to that of the write() method, i.e., a string - obtained through the write() method can be read by this - function. - - @param buf The string to read from. - */ - virtual void read(const std::string& buf) =0; - /*! - @brief Set the data area, if the value has one by copying (cloning) - the buffer pointed to by 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 value has no data area, else 0. - */ - virtual int setDataArea(const byte* buf, long len) { return -1; } - //@} - - //! @name Accessors - //@{ - //! Return the type identifier (Exif data format type). - TypeId typeId() const { return type_; } - /*! - @brief Return the value as a string. Implemented in terms of - write(std::ostream& os) const of the concrete class. - */ - std::string toString() const; - /*! - @brief Return an auto-pointer to a copy of itself (deep copy). - The caller owns this copy and the auto-pointer ensures that - it will be deleted. - */ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @brief Write value to a 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. - @param byteOrder Applicable byte order (little or big endian). - @return Number of bytes written. - */ - virtual long copy(byte* buf, ByteOrder byteOrder) const =0; - //! Return the number of components of the value - virtual long count() const =0; - //! Return the size of the value in bytes - virtual long size() const =0; - /*! - @brief Write the value to an output stream. You do not usually have - to use this function; it is used for the implementation of - the output operator for %Value, - operator<<(std::ostream &os, const Value &value). - */ - virtual std::ostream& write(std::ostream& os) const =0; - /*! - @brief Convert the n-th component of the value to a long. The - behaviour of this method may be undefined if there is no - n-th component. - - @return The converted value. - */ - virtual long toLong(long n =0) const =0; - /*! - @brief Convert the n-th component of the value to a float. The - behaviour of this method may be undefined if there is no - n-th component. - - @return The converted value. - */ - virtual float toFloat(long n =0) const =0; - /*! - @brief Convert the n-th component of the value to a Rational. The - behaviour of this method may be undefined if there is no - n-th component. - - @return The converted value. - */ - virtual Rational toRational(long n =0) const =0; - //! Return the size of the data area, 0 if there is none. - virtual long sizeDataArea() const { return 0; } - /*! - @brief Return a copy of the data area if the value has one. 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. - */ - virtual DataBuf dataArea() const { return DataBuf(0, 0); }; - //@} - - /*! - @brief A (simple) factory to create a Value type. - - The following Value subclasses are created depending on typeId:<BR><BR> - <TABLE> - <TR><TD class="indexkey"><B>typeId</B></TD><TD class="indexvalue"><B>%Value subclass</B></TD></TR> - <TR><TD class="indexkey">invalidTypeId</TD><TD class="indexvalue">%DataValue(invalidTypeId)</TD></TR> - <TR><TD class="indexkey">unsignedByte</TD><TD class="indexvalue">%DataValue(unsignedByte)</TD></TR> - <TR><TD class="indexkey">asciiString</TD><TD class="indexvalue">%AsciiValue</TD></TR> - <TR><TD class="indexkey">string</TD><TD class="indexvalue">%StringValue</TD></TR> - <TR><TD class="indexkey">unsignedShort</TD><TD class="indexvalue">%ValueType &lt; uint16_t &gt;</TD></TR> - <TR><TD class="indexkey">unsignedLong</TD><TD class="indexvalue">%ValueType &lt; uint32_t &gt;</TD></TR> - <TR><TD class="indexkey">unsignedRational</TD><TD class="indexvalue">%ValueType &lt; URational &gt;</TD></TR> - <TR><TD class="indexkey">invalid6</TD><TD class="indexvalue">%DataValue(invalid6)</TD></TR> - <TR><TD class="indexkey">undefined</TD><TD class="indexvalue">%DataValue</TD></TR> - <TR><TD class="indexkey">signedShort</TD><TD class="indexvalue">%ValueType &lt; int16_t &gt;</TD></TR> - <TR><TD class="indexkey">signedLong</TD><TD class="indexvalue">%ValueType &lt; int32_t &gt;</TD></TR> - <TR><TD class="indexkey">signedRational</TD><TD class="indexvalue">%ValueType &lt; Rational &gt;</TD></TR> - <TR><TD class="indexkey">date</TD><TD class="indexvalue">%DateValue</TD></TR> - <TR><TD class="indexkey">time</TD><TD class="indexvalue">%TimeValue</TD></TR> - <TR><TD class="indexkey">comment</TD><TD class="indexvalue">%CommentValue</TD></TR> - <TR><TD class="indexkey"><EM>default:</EM></TD><TD class="indexvalue">%DataValue(typeId)</TD></TR> - </TABLE> - - @param typeId Type of the value. - @return Auto-pointer to the newly created Value. The caller owns this - copy and the auto-pointer ensures that it will be deleted. - */ - static AutoPtr create(TypeId typeId); - - protected: - /*! - @brief Assignment operator. Protected so that it can only be used - by subclasses but not directly. - */ - Value& operator=(const Value& rhs); - - private: - //! Internal virtual copy constructor. - virtual Value* clone_() const =0; - // DATA - TypeId type_; //!< Type of the data - - }; // class Value - - //! Output operator for Value types - inline std::ostream& operator<<(std::ostream& os, const Value& value) - { - return value.write(os); - } - - //! %Value for an undefined data type. - class DataValue : public Value { - public: - //! Shortcut for a %DataValue auto pointer. - typedef std::auto_ptr<DataValue> AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - DataValue(TypeId typeId =undefined) : Value(typeId) {} - //! Constructor - DataValue(const byte* buf, - long len, ByteOrder byteOrder =invalidByteOrder, - TypeId typeId =undefined) - : Value(typeId) { read(buf, len, byteOrder); } - //! Virtual destructor. - virtual ~DataValue() {} - //@} - - //! @name Manipulators - //@{ - //! Assignment operator. - DataValue& operator=(const DataValue& rhs); - /*! - @brief Read the value from a character buffer. - - @note The byte order is required by the interface but not - used by this method, so just use the default. - - @param buf Pointer to the data buffer to read from - @param len Number of bytes in the data buffer - @param byteOrder Byte order. Not needed. - */ - virtual void read(const byte* buf, - long len, - ByteOrder byteOrder =invalidByteOrder); - //! Set the data from a string of integer values (e.g., "0 1 2 3") - virtual void read(const std::string& buf); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @brief Write value to a character data buffer. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - 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 Byte order. Not needed. - @return Number of characters written. - */ - virtual long copy(byte* buf, ByteOrder byteOrder =invalidByteOrder) const; - virtual long count() const { return size(); } - virtual long size() const; - virtual std::ostream& write(std::ostream& os) const; - virtual long toLong(long n =0) const { return value_[n]; } - virtual float toFloat(long n =0) const { return value_[n]; } - virtual Rational toRational(long n =0) const - { return Rational(value_[n], 1); } - //@} - - private: - //! Internal virtual copy constructor. - virtual DataValue* clone_() const; - // DATA - std::vector<byte> value_; - - }; // class DataValue - - /*! - @brief Abstract base class for a string based %Value type. - - Uses a std::string to store the value and implements defaults for - most operations. - */ - class StringValueBase : public Value { - public: - //! Shortcut for a %StringValueBase auto pointer. - typedef std::auto_ptr<StringValueBase> AutoPtr; - - //! @name Creators - //@{ - //! Constructor for subclasses - StringValueBase(TypeId typeId) - : Value(typeId) {} - //! Constructor for subclasses - StringValueBase(TypeId typeId, const std::string& buf) - : Value(typeId) { read(buf); } - //! Copy constructor - StringValueBase(const StringValueBase& rhs) - : Value(rhs), value_(rhs.value_) {} - - //! Virtual destructor. - virtual ~StringValueBase() {} - //@} - - //! @name Manipulators - //@{ - //! Assignment operator. - StringValueBase& operator=(const StringValueBase& rhs); - //! Read the value from buf. This default implementation uses buf as it is. - virtual void read(const std::string& buf); - /*! - @brief Read the value from a character buffer. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - @param buf Pointer to the data buffer to read from - @param len Number of bytes in the data buffer - @param byteOrder Byte order. Not needed. - */ - virtual void read(const byte* buf, - long len, - ByteOrder byteOrder =invalidByteOrder); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @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. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - @param buf Data buffer to write to. - @param byteOrder Byte order. Not used. - @return Number of characters written. - */ - virtual long copy(byte* buf, ByteOrder byteOrder =invalidByteOrder) const; - virtual long count() const { return size(); } - virtual long size() const; - virtual long toLong(long n =0) const { return value_[n]; } - virtual float toFloat(long n =0) const { return value_[n]; } - virtual Rational toRational(long n =0) const - { return Rational(value_[n], 1); } - virtual std::ostream& write(std::ostream& os) const; - //@} - - protected: - //! Internal virtual copy constructor. - virtual StringValueBase* clone_() const =0; - // DATA - std::string value_; //!< Stores the string value. - - }; // class StringValueBase - - /*! - @brief %Value for string type. - - This can be a plain Ascii string or a multipe byte encoded string. It is - left to caller to decode and encode the string to and from readable - text if that is required. - */ - class StringValue : public StringValueBase { - public: - //! Shortcut for a %StringValue auto pointer. - typedef std::auto_ptr<StringValue> AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - StringValue() - : StringValueBase(string) {} - //! Constructor - StringValue(const std::string& buf) - : StringValueBase(string, buf) {} - //! Copy constructor - StringValue(const StringValue& rhs) - : StringValueBase(rhs) {} - //! Virtual destructor. - virtual ~StringValue() {} - //@} - - //! @name Manipulators - //@{ - StringValue& operator=(const StringValue& rhs); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - //@} - - private: - //! Internal virtual copy constructor. - virtual StringValue* clone_() const; - - }; // class StringValue - - /*! - @brief %Value for an Ascii string type. - - This class is for null terminated single byte Ascii strings. - This class also ensures that the string is null terminated. - */ - class AsciiValue : public StringValueBase { - public: - //! Shortcut for a %AsciiValue auto pointer. - typedef std::auto_ptr<AsciiValue> AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - AsciiValue() - : StringValueBase(asciiString) {} - //! Constructor - AsciiValue(const std::string &buf) - : StringValueBase(asciiString, buf) {} - //! Copy constructor - AsciiValue(const AsciiValue& rhs) - : StringValueBase(rhs) {} - //! Virtual destructor. - virtual ~AsciiValue() {} - //@} - - //! @name Manipulators - //@{ - //! Assignment operator - AsciiValue& operator=(const AsciiValue& rhs); - /*! - @brief Set the value to that of the string buf. Overrides base class - to append a terminating '\\0' character if buf doesn't end - with '\\0'. - */ - virtual void read(const std::string& buf); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @brief Write the value to an output stream. Any trailing '\\0' - characters of the ASCII value are stripped and not written to - the output stream. - */ - virtual std::ostream& write(std::ostream& os) const; - //@} - - private: - //! Internal virtual copy constructor. - virtual AsciiValue* clone_() const; - - }; // class AsciiValue - - /*! - @brief %Value for an Exif comment. - - This can be a plain Ascii string or a multipe byte encoded string. The - comment is expected to be encoded in the character set indicated (default - undefined), but this is not checked. It is left to caller to decode and - encode the string to and from readable text if that is required. - */ - class CommentValue : public StringValueBase { - public: - //! Character set identifiers for the character sets defined by %Exif - enum CharsetId { ascii, jis, unicode, undefined, - invalidCharsetId, lastCharsetId }; - //! Information pertaining to the defined character sets - struct CharsetTable { - //! Constructor - CharsetTable(CharsetId charsetId, - const char* name, - const char* code); - CharsetId charsetId_; //!< Charset id - const char* name_; //!< Name of the charset - const char* code_; //!< Code of the charset - }; // struct CharsetTable - //! Charset information lookup functions. Implemented as a static class. - class CharsetInfo { - //! Prevent construction: not implemented. - CharsetInfo() {} - //! Prevent copy-construction: not implemented. - CharsetInfo(const CharsetInfo&); - //! Prevent assignment: not implemented. - CharsetInfo& operator=(const CharsetInfo&); - - public: - //! Return the name for a charset id - static const char* name(CharsetId charsetId); - //! Return the code for a charset id - static const char* code(CharsetId charsetId); - //! Return the charset id for a name - static CharsetId charsetIdByName(const std::string& name); - //! Return the charset id for a code - static CharsetId charsetIdByCode(const std::string& code); - - private: - static const CharsetTable charsetTable_[]; - }; // class CharsetInfo - - //! Shortcut for a %CommentValue auto pointer. - typedef std::auto_ptr<CommentValue> AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - CommentValue() - : StringValueBase(Exiv2::undefined) {} - //! Constructor, uses read(const std::string& comment) - CommentValue(const std::string& comment); - //! Copy constructor - CommentValue(const CommentValue& rhs) - : StringValueBase(rhs) {} - //! Virtual destructor. - virtual ~CommentValue() {} - //@} - - //! @name Manipulators - //@{ - //! Assignment operator. - CommentValue& operator=(const CommentValue& rhs); - /*! - @brief Read the value from a comment - - The format of \em comment is: - <BR> - <CODE>[charset=["]Ascii|Jis|Unicode|Undefined["] ]comment</CODE> - <BR> - The default charset is Undefined. - - @throw Error if an invalid character set is encountered - */ - void read(const std::string& comment); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @brief Write the comment in a format which can be read by - read(const std::string& comment). - */ - std::ostream& write(std::ostream& os) const; - //! Return the comment (without a charset="..." prefix) - std::string comment() const; - //! Return the charset id of the comment - CharsetId charsetId() const; - //@} - - private: - //! Internal virtual copy constructor. - virtual CommentValue* clone_() const; - - }; // class CommentValue - - /*! - @brief %Value for simple ISO 8601 dates - - This class is limited to parsing simple date strings in the ISO 8601 - format CCYYMMDD (century, year, month, day). - */ - class DateValue : public Value { - public: - //! Shortcut for a %DateValue auto pointer. - typedef std::auto_ptr<DateValue> AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - DateValue() : Value(date) { memset(&date_, 0, sizeof(date_)); } - //! Constructor - DateValue(int year, int month, int day); - //! Virtual destructor. - virtual ~DateValue() {} - //@} - - //! Simple Date helper structure - struct Date - { - int year; //!< Year - int month; //!< Month - int day; //!< Day - }; - - //! @name Manipulators - //@{ - //! Assignment operator. - DateValue& operator=(const DateValue& rhs); - /*! - @brief Read the value from a character buffer. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - @param buf Pointer to the data buffer to read from - @param len Number of bytes in the data buffer - @param byteOrder Byte order. Not needed. - - @throw Error in case of an unsupported date format - */ - virtual void read(const byte* buf, - long len, - ByteOrder byteOrder =invalidByteOrder); - /*! - @brief Set the value to that of the string buf. - - @param buf String containing the date - - @throw Error in case of an unsupported date format - */ - virtual void read(const std::string& buf); - //! Set the date - void setDate(const Date& src); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @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. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - @param buf Data buffer to write to. - @param byteOrder Byte order. Not used. - @return Number of characters written. - */ - virtual long copy(byte* buf, ByteOrder byteOrder =invalidByteOrder) const; - //! Return date struct containing date information - virtual const Date& getDate() const { return date_; } - virtual long count() const { return size(); } - virtual long size() const; - /*! - @brief Write the value to an output stream. . - */ - virtual std::ostream& write(std::ostream& os) const; - virtual long toLong(long n =0) const; - virtual float toFloat(long n =0) const - { return static_cast<float>(toLong(n)); } - virtual Rational toRational(long n =0) const - { return Rational(toLong(n), 1); } - //@} - - private: - //! Internal virtual copy constructor. - virtual DateValue* clone_() const; - // DATA - Date date_; - - }; // class DateValue - - /*! - @brief %Value for simple ISO 8601 times. - - This class is limited to handling simple time strings in the ISO 8601 - format HHMMSS±HHMM where HHMMSS refers to local hour, minute and - seconds and ±HHMM refers to hours and minutes ahead or behind - Universal Coordinated Time. - */ - class TimeValue : public Value { - public: - //! Shortcut for a %TimeValue auto pointer. - typedef std::auto_ptr<TimeValue> AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - TimeValue() : Value(time) { memset(&time_, 0, sizeof(time_)); } - //! Constructor - TimeValue(int hour, int minute, int second =0, - int tzHour =0, int tzMinute =0); - - //! Virtual destructor. - virtual ~TimeValue() {} - //@} - - //! Simple Time helper structure - struct Time - { - int hour; //!< Hour - int minute; //!< Minute - int second; //!< Second - int tzHour; //!< Hours ahead or behind UTC - int tzMinute; //!< Minutes ahead or behind UTC - }; - - //! @name Manipulators - //@{ - //! Assignment operator. - TimeValue& operator=(const TimeValue& rhs); - /*! - @brief Read the value from a character buffer. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - @param buf Pointer to the data buffer to read from - @param len Number of bytes in the data buffer - @param byteOrder Byte order. Not needed. - - @throw Error in case of an unsupported time format - */ - virtual void read(const byte* buf, - long len, - ByteOrder byteOrder =invalidByteOrder); - /*! - @brief Set the value to that of the string buf. - - @param buf String containing the time. - - @throw Error in case of an unsupported time format - */ - virtual void read(const std::string& buf); - //! Set the time - void setTime(const Time& src); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - /*! - @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. - - @note The byte order is required by the interface but not used by this - method, so just use the default. - - @param buf Data buffer to write to. - @param byteOrder Byte order. Not used. - @return Number of characters written. - */ - virtual long copy(byte* buf, ByteOrder byteOrder =invalidByteOrder) const; - //! Return time struct containing time information - virtual const Time& getTime() const { return time_; } - virtual long count() const { return size(); } - virtual long size() const; - /*! - @brief Write the value to an output stream. . - */ - virtual std::ostream& write(std::ostream& os) const; - virtual long toLong(long n =0) const; - virtual float toFloat(long n =0) const - { return static_cast<float>(toLong(n)); } - virtual Rational toRational(long n =0) const - { return Rational(toLong(n), 1); } - //@} - - private: - //! Internal virtual copy constructor. - virtual TimeValue* clone_() const; - // DATA - Time time_; - - }; // class TimeValue - //! Template to determine the TypeId for a type T - template<typename T> TypeId getType(); - - //! Specialization for an unsigned short - template<> inline TypeId getType<uint16_t>() { return unsignedShort; } - //! Specialization for an unsigned long - template<> inline TypeId getType<uint32_t>() { return unsignedLong; } - //! Specialization for an unsigned rational - template<> inline TypeId getType<URational>() { return unsignedRational; } - //! Specialization for a signed short - template<> inline TypeId getType<int16_t>() { return signedShort; } - //! Specialization for a signed long - template<> inline TypeId getType<int32_t>() { return signedLong; } - //! Specialization for a signed rational - template<> inline TypeId getType<Rational>() { return signedRational; } - - // No default implementation: let the compiler/linker complain -// template<typename T> inline TypeId getType() { return invalid; } - - /*! - @brief Template for a %Value of a basic type. This is used for unsigned - and signed short, long and rationals. - */ - template<typename T> - class ValueType : public Value { - public: - //! Shortcut for a %ValueType\<T\> auto pointer. - typedef std::auto_ptr<ValueType<T> > AutoPtr; - - //! @name Creators - //@{ - //! Default constructor. - ValueType() : Value(getType<T>()), pDataArea_(0), sizeDataArea_(0) {} - //! Constructor - ValueType(const byte* buf, long len, ByteOrder byteOrder); - //! Constructor - ValueType(const T& val, ByteOrder byteOrder =littleEndian); - //! Copy constructor - ValueType(const ValueType<T>& rhs); - //! Virtual destructor. - virtual ~ValueType(); - //@} - - //! @name Manipulators - //@{ - //! Assignment operator. - ValueType<T>& operator=(const ValueType<T>& rhs); - virtual void read(const byte* buf, long len, ByteOrder byteOrder); - /*! - @brief Set the data from a string of values of type T (e.g., - "0 1 2 3" or "1/2 1/3 1/4" depending on what T is). - Generally, the accepted input format is the same as that - produced by the write() method. - */ - virtual void read(const std::string& buf); - /*! - @brief Set the data area. This method copies (clones) the buffer - pointed to by buf. - */ - virtual int setDataArea(const byte* buf, long len); - //@} - - //! @name Accessors - //@{ - AutoPtr clone() const { return AutoPtr(clone_()); } - virtual long copy(byte* buf, ByteOrder byteOrder) const; - virtual long count() const { return static_cast<long>(value_.size()); } - virtual long size() const; - virtual std::ostream& write(std::ostream& os) const; - virtual long toLong(long n =0) const; - virtual float toFloat(long n =0) const; - virtual Rational toRational(long n =0) const; - //! Return the size of the data area. - virtual long sizeDataArea() const { return sizeDataArea_; } - /*! - @brief Return a copy of the data area in a DataBuf. The caller owns - this copy and DataBuf ensures that it will be deleted. - */ - virtual DataBuf dataArea() const; - //@} - - //! Container for values - typedef std::vector<T> ValueList; - //! Iterator type defined for convenience. - typedef typename std::vector<T>::iterator iterator; - //! Const iterator type defined for convenience. - typedef typename std::vector<T>::const_iterator const_iterator; - - // DATA - /*! - @brief The container for all values. In your application, if you know - what subclass of Value you're dealing with (and possibly the T) - then you can access this STL container through the usual - standard library functions. - */ - ValueList value_; - - private: - //! Internal virtual copy constructor. - virtual ValueType<T>* clone_() const; - - // DATA - //! Pointer to the buffer, 0 if none has been allocated - byte* pDataArea_; - //! The current size of the buffer - long sizeDataArea_; - }; // class ValueType - - //! Unsigned short value type - typedef ValueType<uint16_t> UShortValue; - //! Unsigned long value type - typedef ValueType<uint32_t> ULongValue; - //! Unsigned rational value type - typedef ValueType<URational> URationalValue; - //! Signed short value type - typedef ValueType<int16_t> ShortValue; - //! Signed long value type - typedef ValueType<int32_t> LongValue; - //! Signed rational value type - typedef ValueType<Rational> RationalValue; - -// ***************************************************************************** -// template and inline definitions - - /*! - @brief Read a value of type T from the data buffer. - - We need this template function for the ValueType template classes. - There are only specializations of this function available; no default - implementation is provided. - - @param buf Pointer to the data buffer to read from. - @param byteOrder Applicable byte order (little or big endian). - @return A value of type T. - */ - template<typename T> T getValue(const byte* buf, ByteOrder byteOrder); - // Specialization for a 2 byte unsigned short value. - template<> - inline uint16_t getValue(const byte* buf, ByteOrder byteOrder) - { - return getUShort(buf, byteOrder); - } - // Specialization for a 4 byte unsigned long value. - template<> - inline uint32_t getValue(const byte* buf, ByteOrder byteOrder) - { - return getULong(buf, byteOrder); - } - // Specialization for an 8 byte unsigned rational value. - template<> - inline URational getValue(const byte* buf, ByteOrder byteOrder) - { - return getURational(buf, byteOrder); - } - // Specialization for a 2 byte signed short value. - template<> - inline int16_t getValue(const byte* buf, ByteOrder byteOrder) - { - return getShort(buf, byteOrder); - } - // Specialization for a 4 byte signed long value. - template<> - inline int32_t getValue(const byte* buf, ByteOrder byteOrder) - { - return getLong(buf, byteOrder); - } - // Specialization for an 8 byte signed rational value. - template<> - inline Rational getValue(const byte* buf, ByteOrder byteOrder) - { - return getRational(buf, byteOrder); - } - - /*! - @brief Convert a value of type T to data, write the data to the data buffer. - - We need this template function for the ValueType template classes. - There are only specializations of this function available; no default - implementation is provided. - - @param buf Pointer to the data buffer to write to. - @param t Value to be converted. - @param byteOrder Applicable byte order (little or big endian). - @return The number of bytes written to the buffer. - */ - template<typename T> long toData(byte* buf, T t, ByteOrder byteOrder); - /*! - @brief Specialization to write an unsigned short to the data buffer. - Return the number of bytes written. - */ - template<> - inline long toData(byte* buf, uint16_t t, ByteOrder byteOrder) - { - return us2Data(buf, t, byteOrder); - } - /*! - @brief Specialization to write an unsigned long to the data buffer. - Return the number of bytes written. - */ - template<> - inline long toData(byte* buf, uint32_t t, ByteOrder byteOrder) - { - return ul2Data(buf, t, byteOrder); - } - /*! - @brief Specialization to write an unsigned rational to the data buffer. - Return the number of bytes written. - */ - template<> - inline long toData(byte* buf, URational t, ByteOrder byteOrder) - { - return ur2Data(buf, t, byteOrder); - } - /*! - @brief Specialization to write a signed short to the data buffer. - Return the number of bytes written. - */ - template<> - inline long toData(byte* buf, int16_t t, ByteOrder byteOrder) - { - return s2Data(buf, t, byteOrder); - } - /*! - @brief Specialization to write a signed long to the data buffer. - Return the number of bytes written. - */ - template<> - inline long toData(byte* buf, int32_t t, ByteOrder byteOrder) - { - return l2Data(buf, t, byteOrder); - } - /*! - @brief Specialization to write a signed rational to the data buffer. - Return the number of bytes written. - */ - template<> - inline long toData(byte* buf, Rational t, ByteOrder byteOrder) - { - return r2Data(buf, t, byteOrder); - } - - template<typename T> - ValueType<T>::ValueType(const byte* buf, long len, ByteOrder byteOrder) - : Value(getType<T>()), pDataArea_(0), sizeDataArea_(0) - { - read(buf, len, byteOrder); - } - - template<typename T> - ValueType<T>::ValueType(const T& val, ByteOrder byteOrder) - : Value(getType<T>()), pDataArea_(0), sizeDataArea_(0) - { - read(reinterpret_cast<const byte*>(&val), - TypeInfo::typeSize(typeId()), - byteOrder); - } - - template<typename T> - ValueType<T>::ValueType(const ValueType<T>& rhs) - : Value(rhs), value_(rhs.value_), pDataArea_(0), sizeDataArea_(0) - { - if (rhs.sizeDataArea_ > 0) { - pDataArea_ = new byte[rhs.sizeDataArea_]; - memcpy(pDataArea_, rhs.pDataArea_, rhs.sizeDataArea_); - sizeDataArea_ = rhs.sizeDataArea_; - } - } - - template<typename T> - ValueType<T>::~ValueType() - { - delete[] pDataArea_; - } - - template<typename T> - ValueType<T>& ValueType<T>::operator=(const ValueType<T>& rhs) - { - if (this == &rhs) return *this; - Value::operator=(rhs); - value_ = rhs.value_; - - byte* tmp = 0; - if (rhs.sizeDataArea_ > 0) { - tmp = new byte[rhs.sizeDataArea_]; - memcpy(tmp, rhs.pDataArea_, rhs.sizeDataArea_); - } - delete[] pDataArea_; - pDataArea_ = tmp; - sizeDataArea_ = rhs.sizeDataArea_; - - return *this; - } - - template<typename T> - void ValueType<T>::read(const byte* buf, long len, ByteOrder byteOrder) - { - value_.clear(); - for (long i = 0; i < len; i += TypeInfo::typeSize(typeId())) { - value_.push_back(getValue<T>(buf + i, byteOrder)); - } - } - - template<typename T> - void ValueType<T>::read(const std::string& buf) - { - std::istringstream is(buf); - T tmp; - value_.clear(); - while (is >> tmp) { - value_.push_back(tmp); - } - } - - template<typename T> - long ValueType<T>::copy(byte* buf, ByteOrder byteOrder) const - { - long offset = 0; - typename ValueList::const_iterator end = value_.end(); - for (typename ValueList::const_iterator i = value_.begin(); i != end; ++i) { - offset += toData(buf + offset, *i, byteOrder); - } - return offset; - } - - template<typename T> - long ValueType<T>::size() const - { - return static_cast<long>(TypeInfo::typeSize(typeId()) * value_.size()); - } - - template<typename T> - ValueType<T>* ValueType<T>::clone_() const - { - return new ValueType<T>(*this); - } - - template<typename T> - std::ostream& ValueType<T>::write(std::ostream& os) const - { - typename ValueList::const_iterator end = value_.end(); - typename ValueList::const_iterator i = value_.begin(); - while (i != end) { - os << *i; - if (++i != end) os << " "; - } - return os; - } - // Default implementation - template<typename T> - inline long ValueType<T>::toLong(long n) const - { - return value_[n]; - } - // Specialization for rational - template<> - inline long ValueType<Rational>::toLong(long n) const - { - return value_[n].first / value_[n].second; - } - // Specialization for unsigned rational - template<> - inline long ValueType<URational>::toLong(long n) const - { - return value_[n].first / value_[n].second; - } - // Default implementation - template<typename T> - inline float ValueType<T>::toFloat(long n) const - { - return static_cast<float>(value_[n]); - } - // Specialization for rational - template<> - inline float ValueType<Rational>::toFloat(long n) const - { - return static_cast<float>(value_[n].first) / value_[n].second; - } - // Specialization for unsigned rational - template<> - inline float ValueType<URational>::toFloat(long n) const - { - return static_cast<float>(value_[n].first) / value_[n].second; - } - // Default implementation - template<typename T> - inline Rational ValueType<T>::toRational(long n) const - { - return Rational(value_[n], 1); - } - // Specialization for rational - template<> - inline Rational ValueType<Rational>::toRational(long n) const - { - return Rational(value_[n].first, value_[n].second); - } - // Specialization for unsigned rational - template<> - inline Rational ValueType<URational>::toRational(long n) const - { - return Rational(value_[n].first, value_[n].second); - } - - template<typename T> - inline DataBuf ValueType<T>::dataArea() const - { - return DataBuf(pDataArea_, sizeDataArea_); - } - - template<typename T> - inline int ValueType<T>::setDataArea(const byte* buf, long len) - { - byte* tmp = 0; - if (len > 0) { - tmp = new byte[len]; - memcpy(tmp, buf, len); - } - delete[] pDataArea_; - pDataArea_ = tmp; - sizeDataArea_ = len; - return 0; - } - -} // namespace Exiv2 - -#endif // #ifndef VALUE_HPP_