Blame src/tiffcomposite_int.cpp

Packit 01d647
// ***************************************************************** -*- C++ -*-
Packit 01d647
/*
Packit 01d647
 * Copyright (C) 2004-2018 Exiv2 authors
Packit 01d647
 * This program is part of the Exiv2 distribution.
Packit 01d647
 *
Packit 01d647
 * This program is free software; you can redistribute it and/or
Packit 01d647
 * modify it under the terms of the GNU General Public License
Packit 01d647
 * as published by the Free Software Foundation; either version 2
Packit 01d647
 * of the License, or (at your option) any later version.
Packit 01d647
 *
Packit 01d647
 * This program is distributed in the hope that it will be useful,
Packit 01d647
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 01d647
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 01d647
 * GNU General Public License for more details.
Packit 01d647
 *
Packit 01d647
 * You should have received a copy of the GNU General Public License
Packit 01d647
 * along with this program; if not, write to the Free Software
Packit 01d647
 * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
Packit 01d647
 */
Packit 01d647
/*
Packit 01d647
  File:      tiffcomposite.cpp
Packit 01d647
  Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
Packit 01d647
  History:   11-Apr-06, ahu: created
Packit 01d647
 */
Packit 01d647
// *****************************************************************************
Packit 01d647
// included header files
Packit 01d647
#include "config.h"
Packit 01d647
Packit 01d647
#include "tiffimage_int.hpp"
Packit 01d647
#include "tiffcomposite_int.hpp"
Packit 01d647
#include "tiffvisitor_int.hpp"
Packit 01d647
#include "makernote_int.hpp"
Packit 01d647
#include "value.hpp"
Packit 01d647
#include "error.hpp"
Packit 01d647
#include "enforce.hpp"
Packit 01d647
Packit 01d647
// + standard includes
Packit 01d647
#include <string>
Packit 01d647
#include <cstring>
Packit 01d647
#include <iostream>
Packit 01d647
#include <iomanip>
Packit 01d647
#include <algorithm>
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
namespace {
Packit 01d647
    //! Add \em tobe - \em curr 0x00 filler bytes if necessary
Packit 01d647
    uint32_t fillGap(Exiv2::Internal::IoWrapper& ioWrapper, uint32_t curr, uint32_t tobe);
Packit 01d647
}
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// class member definitions
Packit 01d647
namespace Exiv2 {
Packit 01d647
    namespace Internal {
Packit 01d647
Packit 01d647
    bool TiffMappingInfo::operator==(const TiffMappingInfo::Key& key) const
Packit 01d647
    {
Packit 01d647
        return    (   0 == strcmp("*", make_)
Packit 01d647
                   || 0 == strncmp(make_, key.m_.c_str(), strlen(make_)))
Packit 01d647
               && (Tag::all == extendedTag_ || key.e_ == extendedTag_)
Packit 01d647
               && key.g_ == group_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    IoWrapper::IoWrapper(BasicIo& io, const byte* pHeader, long size, OffsetWriter* pow)
Packit 01d647
        : io_(io), pHeader_(pHeader), size_(size), wroteHeader_(false), pow_(pow)
Packit 01d647
    {
Packit 01d647
        if (pHeader_ == 0 || size_ == 0) wroteHeader_ = true;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    long IoWrapper::write(const byte* pData, long wcount)
Packit 01d647
    {
Packit 01d647
        if (!wroteHeader_ && wcount > 0) {
Packit 01d647
            io_.write(pHeader_, size_);
Packit 01d647
            wroteHeader_ = true;
Packit 01d647
        }
Packit 01d647
        return io_.write(pData, wcount);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    int IoWrapper::putb(byte data)
Packit 01d647
    {
Packit 01d647
        if (!wroteHeader_) {
Packit 01d647
            io_.write(pHeader_, size_);
Packit 01d647
            wroteHeader_ = true;
Packit 01d647
        }
Packit 01d647
        return io_.putb(data);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void IoWrapper::setTarget(int id, uint32_t target)
Packit 01d647
    {
Packit 01d647
        if (pow_) pow_->setTarget(OffsetWriter::OffsetId(id), target);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent::TiffComponent(uint16_t tag, IfdId group)
Packit 01d647
        : tag_(tag), group_(group), pStart_(0)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffEntryBase::TiffEntryBase(uint16_t tag, IfdId group, TiffType tiffType)
Packit 01d647
        : TiffComponent(tag, group),
Packit 01d647
          tiffType_(tiffType), count_(0), offset_(0),
Packit 01d647
          size_(0), pData_(0), isMalloced_(false), idx_(0),
Packit 01d647
          pValue_(0)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffSubIfd::TiffSubIfd(uint16_t tag, IfdId group, IfdId newGroup)
Packit 01d647
        : TiffEntryBase(tag, group, ttUnsignedLong), newGroup_(newGroup)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffMnEntry::TiffMnEntry(uint16_t tag, IfdId group, IfdId mnGroup)
Packit 01d647
        : TiffEntryBase(tag, group, ttUndefined), mnGroup_(mnGroup), mn_(0)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffIfdMakernote::TiffIfdMakernote(uint16_t  tag,
Packit 01d647
                                       IfdId     group,
Packit 01d647
                                       IfdId     mnGroup,
Packit 01d647
                                       MnHeader* pHeader,
Packit 01d647
                                       bool      hasNext)
Packit 01d647
        : TiffComponent(tag, group),
Packit 01d647
          pHeader_(pHeader),
Packit 01d647
          ifd_(tag, mnGroup, hasNext),
Packit 01d647
          mnOffset_(0),
Packit 01d647
          imageByteOrder_(invalidByteOrder)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryArray::TiffBinaryArray(uint16_t tag,
Packit 01d647
                                     IfdId group,
Packit 01d647
                                     const ArrayCfg* arrayCfg,
Packit 01d647
                                     const ArrayDef* arrayDef,
Packit 01d647
                                     int defSize)
Packit 01d647
        : TiffEntryBase(tag, group, arrayCfg->elTiffType_),
Packit 01d647
          cfgSelFct_(0),
Packit 01d647
          arraySet_(0),
Packit 01d647
          arrayCfg_(arrayCfg),
Packit 01d647
          arrayDef_(arrayDef),
Packit 01d647
          defSize_(defSize),
Packit 01d647
          setSize_(0),
Packit 01d647
          origData_(0),
Packit 01d647
          origSize_(0),
Packit 01d647
          pRoot_(0),
Packit 01d647
          decoded_(false)
Packit 01d647
    {
Packit 01d647
        assert(arrayCfg != 0);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryArray::TiffBinaryArray(uint16_t tag,
Packit 01d647
                                     IfdId group,
Packit 01d647
                                     const ArraySet* arraySet,
Packit 01d647
                                     int setSize,
Packit 01d647
                                     CfgSelFct cfgSelFct)
Packit 01d647
        : TiffEntryBase(tag, group), // Todo: Does it make a difference that there is no type?
Packit 01d647
          cfgSelFct_(cfgSelFct),
Packit 01d647
          arraySet_(arraySet),
Packit 01d647
          arrayCfg_(0),
Packit 01d647
          arrayDef_(0),
Packit 01d647
          defSize_(0),
Packit 01d647
          setSize_(setSize),
Packit 01d647
          origData_(0),
Packit 01d647
          origSize_(0),
Packit 01d647
          pRoot_(0),
Packit 01d647
          decoded_(false)
Packit 01d647
    {
Packit 01d647
        // We'll figure out the correct cfg later
Packit 01d647
        assert(cfgSelFct != 0);
Packit 01d647
        assert(arraySet_ != 0);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryElement::TiffBinaryElement(uint16_t tag, IfdId group)
Packit 01d647
        : TiffEntryBase(tag, group),
Packit 01d647
        elByteOrder_(invalidByteOrder)
Packit 01d647
    {
Packit 01d647
        elDef_.idx_ = 0;
Packit 01d647
        elDef_.tiffType_ = ttUndefined;
Packit 01d647
        elDef_.count_ = 0;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent::~TiffComponent()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffDirectory::~TiffDirectory()
Packit 01d647
    {
Packit 01d647
        for (Components::iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            delete *i;
Packit 01d647
        }
Packit 01d647
        delete pNext_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffSubIfd::~TiffSubIfd()
Packit 01d647
    {
Packit 01d647
        for (Ifds::iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            delete *i;
Packit 01d647
        }
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffEntryBase::~TiffEntryBase()
Packit 01d647
    {
Packit 01d647
        if (isMalloced_) {
Packit 01d647
            delete[] pData_;
Packit 01d647
        }
Packit 01d647
        delete pValue_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffEntry::~TiffEntry()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffDataEntryBase::~TiffDataEntryBase()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffDataEntry::~TiffDataEntry()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffImageEntry::~TiffImageEntry()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffSizeEntry::~TiffSizeEntry()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffMnEntry::~TiffMnEntry()
Packit 01d647
    {
Packit 01d647
        delete mn_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffIfdMakernote::~TiffIfdMakernote()
Packit 01d647
    {
Packit 01d647
        delete pHeader_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryArray::~TiffBinaryArray()
Packit 01d647
    {
Packit 01d647
        for (Components::iterator i = elements_.begin(); i != elements_.end(); ++i) {
Packit 01d647
            delete *i;
Packit 01d647
        }
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryElement::~TiffBinaryElement()
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffEntryBase::TiffEntryBase(const TiffEntryBase& rhs)
Packit 01d647
        : TiffComponent(rhs),
Packit 01d647
          tiffType_(rhs.tiffType_),
Packit 01d647
          count_(rhs.count_),
Packit 01d647
          offset_(rhs.offset_),
Packit 01d647
          size_(rhs.size_),
Packit 01d647
          pData_(rhs.pData_),
Packit 01d647
          isMalloced_(rhs.isMalloced_),
Packit 01d647
          idx_(rhs.idx_),
Packit 01d647
          pValue_(rhs.pValue_ ? rhs.pValue_->clone().release() : 0)
Packit 01d647
    {
Packit 01d647
        if (rhs.isMalloced_) {
Packit 01d647
            pData_ = new byte[rhs.size_];
Packit 01d647
            memcpy(pData_, rhs.pData_, rhs.size_);
Packit 01d647
        }
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffDirectory::TiffDirectory(const TiffDirectory& rhs)
Packit 01d647
        : TiffComponent(rhs),
Packit 01d647
          hasNext_(rhs.hasNext_),
Packit 01d647
          pNext_(0)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffSubIfd::TiffSubIfd(const TiffSubIfd& rhs)
Packit 01d647
        : TiffEntryBase(rhs),
Packit 01d647
          newGroup_(rhs.newGroup_)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryArray::TiffBinaryArray(const TiffBinaryArray& rhs)
Packit 01d647
        : TiffEntryBase(rhs),
Packit 01d647
          cfgSelFct_(rhs.cfgSelFct_),
Packit 01d647
          arraySet_(rhs.arraySet_),
Packit 01d647
          arrayCfg_(rhs.arrayCfg_),
Packit 01d647
          arrayDef_(rhs.arrayDef_),
Packit 01d647
          defSize_(rhs.defSize_),
Packit 01d647
          setSize_(rhs.setSize_),
Packit 01d647
          origData_(rhs.origData_),
Packit 01d647
          origSize_(rhs.origSize_),
Packit 01d647
          pRoot_(rhs.pRoot_),
Packit 01d647
          decoded_(false)
Packit 01d647
    {
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent::AutoPtr TiffComponent::clone() const
Packit 01d647
    {
Packit 01d647
        return AutoPtr(doClone());
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffEntry* TiffEntry::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffEntry(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffDataEntry* TiffDataEntry::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffDataEntry(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffImageEntry* TiffImageEntry::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffImageEntry(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffSizeEntry* TiffSizeEntry::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffSizeEntry(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffDirectory* TiffDirectory::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffDirectory(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffSubIfd* TiffSubIfd::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffSubIfd(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffMnEntry* TiffMnEntry::doClone() const
Packit 01d647
    {
Packit 01d647
        assert(false); // Not implemented
Packit 01d647
        return 0;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffIfdMakernote* TiffIfdMakernote::doClone() const
Packit 01d647
    {
Packit 01d647
        assert(false); // Not implemented
Packit 01d647
        return 0;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryArray* TiffBinaryArray::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffBinaryArray(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffBinaryElement* TiffBinaryElement::doClone() const
Packit 01d647
    {
Packit 01d647
        return new TiffBinaryElement(*this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    int TiffComponent::idx() const
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    int TiffEntryBase::idx() const
Packit 01d647
    {
Packit 01d647
        return idx_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffEntryBase::setData(DataBuf buf)
Packit 01d647
    {
Packit 01d647
        std::pair<byte*, long> p = buf.release();
Packit 01d647
        setData(p.first, p.second);
Packit 01d647
        isMalloced_ = true;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffEntryBase::setData(byte* pData, int32_t size)
Packit 01d647
    {
Packit 01d647
        if (isMalloced_) {
Packit 01d647
            delete[] pData_;
Packit 01d647
        }
Packit 01d647
        pData_ = pData;
Packit 01d647
        size_  = size;
Packit 01d647
        if (pData_ == 0) size_ = 0;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffEntryBase::updateValue(Value::AutoPtr value, ByteOrder byteOrder)
Packit 01d647
    {
Packit 01d647
        if (value.get() == 0) return;
Packit 01d647
        uint32_t newSize = value->size();
Packit 01d647
        if (newSize > size_) {
Packit 01d647
            setData(DataBuf(newSize));
Packit 01d647
        }
Packit 01d647
        if (pData_ != NULL) {
Packit 01d647
            memset(pData_, 0x0, size_);
Packit 01d647
        }
Packit 01d647
        size_ = value->copy(pData_, byteOrder);
Packit 01d647
        assert(size_ == newSize);
Packit 01d647
        setValue(value);
Packit 01d647
    } // TiffEntryBase::updateValue
Packit 01d647
Packit 01d647
    void TiffEntryBase::setValue(Value::AutoPtr value)
Packit 01d647
    {
Packit 01d647
        if (value.get() == 0) return;
Packit 01d647
        tiffType_ = toTiffType(value->typeId());
Packit 01d647
        count_ = value->count();
Packit 01d647
        delete pValue_;
Packit 01d647
        pValue_ = value.release();
Packit 01d647
    } // TiffEntryBase::setValue
Packit 01d647
Packit 01d647
    void TiffDataEntry::setStrips(const Value* pSize,
Packit 01d647
                                  const byte*  pData,
Packit 01d647
                                  uint32_t     sizeData,
Packit 01d647
                                  uint32_t     baseOffset)
Packit 01d647
    {
Packit 01d647
        if (!pValue() || !pSize) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Size or data offset value not set, ignoring them.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        if (pValue()->count() == 0) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Data offset entry value is empty, ignoring it.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        if (pValue()->count() != pSize->count()) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Size and data offset entries have different"
Packit 01d647
                        << " number of components, ignoring them.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        uint32_t size = 0;
Packit 01d647
        for (int i = 0; i < pSize->count(); ++i) {
Packit 01d647
            size += static_cast<uint32_t>(pSize->toLong(i));
Packit 01d647
        }
Packit 01d647
        uint32_t offset = static_cast<uint32_t>(pValue()->toLong(0));
Packit 01d647
        // Todo: Remove limitation of JPEG writer: strips must be contiguous
Packit 01d647
        // Until then we check: last offset + last size - first offset == size?
Packit 01d647
        if (  static_cast<uint32_t>(pValue()->toLong(pValue()->count()-1))
Packit 01d647
            + static_cast<uint32_t>(pSize->toLong(pSize->count()-1))
Packit 01d647
            - offset != size) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Data area is not contiguous, ignoring it.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        if (   offset > sizeData
Packit 01d647
            || size > sizeData
Packit 01d647
            || baseOffset + offset > sizeData - size) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Data area exceeds data buffer, ignoring it.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        pDataArea_ = const_cast<byte*>(pData) + baseOffset + offset;
Packit 01d647
        sizeDataArea_ = size;
Packit 01d647
        const_cast<Value*>(pValue())->setDataArea(pDataArea_, sizeDataArea_);
Packit 01d647
    } // TiffDataEntry::setStrips
Packit 01d647
Packit 01d647
    void TiffImageEntry::setStrips(const Value* pSize,
Packit 01d647
                                   const byte*  pData,
Packit 01d647
                                   uint32_t     sizeData,
Packit 01d647
                                   uint32_t     baseOffset)
Packit 01d647
    {
Packit 01d647
        if (!pValue() || !pSize) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Size or data offset value not set, ignoring them.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        if (pValue()->count() != pSize->count()) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << ": Size and data offset entries have different"
Packit 01d647
                        << " number of components, ignoring them.\n";
Packit 01d647
#endif
Packit 01d647
            return;
Packit 01d647
        }
Packit 01d647
        for (int i = 0; i < pValue()->count(); ++i) {
Packit 01d647
            const uint32_t offset = static_cast<uint32_t>(pValue()->toLong(i));
Packit 01d647
            const byte* pStrip = pData + baseOffset + offset;
Packit 01d647
            const uint32_t size = static_cast<uint32_t>(pSize->toLong(i));
Packit 01d647
Packit 01d647
            if (   offset > sizeData
Packit 01d647
                || size > sizeData
Packit 01d647
                || baseOffset + offset > sizeData - size) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
                EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                            << ", entry 0x" << std::setw(4)
Packit 01d647
                            << std::setfill('0') << std::hex << tag()
Packit 01d647
                            << ": Strip " << std::dec << i
Packit 01d647
                            << " is outside of the data area; ignored.\n";
Packit 01d647
#endif
Packit 01d647
            }
Packit 01d647
            else if (size != 0) {
Packit 01d647
                strips_.push_back(std::make_pair(pStrip, size));
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
    } // TiffImageEntry::setStrips
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::ifdOffset() const
Packit 01d647
    {
Packit 01d647
        if (!pHeader_) return 0;
Packit 01d647
        return pHeader_->ifdOffset();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    ByteOrder TiffIfdMakernote::byteOrder() const
Packit 01d647
    {
Packit 01d647
        assert(imageByteOrder_ != invalidByteOrder);
Packit 01d647
        if (!pHeader_ || pHeader_->byteOrder() == invalidByteOrder) {
Packit 01d647
            return imageByteOrder_;
Packit 01d647
        }
Packit 01d647
        return pHeader_->byteOrder();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::mnOffset() const
Packit 01d647
    {
Packit 01d647
        return mnOffset_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::baseOffset() const
Packit 01d647
    {
Packit 01d647
        if (!pHeader_) return 0;
Packit 01d647
        return pHeader_->baseOffset(mnOffset_);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    bool TiffIfdMakernote::readHeader(const byte* pData,
Packit 01d647
                                      uint32_t    size,
Packit 01d647
                                      ByteOrder   byteOrder)
Packit 01d647
    {
Packit 01d647
        if (!pHeader_) return true;
Packit 01d647
        return pHeader_->read(pData, size, byteOrder);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffIfdMakernote::setByteOrder(ByteOrder byteOrder)
Packit 01d647
    {
Packit 01d647
        if (pHeader_) pHeader_->setByteOrder(byteOrder);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::sizeHeader() const
Packit 01d647
    {
Packit 01d647
        if (!pHeader_) return 0;
Packit 01d647
        return pHeader_->size();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::writeHeader(IoWrapper& ioWrapper, ByteOrder byteOrder) const
Packit 01d647
    {
Packit 01d647
        if (!pHeader_) return 0;
Packit 01d647
        return pHeader_->write(ioWrapper, byteOrder);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t ArrayDef::size(uint16_t tag, IfdId group) const
Packit 01d647
    {
Packit 01d647
        TypeId typeId = toTypeId(tiffType_, tag, group);
Packit 01d647
        return count_ * TypeInfo::typeSize(typeId);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    bool TiffBinaryArray::initialize(IfdId group)
Packit 01d647
    {
Packit 01d647
        if (arrayCfg_ != 0) return true; // Not a complex array or already initialized
Packit 01d647
Packit 01d647
        for (int idx = 0; idx < setSize_; ++idx) {
Packit 01d647
            if (arraySet_[idx].cfg_.group_ == group) {
Packit 01d647
                arrayCfg_ = &arraySet_[idx].cfg_;
Packit 01d647
                arrayDef_ = arraySet_[idx].def_;
Packit 01d647
                defSize_  = arraySet_[idx].defSize_;
Packit 01d647
                return true;
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        return false;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    bool TiffBinaryArray::initialize(TiffComponent* const pRoot)
Packit 01d647
    {
Packit 01d647
        if (cfgSelFct_ == 0) return true; // Not a complex array
Packit 01d647
Packit 01d647
        int idx = cfgSelFct_(tag(), pData(), TiffEntryBase::doSize(), pRoot);
Packit 01d647
        if (idx > -1) {
Packit 01d647
            arrayCfg_ = &arraySet_[idx].cfg_;
Packit 01d647
            arrayDef_ = arraySet_[idx].def_;
Packit 01d647
            defSize_  = arraySet_[idx].defSize_;
Packit 01d647
        }
Packit 01d647
        return idx > -1;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffBinaryArray::iniOrigDataBuf()
Packit 01d647
    {
Packit 01d647
        origData_ = const_cast<byte*>(pData());
Packit 01d647
        origSize_ = TiffEntryBase::doSize();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    bool TiffBinaryArray::updOrigDataBuf(const byte* pData, uint32_t size)
Packit 01d647
    {
Packit 01d647
        assert(pData != 0);
Packit 01d647
Packit 01d647
        if (origSize_ != size) return false;
Packit 01d647
        if (origData_ == pData) return true;
Packit 01d647
        memcpy(origData_, pData, origSize_);
Packit 01d647
        return true;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryArray::addElement(uint32_t idx, const ArrayDef& def)
Packit 01d647
    {
Packit 01d647
        uint16_t tag = static_cast<uint16_t>(idx / cfg()->tagStep());
Packit 01d647
        int32_t sz = EXV_MIN(def.size(tag, cfg()->group_), TiffEntryBase::doSize() - idx);
Packit 01d647
        TiffComponent::AutoPtr tc = TiffCreator::create(tag, cfg()->group_);
Packit 01d647
        TiffBinaryElement* tp = dynamic_cast<TiffBinaryElement*>(tc.get());
Packit 01d647
        // The assertion typically fails if a component is not configured in
Packit 01d647
        // the TIFF structure table (TiffCreator::tiffTreeStruct_)
Packit 01d647
        assert(tp);
Packit 01d647
        tp->setStart(pData() + idx);
Packit 01d647
        tp->setData(const_cast<byte*>(pData() + idx), sz);
Packit 01d647
        tp->setElDef(def);
Packit 01d647
        tp->setElByteOrder(cfg()->byteOrder_);
Packit 01d647
        addChild(tc);
Packit 01d647
        return sz;
Packit 01d647
    } // TiffBinaryArray::addElement
Packit 01d647
Packit 01d647
    TiffComponent* TiffComponent::addPath(uint16_t tag,
Packit 01d647
                                          TiffPath& tiffPath,
Packit 01d647
                                          TiffComponent* const pRoot,
Packit 01d647
                                          TiffComponent::AutoPtr object)
Packit 01d647
    {
Packit 01d647
        return doAddPath(tag, tiffPath, pRoot, object);
Packit 01d647
    } // TiffComponent::addPath
Packit 01d647
Packit 01d647
    TiffComponent* TiffComponent::doAddPath(uint16_t  /*tag*/,
Packit 01d647
                                            TiffPath& /*tiffPath*/,
Packit 01d647
                                            TiffComponent* const /*pRoot*/,
Packit 01d647
                                            TiffComponent::AutoPtr /*object*/)
Packit 01d647
    {
Packit 01d647
        return this;
Packit 01d647
    } // TiffComponent::doAddPath
Packit 01d647
Packit 01d647
    TiffComponent* TiffDirectory::doAddPath(uint16_t tag,
Packit 01d647
                                            TiffPath& tiffPath,
Packit 01d647
                                            TiffComponent* const pRoot,
Packit 01d647
                                            TiffComponent::AutoPtr object)
Packit 01d647
    {
Packit 01d647
        assert(tiffPath.size() > 1);
Packit 01d647
        tiffPath.pop();
Packit 01d647
        const TiffPathItem tpi = tiffPath.top();
Packit 01d647
Packit 01d647
        TiffComponent* tc = 0;
Packit 01d647
        // Try to use an existing component if there is still at least one
Packit 01d647
        // composite tag on the stack or the tag to add is the MakerNote tag.
Packit 01d647
        // This is used to prevent duplicate entries. Sub-IFDs also, but the > 1
Packit 01d647
        // condition takes care of them, see below.
Packit 01d647
        if (   tiffPath.size() > 1
Packit 01d647
            || (tpi.extendedTag() == 0x927c && tpi.group() == exifId)) {
Packit 01d647
            if (tpi.extendedTag() == Tag::next) {
Packit 01d647
                tc = pNext_;
Packit 01d647
            }
Packit 01d647
            else {
Packit 01d647
                for (Components::iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
                    if ((*i)->tag() == tpi.tag() && (*i)->group() == tpi.group()) {
Packit 01d647
                        tc = *i;
Packit 01d647
                        break;
Packit 01d647
                    }
Packit 01d647
                }
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        if (tc == 0) {
Packit 01d647
            TiffComponent::AutoPtr atc;
Packit 01d647
            if (tiffPath.size() == 1 && object.get() != 0) {
Packit 01d647
                atc = object;
Packit 01d647
            }
Packit 01d647
            else {
Packit 01d647
                atc = TiffCreator::create(tpi.extendedTag(), tpi.group());
Packit 01d647
            }
Packit 01d647
            assert(atc.get() != 0);
Packit 01d647
Packit 01d647
            // Prevent dangling sub-IFD tags: Do not add a sub-IFD component without children.
Packit 01d647
            // Todo: How to check before creating the component?
Packit 01d647
            if (tiffPath.size() == 1 && dynamic_cast<TiffSubIfd*>(atc.get()) != 0) return 0;
Packit 01d647
Packit 01d647
            if (tpi.extendedTag() == Tag::next) {
Packit 01d647
                tc = this->addNext(atc);
Packit 01d647
            }
Packit 01d647
            else {
Packit 01d647
                tc = this->addChild(atc);
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        return tc->addPath(tag, tiffPath, pRoot, object);
Packit 01d647
    } // TiffDirectory::doAddPath
Packit 01d647
Packit 01d647
    TiffComponent* TiffSubIfd::doAddPath(uint16_t tag,
Packit 01d647
                                         TiffPath& tiffPath,
Packit 01d647
                                         TiffComponent* const pRoot,
Packit 01d647
                                         TiffComponent::AutoPtr object)
Packit 01d647
    {
Packit 01d647
        assert(!tiffPath.empty());
Packit 01d647
        const TiffPathItem tpi1 = tiffPath.top();
Packit 01d647
        tiffPath.pop();
Packit 01d647
        if (tiffPath.empty()) {
Packit 01d647
            // If the last element in the path is the sub-IFD tag itself we're done.
Packit 01d647
            // But that shouldn't happen - see TiffDirectory::doAddPath
Packit 01d647
            return this;
Packit 01d647
        }
Packit 01d647
        const TiffPathItem tpi2 = tiffPath.top();
Packit 01d647
        tiffPath.push(tpi1);
Packit 01d647
        TiffComponent* tc = 0;
Packit 01d647
        for (Ifds::iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            if ((*i)->group() == tpi2.group()) {
Packit 01d647
                tc = *i;
Packit 01d647
                break;
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        if (tc == 0) {
Packit 01d647
            if (tiffPath.size() == 1 && object.get() != 0) {
Packit 01d647
                tc = addChild(object);
Packit 01d647
            }
Packit 01d647
            else {
Packit 01d647
                TiffComponent::AutoPtr atc(new TiffDirectory(tpi1.tag(), tpi2.group()));
Packit 01d647
                tc = addChild(atc);
Packit 01d647
            }
Packit 01d647
            setCount(static_cast<uint32_t>(ifds_.size()));
Packit 01d647
        }
Packit 01d647
        return tc->addPath(tag, tiffPath, pRoot, object);
Packit 01d647
    } // TiffSubIfd::doAddPath
Packit 01d647
Packit 01d647
    TiffComponent* TiffMnEntry::doAddPath(uint16_t tag,
Packit 01d647
                                          TiffPath& tiffPath,
Packit 01d647
                                          TiffComponent* const pRoot,
Packit 01d647
                                          TiffComponent::AutoPtr object)
Packit 01d647
    {
Packit 01d647
        assert(!tiffPath.empty());
Packit 01d647
        const TiffPathItem tpi1 = tiffPath.top();
Packit 01d647
        tiffPath.pop();
Packit 01d647
        if (tiffPath.empty()) {
Packit 01d647
            // If the last element in the path is the makernote tag itself we're done
Packit 01d647
            return this;
Packit 01d647
        }
Packit 01d647
        const TiffPathItem tpi2 = tiffPath.top();
Packit 01d647
        tiffPath.push(tpi1);
Packit 01d647
        if (mn_ == 0) {
Packit 01d647
            mnGroup_ = tpi2.group();
Packit 01d647
            mn_ = TiffMnCreator::create(tpi1.tag(), tpi1.group(), mnGroup_);
Packit 01d647
            assert(mn_);
Packit 01d647
        }
Packit 01d647
        return mn_->addPath(tag, tiffPath, pRoot, object);
Packit 01d647
    } // TiffMnEntry::doAddPath
Packit 01d647
Packit 01d647
    TiffComponent* TiffIfdMakernote::doAddPath(uint16_t tag,
Packit 01d647
                                               TiffPath& tiffPath,
Packit 01d647
                                               TiffComponent* const pRoot,
Packit 01d647
                                               TiffComponent::AutoPtr object)
Packit 01d647
    {
Packit 01d647
        return ifd_.addPath(tag, tiffPath, pRoot, object);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent* TiffBinaryArray::doAddPath(uint16_t tag,
Packit 01d647
                                              TiffPath& tiffPath,
Packit 01d647
                                              TiffComponent* const pRoot,
Packit 01d647
                                              TiffComponent::AutoPtr object)
Packit 01d647
    {
Packit 01d647
        pRoot_ = pRoot;
Packit 01d647
        if (tiffPath.size() == 1) {
Packit 01d647
            // An unknown complex binary array has no children and acts like a standard TIFF entry
Packit 01d647
            return this;
Packit 01d647
        }
Packit 01d647
        tiffPath.pop();
Packit 01d647
        const TiffPathItem tpi = tiffPath.top();
Packit 01d647
        // Initialize the binary array (if it is a complex array)
Packit 01d647
        initialize(tpi.group());
Packit 01d647
        TiffComponent* tc = 0;
Packit 01d647
        // Todo: Duplicates are not allowed!
Packit 01d647
        // To allow duplicate entries, we only check if the new component already
Packit 01d647
        // exists if there is still at least one composite tag on the stack
Packit 01d647
        if (tiffPath.size() > 1) {
Packit 01d647
            for (Components::iterator i = elements_.begin(); i != elements_.end(); ++i) {
Packit 01d647
                if ((*i)->tag() == tpi.tag() && (*i)->group() == tpi.group()) {
Packit 01d647
                    tc = *i;
Packit 01d647
                    break;
Packit 01d647
                }
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        if (tc == 0) {
Packit 01d647
            TiffComponent::AutoPtr atc;
Packit 01d647
            if (tiffPath.size() == 1 && object.get() != 0) {
Packit 01d647
                atc = object;
Packit 01d647
            }
Packit 01d647
            else {
Packit 01d647
                atc = TiffCreator::create(tpi.extendedTag(), tpi.group());
Packit 01d647
            }
Packit 01d647
            assert(atc.get() != 0);
Packit 01d647
            assert(tpi.extendedTag() != Tag::next);
Packit 01d647
            tc = addChild(atc);
Packit 01d647
            setCount(static_cast<uint32_t>(elements_.size()));
Packit 01d647
        }
Packit 01d647
        return tc->addPath(tag, tiffPath, pRoot, object);
Packit 01d647
    } // TiffBinaryArray::doAddPath
Packit 01d647
Packit 01d647
    TiffComponent* TiffComponent::addChild(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        return doAddChild(tiffComponent);
Packit 01d647
    } // TiffComponent::addChild
Packit 01d647
Packit 01d647
    TiffComponent* TiffComponent::doAddChild(AutoPtr /*tiffComponent*/)
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    } // TiffComponent::doAddChild
Packit 01d647
Packit 01d647
    TiffComponent* TiffDirectory::doAddChild(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        TiffComponent* tc = tiffComponent.release();
Packit 01d647
        components_.push_back(tc);
Packit 01d647
        return tc;
Packit 01d647
    } // TiffDirectory::doAddChild
Packit 01d647
Packit 01d647
    TiffComponent* TiffSubIfd::doAddChild(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        TiffDirectory* d = dynamic_cast<TiffDirectory*>(tiffComponent.release());
Packit 01d647
        assert(d);
Packit 01d647
        ifds_.push_back(d);
Packit 01d647
        return d;
Packit 01d647
    } // TiffSubIfd::doAddChild
Packit 01d647
Packit 01d647
    TiffComponent* TiffMnEntry::doAddChild(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        TiffComponent* tc = 0;
Packit 01d647
        if (mn_) {
Packit 01d647
            tc =  mn_->addChild(tiffComponent);
Packit 01d647
        }
Packit 01d647
        return tc;
Packit 01d647
    } // TiffMnEntry::doAddChild
Packit 01d647
Packit 01d647
    TiffComponent* TiffIfdMakernote::doAddChild(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        return ifd_.addChild(tiffComponent);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent* TiffBinaryArray::doAddChild(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        TiffComponent* tc = tiffComponent.release();
Packit 01d647
        elements_.push_back(tc);
Packit 01d647
        setDecoded(true);
Packit 01d647
        return tc;
Packit 01d647
    } // TiffBinaryArray::doAddChild
Packit 01d647
Packit 01d647
    TiffComponent* TiffComponent::addNext(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        return doAddNext(tiffComponent);
Packit 01d647
    } // TiffComponent::addNext
Packit 01d647
Packit 01d647
    TiffComponent* TiffComponent::doAddNext(AutoPtr /*tiffComponent*/)
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    } // TiffComponent::doAddNext
Packit 01d647
Packit 01d647
    TiffComponent* TiffDirectory::doAddNext(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        TiffComponent* tc = 0;
Packit 01d647
        if (hasNext_) {
Packit 01d647
            tc = tiffComponent.release();
Packit 01d647
            pNext_ = tc;
Packit 01d647
        }
Packit 01d647
        return tc;
Packit 01d647
    } // TiffDirectory::doAddNext
Packit 01d647
Packit 01d647
    TiffComponent* TiffMnEntry::doAddNext(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        TiffComponent* tc = 0;
Packit 01d647
        if (mn_) {
Packit 01d647
            tc = mn_->addNext(tiffComponent);
Packit 01d647
        }
Packit 01d647
        return tc;
Packit 01d647
    } // TiffMnEntry::doAddNext
Packit 01d647
Packit 01d647
    TiffComponent* TiffIfdMakernote::doAddNext(TiffComponent::AutoPtr tiffComponent)
Packit 01d647
    {
Packit 01d647
        return ifd_.addNext(tiffComponent);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffComponent::accept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        if (visitor.go(TiffVisitor::geTraverse)) doAccept(visitor); // one for NVI :)
Packit 01d647
    } // TiffComponent::accept
Packit 01d647
Packit 01d647
    void TiffEntry::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitEntry(this);
Packit 01d647
    } // TiffEntry::doAccept
Packit 01d647
Packit 01d647
    void TiffDataEntry::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitDataEntry(this);
Packit 01d647
    } // TiffDataEntry::doAccept
Packit 01d647
Packit 01d647
    void TiffImageEntry::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitImageEntry(this);
Packit 01d647
    } // TiffImageEntry::doAccept
Packit 01d647
Packit 01d647
    void TiffSizeEntry::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitSizeEntry(this);
Packit 01d647
    } // TiffSizeEntry::doAccept
Packit 01d647
Packit 01d647
    void TiffDirectory::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitDirectory(this);
Packit 01d647
        for (Components::const_iterator i = components_.begin();
Packit 01d647
             visitor.go(TiffVisitor::geTraverse) && i != components_.end(); ++i) {
Packit 01d647
            (*i)->accept(visitor);
Packit 01d647
        }
Packit 01d647
        if (visitor.go(TiffVisitor::geTraverse)) visitor.visitDirectoryNext(this);
Packit 01d647
        if (pNext_) pNext_->accept(visitor);
Packit 01d647
        if (visitor.go(TiffVisitor::geTraverse)) visitor.visitDirectoryEnd(this);
Packit 01d647
    } // TiffDirectory::doAccept
Packit 01d647
Packit 01d647
    void TiffSubIfd::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitSubIfd(this);
Packit 01d647
        for (Ifds::iterator i = ifds_.begin();
Packit 01d647
             visitor.go(TiffVisitor::geTraverse) && i != ifds_.end(); ++i) {
Packit 01d647
            (*i)->accept(visitor);
Packit 01d647
        }
Packit 01d647
    } // TiffSubIfd::doAccept
Packit 01d647
Packit 01d647
    void TiffMnEntry::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitMnEntry(this);
Packit 01d647
        if (mn_) mn_->accept(visitor);
Packit 01d647
        if (!visitor.go(TiffVisitor::geKnownMakernote)) {
Packit 01d647
            delete mn_;
Packit 01d647
            mn_ = 0;
Packit 01d647
        }
Packit 01d647
Packit 01d647
    } // TiffMnEntry::doAccept
Packit 01d647
Packit 01d647
    void TiffIfdMakernote::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        if (visitor.go(TiffVisitor::geTraverse)) visitor.visitIfdMakernote(this);
Packit 01d647
        if (visitor.go(TiffVisitor::geKnownMakernote)) ifd_.accept(visitor);
Packit 01d647
        if (   visitor.go(TiffVisitor::geKnownMakernote)
Packit 01d647
            && visitor.go(TiffVisitor::geTraverse)) visitor.visitIfdMakernoteEnd(this);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    void TiffBinaryArray::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitBinaryArray(this);
Packit 01d647
        for (Components::const_iterator i = elements_.begin();
Packit 01d647
             visitor.go(TiffVisitor::geTraverse) && i != elements_.end(); ++i) {
Packit 01d647
            (*i)->accept(visitor);
Packit 01d647
        }
Packit 01d647
        if (visitor.go(TiffVisitor::geTraverse)) visitor.visitBinaryArrayEnd(this);
Packit 01d647
    } // TiffBinaryArray::doAccept
Packit 01d647
Packit 01d647
    void TiffBinaryElement::doAccept(TiffVisitor& visitor)
Packit 01d647
    {
Packit 01d647
        visitor.visitBinaryElement(this);
Packit 01d647
    } // TiffBinaryElement::doAccept
Packit 01d647
Packit 01d647
    void TiffEntryBase::encode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        doEncode(encoder, datum);
Packit 01d647
    } // TiffComponent::encode
Packit 01d647
Packit 01d647
    void TiffBinaryElement::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeBinaryElement(this, datum);
Packit 01d647
    } // TiffBinaryElement::doEncode
Packit 01d647
Packit 01d647
    void TiffBinaryArray::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeBinaryArray(this, datum);
Packit 01d647
    } // TiffBinaryArray::doEncode
Packit 01d647
Packit 01d647
    void TiffDataEntry::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeDataEntry(this, datum);
Packit 01d647
    } // TiffDataEntry::doEncode
Packit 01d647
Packit 01d647
    void TiffEntry::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeTiffEntry(this, datum);
Packit 01d647
    } // TiffEntry::doEncode
Packit 01d647
Packit 01d647
    void TiffImageEntry::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeImageEntry(this, datum);
Packit 01d647
    } // TiffImageEntry::doEncode
Packit 01d647
Packit 01d647
    void TiffMnEntry::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeMnEntry(this, datum);
Packit 01d647
    } // TiffMnEntry::doEncode
Packit 01d647
Packit 01d647
    void TiffSizeEntry::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeSizeEntry(this, datum);
Packit 01d647
    } // TiffSizeEntry::doEncode
Packit 01d647
Packit 01d647
    void TiffSubIfd::doEncode(TiffEncoder& encoder, const Exifdatum* datum)
Packit 01d647
    {
Packit 01d647
        encoder.encodeSubIfd(this, datum);
Packit 01d647
    } // TiffSubIfd::doEncode
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::count() const
Packit 01d647
    {
Packit 01d647
        return doCount();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doCount() const
Packit 01d647
    {
Packit 01d647
        return static_cast<uint32_t>(components_.size());
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doCount() const
Packit 01d647
    {
Packit 01d647
        return count_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffMnEntry::doCount() const
Packit 01d647
    {
Packit 01d647
        if (!mn_) {
Packit 01d647
            return TiffEntryBase::doCount();
Packit 01d647
        }
Packit 01d647
        // Count of IFD makernote in tag Exif.Photo.MakerNote is the size of the
Packit 01d647
        // Makernote in bytes
Packit 01d647
        assert(tiffType() == ttUndefined || tiffType() == ttUnsignedByte || tiffType() == ttSignedByte);
Packit 01d647
        return mn_->size();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doCount() const
Packit 01d647
    {
Packit 01d647
        return ifd_.count();
Packit 01d647
    } // TiffIfdMakernote::doCount
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryArray::doCount() const
Packit 01d647
    {
Packit 01d647
        if (cfg() == 0 || !decoded()) return TiffEntryBase::doCount();
Packit 01d647
Packit 01d647
        if (elements_.empty()) return 0;
Packit 01d647
Packit 01d647
        TypeId typeId = toTypeId(tiffType(), tag(), group());
Packit 01d647
        long typeSize = TypeInfo::typeSize(typeId);
Packit 01d647
        if (0 == typeSize) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_WARNING << "Directory " << groupName(group())
Packit 01d647
                        << ", entry 0x" << std::setw(4)
Packit 01d647
                        << std::setfill('0') << std::hex << tag()
Packit 01d647
                        << " has unknown Exif (TIFF) type " << std::dec << tiffType()
Packit 01d647
                        << "; setting type size 1.\n";
Packit 01d647
#endif
Packit 01d647
            typeSize = 1;
Packit 01d647
        }
Packit 01d647
Packit 01d647
        return static_cast<uint32_t>(static_cast<double>(size()) / typeSize + 0.5);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryElement::doCount() const
Packit 01d647
    {
Packit 01d647
        return elDef_.count_;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::write(IoWrapper& ioWrapper,
Packit 01d647
                                  ByteOrder byteOrder,
Packit 01d647
                                  int32_t   offset,
Packit 01d647
                                  uint32_t  valueIdx,
Packit 01d647
                                  uint32_t  dataIdx,
Packit 01d647
                                  uint32_t& imageIdx)
Packit 01d647
    {
Packit 01d647
        return doWrite(ioWrapper, byteOrder, offset, valueIdx, dataIdx, imageIdx);
Packit 01d647
    } // TiffComponent::write
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                    ByteOrder byteOrder,
Packit 01d647
                                    int32_t   offset,
Packit 01d647
                                    uint32_t  valueIdx,
Packit 01d647
                                    uint32_t  dataIdx,
Packit 01d647
                                    uint32_t& imageIdx)
Packit 01d647
    {
Packit 01d647
        bool isRootDir = (imageIdx == uint32_t(-1));
Packit 01d647
Packit 01d647
        // Number of components to write
Packit 01d647
        const uint32_t compCount = count();
Packit 01d647
        if (compCount > 0xffff) throw Error(kerTooManyTiffDirectoryEntries, groupName(group()));
Packit 01d647
Packit 01d647
        // Size of next IFD, if any
Packit 01d647
        uint32_t sizeNext = 0;
Packit 01d647
        if (pNext_) sizeNext = pNext_->size();
Packit 01d647
Packit 01d647
        // Nothing to do if there are no entries and the size of the next IFD is 0
Packit 01d647
        if (compCount == 0 && sizeNext == 0) return 0;
Packit 01d647
Packit 01d647
        // Remember the offset of the CR2 RAW IFD
Packit 01d647
        if (group() == ifd3Id) {
Packit 01d647
#ifdef EXIV2_DEBUG_MESSAGES
Packit 01d647
            std::cerr << "Directory " << groupName(group()) << " offset is 0x"
Packit 01d647
                      << std::setw(8) << std::setfill('0') << std::hex << offset << std::dec
Packit 01d647
                      << "\n";
Packit 01d647
#endif
Packit 01d647
            ioWrapper.setTarget(OffsetWriter::cr2RawIfdOffset, offset);
Packit 01d647
        }
Packit 01d647
        // Size of all directory entries, without values and additional data
Packit 01d647
        const uint32_t sizeDir = 2 + 12 * compCount + (hasNext_ ? 4 : 0);
Packit 01d647
Packit 01d647
        // TIFF standard requires IFD entries to be sorted in ascending order by tag.
Packit 01d647
        // Not sorting makernote directories sometimes preserves them better.
Packit 01d647
        if (group() < mnId) {
Packit 01d647
            std::sort(components_.begin(), components_.end(), cmpTagLt);
Packit 01d647
        }
Packit 01d647
        // Size of IFD values and additional data
Packit 01d647
        uint32_t sizeValue = 0;
Packit 01d647
        uint32_t sizeData = 0;
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            uint32_t sv = (*i)->size();
Packit 01d647
            if (sv > 4) {
Packit 01d647
                sv += sv & 1;               // Align value to word boundary
Packit 01d647
                sizeValue += sv;
Packit 01d647
            }
Packit 01d647
            // Also add the size of data, but only if needed
Packit 01d647
            if (isRootDir) {
Packit 01d647
                uint32_t sd = (*i)->sizeData();
Packit 01d647
                sd += sd & 1;               // Align data to word boundary
Packit 01d647
                sizeData += sd;
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
Packit 01d647
        uint32_t idx = 0;                   // Current IFD index / bytes written
Packit 01d647
        valueIdx = sizeDir;                 // Offset to the current IFD value
Packit 01d647
        dataIdx  = sizeDir + sizeValue;     // Offset to the entry's data area
Packit 01d647
        if (isRootDir) {                    // Absolute offset to the image data
Packit 01d647
            imageIdx = offset + dataIdx + sizeData + sizeNext;
Packit 01d647
            imageIdx += imageIdx & 1;       // Align image data to word boundary
Packit 01d647
        }
Packit 01d647
Packit 01d647
        // 1st: Write the IFD, a) Number of directory entries
Packit 01d647
        byte buf[4];
Packit 01d647
        us2Data(buf, static_cast<uint16_t>(compCount), byteOrder);
Packit 01d647
        ioWrapper.write(buf, 2);
Packit 01d647
        idx += 2;
Packit 01d647
        // b) Directory entries - may contain pointers to the value or data
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            idx += writeDirEntry(ioWrapper, byteOrder, offset, *i, valueIdx, dataIdx, imageIdx);
Packit 01d647
            uint32_t sv = (*i)->size();
Packit 01d647
            if (sv > 4) {
Packit 01d647
                sv += sv & 1;               // Align value to word boundary
Packit 01d647
                valueIdx += sv;
Packit 01d647
            }
Packit 01d647
            uint32_t sd = (*i)->sizeData();
Packit 01d647
            sd += sd & 1;                   // Align data to word boundary
Packit 01d647
            dataIdx += sd;
Packit 01d647
        }
Packit 01d647
        // c) Pointer to the next IFD
Packit 01d647
        if (hasNext_) {
Packit 01d647
            memset(buf, 0x0, 4);
Packit 01d647
            if (pNext_ && sizeNext) {
Packit 01d647
                l2Data(buf, offset + dataIdx, byteOrder);
Packit 01d647
            }
Packit 01d647
            ioWrapper.write(buf, 4);
Packit 01d647
            idx += 4;
Packit 01d647
        }
Packit 01d647
        assert(idx == sizeDir);
Packit 01d647
Packit 01d647
        // 2nd: Write IFD values - may contain pointers to additional data
Packit 01d647
        valueIdx = sizeDir;
Packit 01d647
        dataIdx = sizeDir + sizeValue;
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            uint32_t sv = (*i)->size();
Packit 01d647
            if (sv > 4) {
Packit 01d647
                uint32_t d = (*i)->write(ioWrapper, byteOrder, offset, valueIdx, dataIdx, imageIdx);
Packit 01d647
                enforce(sv == d, kerImageWriteFailed);
Packit 01d647
                if ((sv & 1) == 1) {
Packit 01d647
                    ioWrapper.putb(0x0);    // Align value to word boundary
Packit 01d647
                    sv += 1;
Packit 01d647
                }
Packit 01d647
                idx += sv;
Packit 01d647
                valueIdx += sv;
Packit 01d647
            }
Packit 01d647
            uint32_t sd = (*i)->sizeData();
Packit 01d647
            sd += sd & 1;                   // Align data to word boundary
Packit 01d647
            dataIdx += sd;
Packit 01d647
        }
Packit 01d647
        assert(idx == sizeDir + sizeValue);
Packit 01d647
Packit 01d647
        // 3rd: Write data - may contain offsets too (eg sub-IFD)
Packit 01d647
        dataIdx = sizeDir + sizeValue;
Packit 01d647
        idx += writeData(ioWrapper, byteOrder, offset, dataIdx, imageIdx);
Packit 01d647
Packit 01d647
        // 4th: Write next-IFD
Packit 01d647
        if (pNext_ && sizeNext) {
Packit 01d647
            idx += pNext_->write(ioWrapper, byteOrder, offset + idx, uint32_t(-1), uint32_t(-1), imageIdx);
Packit 01d647
        }
Packit 01d647
Packit 01d647
        // 5th, at the root directory level only: write image data
Packit 01d647
        if (isRootDir) {
Packit 01d647
            idx += writeImage(ioWrapper, byteOrder);
Packit 01d647
        }
Packit 01d647
Packit 01d647
        return idx;
Packit 01d647
    } // TiffDirectory::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::writeDirEntry(IoWrapper&     ioWrapper,
Packit 01d647
                                          ByteOrder      byteOrder,
Packit 01d647
                                          int32_t        offset,
Packit 01d647
                                          TiffComponent* pTiffComponent,
Packit 01d647
                                          uint32_t       valueIdx,
Packit 01d647
                                          uint32_t       dataIdx,
Packit 01d647
                                          uint32_t&      imageIdx) const
Packit 01d647
    {
Packit 01d647
        assert(pTiffComponent);
Packit 01d647
        TiffEntryBase* pDirEntry = dynamic_cast<TiffEntryBase*>(pTiffComponent);
Packit 01d647
        assert(pDirEntry);
Packit 01d647
        byte buf[8];
Packit 01d647
        us2Data(buf,     pDirEntry->tag(),      byteOrder);
Packit 01d647
        us2Data(buf + 2, pDirEntry->tiffType(), byteOrder);
Packit 01d647
        ul2Data(buf + 4, pDirEntry->count(),    byteOrder);
Packit 01d647
        ioWrapper.write(buf, 8);
Packit 01d647
        if (pDirEntry->size() > 4) {
Packit 01d647
            pDirEntry->setOffset(offset + static_cast<int32_t>(valueIdx));
Packit 01d647
            l2Data(buf, pDirEntry->offset(), byteOrder);
Packit 01d647
            ioWrapper.write(buf, 4);
Packit 01d647
        }
Packit 01d647
        else {
Packit 01d647
            const uint32_t len = pDirEntry->write(ioWrapper,
Packit 01d647
                                                  byteOrder,
Packit 01d647
                                                  offset,
Packit 01d647
                                                  valueIdx,
Packit 01d647
                                                  dataIdx,
Packit 01d647
                                                  imageIdx);
Packit 01d647
            assert(len <= 4);
Packit 01d647
            if (len < 4) {
Packit 01d647
                memset(buf, 0x0, 4);
Packit 01d647
                ioWrapper.write(buf, 4 - len);
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        return 12;
Packit 01d647
    } // TiffDirectory::writeDirEntry
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                    ByteOrder byteOrder,
Packit 01d647
                                    int32_t   /*offset*/,
Packit 01d647
                                    uint32_t  /*valueIdx*/,
Packit 01d647
                                    uint32_t  /*dataIdx*/,
Packit 01d647
                                    uint32_t& /*imageIdx*/)
Packit 01d647
    {
Packit 01d647
        if (!pValue_) return 0;
Packit 01d647
Packit 01d647
        DataBuf buf(pValue_->size());
Packit 01d647
        pValue_->copy(buf.pData_, byteOrder);
Packit 01d647
        ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        return buf.size_;
Packit 01d647
    } // TiffEntryBase::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::writeOffset(byte*     buf,
Packit 01d647
                                        int32_t   offset,
Packit 01d647
                                        TiffType  tiffType,
Packit 01d647
                                        ByteOrder byteOrder)
Packit 01d647
    {
Packit 01d647
        uint32_t rc = 0;
Packit 01d647
        switch(tiffType) {
Packit 01d647
        case ttUnsignedShort:
Packit 01d647
        case ttSignedShort:
Packit 01d647
            if (static_cast<uint32_t>(offset) > 0xffff) throw Error(kerOffsetOutOfRange);
Packit 01d647
            rc = s2Data(buf, static_cast<int16_t>(offset), byteOrder);
Packit 01d647
            break;
Packit 01d647
        case ttUnsignedLong:
Packit 01d647
        case ttSignedLong:
Packit 01d647
            rc = l2Data(buf, static_cast<int32_t>(offset), byteOrder);
Packit 01d647
            break;
Packit 01d647
        default:
Packit 01d647
            throw Error(kerUnsupportedDataAreaOffsetType);
Packit 01d647
            break;
Packit 01d647
        }
Packit 01d647
        return rc;
Packit 01d647
    } // TiffEntryBase::writeOffset
Packit 01d647
Packit 01d647
    uint32_t TiffDataEntry::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                    ByteOrder byteOrder,
Packit 01d647
                                    int32_t   offset,
Packit 01d647
                                    uint32_t  /*valueIdx*/,
Packit 01d647
                                    uint32_t  dataIdx,
Packit 01d647
                                    uint32_t& /*imageIdx*/)
Packit 01d647
    {
Packit 01d647
        if (!pValue() || pValue()->count() == 0) return 0;
Packit 01d647
Packit 01d647
        DataBuf buf(pValue()->size());
Packit 01d647
        uint32_t idx = 0;
Packit 01d647
        const long prevOffset = pValue()->toLong(0);
Packit 01d647
        for (uint32_t i = 0; i < count(); ++i) {
Packit 01d647
            const long newDataIdx =   pValue()->toLong(i) - prevOffset
Packit 01d647
                                    + static_cast<long>(dataIdx);
Packit 01d647
            idx += writeOffset(buf.pData_ + idx,
Packit 01d647
                               offset + newDataIdx,
Packit 01d647
                               tiffType(),
Packit 01d647
                               byteOrder);
Packit 01d647
        }
Packit 01d647
        ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        return buf.size_;
Packit 01d647
    } // TiffDataEntry::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffImageEntry::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                     ByteOrder byteOrder,
Packit 01d647
                                     int32_t   offset,
Packit 01d647
                                     uint32_t  /*valueIdx*/,
Packit 01d647
                                     uint32_t  dataIdx,
Packit 01d647
                                     uint32_t& imageIdx)
Packit 01d647
    {
Packit 01d647
        uint32_t o2 = imageIdx;
Packit 01d647
        // For makernotes, write TIFF image data to the data area
Packit 01d647
        if (group() > mnId) o2 = offset + dataIdx;
Packit 01d647
#ifdef EXIV2_DEBUG_MESSAGES
Packit 01d647
        std::cerr << "TiffImageEntry, Directory " << groupName(group())
Packit 01d647
                  << ", entry 0x" << std::setw(4)
Packit 01d647
                  << std::setfill('0') << std::hex << tag() << std::dec
Packit 01d647
                  << ": Writing offset " << o2 << "\n";
Packit 01d647
#endif
Packit 01d647
        DataBuf buf(static_cast<long>(strips_.size()) * 4);
Packit 01d647
        memset(buf.pData_, 0x0, buf.size_);
Packit 01d647
        uint32_t idx = 0;
Packit 01d647
        for (Strips::const_iterator i = strips_.begin(); i != strips_.end(); ++i) {
Packit 01d647
            idx += writeOffset(buf.pData_ + idx, o2, tiffType(), byteOrder);
Packit 01d647
            o2 += i->second;
Packit 01d647
            o2 += i->second & 1;                // Align strip data to word boundary
Packit 01d647
            if (!(group() > mnId)) {            // Todo: FIX THIS!! SHOULDN'T USE >
Packit 01d647
                imageIdx += i->second;
Packit 01d647
                imageIdx += i->second & 1;      // Align strip data to word boundary
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        return buf.size_;
Packit 01d647
    } // TiffImageEntry::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffSubIfd::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                 ByteOrder byteOrder,
Packit 01d647
                                 int32_t   offset,
Packit 01d647
                                 uint32_t  /*valueIdx*/,
Packit 01d647
                                 uint32_t  dataIdx,
Packit 01d647
                                 uint32_t& /*imageIdx*/)
Packit 01d647
    {
Packit 01d647
        DataBuf buf(static_cast<long>(ifds_.size()) * 4);
Packit 01d647
        uint32_t idx = 0;
Packit 01d647
        // Sort IFDs by group, needed if image data tags were copied first
Packit 01d647
        std::sort(ifds_.begin(), ifds_.end(), cmpGroupLt);
Packit 01d647
        for (Ifds::const_iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            idx += writeOffset(buf.pData_ + idx, offset + dataIdx, tiffType(), byteOrder);
Packit 01d647
            dataIdx += (*i)->size();
Packit 01d647
        }
Packit 01d647
        ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        return buf.size_;
Packit 01d647
    } // TiffSubIfd::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffMnEntry::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                  ByteOrder byteOrder,
Packit 01d647
                                  int32_t   offset,
Packit 01d647
                                  uint32_t  valueIdx,
Packit 01d647
                                  uint32_t  dataIdx,
Packit 01d647
                                  uint32_t& imageIdx)
Packit 01d647
    {
Packit 01d647
        if (!mn_) {
Packit 01d647
            return TiffEntryBase::doWrite(ioWrapper, byteOrder, offset, valueIdx, dataIdx, imageIdx);
Packit 01d647
        }
Packit 01d647
        return mn_->write(ioWrapper, byteOrder, offset + valueIdx, uint32_t(-1), uint32_t(-1), imageIdx);
Packit 01d647
    } // TiffMnEntry::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                       ByteOrder byteOrder,
Packit 01d647
                                       int32_t   offset,
Packit 01d647
                                       uint32_t  /*valueIdx*/,
Packit 01d647
                                       uint32_t  /*dataIdx*/,
Packit 01d647
                                       uint32_t& imageIdx)
Packit 01d647
    {
Packit 01d647
        mnOffset_ = offset;
Packit 01d647
        setImageByteOrder(byteOrder);
Packit 01d647
        uint32_t len = writeHeader(ioWrapper, this->byteOrder());
Packit 01d647
        len += ifd_.write(ioWrapper, this->byteOrder(),
Packit 01d647
                          offset - baseOffset() + len,
Packit 01d647
                          uint32_t(-1), uint32_t(-1),
Packit 01d647
                          imageIdx);
Packit 01d647
        return len;
Packit 01d647
    } // TiffIfdMakernote::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryArray::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                      ByteOrder byteOrder,
Packit 01d647
                                      int32_t   offset,
Packit 01d647
                                      uint32_t  valueIdx,
Packit 01d647
                                      uint32_t  dataIdx,
Packit 01d647
                                      uint32_t& imageIdx)
Packit 01d647
    {
Packit 01d647
        if (cfg() == 0 || !decoded()) return TiffEntryBase::doWrite(ioWrapper,
Packit 01d647
                                                                    byteOrder,
Packit 01d647
                                                                    offset,
Packit 01d647
                                                                    valueIdx,
Packit 01d647
                                                                    dataIdx,
Packit 01d647
                                                                    imageIdx);
Packit 01d647
        if (cfg()->byteOrder_ != invalidByteOrder) byteOrder = cfg()->byteOrder_;
Packit 01d647
        // Tags must be sorted in ascending order
Packit 01d647
        std::sort(elements_.begin(), elements_.end(), cmpTagLt);
Packit 01d647
        uint32_t idx = 0;
Packit 01d647
        MemIo mio;
Packit 01d647
        IoWrapper mioWrapper(mio, 0, 0, 0);
Packit 01d647
        // Some array entries need to have the size in the first element
Packit 01d647
        if (cfg()->hasSize_) {
Packit 01d647
            byte buf[4];
Packit 01d647
            long elSize = TypeInfo::typeSize(toTypeId(cfg()->elTiffType_, 0, cfg()->group_));
Packit 01d647
            switch (elSize) {
Packit 01d647
            case 2:
Packit 01d647
                idx += us2Data(buf, size(), byteOrder);
Packit 01d647
                break;
Packit 01d647
            case 4:
Packit 01d647
                idx += ul2Data(buf, size(), byteOrder);
Packit 01d647
                break;
Packit 01d647
            default:
Packit 01d647
                assert(false);
Packit 01d647
            }
Packit 01d647
            mioWrapper.write(buf, elSize);
Packit 01d647
        }
Packit 01d647
        // write all tags of the array (Todo: assumes that there are no duplicates, need check)
Packit 01d647
        for (Components::const_iterator i = elements_.begin(); i != elements_.end(); ++i) {
Packit 01d647
            // Skip the manufactured tag, if it exists
Packit 01d647
            if (cfg()->hasSize_ && (*i)->tag() == 0) continue;
Packit 01d647
            uint32_t newIdx = (*i)->tag() * cfg()->tagStep();
Packit 01d647
            idx += fillGap(mioWrapper, idx, newIdx);
Packit 01d647
            idx += (*i)->write(mioWrapper, byteOrder, offset + newIdx, valueIdx, dataIdx, imageIdx);
Packit 01d647
        }
Packit 01d647
        if (cfg()->hasFillers_ && def()) {
Packit 01d647
            const ArrayDef* lastDef = def() + defSize() - 1;
Packit 01d647
            uint16_t lastTag = static_cast<uint16_t>(lastDef->idx_ / cfg()->tagStep());
Packit 01d647
            idx += fillGap(mioWrapper, idx, lastDef->idx_ + lastDef->size(lastTag, cfg()->group_));
Packit 01d647
        }
Packit 01d647
        DataBuf buf;
Packit 01d647
        if (cfg()->cryptFct_) {
Packit 01d647
            buf = cfg()->cryptFct_(tag(), mio.mmap(), static_cast<uint32_t>(mio.size()), pRoot_);
Packit 01d647
        }
Packit 01d647
        if (buf.size_ > 0) {
Packit 01d647
            ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        }
Packit 01d647
        else {
Packit 01d647
            ioWrapper.write(mio.mmap(), static_cast<uint32_t>(mio.size()));
Packit 01d647
        }
Packit 01d647
Packit 01d647
        return idx;
Packit 01d647
    } // TiffBinaryArray::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryElement::doWrite(IoWrapper& ioWrapper,
Packit 01d647
                                        ByteOrder byteOrder,
Packit 01d647
                                        int32_t   /*offset*/,
Packit 01d647
                                        uint32_t  /*valueIdx*/,
Packit 01d647
                                        uint32_t  /*dataIdx*/,
Packit 01d647
                                        uint32_t& /*imageIdx*/)
Packit 01d647
    {
Packit 01d647
        Value const* pv = pValue();
Packit 01d647
        if (!pv || pv->count() == 0) return 0;
Packit 01d647
        DataBuf buf(pv->size());
Packit 01d647
        pv->copy(buf.pData_, byteOrder);
Packit 01d647
        ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        return buf.size_;
Packit 01d647
    } // TiffBinaryElement::doWrite
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::writeData(IoWrapper& ioWrapper,
Packit 01d647
                                      ByteOrder byteOrder,
Packit 01d647
                                      int32_t   offset,
Packit 01d647
                                      uint32_t  dataIdx,
Packit 01d647
                                      uint32_t& imageIdx) const
Packit 01d647
    {
Packit 01d647
        return doWriteData(ioWrapper, byteOrder, offset, dataIdx, imageIdx);
Packit 01d647
    } // TiffComponent::writeData
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doWriteData(IoWrapper& ioWrapper,
Packit 01d647
                                        ByteOrder byteOrder,
Packit 01d647
                                        int32_t   offset,
Packit 01d647
                                        uint32_t  dataIdx,
Packit 01d647
                                        uint32_t& imageIdx) const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            len += (*i)->writeData(ioWrapper, byteOrder, offset, dataIdx + len, imageIdx);
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffDirectory::doWriteData
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doWriteData(IoWrapper&/*ioWrapper*/,
Packit 01d647
                                        ByteOrder /*byteOrder*/,
Packit 01d647
                                        int32_t   /*offset*/,
Packit 01d647
                                        uint32_t  /*dataIdx*/,
Packit 01d647
                                        uint32_t& /*imageIdx*/) const
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    } // TiffEntryBase::doWriteData
Packit 01d647
Packit 01d647
    uint32_t TiffImageEntry::doWriteData(IoWrapper& ioWrapper,
Packit 01d647
                                         ByteOrder byteOrder,
Packit 01d647
                                         int32_t   /*offset*/,
Packit 01d647
                                         uint32_t  /*dataIdx*/,
Packit 01d647
                                         uint32_t& /*imageIdx*/) const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        // For makernotes, write TIFF image data to the data area
Packit 01d647
        if (group() > mnId) { // Todo: FIX THIS HACK!!!
Packit 01d647
            len = writeImage(ioWrapper, byteOrder);
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffImageEntry::doWriteData
Packit 01d647
Packit 01d647
    uint32_t TiffDataEntry::doWriteData(IoWrapper& ioWrapper,
Packit 01d647
                                        ByteOrder /*byteOrder*/,
Packit 01d647
                                        int32_t   /*offset*/,
Packit 01d647
                                        uint32_t  /*dataIdx*/,
Packit 01d647
                                        uint32_t& /*imageIdx*/) const
Packit 01d647
    {
Packit 01d647
        if (!pValue()) return 0;
Packit 01d647
Packit 01d647
        DataBuf buf = pValue()->dataArea();
Packit 01d647
        ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
        // Align data to word boundary
Packit 01d647
        uint32_t align = (buf.size_ & 1);
Packit 01d647
        if (align) ioWrapper.putb(0x0);
Packit 01d647
Packit 01d647
        return buf.size_ + align;
Packit 01d647
    } // TiffDataEntry::doWriteData
Packit 01d647
Packit 01d647
    uint32_t TiffSubIfd::doWriteData(IoWrapper& ioWrapper,
Packit 01d647
                                     ByteOrder byteOrder,
Packit 01d647
                                     int32_t   offset,
Packit 01d647
                                     uint32_t  dataIdx,
Packit 01d647
                                     uint32_t& imageIdx) const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        for (Ifds::const_iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            len  += (*i)->write(ioWrapper, byteOrder, offset + dataIdx + len, uint32_t(-1), uint32_t(-1), imageIdx);
Packit 01d647
        }
Packit 01d647
        // Align data to word boundary
Packit 01d647
        uint32_t align = (len & 1);
Packit 01d647
        if (align) ioWrapper.putb(0x0);
Packit 01d647
Packit 01d647
        return len + align;
Packit 01d647
    } // TiffSubIfd::doWriteData
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doWriteData(IoWrapper&/*ioWrapper*/,
Packit 01d647
                                           ByteOrder /*byteOrder*/,
Packit 01d647
                                           int32_t   /*offset*/,
Packit 01d647
                                           uint32_t  /*dataIdx*/,
Packit 01d647
                                           uint32_t& /*imageIdx*/) const
Packit 01d647
    {
Packit 01d647
        assert(false);
Packit 01d647
        return 0;
Packit 01d647
    } // TiffIfdMakernote::doWriteData
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::writeImage(IoWrapper& ioWrapper,
Packit 01d647
                                       ByteOrder byteOrder) const
Packit 01d647
    {
Packit 01d647
        return doWriteImage(ioWrapper, byteOrder);
Packit 01d647
    } // TiffComponent::writeImage
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doWriteImage(IoWrapper& ioWrapper,
Packit 01d647
                                         ByteOrder byteOrder) const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        TiffComponent* pSubIfd = 0;
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            if ((*i)->tag() == 0x014a) {
Packit 01d647
                // Hack: delay writing of sub-IFD image data to get the order correct
Packit 01d647
                assert(pSubIfd == 0);
Packit 01d647
                pSubIfd = *i;
Packit 01d647
                continue;
Packit 01d647
            }
Packit 01d647
            len += (*i)->writeImage(ioWrapper, byteOrder);
Packit 01d647
        }
Packit 01d647
        if (pSubIfd) {
Packit 01d647
            len += pSubIfd->writeImage(ioWrapper, byteOrder);
Packit 01d647
        }
Packit 01d647
        if (pNext_) {
Packit 01d647
            len += pNext_->writeImage(ioWrapper, byteOrder);
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffDirectory::doWriteImage
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doWriteImage(IoWrapper&/*ioWrapper*/,
Packit 01d647
                                         ByteOrder /*byteOrder*/) const
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    } // TiffEntryBase::doWriteImage
Packit 01d647
Packit 01d647
    uint32_t TiffSubIfd::doWriteImage(IoWrapper& ioWrapper,
Packit 01d647
                                      ByteOrder byteOrder) const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        for (Ifds::const_iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            len  += (*i)->writeImage(ioWrapper, byteOrder);
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffSubIfd::doWriteImage
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doWriteImage(IoWrapper& ioWrapper,
Packit 01d647
                                            ByteOrder byteOrder) const
Packit 01d647
    {
Packit 01d647
        if (this->byteOrder() != invalidByteOrder) {
Packit 01d647
            byteOrder = this->byteOrder();
Packit 01d647
        }
Packit 01d647
        uint32_t len = ifd_.writeImage(ioWrapper, byteOrder);
Packit 01d647
        return len;
Packit 01d647
    } // TiffIfdMakernote::doWriteImage
Packit 01d647
Packit 01d647
    uint32_t TiffImageEntry::doWriteImage(IoWrapper& ioWrapper,
Packit 01d647
                                          ByteOrder  /*byteOrder*/) const
Packit 01d647
    {
Packit 01d647
        if ( !pValue() ) throw Error(kerImageWriteFailed); // #1296
Packit 01d647
Packit 01d647
        uint32_t len = pValue()->sizeDataArea();
Packit 01d647
        if (len > 0) {
Packit 01d647
#ifdef EXIV2_DEBUG_MESSAGES
Packit 01d647
            std::cerr << "TiffImageEntry, Directory " << groupName(group())
Packit 01d647
                      << ", entry 0x" << std::setw(4)
Packit 01d647
                      << std::setfill('0') << std::hex << tag() << std::dec
Packit 01d647
                      << ": Writing data area, size = " << len;
Packit 01d647
#endif
Packit 01d647
            DataBuf buf = pValue()->dataArea();
Packit 01d647
            ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
            uint32_t align = len & 1;       // Align image data to word boundary
Packit 01d647
            if (align) ioWrapper.putb(0x0);
Packit 01d647
            len += align;
Packit 01d647
        }
Packit 01d647
        else {
Packit 01d647
#ifdef EXIV2_DEBUG_MESSAGES
Packit 01d647
            std::cerr << "TiffImageEntry, Directory " << groupName(group())
Packit 01d647
                      << ", entry 0x" << std::setw(4)
Packit 01d647
                      << std::setfill('0') << std::hex << tag() << std::dec
Packit 01d647
                      << ": Writing " << strips_.size() << " strips";
Packit 01d647
#endif
Packit 01d647
            len = 0;
Packit 01d647
            for (Strips::const_iterator i = strips_.begin(); i != strips_.end(); ++i) {
Packit 01d647
                ioWrapper.write(i->first, i->second);
Packit 01d647
                len += i->second;
Packit 01d647
                uint32_t align = i->second & 1; // Align strip data to word boundary
Packit 01d647
                if (align) ioWrapper.putb(0x0);
Packit 01d647
                len += align;
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
#ifdef EXIV2_DEBUG_MESSAGES
Packit 01d647
        std::cerr << ", len = " << len << " bytes\n";
Packit 01d647
#endif
Packit 01d647
        return len;
Packit 01d647
    } // TiffImageEntry::doWriteImage
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::size() const
Packit 01d647
    {
Packit 01d647
        return doSize();
Packit 01d647
    } // TiffComponent::size
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doSize() const
Packit 01d647
    {
Packit 01d647
        uint32_t compCount = count();
Packit 01d647
        // Size of the directory, without values and additional data
Packit 01d647
        uint32_t len = 2 + 12 * compCount + (hasNext_ ? 4 : 0);
Packit 01d647
        // Size of IFD values and data
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            uint32_t sv = (*i)->size();
Packit 01d647
            if (sv > 4) {
Packit 01d647
                sv += sv & 1;               // Align value to word boundary
Packit 01d647
                len += sv;
Packit 01d647
            }
Packit 01d647
            uint32_t sd = (*i)->sizeData();
Packit 01d647
            sd += sd & 1;                   // Align data to word boundary
Packit 01d647
            len += sd;
Packit 01d647
        }
Packit 01d647
        // Size of next-IFD, if any
Packit 01d647
        uint32_t sizeNext = 0;
Packit 01d647
        if (pNext_) {
Packit 01d647
            sizeNext = pNext_->size();
Packit 01d647
            len += sizeNext;
Packit 01d647
        }
Packit 01d647
        // Reset size of IFD if it has no entries and no or empty next IFD.
Packit 01d647
        if (compCount == 0 && sizeNext == 0) len = 0;
Packit 01d647
        return len;
Packit 01d647
    } // TiffDirectory::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doSize() const
Packit 01d647
    {
Packit 01d647
        return size_;
Packit 01d647
    } // TiffEntryBase::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffImageEntry::doSize() const
Packit 01d647
    {
Packit 01d647
        return static_cast<uint32_t>(strips_.size()) * 4;
Packit 01d647
    } // TiffImageEntry::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffSubIfd::doSize() const
Packit 01d647
    {
Packit 01d647
        return static_cast<uint32_t>(ifds_.size()) * 4;
Packit 01d647
    } // TiffSubIfd::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffMnEntry::doSize() const
Packit 01d647
    {
Packit 01d647
        if (!mn_) {
Packit 01d647
            return TiffEntryBase::doSize();
Packit 01d647
        }
Packit 01d647
        return mn_->size();
Packit 01d647
    } // TiffMnEntry::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doSize() const
Packit 01d647
    {
Packit 01d647
        return sizeHeader() + ifd_.size();
Packit 01d647
    } // TiffIfdMakernote::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryArray::doSize() const
Packit 01d647
    {
Packit 01d647
        if (cfg() == 0 || !decoded()) return TiffEntryBase::doSize();
Packit 01d647
Packit 01d647
        if (elements_.empty()) return 0;
Packit 01d647
Packit 01d647
        // Remaining assumptions:
Packit 01d647
        // - array elements don't "overlap"
Packit 01d647
        // - no duplicate tags in the array
Packit 01d647
        uint32_t idx = 0;
Packit 01d647
        uint32_t sz = cfg()->tagStep();
Packit 01d647
        for (Components::const_iterator i = elements_.begin(); i != elements_.end(); ++i) {
Packit 01d647
            if ((*i)->tag() > idx) {
Packit 01d647
                idx = (*i)->tag();
Packit 01d647
                sz = (*i)->size();
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        idx = idx * cfg()->tagStep() + sz;
Packit 01d647
Packit 01d647
        if (cfg()->hasFillers_ && def()) {
Packit 01d647
            const ArrayDef* lastDef = def() + defSize() - 1;
Packit 01d647
            uint16_t lastTag = static_cast<uint16_t>(lastDef->idx_ / cfg()->tagStep());
Packit 01d647
            idx = EXV_MAX(idx, lastDef->idx_ + lastDef->size(lastTag, cfg()->group_));
Packit 01d647
        }
Packit 01d647
        return idx;
Packit 01d647
Packit 01d647
    } // TiffBinaryArray::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffBinaryElement::doSize() const
Packit 01d647
    {
Packit 01d647
        if (!pValue()) return 0;
Packit 01d647
        return pValue()->size();
Packit 01d647
    } // TiffBinaryElement::doSize
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::sizeData() const
Packit 01d647
    {
Packit 01d647
        return doSizeData();
Packit 01d647
    } // TiffComponent::sizeData
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doSizeData() const
Packit 01d647
    {
Packit 01d647
        assert(false);
Packit 01d647
        return 0;
Packit 01d647
    } // TiffDirectory::doSizeData
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doSizeData() const
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    } // TiffEntryBase::doSizeData
Packit 01d647
Packit 01d647
    uint32_t TiffImageEntry::doSizeData() const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        // For makernotes, TIFF image data is written to the data area
Packit 01d647
        if (group() > mnId) { // Todo: Fix this hack!!
Packit 01d647
            len = sizeImage();
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffImageEntry::doSizeData
Packit 01d647
Packit 01d647
    uint32_t TiffDataEntry::doSizeData() const
Packit 01d647
    {
Packit 01d647
        if (!pValue()) return 0;
Packit 01d647
        return pValue()->sizeDataArea();
Packit 01d647
    } // TiffDataEntry::doSizeData
Packit 01d647
Packit 01d647
    uint32_t TiffSubIfd::doSizeData() const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        for (Ifds::const_iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            len += (*i)->size();
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffSubIfd::doSizeData
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doSizeData() const
Packit 01d647
    {
Packit 01d647
        assert(false);
Packit 01d647
        return 0;
Packit 01d647
    } // TiffIfdMakernote::doSizeData
Packit 01d647
Packit 01d647
    uint32_t TiffComponent::sizeImage() const
Packit 01d647
    {
Packit 01d647
        return doSizeImage();
Packit 01d647
    } // TiffComponent::sizeImage
Packit 01d647
Packit 01d647
    uint32_t TiffDirectory::doSizeImage() const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        for (Components::const_iterator i = components_.begin(); i != components_.end(); ++i) {
Packit 01d647
            len += (*i)->sizeImage();
Packit 01d647
        }
Packit 01d647
        if (pNext_) {
Packit 01d647
            len += pNext_->sizeImage();
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffDirectory::doSizeImage
Packit 01d647
Packit 01d647
    uint32_t TiffSubIfd::doSizeImage() const
Packit 01d647
    {
Packit 01d647
        uint32_t len = 0;
Packit 01d647
        for (Ifds::const_iterator i = ifds_.begin(); i != ifds_.end(); ++i) {
Packit 01d647
            len += (*i)->sizeImage();
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffSubIfd::doSizeImage
Packit 01d647
Packit 01d647
    uint32_t TiffIfdMakernote::doSizeImage() const
Packit 01d647
    {
Packit 01d647
        return ifd_.sizeImage();
Packit 01d647
    } // TiffIfdMakernote::doSizeImage
Packit 01d647
Packit 01d647
    uint32_t TiffEntryBase::doSizeImage() const
Packit 01d647
    {
Packit 01d647
        return 0;
Packit 01d647
    } // TiffEntryBase::doSizeImage
Packit 01d647
Packit 01d647
    uint32_t TiffImageEntry::doSizeImage() const
Packit 01d647
    {
Packit 01d647
        if (!pValue()) return 0;
Packit 01d647
        uint32_t len = pValue()->sizeDataArea();
Packit 01d647
        if (len == 0) {
Packit 01d647
            for (Strips::const_iterator i = strips_.begin(); i != strips_.end(); ++i) {
Packit 01d647
                len += i->second;
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        return len;
Packit 01d647
    } // TiffImageEntry::doSizeImage
Packit 01d647
Packit Service fb147c
    static const TagInfo* findTagInfo(uint16_t tag,IfdId group)
Packit Service fb147c
    {
Packit Service fb147c
        const TagInfo* result = NULL ;
Packit Service fb147c
        const TagInfo* tags   = group == exifId ? Internal::exifTagList()
Packit Service fb147c
                              : group == gpsId  ? Internal::gpsTagList()
Packit Service fb147c
                              : NULL
Packit Service fb147c
                              ;
Packit Service fb147c
        if ( tags ) {
Packit Service fb147c
            for ( size_t idx = 0; result==NULL && tags[idx].tag_ != 0xffff; ++idx) {
Packit Service fb147c
                if ( tags[idx].tag_ == tag ) {
Packit Service fb147c
                      result = tags+idx;
Packit Service fb147c
                }
Packit Service fb147c
            }
Packit Service fb147c
        }
Packit Service fb147c
        return result;
Packit Service fb147c
    }
Packit Service fb147c
Packit 01d647
    // *************************************************************************
Packit 01d647
    // free functions
Packit 01d647
    TypeId toTypeId(TiffType tiffType, uint16_t tag, IfdId group)
Packit 01d647
    {
Packit 01d647
        TypeId ti = TypeId(tiffType);
Packit Service fb147c
        // On the fly type conversion for Exif.Photo.UserComment, Exif.GPSProcessingMethod, GPSAreaInformation
Packit Service fb147c
        if ( const TagInfo* pTag = ti == undefined ? findTagInfo(tag,group) : NULL ) {
Packit Service fb147c
            if ( pTag->typeId_ == comment ) {
Packit Service fb147c
                ti = comment;
Packit Service fb147c
            }
Packit 01d647
        }
Packit 01d647
        // http://dev.exiv2.org/boards/3/topics/1337 change unsignedByte to signedByte
Packit 01d647
        // Exif.NikonAFT.AFFineTuneAdj || Exif.Pentax.Temperature
Packit 01d647
        if ( ti == Exiv2::unsignedByte ) {
Packit 01d647
            if ( (tag == 0x0002 && group == nikonAFTId ) || (tag == 0x0047 && group == pentaxId) ) {
Packit 01d647
                ti = Exiv2::signedByte;
Packit 01d647
            }
Packit 01d647
        }
Packit 01d647
        return ti;
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffType toTiffType(TypeId typeId)
Packit 01d647
    {
Packit 01d647
        if (static_cast<uint32_t>(typeId) > 0xffff) {
Packit 01d647
#ifndef SUPPRESS_WARNINGS
Packit 01d647
            EXV_ERROR << "'" << TypeInfo::typeName(typeId)
Packit 01d647
                      << "' is not a valid Exif (TIFF) type; using type '"
Packit 01d647
                      << TypeInfo::typeName(undefined) << "'.\n";
Packit 01d647
#endif
Packit 01d647
            return undefined;
Packit 01d647
        }
Packit 01d647
        return static_cast<uint16_t>(typeId);
Packit 01d647
    }
Packit 01d647
Packit 01d647
    bool cmpTagLt(TiffComponent const* lhs, TiffComponent const* rhs)
Packit 01d647
    {
Packit 01d647
        assert(lhs != 0);
Packit 01d647
        assert(rhs != 0);
Packit 01d647
        if (lhs->tag() != rhs->tag()) return lhs->tag() < rhs->tag();
Packit 01d647
        return lhs->idx() < rhs->idx();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    bool cmpGroupLt(TiffComponent const* lhs, TiffComponent const* rhs)
Packit 01d647
    {
Packit 01d647
        assert(lhs != 0);
Packit 01d647
        assert(rhs != 0);
Packit 01d647
        return lhs->group() < rhs->group();
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent::AutoPtr newTiffEntry(uint16_t tag, IfdId group)
Packit 01d647
    {
Packit 01d647
        return TiffComponent::AutoPtr(new TiffEntry(tag, group));
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent::AutoPtr newTiffMnEntry(uint16_t tag, IfdId group)
Packit 01d647
    {
Packit 01d647
        return TiffComponent::AutoPtr(new TiffMnEntry(tag, group, mnId));
Packit 01d647
    }
Packit 01d647
Packit 01d647
    TiffComponent::AutoPtr newTiffBinaryElement(uint16_t tag, IfdId group)
Packit 01d647
    {
Packit 01d647
        return TiffComponent::AutoPtr(new TiffBinaryElement(tag, group));
Packit 01d647
    }
Packit 01d647
Packit 01d647
}}                                      // namespace Internal, Exiv2
Packit 01d647
Packit 01d647
// *****************************************************************************
Packit 01d647
// local definitions
Packit 01d647
namespace {
Packit 01d647
    uint32_t fillGap(Exiv2::Internal::IoWrapper& ioWrapper, uint32_t curr, uint32_t tobe)
Packit 01d647
    {
Packit 01d647
        if (curr < tobe) {
Packit 01d647
            Exiv2::DataBuf buf(tobe - curr);
Packit 01d647
            memset(buf.pData_, 0x0, buf.size_);
Packit 01d647
            ioWrapper.write(buf.pData_, buf.size_);
Packit 01d647
            return tobe - curr;
Packit 01d647
        }
Packit 01d647
        return 0;
Packit 01d647
Packit 01d647
    } // fillGap
Packit 01d647
}