// ***************************************************************** -*- C++ -*- /* * Copyright (C) 2004-2007 Andreas Huggel * * This program is part of the Exiv2 distribution. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA. */ /* File: image.cpp Version: $Rev$ Author(s): Andreas Huggel (ahu) Brad Schick (brad) 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$") // ***************************************************************************** // 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" #include "jpgimage.hpp" #include "cr2image.hpp" #include "crwimage.hpp" #include "mrwimage.hpp" #include "tiffimage.hpp" #ifdef EXV_HAVE_LIBZ # include "pngimage.hpp" #endif // EXV_HAVE_LIBZ // + standard includes #include #include #include #include #include #include #ifdef _MSC_VER # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif #ifdef EXV_HAVE_UNISTD_H # include // stat #endif // ***************************************************************************** // class member definitions namespace Exiv2 { const ImageFactory::Registry ImageFactory::registry_[] = { //image type creation fct type check Exif mode IPTC mode Comment mode //--------------- --------------- ---------- ----------- ----------- ------------ { ImageType::jpeg, newJpegInstance, isJpegType, amReadWrite, amReadWrite, amReadWrite }, { ImageType::exv, newExvInstance, isExvType, amReadWrite, amReadWrite, amReadWrite }, { ImageType::cr2, newCr2Instance, isCr2Type, amRead, amRead, amNone }, { ImageType::crw, newCrwInstance, isCrwType, amReadWrite, amNone, amReadWrite }, { ImageType::mrw, newMrwInstance, isMrwType, amRead, amRead, amNone }, { ImageType::tiff, newTiffInstance, isTiffType, amRead, amRead, amNone }, #ifdef EXV_HAVE_LIBZ { ImageType::png, newPngInstance, isPngType, amRead, amRead, amNone }, #endif // EXV_HAVE_LIBZ // End of list marker { ImageType::none, 0, 0, amNone, amNone, amNone } }; bool ImageFactory::Registry::operator==(const int& imageType) const { return imageType == imageType_; } bool Image::supportsMetadata(MetadataId metadataId) const { return (supportedMetadata_ & metadataId) != 0; } AccessMode ImageFactory::checkMode(int imageType, MetadataId metadataId) { const Registry* r = find(registry_, imageType); if (!r) throw Error(13, imageType); AccessMode am = amNone; switch (metadataId) { case mdExif: am = r->exifSupport_; break; case mdIptc: am = r->iptcSupport_; break; case mdComment: am = r->commentSupport_; break; // no default: let the compiler complain } return am; } int ImageFactory::getType(const std::string& path) { FileIo fileIo(path); return getType(fileIo); } int ImageFactory::getType(const byte* data, long size) { MemIo memIo(data, size); return getType(memIo); } int ImageFactory::getType(BasicIo& io) { if (io.open() != 0) return ImageType::none; IoCloser closer(io); for (unsigned int i = 0; registry_[i].imageType_ != ImageType::none; ++i) { if (registry_[i].isThisType_(io, false)) { return registry_[i].imageType_; } } return ImageType::none; } // 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) { BasicIo::AutoPtr io(new MemIo(data, size)); 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()); } for (unsigned int i = 0; registry_[i].imageType_ != ImageType::none; ++i) { if (registry_[i].isThisType_(*io, false)) { return registry_[i].newInstance_(io, false); } } return Image::AutoPtr(); } // ImageFactory::open Image::AutoPtr ImageFactory::create(int type, const std::string& path) { std::auto_ptr 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(int 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(int type, BasicIo::AutoPtr io) { // BasicIo instance does not need to be open const Registry* r = find(registry_, type); if (0 != r) { return r->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 // ***************************************************************************** // template, inline and free functions void append(Blob& blob, const byte* buf, uint32_t len) { if (len != 0) { assert(buf != 0); Blob::size_type size = blob.size(); if (blob.capacity() - size < len) { blob.reserve(size + 65536); } blob.resize(size + len); std::memcpy(&blob[size], buf, len); } } // append } // namespace Exiv2