Blame src/image.cpp

Packit Service 21b5d1
// ***************************************************************** -*- C++ -*-
Packit Service 21b5d1
/*
Packit Service 21b5d1
 * Copyright (C) 2004-2018 Exiv2 authors
Packit Service 21b5d1
 * This program is part of the Exiv2 distribution.
Packit Service 21b5d1
 *
Packit Service 21b5d1
 * This program is free software; you can redistribute it and/or
Packit Service 21b5d1
 * modify it under the terms of the GNU General Public License
Packit Service 21b5d1
 * as published by the Free Software Foundation; either version 2
Packit Service 21b5d1
 * of the License, or (at your option) any later version.
Packit Service 21b5d1
 *
Packit Service 21b5d1
 * This program is distributed in the hope that it will be useful,
Packit Service 21b5d1
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 21b5d1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 21b5d1
 * GNU General Public License for more details.
Packit Service 21b5d1
 *
Packit Service 21b5d1
 * You should have received a copy of the GNU General Public License
Packit Service 21b5d1
 * along with this program; if not, write to the Free Software
Packit Service 21b5d1
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit Service 21b5d1
 */
Packit Service 21b5d1
/*
Packit Service 21b5d1
  File:      image.cpp
Packit Service 21b5d1
 */
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// included header files
Packit Service 21b5d1
#include "config.h"
Packit Service 21b5d1
Packit Service 21b5d1
#include "image.hpp"
Packit Service 21b5d1
#include "image_int.hpp"
Packit Service 21b5d1
#include "error.hpp"
Packit Service 21b5d1
#include "futils.hpp"
Packit Service 21b5d1
#include "safe_op.hpp"
Packit Service 21b5d1
#include "slice.hpp"
Packit Service 21b5d1
Packit Service 21b5d1
#include "cr2image.hpp"
Packit Service 21b5d1
#include "crwimage.hpp"
Packit Service 21b5d1
#include "epsimage.hpp"
Packit Service 21b5d1
#include "jpgimage.hpp"
Packit Service 21b5d1
#include "mrwimage.hpp"
Packit Service 21b5d1
#ifdef EXV_HAVE_LIBZ
Packit Service 21b5d1
# include "pngimage.hpp"
Packit Service 21b5d1
#endif // EXV_HAVE_LIBZ
Packit Service 21b5d1
#include "rafimage.hpp"
Packit Service 21b5d1
#include "tiffimage.hpp"
Packit Service 21b5d1
#include "tiffimage_int.hpp"
Packit Service 21b5d1
#include "tiffcomposite_int.hpp"
Packit Service 21b5d1
#include "tiffvisitor_int.hpp"
Packit Service 21b5d1
#include "bigtiffimage.hpp"
Packit Service 21b5d1
#include "webpimage.hpp"
Packit Service 21b5d1
#include "orfimage.hpp"
Packit Service 21b5d1
#include "gifimage.hpp"
Packit Service 21b5d1
#include "psdimage.hpp"
Packit Service 21b5d1
#include "tgaimage.hpp"
Packit Service 21b5d1
#include "bmpimage.hpp"
Packit Service 21b5d1
#include "jp2image.hpp"
Packit Service 21b5d1
#include "nikonmn_int.hpp"
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_ENABLE_VIDEO
Packit Service 21b5d1
#include "matroskavideo.hpp"
Packit Service 21b5d1
#include "quicktimevideo.hpp"
Packit Service 21b5d1
#include "riffvideo.hpp"
Packit Service 21b5d1
#include "asfvideo.hpp"
Packit Service 21b5d1
#endif // EXV_ENABLE_VIDEO
Packit Service 21b5d1
#include "rw2image.hpp"
Packit Service 21b5d1
#include "pgfimage.hpp"
Packit Service 21b5d1
#include "xmpsidecar.hpp"
Packit Service 21b5d1
Packit Service 21b5d1
// + standard includes
Packit Service 21b5d1
#include <cerrno>
Packit Service 21b5d1
#include <cstdio>
Packit Service 21b5d1
#include <cstring>
Packit Service 21b5d1
#include <cassert>
Packit Service 21b5d1
#include <iostream>
Packit Service 21b5d1
#include <limits>
Packit Service 21b5d1
Packit Service 21b5d1
#include <sys/types.h>
Packit Service 21b5d1
#include <sys/stat.h>
Packit Service 21b5d1
#ifdef _MSC_VER
Packit Service 21b5d1
# define S_ISREG(m)      (((m) & S_IFMT) == S_IFREG)
Packit Service 21b5d1
#endif
Packit Service 21b5d1
#ifdef EXV_HAVE_UNISTD_H
Packit Service 21b5d1
# include <unistd.h>                            // stat
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
namespace {
Packit Service 21b5d1
Packit Service 21b5d1
    using namespace Exiv2;
Packit Service 21b5d1
Packit Service 21b5d1
    //! Struct for storing image types and function pointers.
Packit Service 21b5d1
    struct Registry {
Packit Service 21b5d1
        //! Comparison operator to compare a Registry structure with an image type
Packit Service 21b5d1
        bool operator==(const int& imageType) const { return imageType == imageType_; }
Packit Service 21b5d1
Packit Service 21b5d1
        // DATA
Packit Service 21b5d1
        int            imageType_;
Packit Service 21b5d1
        NewInstanceFct newInstance_;
Packit Service 21b5d1
        IsThisTypeFct  isThisType_;
Packit Service 21b5d1
        AccessMode     exifSupport_;
Packit Service 21b5d1
        AccessMode     iptcSupport_;
Packit Service 21b5d1
        AccessMode     xmpSupport_;
Packit Service 21b5d1
        AccessMode     commentSupport_;
Packit Service 21b5d1
    };
Packit Service 21b5d1
Packit Service 21b5d1
    const Registry registry[] = {
Packit Service 21b5d1
        //image type       creation fct     type check  Exif mode    IPTC mode    XMP mode     Comment mode
Packit Service 21b5d1
        //---------------  ---------------  ----------  -----------  -----------  -----------  ------------
Packit Service 21b5d1
        { ImageType::jpeg, newJpegInstance, isJpegType, amReadWrite, amReadWrite, amReadWrite, amReadWrite },
Packit Service 21b5d1
        { ImageType::exv,  newExvInstance,  isExvType,  amReadWrite, amReadWrite, amReadWrite, amReadWrite },
Packit Service 21b5d1
        { ImageType::cr2,  newCr2Instance,  isCr2Type,  amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::crw,  newCrwInstance,  isCrwType,  amReadWrite, amNone,      amNone,      amReadWrite },
Packit Service 21b5d1
        { ImageType::mrw,  newMrwInstance,  isMrwType,  amRead,      amRead,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::tiff, newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::bigtiff, newBigTiffInstance, isBigTiffType, amRead, amRead,  amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::webp, newWebPInstance, isWebPType, amReadWrite, amNone,      amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::dng,  newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::nef,  newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::pef,  newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::arw,  newTiffInstance, isTiffType, amRead,      amRead,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::rw2,  newRw2Instance,  isRw2Type,  amRead,      amRead,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::sr2,  newTiffInstance, isTiffType, amRead,      amRead,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::srw,  newTiffInstance, isTiffType, amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::orf,  newOrfInstance,  isOrfType,  amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
#ifdef EXV_HAVE_LIBZ
Packit Service 21b5d1
        { ImageType::png,  newPngInstance,  isPngType,  amReadWrite, amReadWrite, amReadWrite, amReadWrite },
Packit Service 21b5d1
#endif // EXV_HAVE_LIBZ
Packit Service 21b5d1
        { ImageType::pgf,  newPgfInstance,  isPgfType,  amReadWrite, amReadWrite, amReadWrite, amReadWrite },
Packit Service 21b5d1
        { ImageType::raf,  newRafInstance,  isRafType,  amRead,      amRead,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::eps,  newEpsInstance,  isEpsType,  amNone,      amNone,      amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::xmp,  newXmpInstance,  isXmpType,  amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
        { ImageType::gif,  newGifInstance,  isGifType,  amNone,      amNone,      amNone,      amNone      },
Packit Service 21b5d1
        { ImageType::psd,  newPsdInstance,  isPsdType,  amRead,      amRead,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::tga,  newTgaInstance,  isTgaType,  amNone,      amNone,      amNone,      amNone      },
Packit Service 21b5d1
        { ImageType::bmp,  newBmpInstance,  isBmpType,  amNone,      amNone,      amNone,      amNone      },
Packit Service 21b5d1
        { ImageType::jp2,  newJp2Instance,  isJp2Type,  amReadWrite, amReadWrite, amReadWrite, amNone      },
Packit Service 21b5d1
#ifdef EXV_ENABLE_VIDEO
Packit Service 21b5d1
        { ImageType::qtime,newQTimeInstance,isQTimeType,amRead,      amNone,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::riff, newRiffInstance, isRiffType, amRead,      amNone,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::asf,  newAsfInstance,  isAsfType,  amNone,      amNone,      amRead,      amNone      },
Packit Service 21b5d1
        { ImageType::mkv,  newMkvInstance,  isMkvType,  amNone,      amNone,      amRead,      amNone      },
Packit Service 21b5d1
#endif // EXV_ENABLE_VIDEO
Packit Service 21b5d1
        // End of list marker
Packit Service 21b5d1
        { ImageType::none, 0,               0,          amNone,      amNone,      amNone,      amNone      }
Packit Service 21b5d1
    };
Packit Service 21b5d1
Packit Service 21b5d1
}
Packit Service 21b5d1
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// class member definitions
Packit Service 21b5d1
namespace Exiv2 {
Packit Service 21b5d1
Packit Service 21b5d1
    Image::Image(int              imageType,
Packit Service 21b5d1
                 uint16_t         supportedMetadata,
Packit Service 21b5d1
                 BasicIo::AutoPtr io)
Packit Service 21b5d1
        : io_(io),
Packit Service 21b5d1
          pixelWidth_(0),
Packit Service 21b5d1
          pixelHeight_(0),
Packit Service 21b5d1
          imageType_(imageType),
Packit Service 21b5d1
          supportedMetadata_(supportedMetadata),
Packit Service 21b5d1
#ifdef EXV_HAVE_XMP_TOOLKIT
Packit Service 21b5d1
          writeXmpFromPacket_(false),
Packit Service 21b5d1
#else
Packit Service 21b5d1
          writeXmpFromPacket_(true),
Packit Service 21b5d1
#endif
Packit Service 21b5d1
          byteOrder_(invalidByteOrder),
Packit Service 21b5d1
          tags_(),
Packit Service 21b5d1
          init_(true)
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Image::~Image()
Packit Service 21b5d1
    {
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::printStructure(std::ostream&, PrintStructureOption,int /*depth*/)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        throw Error(kerUnsupportedImageType, io_->path());
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Image::isStringType(uint16_t type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return type == Exiv2::asciiString
Packit Service 21b5d1
            || type == Exiv2::unsignedByte
Packit Service 21b5d1
            || type == Exiv2::signedByte
Packit Service 21b5d1
            || type == Exiv2::undefined
Packit Service 21b5d1
            ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isShortType(uint16_t type) {
Packit Service 21b5d1
         return type == Exiv2::unsignedShort
Packit Service 21b5d1
             || type == Exiv2::signedShort
Packit Service 21b5d1
             ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isLongType(uint16_t type) {
Packit Service 21b5d1
         return type == Exiv2::unsignedLong
Packit Service 21b5d1
             || type == Exiv2::signedLong
Packit Service 21b5d1
             ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isLongLongType(uint16_t type) {
Packit Service 21b5d1
        return type == Exiv2::unsignedLongLong
Packit Service 21b5d1
            || type == Exiv2::signedLongLong
Packit Service 21b5d1
            ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isRationalType(uint16_t type) {
Packit Service 21b5d1
         return type == Exiv2::unsignedRational
Packit Service 21b5d1
             || type == Exiv2::signedRational
Packit Service 21b5d1
             ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::is2ByteType(uint16_t type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return isShortType(type);
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::is4ByteType(uint16_t type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return isLongType(type)
Packit Service 21b5d1
            || type == Exiv2::tiffFloat
Packit Service 21b5d1
            || type == Exiv2::tiffIfd
Packit Service 21b5d1
            ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::is8ByteType(uint16_t type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return isRationalType(type)
Packit Service 21b5d1
             || isLongLongType(type)
Packit Service 21b5d1
             || type == Exiv2::tiffIfd8
Packit Service 21b5d1
             || type == Exiv2::tiffDouble
Packit Service 21b5d1
            ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isPrintXMP(uint16_t type, Exiv2::PrintStructureOption option)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return type == 700 && option == kpsXMP;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isPrintICC(uint16_t type, Exiv2::PrintStructureOption option)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return type == 0x8773 && option == kpsIccProfile;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Image::isBigEndianPlatform()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        union {
Packit Service 21b5d1
            uint32_t i;
Packit Service 21b5d1
            char c[4];
Packit Service 21b5d1
        } e = { 0x01000000 };
Packit Service 21b5d1
Packit Service 21b5d1
        return e.c[0]?true:false;
Packit Service 21b5d1
    }
Packit Service 21b5d1
    bool Image::isLittleEndianPlatform() { return !isBigEndianPlatform(); }
Packit Service 21b5d1
Packit Service 21b5d1
    uint64_t Image::byteSwap(uint64_t value,bool bSwap) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        uint64_t result = 0;
Packit Service 21b5d1
        byte* source_value = reinterpret_cast<byte *>(&value);
Packit Service 21b5d1
        byte* destination_value = reinterpret_cast<byte *>(&result);
Packit Service 21b5d1
Packit Service 21b5d1
        for (int i = 0; i < 8; i++)
Packit Service 21b5d1
            destination_value[i] = source_value[8 - i - 1];
Packit Service 21b5d1
Packit Service 21b5d1
        return bSwap ? result : value;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    uint32_t Image::byteSwap(uint32_t value,bool bSwap) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        uint32_t result = 0;
Packit Service 21b5d1
        result |= (value & 0x000000FF) << 24;
Packit Service 21b5d1
        result |= (value & 0x0000FF00) << 8;
Packit Service 21b5d1
        result |= (value & 0x00FF0000) >> 8;
Packit Service 21b5d1
        result |= (value & 0xFF000000) >> 24;
Packit Service 21b5d1
        return bSwap ? result : value;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    uint16_t Image::byteSwap(uint16_t value,bool bSwap) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        uint16_t result = 0;
Packit Service 21b5d1
        result |= (value & 0x00FF) << 8;
Packit Service 21b5d1
        result |= (value & 0xFF00) >> 8;
Packit Service 21b5d1
        return bSwap ? result : value;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    uint16_t Image::byteSwap2(const DataBuf& buf,size_t offset,bool bSwap) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        uint16_t v;
Packit Service 21b5d1
        char*    p = (char*) &v;
Packit Service 21b5d1
        p[0] = buf.pData_[offset];
Packit Service 21b5d1
        p[1] = buf.pData_[offset+1];
Packit Service 21b5d1
        return Image::byteSwap(v,bSwap);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    uint32_t Image::byteSwap4(const DataBuf& buf,size_t offset,bool bSwap) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        uint32_t v;
Packit Service 21b5d1
        char*    p = (char*) &v;
Packit Service 21b5d1
        p[0] = buf.pData_[offset];
Packit Service 21b5d1
        p[1] = buf.pData_[offset+1];
Packit Service 21b5d1
        p[2] = buf.pData_[offset+2];
Packit Service 21b5d1
        p[3] = buf.pData_[offset+3];
Packit Service 21b5d1
        return Image::byteSwap(v,bSwap);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    uint64_t Image::byteSwap8(const DataBuf& buf,size_t offset,bool bSwap) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        uint64_t v;
Packit Service 21b5d1
        byte*    p = reinterpret_cast<byte *>(&v);
Packit Service 21b5d1
Packit Service 21b5d1
        for(int i = 0; i < 8; i++)
Packit Service 21b5d1
            p[i] = buf.pData_[offset + i];
Packit Service 21b5d1
Packit Service 21b5d1
        return Image::byteSwap(v,bSwap);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const char* Image::typeName(uint16_t tag) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        //! List of TIFF image tags
Packit Service 21b5d1
        const char* result = NULL;
Packit Service 21b5d1
        switch (tag ) {
Packit Service 21b5d1
            case Exiv2::unsignedByte     : result = "BYTE"      ; break;
Packit Service 21b5d1
            case Exiv2::asciiString      : result = "ASCII"     ; break;
Packit Service 21b5d1
            case Exiv2::unsignedShort    : result = "SHORT"     ; break;
Packit Service 21b5d1
            case Exiv2::unsignedLong     : result = "LONG"      ; break;
Packit Service 21b5d1
            case Exiv2::unsignedRational : result = "RATIONAL"  ; break;
Packit Service 21b5d1
            case Exiv2::signedByte       : result = "SBYTE"     ; break;
Packit Service 21b5d1
            case Exiv2::undefined        : result = "UNDEFINED" ; break;
Packit Service 21b5d1
            case Exiv2::signedShort      : result = "SSHORT"    ; break;
Packit Service 21b5d1
            case Exiv2::signedLong       : result = "SLONG"     ; break;
Packit Service 21b5d1
            case Exiv2::signedRational   : result = "SRATIONAL" ; break;
Packit Service 21b5d1
            case Exiv2::tiffFloat        : result = "FLOAT"     ; break;
Packit Service 21b5d1
            case Exiv2::tiffDouble       : result = "DOUBLE"    ; break;
Packit Service 21b5d1
            case Exiv2::tiffIfd          : result = "IFD"       ; break;
Packit Service 21b5d1
            default                      : result = "unknown"   ; break;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return result;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    static bool typeValid(uint16_t type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return type >= 1 && type <= 13 ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::printIFDStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,uint32_t start,bool bSwap,char c,int depth)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        depth++;
Packit Service 21b5d1
        bool bFirst  = true  ;
Packit Service 21b5d1
Packit Service 21b5d1
        // buffer
Packit Service 21b5d1
        const size_t dirSize = 32;
Packit Service 21b5d1
        DataBuf  dir(dirSize);
Packit Service 21b5d1
        bool bPrint = option == kpsBasic || option == kpsRecursive;
Packit Service 21b5d1
Packit Service 21b5d1
        do {
Packit Service 21b5d1
            // Read top of directory
Packit Service 21b5d1
            const int seekSuccess = !io.seek(start,BasicIo::beg);
Packit Service 21b5d1
            const long bytesRead = io.read(dir.pData_, 2);
Packit Service 21b5d1
            if (!seekSuccess || bytesRead == 0) {
Packit Service 21b5d1
                throw Error(kerCorruptedMetadata);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            uint16_t   dirLength = byteSwap2(dir,0,bSwap);
Packit Service 21b5d1
Packit Service 21b5d1
            bool tooBig = dirLength > 500;
Packit Service 21b5d1
            if ( tooBig ) throw Error(kerTiffDirectoryTooLarge);
Packit Service 21b5d1
Packit Service 21b5d1
            if ( bFirst && bPrint ) {
Packit Service 21b5d1
                out << Internal::indent(depth) << Internal::stringFormat("STRUCTURE OF TIFF FILE (%c%c): ",c,c) << io.path() << std::endl;
Packit Service 21b5d1
                if ( tooBig ) out << Internal::indent(depth) << "dirLength = " << dirLength << std::endl;
Packit Service 21b5d1
            }
Packit Service 21b5d1
Packit Service 21b5d1
            // Read the dictionary
Packit Service 21b5d1
            for ( int i = 0 ; i < dirLength ; i ++ ) {
Packit Service 21b5d1
                if ( bFirst && bPrint ) {
Packit Service 21b5d1
                    out << Internal::indent(depth)
Packit Service 21b5d1
                        << " address |    tag                              |     "
Packit Service 21b5d1
                        << " type |    count |    offset | value\n";
Packit Service 21b5d1
                }
Packit Service 21b5d1
                bFirst = false;
Packit Service 21b5d1
Packit Service 21b5d1
                io.read(dir.pData_, 12);
Packit Service 21b5d1
                uint16_t tag    = byteSwap2(dir,0,bSwap);
Packit Service 21b5d1
                uint16_t type   = byteSwap2(dir,2,bSwap);
Packit Service 21b5d1
                uint32_t count  = byteSwap4(dir,4,bSwap);
Packit Service 21b5d1
                uint32_t offset = byteSwap4(dir,8,bSwap);
Packit Service 21b5d1
Packit Service 21b5d1
                // Break for unknown tag types else we may segfault.
Packit Service 21b5d1
                if ( !typeValid(type) ) {
Packit Service 21b5d1
                    std::cerr << "invalid type value detected in Image::printIFDStructure:  " << type << std::endl;
Packit Service 21b5d1
                    start = 0; // break from do loop
Packit Service 21b5d1
                    throw Error(kerInvalidTypeValue);
Packit Service 21b5d1
                }
Packit Service 21b5d1
Packit Service 21b5d1
                std::string sp  = "" ; // output spacer
Packit Service 21b5d1
Packit Service 21b5d1
                //prepare to print the value
Packit Service 21b5d1
                uint32_t kount  = isPrintXMP(tag,option) ? count // haul in all the data
Packit Service 21b5d1
                                : isPrintICC(tag,option) ? count // ditto
Packit Service 21b5d1
                                : isStringType(type)     ? (count > 32 ? 32 : count) // restrict long arrays
Packit Service 21b5d1
                                : count > 5              ? 5
Packit Service 21b5d1
                                : count
Packit Service 21b5d1
                                ;
Packit Service 21b5d1
                uint32_t pad    = isStringType(type) ? 1 : 0;
Packit Service 21b5d1
                uint32_t size   = isStringType(type) ? 1
Packit Service 21b5d1
                                : is2ByteType(type)  ? 2
Packit Service 21b5d1
                                : is4ByteType(type)  ? 4
Packit Service 21b5d1
                                : is8ByteType(type)  ? 8
Packit Service 21b5d1
                                : 1
Packit Service 21b5d1
                                ;
Packit Service 21b5d1
Packit Service 21b5d1
                // if ( offset > io.size() ) offset = 0; // Denial of service?
Packit Service 21b5d1
Packit Service 21b5d1
                // #55 and #56 memory allocation crash test/data/POC8
Packit Service 21b5d1
                long long allocate = (long long) size*count + pad+20;
Packit Service 21b5d1
                if ( allocate > (long long) io.size() ) {
Packit Service 21b5d1
                    throw Error(kerInvalidMalloc);
Packit Service 21b5d1
                }
Packit Service 21b5d1
                DataBuf  buf((long)allocate);  // allocate a buffer
Packit Service 21b5d1
                std::memset(buf.pData_, 0, buf.size_);
Packit Service 21b5d1
                std::memcpy(buf.pData_,dir.pData_+8,4);  // copy dir[8:11] into buffer (short strings)
Packit Service 21b5d1
                const bool bOffsetIsPointer = count*size > 4;
Packit Service 21b5d1
Packit Service 21b5d1
                if ( bOffsetIsPointer ) {         // read into buffer
Packit Service 21b5d1
                    size_t   restore = io.tell();  // save
Packit Service 21b5d1
                    io.seek(offset,BasicIo::beg);  // position
Packit Service 21b5d1
                    io.read(buf.pData_,count*size);// read
Packit Service 21b5d1
                    io.seek(restore,BasicIo::beg); // restore
Packit Service 21b5d1
                }
Packit Service 21b5d1
Packit Service 21b5d1
                if ( bPrint ) {
Packit Service 21b5d1
                    const uint32_t address = start + 2 + i*12 ;
Packit Service 21b5d1
                    const std::string offsetString = bOffsetIsPointer?
Packit Service 21b5d1
                        Internal::stringFormat("%10u", offset):
Packit Service 21b5d1
                        "";
Packit Service 21b5d1
Packit Service 21b5d1
                    out << Internal::indent(depth)
Packit Service 21b5d1
                    << Internal::stringFormat("%8u | %#06x %-28s |%10s |%9u |%10s | "
Packit Service 21b5d1
                                              ,address,tag,tagName(tag).c_str(),typeName(type),count,offsetString.c_str());
Packit Service 21b5d1
                    if ( isShortType(type) ){
Packit Service 21b5d1
                        for ( size_t k = 0 ; k < kount ; k++ ) {
Packit Service 21b5d1
                            out << sp << byteSwap2(buf,k*size,bSwap);
Packit Service 21b5d1
                            sp = " ";
Packit Service 21b5d1
                        }
Packit Service 21b5d1
                    } else if ( isLongType(type) ){
Packit Service 21b5d1
                        for ( size_t k = 0 ; k < kount ; k++ ) {
Packit Service 21b5d1
                            out << sp << byteSwap4(buf,k*size,bSwap);
Packit Service 21b5d1
                            sp = " ";
Packit Service 21b5d1
                        }
Packit Service 21b5d1
Packit Service 21b5d1
                    } else if ( isRationalType(type) ){
Packit Service 21b5d1
                        for ( size_t k = 0 ; k < kount ; k++ ) {
Packit Service 21b5d1
                            uint32_t a = byteSwap4(buf,k*size+0,bSwap);
Packit Service 21b5d1
                            uint32_t b = byteSwap4(buf,k*size+4,bSwap);
Packit Service 21b5d1
                            out << sp << a << "/" << b;
Packit Service 21b5d1
                            sp = " ";
Packit Service 21b5d1
                        }
Packit Service 21b5d1
                    } else if ( isStringType(type) ) {
Packit Service 21b5d1
                        out << sp << Internal::binaryToString(makeSlice(buf, 0, kount));
Packit Service 21b5d1
                    }
Packit Service 21b5d1
Packit Service 21b5d1
                    sp = kount == count ? "" : " ...";
Packit Service 21b5d1
                    out << sp << std::endl;
Packit Service 21b5d1
Packit Service 21b5d1
                    if ( option == kpsRecursive && (tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/  || type == tiffIfd) ) {
Packit Service 21b5d1
                        for ( size_t k = 0 ; k < count ; k++ ) {
Packit Service 21b5d1
                            size_t   restore = io.tell();
Packit Service 21b5d1
                            uint32_t offset = byteSwap4(buf,k*size,bSwap);
Packit Service 21b5d1
                            printIFDStructure(io,out,option,offset,bSwap,c,depth);
Packit Service 21b5d1
                            io.seek(restore,BasicIo::beg);
Packit Service 21b5d1
                        }
Packit Service 21b5d1
                    } else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ ) {
Packit Service 21b5d1
Packit Service 21b5d1
                        if (static_cast<size_t>(Safe::add(count, offset)) > io.size()) {
Packit Service 21b5d1
                            throw Error(kerCorruptedMetadata);
Packit Service 21b5d1
                        }
Packit Service 21b5d1
Packit Service 21b5d1
                        const size_t restore = io.tell();
Packit Service 21b5d1
                        io.seek(offset, BasicIo::beg);  // position
Packit Service 21b5d1
                        std::vector<byte> bytes(count) ;  // allocate memory
Packit Service 21b5d1
                        // TODO: once we have C++11 use bytes.data()
Packit Service 21b5d1
                        const long read_bytes = io.read(&bytes[0], count);
Packit Service 21b5d1
                        io.seek(restore, BasicIo::beg);
Packit Service 21b5d1
                        // TODO: once we have C++11 use bytes.data()
Packit Service 21b5d1
                        IptcData::printStructure(out, makeSliceUntil(&bytes[0], read_bytes), depth);
Packit Service 21b5d1
Packit Service 21b5d1
                    }  else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10) {
Packit Service 21b5d1
                        size_t   restore = io.tell();  // save
Packit Service 21b5d1
Packit Service 21b5d1
                        uint32_t jump= 10           ;
Packit Service 21b5d1
                        byte     bytes[20]          ;
Packit Service 21b5d1
                        const char* chars = (const char*) &bytes[0] ;
Packit Service 21b5d1
                        io.seek(offset,BasicIo::beg);  // position
Packit Service 21b5d1
                        io.read(bytes,jump    )     ;  // read
Packit Service 21b5d1
                        bytes[jump]=0               ;
Packit Service 21b5d1
                        if ( ::strcmp("Nikon",chars) == 0 ) {
Packit Service 21b5d1
                            // tag is an embedded tiff
Packit Service 21b5d1
                            byte* bytes=new byte[count-jump] ;  // allocate memory
Packit Service 21b5d1
                            io.read(bytes,count-jump)        ;  // read
Packit Service 21b5d1
                            MemIo memIo(bytes,count-jump)    ;  // create a file
Packit Service 21b5d1
                            printTiffStructure(memIo,out,option,depth);
Packit Service 21b5d1
                            delete[] bytes                   ;  // free
Packit Service 21b5d1
                        } else {
Packit Service 21b5d1
                            // tag is an IFD
Packit Service 21b5d1
                            io.seek(0,BasicIo::beg);  // position
Packit Service 21b5d1
                            printIFDStructure(io,out,option,offset,bSwap,c,depth);
Packit Service 21b5d1
                        }
Packit Service 21b5d1
Packit Service 21b5d1
                        io.seek(restore,BasicIo::beg); // restore
Packit Service 21b5d1
                    }
Packit Service 21b5d1
                }
Packit Service 21b5d1
Packit Service 21b5d1
                if ( isPrintXMP(tag,option) ) {
Packit Service 21b5d1
                    buf.pData_[count]=0;
Packit Service 21b5d1
                    out << (char*) buf.pData_;
Packit Service 21b5d1
                }
Packit Service 21b5d1
                if ( isPrintICC(tag,option) ) {
Packit Service 21b5d1
                    out.write((const char*)buf.pData_,count);
Packit Service 21b5d1
                }
Packit Service 21b5d1
            }
Packit Service 21b5d1
            if ( start ) {
Packit Service 21b5d1
                io.read(dir.pData_, 4);
Packit Service 21b5d1
                start = tooBig ? 0 : byteSwap4(dir,0,bSwap);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        } while (start) ;
Packit Service 21b5d1
Packit Service 21b5d1
        if ( bPrint ) {
Packit Service 21b5d1
            out << Internal::indent(depth) << "END " << io.path() << std::endl;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        out.flush();
Packit Service 21b5d1
        depth--;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::printTiffStructure(BasicIo& io, std::ostream& out, Exiv2::PrintStructureOption option,int depth,size_t offset /*=0*/)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if ( option == kpsBasic || option == kpsXMP || option == kpsRecursive || option == kpsIccProfile ) {
Packit Service 21b5d1
            // buffer
Packit Service 21b5d1
            const size_t dirSize = 32;
Packit Service 21b5d1
            DataBuf  dir(dirSize);
Packit Service 21b5d1
Packit Service 21b5d1
            // read header (we already know for certain that we have a Tiff file)
Packit Service 21b5d1
            io.read(dir.pData_,  8);
Packit Service 21b5d1
            char c = (char) dir.pData_[0] ;
Packit Service 21b5d1
            bool bSwap   = ( c == 'M' && isLittleEndianPlatform() )
Packit Service 21b5d1
                        || ( c == 'I' && isBigEndianPlatform()    )
Packit Service 21b5d1
                        ;
Packit Service 21b5d1
            uint32_t start = byteSwap4(dir,4,bSwap);
Packit Service 21b5d1
            printIFDStructure(io,out,option,start+(uint32_t)offset,bSwap,c,depth);
Packit Service 21b5d1
        }
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearMetadata()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        clearExifData();
Packit Service 21b5d1
        clearIptcData();
Packit Service 21b5d1
        clearXmpPacket();
Packit Service 21b5d1
        clearXmpData();
Packit Service 21b5d1
        clearComment();
Packit Service 21b5d1
        clearIccProfile();
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    ExifData& Image::exifData()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return exifData_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    IptcData& Image::iptcData()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return iptcData_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    XmpData& Image::xmpData()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return xmpData_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    std::string& Image::xmpPacket()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        // Serialize the current XMP
Packit Service 21b5d1
        if (xmpData_.count() > 0 && !writeXmpFromPacket()) {
Packit Service 21b5d1
            XmpParser::encode(xmpPacket_, xmpData_,
Packit Service 21b5d1
                              XmpParser::useCompactFormat |
Packit Service 21b5d1
                              XmpParser::omitAllFormatting);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return xmpPacket_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setMetadata(const Image& image)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (checkMode(mdExif) & amWrite) {
Packit Service 21b5d1
            setExifData(image.exifData());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (checkMode(mdIptc) & amWrite) {
Packit Service 21b5d1
            setIptcData(image.iptcData());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (checkMode(mdIccProfile) & amWrite && iccProfile()) {
Packit Service 21b5d1
            setIccProfile(*iccProfile());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (checkMode(mdXmp) & amWrite) {
Packit Service 21b5d1
            setXmpPacket(image.xmpPacket());
Packit Service 21b5d1
            setXmpData(image.xmpData());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        if (checkMode(mdComment) & amWrite) {
Packit Service 21b5d1
            setComment(image.comment());
Packit Service 21b5d1
        }
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearExifData()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        exifData_.clear();
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setExifData(const ExifData& exifData)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        exifData_ = exifData;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearIptcData()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        iptcData_.clear();
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setIptcData(const IptcData& iptcData)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        iptcData_ = iptcData;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearXmpPacket()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        xmpPacket_.clear();
Packit Service 21b5d1
        writeXmpFromPacket(true);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setXmpPacket(const std::string& xmpPacket)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        xmpPacket_ = xmpPacket;
Packit Service 21b5d1
        if ( XmpParser::decode(xmpData_, xmpPacket) ) {
Packit Service 21b5d1
            throw Error(kerInvalidXMP);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        xmpPacket_ = xmpPacket;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearXmpData()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        xmpData_.clear();
Packit Service 21b5d1
        writeXmpFromPacket(false);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setXmpData(const XmpData& xmpData)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        xmpData_ = xmpData;
Packit Service 21b5d1
        writeXmpFromPacket(false);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_HAVE_XMP_TOOLKIT
Packit Service 21b5d1
    void Image::writeXmpFromPacket(bool flag)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        writeXmpFromPacket_ = flag;
Packit Service 21b5d1
    }
Packit Service 21b5d1
#else
Packit Service 21b5d1
    void Image::writeXmpFromPacket(bool) {}
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearComment()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        comment_.erase();
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setComment(const std::string& comment)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        comment_ = comment;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setIccProfile(Exiv2::DataBuf& iccProfile,bool bTestValid)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if ( bTestValid ) {
Packit Service 21b5d1
            if ( iccProfile.pData_ && ( iccProfile.size_ < (long) sizeof(long)) ) throw Error(kerInvalidIccProfile);
Packit Service 21b5d1
            long size = iccProfile.pData_ ? getULong(iccProfile.pData_, bigEndian): -1;
Packit Service 21b5d1
            if ( size!= iccProfile.size_ ) throw Error(kerInvalidIccProfile);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        iccProfile_ = iccProfile;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::clearIccProfile()
Packit Service 21b5d1
    {
Packit Service 21b5d1
        iccProfile_.free();
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    void Image::setByteOrder(ByteOrder byteOrder)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        byteOrder_ = byteOrder;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    ByteOrder Image::byteOrder() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return byteOrder_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Image::pixelWidth() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return pixelWidth_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int Image::pixelHeight() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return pixelHeight_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const ExifData& Image::exifData() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return exifData_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const IptcData& Image::iptcData() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return iptcData_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const XmpData& Image::xmpData() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return xmpData_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    std::string Image::comment() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return comment_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const std::string& Image::xmpPacket() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return xmpPacket_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    BasicIo& Image::io() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return *io_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Image::writeXmpFromPacket() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return writeXmpFromPacket_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const NativePreviewList& Image::nativePreviews() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return nativePreviews_;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Image::good() const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (io_->open() != 0) return false;
Packit Service 21b5d1
        IoCloser closer(*io_);
Packit Service 21b5d1
        return ImageFactory::checkType(imageType_, *io_, false);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool Image::supportsMetadata(MetadataId metadataId) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return (supportedMetadata_ & metadataId) != 0;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    AccessMode Image::checkMode(MetadataId metadataId) const
Packit Service 21b5d1
    {
Packit Service 21b5d1
        return ImageFactory::checkMode(imageType_, metadataId);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    const std::string& Image::tagName(uint16_t tag)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if ( init_ ) {
Packit Service 21b5d1
            int idx;
Packit Service 21b5d1
            const TagInfo* ti ;
Packit Service 21b5d1
            for (ti = Internal::  mnTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
            for (ti = Internal:: iopTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
            for (ti = Internal:: gpsTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
            for (ti = Internal:: ifdTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
            for (ti = Internal::exifTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
            for (ti = Internal:: mpfTagList(), idx = 0; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
            for (ti = Internal::Nikon1MakerNote::tagList(), idx = 0
Packit Service 21b5d1
                                                    ; ti[idx].tag_ != 0xffff; ++idx) tags_[ti[idx].tag_] = ti[idx].name_;
Packit Service 21b5d1
        }
Packit Service 21b5d1
        init_ = false;
Packit Service 21b5d1
Packit Service 21b5d1
        return tags_[tag] ;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    AccessMode ImageFactory::checkMode(int type, MetadataId metadataId)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        const Registry* r = find(registry, type);
Packit Service 21b5d1
        if (!r) throw Error(kerUnsupportedImageType, type);
Packit Service 21b5d1
        AccessMode am = amNone;
Packit Service 21b5d1
        switch (metadataId) {
Packit Service 21b5d1
        case mdNone:
Packit Service 21b5d1
            break;
Packit Service 21b5d1
        case mdExif:
Packit Service 21b5d1
            am = r->exifSupport_;
Packit Service 21b5d1
            break;
Packit Service 21b5d1
        case mdIptc:
Packit Service 21b5d1
            am = r->iptcSupport_;
Packit Service 21b5d1
            break;
Packit Service 21b5d1
        case mdXmp:
Packit Service 21b5d1
            am = r->xmpSupport_;
Packit Service 21b5d1
            break;
Packit Service 21b5d1
        case mdComment:
Packit Service 21b5d1
            am = r->commentSupport_;
Packit Service 21b5d1
            break;
Packit Service 21b5d1
        case mdIccProfile: break;
Packit Service 21b5d1
Packit Service 21b5d1
        // no default: let the compiler complain
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return am;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    bool ImageFactory::checkType(int type, BasicIo& io, bool advance)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        const Registry* r = find(registry, type);
Packit Service 21b5d1
        if (0 != r) {
Packit Service 21b5d1
            return r->isThisType_(io, advance);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return false;
Packit Service 21b5d1
    } // ImageFactory::checkType
Packit Service 21b5d1
Packit Service 21b5d1
    int ImageFactory::getType(const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        FileIo fileIo(path);
Packit Service 21b5d1
        return getType(fileIo);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_UNICODE_PATH
Packit Service 21b5d1
    int ImageFactory::getType(const std::wstring& wpath)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        FileIo fileIo(wpath);
Packit Service 21b5d1
        return getType(fileIo);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#endif
Packit Service 21b5d1
    int ImageFactory::getType(const byte* data, long size)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        MemIo memIo(data, size);
Packit Service 21b5d1
        return getType(memIo);
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    int ImageFactory::getType(BasicIo& io)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (io.open() != 0) return ImageType::none;
Packit Service 21b5d1
        IoCloser closer(io);
Packit Service 21b5d1
        for (unsigned int i = 0; registry[i].imageType_ != ImageType::none; ++i) {
Packit Service 21b5d1
            if (registry[i].isThisType_(io, false)) {
Packit Service 21b5d1
                return registry[i].imageType_;
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return ImageType::none;
Packit Service 21b5d1
    } // ImageFactory::getType
Packit Service 21b5d1
Packit Service 21b5d1
    BasicIo::AutoPtr ImageFactory::createIo(const std::string& path, bool useCurl)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Protocol fProt = fileProtocol(path);
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_USE_SSH
Packit Service 21b5d1
        if (fProt == pSsh || fProt == pSftp) {
Packit Service 21b5d1
            return BasicIo::AutoPtr(new SshIo(path)); // may throw
Packit Service 21b5d1
        }
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_USE_CURL
Packit Service 21b5d1
        if (useCurl && (fProt == pHttp || fProt == pHttps || fProt == pFtp)) {
Packit Service 21b5d1
            return BasicIo::AutoPtr(new CurlIo(path)); // may throw
Packit Service 21b5d1
        }
Packit Service 21b5d1
#endif
Packit Service 21b5d1
Packit Service 21b5d1
        if (fProt == pHttp)
Packit Service 21b5d1
            return BasicIo::AutoPtr(new HttpIo(path)); // may throw
Packit Service 21b5d1
        if (fProt == pFileUri)
Packit Service 21b5d1
            return BasicIo::AutoPtr(new FileIo(pathOfFileUrl(path)));
Packit Service 21b5d1
        if (fProt == pStdin || fProt == pDataUri)
Packit Service 21b5d1
            return BasicIo::AutoPtr(new XPathIo(path)); // may throw
Packit Service 21b5d1
Packit Service 21b5d1
        return BasicIo::AutoPtr(new FileIo(path));
Packit Service 21b5d1
Packit Service 21b5d1
        (void)(useCurl);
Packit Service 21b5d1
    } // ImageFactory::createIo
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_UNICODE_PATH
Packit Service 21b5d1
    BasicIo::AutoPtr ImageFactory::createIo(const std::wstring& wpath, bool useCurl)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Protocol fProt = fileProtocol(wpath);
Packit Service 21b5d1
#if EXV_USE_SSH == 1
Packit Service 21b5d1
        if (fProt == pSsh || fProt == pSftp) {
Packit Service 21b5d1
            return BasicIo::AutoPtr(new SshIo(wpath));
Packit Service 21b5d1
        }
Packit Service 21b5d1
#endif
Packit Service 21b5d1
#if EXV_USE_CURL == 1
Packit Service 21b5d1
        if (useCurl && (fProt == pHttp || fProt == pHttps || fProt == pFtp)) {
Packit Service 21b5d1
            return BasicIo::AutoPtr(new CurlIo(wpath));
Packit Service 21b5d1
        }
Packit Service 21b5d1
#endif
Packit Service 21b5d1
        if (fProt == pHttp)
Packit Service 21b5d1
            return BasicIo::AutoPtr(new HttpIo(wpath));
Packit Service 21b5d1
        if (fProt == pFileUri)
Packit Service 21b5d1
            return BasicIo::AutoPtr(new FileIo(pathOfFileUrl(wpath)));
Packit Service 21b5d1
        if (fProt == pStdin || fProt == pDataUri)
Packit Service 21b5d1
            return BasicIo::AutoPtr(new XPathIo(wpath)); // may throw
Packit Service 21b5d1
        return BasicIo::AutoPtr(new FileIo(wpath));
Packit Service 21b5d1
    } // ImageFactory::createIo
Packit Service 21b5d1
#endif
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::open(const std::string& path, bool useCurl)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Image::AutoPtr image = open(ImageFactory::createIo(path, useCurl)); // may throw
Packit Service 21b5d1
        if (image.get() == 0) throw Error(kerFileContainsUnknownImageType, path);
Packit Service 21b5d1
        return image;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_UNICODE_PATH
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::open(const std::wstring& wpath, bool useCurl)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        Image::AutoPtr image = open(ImageFactory::createIo(wpath, useCurl)); // may throw
Packit Service 21b5d1
        if (image.get() == 0) throw WError(kerFileContainsUnknownImageType, wpath);
Packit Service 21b5d1
        return image;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#endif
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::open(const byte* data, long size)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        BasicIo::AutoPtr io(new MemIo(data, size));
Packit Service 21b5d1
        Image::AutoPtr image = open(io); // may throw
Packit Service 21b5d1
        if (image.get() == 0) throw Error(kerMemoryContainsUnknownImageType);
Packit Service 21b5d1
        return image;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::open(BasicIo::AutoPtr io)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (io->open() != 0) {
Packit Service 21b5d1
            throw Error(kerDataSourceOpenFailed, io->path(), strError());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        for (unsigned int i = 0; registry[i].imageType_ != ImageType::none; ++i) {
Packit Service 21b5d1
            if (registry[i].isThisType_(*io, false)) {
Packit Service 21b5d1
                return registry[i].newInstance_(io, false);
Packit Service 21b5d1
            }
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return Image::AutoPtr();
Packit Service 21b5d1
    } // ImageFactory::open
Packit Service 21b5d1
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::create(int type,
Packit Service 21b5d1
                                        const std::string& path)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::auto_ptr<FileIo> fileIo(new FileIo(path));
Packit Service 21b5d1
        // Create or overwrite the file, then close it
Packit Service 21b5d1
        if (fileIo->open("w+b") != 0) {
Packit Service 21b5d1
            throw Error(kerFileOpenFailed, path, "w+b", strError());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        fileIo->close();
Packit Service 21b5d1
        BasicIo::AutoPtr io(fileIo);
Packit Service 21b5d1
        Image::AutoPtr image = create(type, io);
Packit Service 21b5d1
        if (image.get() == 0) throw Error(kerUnsupportedImageType, type);
Packit Service 21b5d1
        return image;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#ifdef EXV_UNICODE_PATH
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::create(int type,
Packit Service 21b5d1
                                        const std::wstring& wpath)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        std::auto_ptr<FileIo> fileIo(new FileIo(wpath));
Packit Service 21b5d1
        // Create or overwrite the file, then close it
Packit Service 21b5d1
        if (fileIo->open("w+b") != 0) {
Packit Service 21b5d1
            throw WError(kerFileOpenFailed, wpath, "w+b", strError().c_str());
Packit Service 21b5d1
        }
Packit Service 21b5d1
        fileIo->close();
Packit Service 21b5d1
        BasicIo::AutoPtr io(fileIo);
Packit Service 21b5d1
        Image::AutoPtr image = create(type, io);
Packit Service 21b5d1
        if (image.get() == 0) throw Error(kerUnsupportedImageType, type);
Packit Service 21b5d1
        return image;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
#endif
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::create(int type)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        BasicIo::AutoPtr io(new MemIo);
Packit Service 21b5d1
        Image::AutoPtr image = create(type, io);
Packit Service 21b5d1
        if (image.get() == 0) throw Error(kerUnsupportedImageType, type);
Packit Service 21b5d1
        return image;
Packit Service 21b5d1
    }
Packit Service 21b5d1
Packit Service 21b5d1
    Image::AutoPtr ImageFactory::create(int type,
Packit Service 21b5d1
                                        BasicIo::AutoPtr io)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        // BasicIo instance does not need to be open
Packit Service 21b5d1
        const Registry* r = find(registry, type);
Packit Service 21b5d1
        if (0 != r) {
Packit Service 21b5d1
            return r->newInstance_(io, true);
Packit Service 21b5d1
        }
Packit Service 21b5d1
        return Image::AutoPtr();
Packit Service 21b5d1
    } // ImageFactory::create
Packit Service 21b5d1
Packit Service 21b5d1
// *****************************************************************************
Packit Service 21b5d1
// template, inline and free functions
Packit Service 21b5d1
Packit Service 21b5d1
    void append(Blob& blob, const byte* buf, uint32_t len)
Packit Service 21b5d1
    {
Packit Service 21b5d1
        if (len != 0) {
Packit Service 21b5d1
            assert(buf != 0);
Packit Service 21b5d1
            Blob::size_type size = blob.size();
Packit Service 21b5d1
            if (blob.capacity() - size < len) {
Packit Service 21b5d1
                blob.reserve(size + 65536);
Packit Service 21b5d1
            }
Packit Service 21b5d1
            blob.resize(size + len);
Packit Service 21b5d1
            std::memcpy(&blob[size], buf, len);
Packit Service 21b5d1
        }
Packit Service 21b5d1
    } // append
Packit Service 21b5d1
Packit Service 21b5d1
}                                       // namespace Exiv2