|
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 |
}
|