|
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: exif.cpp
|
|
Packit |
01d647 |
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
|
|
Packit |
01d647 |
History: 26-Jan-04, ahu: created
|
|
Packit |
01d647 |
11-Feb-04, ahu: isolated as a component
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
// included header files
|
|
Packit |
01d647 |
#include "config.h"
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#include "exif.hpp"
|
|
Packit |
01d647 |
#include "metadatum.hpp"
|
|
Packit |
01d647 |
#include "tags.hpp"
|
|
Packit |
01d647 |
#include "tags_int.hpp"
|
|
Packit |
01d647 |
#include "value.hpp"
|
|
Packit |
01d647 |
#include "types.hpp"
|
|
Packit |
01d647 |
#include "error.hpp"
|
|
Packit |
01d647 |
#include "basicio.hpp"
|
|
Packit |
01d647 |
#include "tiffimage.hpp"
|
|
Packit |
01d647 |
#include "tiffimage_int.hpp"
|
|
Packit |
01d647 |
#include "tiffcomposite_int.hpp" // for Tag::root
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// + standard includes
|
|
Packit |
01d647 |
#include <iostream>
|
|
Packit |
01d647 |
#include <sstream>
|
|
Packit |
01d647 |
#include <utility>
|
|
Packit |
01d647 |
#include <algorithm>
|
|
Packit |
01d647 |
#include <cstring>
|
|
Packit |
01d647 |
#include <cassert>
|
|
Packit |
01d647 |
#include <cstdio>
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
namespace {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Unary predicate that matches a Exifdatum with a given key
|
|
Packit |
01d647 |
class FindExifdatumByKey {
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
//! Constructor, initializes the object with the key to look for
|
|
Packit |
01d647 |
FindExifdatumByKey(const std::string& key) : key_(key) {}
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Returns true if the key of \em exifdatum is equal
|
|
Packit |
01d647 |
to that of the object.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
bool operator()(const Exiv2::Exifdatum& exifdatum) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_ == exifdatum.key();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
private:
|
|
Packit |
01d647 |
const std::string& key_;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
}; // class FindExifdatumByKey
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Exif %Thumbnail image. This abstract base class provides the
|
|
Packit |
01d647 |
interface for the thumbnail image that is optionally embedded in
|
|
Packit |
01d647 |
the Exif data. This class is used internally by ExifData, it is
|
|
Packit |
01d647 |
probably not useful for a client as a standalone class. Instead,
|
|
Packit |
01d647 |
use an instance of ExifData to access the Exif thumbnail image.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
class Thumbnail {
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
//! Shortcut for a %Thumbnail auto pointer.
|
|
Packit |
01d647 |
typedef std::auto_ptr<Thumbnail> AutoPtr;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @name Creators
|
|
Packit |
01d647 |
//@{
|
|
Packit |
01d647 |
//! Virtual destructor
|
|
Packit |
01d647 |
virtual ~Thumbnail() {}
|
|
Packit |
01d647 |
//@}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Factory function to create a thumbnail for the Exif metadata provided.
|
|
Packit |
01d647 |
static AutoPtr create(const Exiv2::ExifData& exifData);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @name Accessors
|
|
Packit |
01d647 |
//@{
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Return the thumbnail image in a %DataBuf. The caller owns the
|
|
Packit |
01d647 |
data buffer and %DataBuf ensures that it will be deleted.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
virtual Exiv2::DataBuf copy(const Exiv2::ExifData& exifData) const =0;
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Return the MIME type of the thumbnail ("image/tiff" or
|
|
Packit |
01d647 |
"image/jpeg").
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
virtual const char* mimeType() const =0;
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Return the file extension for the format of the thumbnail
|
|
Packit |
01d647 |
(".tif", ".jpg").
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
virtual const char* extension() const =0;
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Like extension() but returns the extension in a wchar_t.
|
|
Packit |
01d647 |
@note This function is only available on Windows.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
virtual const wchar_t* wextension() const =0;
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
//@}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
}; // class Thumbnail
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Exif thumbnail image in TIFF format
|
|
Packit |
01d647 |
class TiffThumbnail : public Thumbnail {
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
//! Shortcut for a %TiffThumbnail auto pointer.
|
|
Packit |
01d647 |
typedef std::auto_ptr<TiffThumbnail> AutoPtr;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @name Manipulators
|
|
Packit |
01d647 |
//@{
|
|
Packit |
01d647 |
//! Assignment operator.
|
|
Packit |
01d647 |
TiffThumbnail& operator=(const TiffThumbnail& rhs);
|
|
Packit |
01d647 |
//@}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @name Accessors
|
|
Packit |
01d647 |
//@{
|
|
Packit |
01d647 |
Exiv2::DataBuf copy(const Exiv2::ExifData& exifData) const;
|
|
Packit |
01d647 |
const char* mimeType() const;
|
|
Packit |
01d647 |
const char* extension() const;
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
const wchar_t* wextension() const;
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
//@}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
}; // class TiffThumbnail
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Exif thumbnail image in JPEG format
|
|
Packit |
01d647 |
class JpegThumbnail : public Thumbnail {
|
|
Packit |
01d647 |
public:
|
|
Packit |
01d647 |
//! Shortcut for a %JpegThumbnail auto pointer.
|
|
Packit |
01d647 |
typedef std::auto_ptr<JpegThumbnail> AutoPtr;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @name Manipulators
|
|
Packit |
01d647 |
//@{
|
|
Packit |
01d647 |
//! Assignment operator.
|
|
Packit |
01d647 |
JpegThumbnail& operator=(const JpegThumbnail& rhs);
|
|
Packit |
01d647 |
//@}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @name Accessors
|
|
Packit |
01d647 |
//@{
|
|
Packit |
01d647 |
Exiv2::DataBuf copy(const Exiv2::ExifData& exifData) const;
|
|
Packit |
01d647 |
const char* mimeType() const;
|
|
Packit |
01d647 |
const char* extension() const;
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
const wchar_t* wextension() const;
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
//@}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
}; // class JpegThumbnail
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Helper function to sum all components of the value of a metadatum
|
|
Packit |
01d647 |
long sumToLong(const Exiv2::Exifdatum& md);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! Helper function to delete all tags of a specific IFD from the metadata.
|
|
Packit |
01d647 |
void eraseIfd(Exiv2::ExifData& ed, Exiv2::Internal::IfdId ifdId);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
// class member definitions
|
|
Packit |
01d647 |
namespace Exiv2 {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
using namespace Internal;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
/*!
|
|
Packit |
01d647 |
@brief Set the value of \em exifDatum to \em value. If the object already
|
|
Packit |
01d647 |
has a value, it is replaced. Otherwise a new ValueType\<T\> value
|
|
Packit |
01d647 |
is created and set to \em value.
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
This is a helper function, called from Exifdatum members. It is meant to
|
|
Packit |
01d647 |
be used with T = (u)int16_t, (u)int32_t or (U)Rational. Do not use directly.
|
|
Packit |
01d647 |
*/
|
|
Packit |
01d647 |
template<typename T>
|
|
Packit |
01d647 |
Exiv2::Exifdatum& setValue(Exiv2::Exifdatum& exifDatum, const T& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
std::auto_ptr<Exiv2::ValueType<T> > v
|
|
Packit |
01d647 |
= std::auto_ptr<Exiv2::ValueType<T> >(new Exiv2::ValueType<T>);
|
|
Packit |
01d647 |
v->value_.push_back(value);
|
|
Packit |
01d647 |
exifDatum.value_ = v;
|
|
Packit |
01d647 |
return exifDatum;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum::Exifdatum(const ExifKey& key, const Value* pValue)
|
|
Packit |
01d647 |
: key_(key.clone())
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (pValue) value_ = pValue->clone();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum::~Exifdatum()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum::Exifdatum(const Exifdatum& rhs)
|
|
Packit |
01d647 |
: Metadatum(rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (rhs.key_.get() != 0) key_ = rhs.key_->clone(); // deep copy
|
|
Packit |
01d647 |
if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::ostream& Exifdatum::write(std::ostream& os, const ExifData* pMetadata) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (value().count() == 0) return os;
|
|
Packit Service |
fb147c |
|
|
Packit Service |
fb147c |
PrintFct fct = printValue;
|
|
Packit Service |
fb147c |
const TagInfo* ti = Internal::tagInfo(tag(), static_cast<IfdId>(ifdId()));
|
|
Packit Service |
fb147c |
// be careful with comments (User.Photo.UserComment, GPSAreaInfo etc).
|
|
Packit Service |
fb147c |
if ( ti ) {
|
|
Packit Service |
fb147c |
fct = ti->printFct_;
|
|
Packit Service |
fb147c |
if ( ti->typeId_ == comment ) {
|
|
Packit Service |
fb147c |
os << value().toString();
|
|
Packit Service |
fb147c |
fct=NULL;
|
|
Packit Service |
fb147c |
}
|
|
Packit Service |
fb147c |
}
|
|
Packit Service |
fb147c |
if ( fct ) fct(os, value(), pMetadata);
|
|
Packit Service |
fb147c |
return os;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const Value& Exifdatum::value() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (value_.get() == 0) throw Error(kerValueNotSet);
|
|
Packit |
01d647 |
return *value_;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const Exifdatum& rhs)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (this == &rhs) return *this;
|
|
Packit |
01d647 |
Metadatum::operator=(rhs);
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
key_.reset();
|
|
Packit |
01d647 |
if (rhs.key_.get() != 0) key_ = rhs.key_->clone(); // deep copy
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
value_.reset();
|
|
Packit |
01d647 |
if (rhs.value_.get() != 0) value_ = rhs.value_->clone(); // deep copy
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
} // Exifdatum::operator=
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const std::string& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
setValue(value);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const uint16_t& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Exiv2::setValue(*this, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const uint32_t& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Exiv2::setValue(*this, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const URational& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Exiv2::setValue(*this, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const int16_t& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Exiv2::setValue(*this, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const int32_t& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Exiv2::setValue(*this, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const Rational& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return Exiv2::setValue(*this, value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& Exifdatum::operator=(const Value& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
setValue(&value);
|
|
Packit |
01d647 |
return *this;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void Exifdatum::setValue(const Value* pValue)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
value_.reset();
|
|
Packit |
01d647 |
if (pValue) value_ = pValue->clone();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int Exifdatum::setValue(const std::string& value)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
if (value_.get() == 0) {
|
|
Packit |
01d647 |
TypeId type = key_->defaultTypeId();
|
|
Packit |
01d647 |
value_ = Value::create(type);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return value_->read(value);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int Exifdatum::setDataArea(const byte* buf, long len)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? -1 : value_->setDataArea(buf, len);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Exifdatum::key() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? "" : key_->key();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* Exifdatum::familyName() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? "" : key_->familyName();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Exifdatum::groupName() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? "" : key_->groupName();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Exifdatum::tagName() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? "" : key_->tagName();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Exifdatum::tagLabel() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? "" : key_->tagLabel();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
uint16_t Exifdatum::tag() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? 0xffff : key_->tag();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int Exifdatum::ifdId() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? ifdIdNotSet : key_->ifdId();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* Exifdatum::ifdName() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? "" : Internal::ifdName(static_cast<Internal::IfdId>(key_->ifdId()));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
int Exifdatum::idx() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return key_.get() == 0 ? 0 : key_->idx();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long Exifdatum::copy(byte* buf, ByteOrder byteOrder) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? 0 : value_->copy(buf, byteOrder);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
TypeId Exifdatum::typeId() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? invalidTypeId : value_->typeId();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* Exifdatum::typeName() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return TypeInfo::typeName(typeId());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long Exifdatum::typeSize() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return TypeInfo::typeSize(typeId());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long Exifdatum::count() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? 0 : value_->count();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long Exifdatum::size() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? 0 : value_->size();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Exifdatum::toString() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? "" : value_->toString();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
std::string Exifdatum::toString(long n) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? "" : value_->toString(n);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long Exifdatum::toLong(long n) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? -1 : value_->toLong(n);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
float Exifdatum::toFloat(long n) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? -1 : value_->toFloat(n);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Rational Exifdatum::toRational(long n) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? Rational(-1, 1) : value_->toRational(n);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Value::AutoPtr Exifdatum::getValue() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? Value::AutoPtr(0) : value_->clone();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long Exifdatum::sizeDataArea() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? 0 : value_->sizeDataArea();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf Exifdatum::dataArea() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return value_.get() == 0 ? DataBuf(0, 0) : value_->dataArea();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
ExifThumbC::ExifThumbC(const ExifData& exifData)
|
|
Packit |
01d647 |
: exifData_(exifData)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
DataBuf ExifThumbC::copy() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail = Thumbnail::create(exifData_);
|
|
Packit |
01d647 |
if (thumbnail.get() == 0) return DataBuf();
|
|
Packit |
01d647 |
return thumbnail->copy(exifData_);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long ExifThumbC::writeFile(const std::string& path) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail = Thumbnail::create(exifData_);
|
|
Packit |
01d647 |
if (thumbnail.get() == 0) return 0;
|
|
Packit |
01d647 |
std::string name = path + thumbnail->extension();
|
|
Packit |
01d647 |
DataBuf buf(thumbnail->copy(exifData_));
|
|
Packit |
01d647 |
if (buf.size_ == 0) return 0;
|
|
Packit |
01d647 |
return Exiv2::writeFile(buf, name);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
long ExifThumbC::writeFile(const std::wstring& wpath) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail = Thumbnail::create(exifData_);
|
|
Packit |
01d647 |
if (thumbnail.get() == 0) return 0;
|
|
Packit |
01d647 |
std::wstring name = wpath + thumbnail->wextension();
|
|
Packit |
01d647 |
DataBuf buf(thumbnail->copy(exifData_));
|
|
Packit |
01d647 |
if (buf.size_ == 0) return 0;
|
|
Packit |
01d647 |
return Exiv2::writeFile(buf, name);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
const char* ExifThumbC::mimeType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail = Thumbnail::create(exifData_);
|
|
Packit |
01d647 |
if (thumbnail.get() == 0) return "";
|
|
Packit |
01d647 |
return thumbnail->mimeType();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* ExifThumbC::extension() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail = Thumbnail::create(exifData_);
|
|
Packit |
01d647 |
if (thumbnail.get() == 0) return "";
|
|
Packit |
01d647 |
return thumbnail->extension();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
const wchar_t* ExifThumbC::wextension() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail = Thumbnail::create(exifData_);
|
|
Packit |
01d647 |
if (thumbnail.get() == 0) return EXV_WIDEN("");
|
|
Packit |
01d647 |
return thumbnail->wextension();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
ExifThumb::ExifThumb(ExifData& exifData)
|
|
Packit |
01d647 |
: ExifThumbC(exifData), exifData_(exifData)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifThumb::setJpegThumbnail(
|
|
Packit |
01d647 |
const std::string& path,
|
|
Packit |
01d647 |
URational xres,
|
|
Packit |
01d647 |
URational yres,
|
|
Packit |
01d647 |
uint16_t unit
|
|
Packit |
01d647 |
)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
DataBuf thumb = readFile(path); // may throw
|
|
Packit |
01d647 |
setJpegThumbnail(thumb.pData_, thumb.size_, xres, yres, unit);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
void ExifThumb::setJpegThumbnail(
|
|
Packit |
01d647 |
const std::wstring& wpath,
|
|
Packit |
01d647 |
URational xres,
|
|
Packit |
01d647 |
URational yres,
|
|
Packit |
01d647 |
uint16_t unit
|
|
Packit |
01d647 |
)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
DataBuf thumb = readFile(wpath); // may throw
|
|
Packit |
01d647 |
setJpegThumbnail(thumb.pData_, thumb.size_, xres, yres, unit);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
void ExifThumb::setJpegThumbnail(
|
|
Packit |
01d647 |
const byte* buf,
|
|
Packit |
01d647 |
long size,
|
|
Packit |
01d647 |
URational xres,
|
|
Packit |
01d647 |
URational yres,
|
|
Packit |
01d647 |
uint16_t unit
|
|
Packit |
01d647 |
)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
setJpegThumbnail(buf, size);
|
|
Packit |
01d647 |
exifData_["Exif.Thumbnail.XResolution"] = xres;
|
|
Packit |
01d647 |
exifData_["Exif.Thumbnail.YResolution"] = yres;
|
|
Packit |
01d647 |
exifData_["Exif.Thumbnail.ResolutionUnit"] = unit;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifThumb::setJpegThumbnail(const std::string& path)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
DataBuf thumb = readFile(path); // may throw
|
|
Packit |
01d647 |
setJpegThumbnail(thumb.pData_, thumb.size_);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
void ExifThumb::setJpegThumbnail(const std::wstring& wpath)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
DataBuf thumb = readFile(wpath); // may throw
|
|
Packit |
01d647 |
setJpegThumbnail(thumb.pData_, thumb.size_);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
void ExifThumb::setJpegThumbnail(const byte* buf, long size)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
exifData_["Exif.Thumbnail.Compression"] = uint16_t(6);
|
|
Packit |
01d647 |
Exifdatum& format = exifData_["Exif.Thumbnail.JPEGInterchangeFormat"];
|
|
Packit |
01d647 |
format = uint32_t(0);
|
|
Packit |
01d647 |
format.setDataArea(buf, size);
|
|
Packit |
01d647 |
exifData_["Exif.Thumbnail.JPEGInterchangeFormatLength"] = uint32_t(size);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifThumb::erase()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
eraseIfd(exifData_, ifd1Id);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exifdatum& ExifData::operator[](const std::string& key)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
ExifKey exifKey(key);
|
|
Packit |
01d647 |
iterator pos = findKey(exifKey);
|
|
Packit |
01d647 |
if (pos == end()) {
|
|
Packit |
01d647 |
add(Exifdatum(exifKey));
|
|
Packit |
01d647 |
pos = findKey(exifKey);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return *pos;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifData::add(const ExifKey& key, const Value* pValue)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
add(Exifdatum(key, pValue));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifData::add(const Exifdatum& exifdatum)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
// allow duplicates
|
|
Packit |
01d647 |
exifMetadata_.push_back(exifdatum);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
ExifData::const_iterator ExifData::findKey(const ExifKey& key) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return std::find_if(exifMetadata_.begin(), exifMetadata_.end(),
|
|
Packit |
01d647 |
FindExifdatumByKey(key.key()));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
ExifData::iterator ExifData::findKey(const ExifKey& key)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return std::find_if(exifMetadata_.begin(), exifMetadata_.end(),
|
|
Packit |
01d647 |
FindExifdatumByKey(key.key()));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifData::clear()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
exifMetadata_.clear();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifData::sortByKey()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
exifMetadata_.sort(cmpMetadataByKey);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void ExifData::sortByTag()
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
exifMetadata_.sort(cmpMetadataByTag);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
ExifData::iterator ExifData::erase(ExifData::iterator beg, ExifData::iterator end)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return exifMetadata_.erase(beg, end);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
ExifData::iterator ExifData::erase(ExifData::iterator pos)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return exifMetadata_.erase(pos);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
ByteOrder ExifParser::decode(
|
|
Packit |
01d647 |
ExifData& exifData,
|
|
Packit |
01d647 |
const byte* pData,
|
|
Packit |
01d647 |
uint32_t size
|
|
Packit |
01d647 |
)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
IptcData iptcData;
|
|
Packit |
01d647 |
XmpData xmpData;
|
|
Packit |
01d647 |
ByteOrder bo = TiffParser::decode(exifData,
|
|
Packit |
01d647 |
iptcData,
|
|
Packit |
01d647 |
xmpData,
|
|
Packit |
01d647 |
pData,
|
|
Packit |
01d647 |
size);
|
|
Packit |
01d647 |
#ifndef SUPPRESS_WARNINGS
|
|
Packit |
01d647 |
if (!iptcData.empty()) {
|
|
Packit |
01d647 |
EXV_WARNING << "Ignoring IPTC information encoded in the Exif data.\n";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
if (!xmpData.empty()) {
|
|
Packit |
01d647 |
EXV_WARNING << "Ignoring XMP information encoded in the Exif data.\n";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
return bo;
|
|
Packit |
01d647 |
} // ExifParser::decode
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @cond IGNORE
|
|
Packit |
01d647 |
enum Ptt { pttLen, pttTag, pttIfd };
|
|
Packit |
01d647 |
struct PreviewTags {
|
|
Packit |
01d647 |
Ptt ptt_;
|
|
Packit |
01d647 |
const char* key_;
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
//! @endcond
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
WriteMethod ExifParser::encode(
|
|
Packit |
01d647 |
Blob& blob,
|
|
Packit |
01d647 |
const byte* pData,
|
|
Packit |
01d647 |
uint32_t size,
|
|
Packit |
01d647 |
ByteOrder byteOrder,
|
|
Packit |
01d647 |
const ExifData& exifData
|
|
Packit |
01d647 |
)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
ExifData ed = exifData;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Delete IFD0 tags that are "not recorded" in compressed images
|
|
Packit |
01d647 |
// Reference: Exif 2.2 specs, 4.6.8 Tag Support Levels, section A
|
|
Packit |
01d647 |
static const char* filteredIfd0Tags[] = {
|
|
Packit |
01d647 |
"Exif.Image.PhotometricInterpretation",
|
|
Packit |
01d647 |
"Exif.Image.StripOffsets",
|
|
Packit |
01d647 |
"Exif.Image.RowsPerStrip",
|
|
Packit |
01d647 |
"Exif.Image.StripByteCounts",
|
|
Packit |
01d647 |
"Exif.Image.JPEGInterchangeFormat",
|
|
Packit |
01d647 |
"Exif.Image.JPEGInterchangeFormatLength",
|
|
Packit Service |
fb147c |
"Exif.Image.SubIFDs",
|
|
Packit Service |
fb147c |
// Issue 981. Never allow manufactured data to be written
|
|
Packit Service |
fb147c |
"Exif.Canon.AFInfoSize",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFAreaMode",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFNumPoints",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFValidPoints",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFCanonImageWidth",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFCanonImageHeight",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFImageWidth",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFImageHeight",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFAreaWidths",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFAreaHeights",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFXPositions",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFYPositions",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFPointsInFocus",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFPointsSelected",
|
|
Packit Service |
fb147c |
"Exif.Canon.AFPointsUnusable",
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
for (unsigned int i = 0; i < EXV_COUNTOF(filteredIfd0Tags); ++i) {
|
|
Packit |
01d647 |
ExifData::iterator pos = ed.findKey(ExifKey(filteredIfd0Tags[i]));
|
|
Packit |
01d647 |
if (pos != ed.end()) {
|
|
Packit |
01d647 |
#ifdef EXIV2_DEBUG_MESSAGES
|
|
Packit |
01d647 |
std::cerr << "Warning: Exif tag " << pos->key() << " not encoded\n";
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
ed.erase(pos);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Delete IFDs which do not occur in JPEGs
|
|
Packit |
01d647 |
static const IfdId filteredIfds[] = {
|
|
Packit |
01d647 |
subImage1Id,
|
|
Packit |
01d647 |
subImage2Id,
|
|
Packit |
01d647 |
subImage3Id,
|
|
Packit |
01d647 |
subImage4Id,
|
|
Packit |
01d647 |
subImage5Id,
|
|
Packit |
01d647 |
subImage6Id,
|
|
Packit |
01d647 |
subImage7Id,
|
|
Packit |
01d647 |
subImage8Id,
|
|
Packit |
01d647 |
subImage9Id,
|
|
Packit |
01d647 |
subThumb1Id,
|
|
Packit |
01d647 |
panaRawId,
|
|
Packit |
01d647 |
ifd2Id,
|
|
Packit |
01d647 |
ifd3Id
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
for (unsigned int i = 0; i < EXV_COUNTOF(filteredIfds); ++i) {
|
|
Packit |
01d647 |
#ifdef EXIV2_DEBUG_MESSAGES
|
|
Packit |
01d647 |
std::cerr << "Warning: Exif IFD " << filteredIfds[i] << " not encoded\n";
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
eraseIfd(ed, filteredIfds[i]);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// IPTC and XMP are stored elsewhere, not in the Exif APP1 segment.
|
|
Packit |
01d647 |
IptcData emptyIptc;
|
|
Packit |
01d647 |
XmpData emptyXmp;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Encode and check if the result fits into a JPEG Exif APP1 segment
|
|
Packit |
01d647 |
MemIo mio1;
|
|
Packit |
01d647 |
std::auto_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder, 0x00000008, false));
|
|
Packit |
01d647 |
WriteMethod wm = TiffParserWorker::encode(mio1,
|
|
Packit |
01d647 |
pData,
|
|
Packit |
01d647 |
size,
|
|
Packit |
01d647 |
ed,
|
|
Packit |
01d647 |
emptyIptc,
|
|
Packit |
01d647 |
emptyXmp,
|
|
Packit |
01d647 |
Tag::root,
|
|
Packit |
01d647 |
TiffMapping::findEncoder,
|
|
Packit |
01d647 |
header.get(),
|
|
Packit |
01d647 |
0);
|
|
Packit |
01d647 |
if (mio1.size() <= 65527) {
|
|
Packit |
01d647 |
append(blob, mio1.mmap(), (uint32_t) mio1.size());
|
|
Packit |
01d647 |
return wm;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// If it doesn't fit, remove additional tags
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Delete preview tags if the preview is larger than 32kB.
|
|
Packit |
01d647 |
// Todo: Enhance preview classes to be able to write and delete previews and use that instead.
|
|
Packit |
01d647 |
// Table must be sorted by preview, the first tag in each group is the size
|
|
Packit |
01d647 |
static const PreviewTags filteredPvTags[] = {
|
|
Packit |
01d647 |
{ pttLen, "Exif.Minolta.ThumbnailLength" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.Minolta.ThumbnailOffset" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Minolta.Thumbnail" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.NikonPreview.JPEGInterchangeFormatLength" },
|
|
Packit |
01d647 |
{ pttIfd, "NikonPreview" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Olympus.ThumbnailLength" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.Olympus.ThumbnailOffset" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Olympus.ThumbnailImage" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Olympus.Thumbnail" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Olympus2.ThumbnailLength" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.Olympus2.ThumbnailOffset" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Olympus2.ThumbnailImage" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Olympus2.Thumbnail" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.OlympusCs.PreviewImageLength" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.OlympusCs.PreviewImageStart" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.OlympusCs.PreviewImageValid" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Pentax.PreviewLength" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.Pentax.PreviewOffset" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.Pentax.PreviewResolution" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.PentaxDng.PreviewLength" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.PentaxDng.PreviewOffset" },
|
|
Packit |
01d647 |
{ pttTag, "Exif.PentaxDng.PreviewResolution" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.SamsungPreview.JPEGInterchangeFormatLength" },
|
|
Packit |
01d647 |
{ pttIfd, "SamsungPreview" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Thumbnail.StripByteCounts" },
|
|
Packit |
01d647 |
{ pttIfd, "Thumbnail" },
|
|
Packit |
01d647 |
{ pttLen, "Exif.Thumbnail.JPEGInterchangeFormatLength" },
|
|
Packit |
01d647 |
{ pttIfd, "Thumbnail" }
|
|
Packit |
01d647 |
};
|
|
Packit |
01d647 |
bool delTags = false;
|
|
Packit |
01d647 |
ExifData::iterator pos;
|
|
Packit |
01d647 |
for (unsigned int i = 0; i < EXV_COUNTOF(filteredPvTags); ++i) {
|
|
Packit |
01d647 |
switch (filteredPvTags[i].ptt_) {
|
|
Packit |
01d647 |
case pttLen:
|
|
Packit |
01d647 |
delTags = false;
|
|
Packit |
01d647 |
pos = ed.findKey(ExifKey(filteredPvTags[i].key_));
|
|
Packit |
01d647 |
if (pos != ed.end() && sumToLong(*pos) > 32768) {
|
|
Packit |
01d647 |
delTags = true;
|
|
Packit |
01d647 |
#ifndef SUPPRESS_WARNINGS
|
|
Packit |
01d647 |
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
ed.erase(pos);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
case pttTag:
|
|
Packit |
01d647 |
if (delTags) {
|
|
Packit |
01d647 |
pos = ed.findKey(ExifKey(filteredPvTags[i].key_));
|
|
Packit |
01d647 |
if (pos != ed.end()) {
|
|
Packit |
01d647 |
#ifndef SUPPRESS_WARNINGS
|
|
Packit |
01d647 |
EXV_WARNING << "Exif tag " << pos->key() << " not encoded\n";
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
ed.erase(pos);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
case pttIfd:
|
|
Packit |
01d647 |
if (delTags) {
|
|
Packit |
01d647 |
#ifndef SUPPRESS_WARNINGS
|
|
Packit |
01d647 |
EXV_WARNING << "Exif IFD " << filteredPvTags[i].key_ << " not encoded\n";
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
eraseIfd(ed, Internal::groupId(filteredPvTags[i].key_));
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
break;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Delete unknown tags larger than 4kB and known tags larger than 20kB.
|
|
Packit |
01d647 |
for (ExifData::iterator tag_iter = ed.begin(); tag_iter != ed.end(); ) {
|
|
Packit |
01d647 |
if ( (tag_iter->size() > 4096 && tag_iter->tagName().substr(0, 2) == "0x") ||
|
|
Packit |
01d647 |
tag_iter->size() > 20480) {
|
|
Packit |
01d647 |
#ifndef SUPPRESS_WARNINGS
|
|
Packit |
01d647 |
EXV_WARNING << "Exif tag " << tag_iter->key() << " not encoded\n";
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
tag_iter = ed.erase(tag_iter);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
++tag_iter;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// Encode the remaining Exif tags again, don't care if it fits this time
|
|
Packit |
01d647 |
MemIo mio2;
|
|
Packit |
01d647 |
wm = TiffParserWorker::encode(mio2,
|
|
Packit |
01d647 |
pData,
|
|
Packit |
01d647 |
size,
|
|
Packit |
01d647 |
ed,
|
|
Packit |
01d647 |
emptyIptc,
|
|
Packit |
01d647 |
emptyXmp,
|
|
Packit |
01d647 |
Tag::root,
|
|
Packit |
01d647 |
TiffMapping::findEncoder,
|
|
Packit |
01d647 |
header.get(),
|
|
Packit |
01d647 |
0);
|
|
Packit |
01d647 |
append(blob, mio2.mmap(), (uint32_t) mio2.size());
|
|
Packit |
01d647 |
#ifdef EXIV2_DEBUG_MESSAGES
|
|
Packit |
01d647 |
if (wm == wmIntrusive) {
|
|
Packit |
01d647 |
std::cerr << "SIZE OF EXIF DATA IS " << std::dec << mio2.size() << " BYTES\n";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
std::cerr << "SIZE DOESN'T MATTER, NON-INTRUSIVE WRITING USED\n";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
return wm;
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
} // ExifParser::encode
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
} // namespace Exiv2
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
// *****************************************************************************
|
|
Packit |
01d647 |
// local definitions
|
|
Packit |
01d647 |
namespace {
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
//! @cond IGNORE
|
|
Packit |
01d647 |
Thumbnail::AutoPtr Thumbnail::create(const Exiv2::ExifData& exifData)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Thumbnail::AutoPtr thumbnail;
|
|
Packit |
01d647 |
const Exiv2::ExifKey k1("Exif.Thumbnail.Compression");
|
|
Packit |
01d647 |
Exiv2::ExifData::const_iterator pos = exifData.findKey(k1);
|
|
Packit |
01d647 |
if (pos != exifData.end()) {
|
|
Packit |
01d647 |
if (pos->count() == 0) return thumbnail;
|
|
Packit |
01d647 |
long compression = pos->toLong();
|
|
Packit |
01d647 |
if (compression == 6) {
|
|
Packit |
01d647 |
thumbnail = Thumbnail::AutoPtr(new JpegThumbnail);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
thumbnail = Thumbnail::AutoPtr(new TiffThumbnail);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
else {
|
|
Packit |
01d647 |
const Exiv2::ExifKey k2("Exif.Thumbnail.JPEGInterchangeFormat");
|
|
Packit |
01d647 |
pos = exifData.findKey(k2);
|
|
Packit |
01d647 |
if (pos != exifData.end()) {
|
|
Packit |
01d647 |
thumbnail = Thumbnail::AutoPtr(new JpegThumbnail);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return thumbnail;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* TiffThumbnail::mimeType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return "image/tiff";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* TiffThumbnail::extension() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return ".tif";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
const wchar_t* TiffThumbnail::wextension() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return EXV_WIDEN(".tif");
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
Exiv2::DataBuf TiffThumbnail::copy(const Exiv2::ExifData& exifData) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Exiv2::ExifData thumb;
|
|
Packit |
01d647 |
// Copy all Thumbnail (IFD1) tags from exifData to Image (IFD0) tags in thumb
|
|
Packit |
01d647 |
for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifData.end(); ++i) {
|
|
Packit |
01d647 |
if (i->groupName() == "Thumbnail") {
|
|
Packit |
01d647 |
std::string key = "Exif.Image." + i->tagName();
|
|
Packit |
01d647 |
thumb.add(Exiv2::ExifKey(key), &i->value());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
Exiv2::MemIo io;
|
|
Packit |
01d647 |
Exiv2::IptcData emptyIptc;
|
|
Packit |
01d647 |
Exiv2::XmpData emptyXmp;
|
|
Packit |
01d647 |
Exiv2::TiffParser::encode(io, 0, 0, Exiv2::littleEndian, thumb, emptyIptc, emptyXmp);
|
|
Packit |
01d647 |
return io.read((long) io.size());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* JpegThumbnail::mimeType() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return "image/jpeg";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
const char* JpegThumbnail::extension() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return ".jpg";
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#ifdef EXV_UNICODE_PATH
|
|
Packit |
01d647 |
const wchar_t* JpegThumbnail::wextension() const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
return EXV_WIDEN(".jpg");
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
#endif
|
|
Packit |
01d647 |
Exiv2::DataBuf JpegThumbnail::copy(const Exiv2::ExifData& exifData) const
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
Exiv2::ExifKey key("Exif.Thumbnail.JPEGInterchangeFormat");
|
|
Packit |
01d647 |
Exiv2::ExifData::const_iterator format = exifData.findKey(key);
|
|
Packit |
01d647 |
if (format == exifData.end()) return Exiv2::DataBuf();
|
|
Packit |
01d647 |
return format->dataArea();
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
long sumToLong(const Exiv2::Exifdatum& md)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
long sum = 0;
|
|
Packit |
01d647 |
for (int i = 0; i < md.count(); ++i) {
|
|
Packit |
01d647 |
sum += md.toLong(i);
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
return sum;
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
|
|
Packit |
01d647 |
void eraseIfd(Exiv2::ExifData& ed, Exiv2::IfdId ifdId)
|
|
Packit |
01d647 |
{
|
|
Packit |
01d647 |
ed.erase(std::remove_if(ed.begin(),
|
|
Packit |
01d647 |
ed.end(),
|
|
Packit |
01d647 |
Exiv2::FindExifdatum(ifdId)),
|
|
Packit |
01d647 |
ed.end());
|
|
Packit |
01d647 |
}
|
|
Packit |
01d647 |
//! @endcond
|
|
Packit |
01d647 |
}
|