|
rpm-build |
d2b433 |
/*
|
|
rpm-build |
d2b433 |
* libopenraw - ifdentry.cpp
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* Copyright (C) 2006-2017 Hubert Figuière
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* This library is free software: you can redistribute it and/or
|
|
rpm-build |
d2b433 |
* modify it under the terms of the GNU Lesser General Public License
|
|
rpm-build |
d2b433 |
* as published by the Free Software Foundation, either version 3 of
|
|
rpm-build |
d2b433 |
* the License, or (at your option) any later version.
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* This library is distributed in the hope that it will be useful,
|
|
rpm-build |
d2b433 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
rpm-build |
d2b433 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
rpm-build |
d2b433 |
* Lesser General Public License for more details.
|
|
rpm-build |
d2b433 |
*
|
|
rpm-build |
d2b433 |
* You should have received a copy of the GNU Lesser General Public
|
|
rpm-build |
d2b433 |
* License along with this library. If not, see
|
|
rpm-build |
d2b433 |
* <http://www.gnu.org/licenses/>.
|
|
rpm-build |
d2b433 |
*/
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include <stdlib.h>
|
|
rpm-build |
d2b433 |
#include <math.h>
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include <cstdint>
|
|
rpm-build |
d2b433 |
#include <string>
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include <libopenraw/debug.h>
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
#include "metavalue.hpp"
|
|
rpm-build |
d2b433 |
#include "trace.hpp"
|
|
rpm-build |
d2b433 |
#include "ifdfilecontainer.hpp"
|
|
rpm-build |
d2b433 |
#include "ifdentry.hpp"
|
|
rpm-build |
d2b433 |
#include "ifd.hpp"
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
using namespace Debug;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
namespace OpenRaw {
|
|
rpm-build |
d2b433 |
namespace Internals {
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
IfdEntry::IfdEntry(uint16_t _id, int16_t _type,
|
|
rpm-build |
d2b433 |
int32_t _count, uint32_t _data,
|
|
rpm-build |
d2b433 |
IfdFileContainer &_container)
|
|
rpm-build |
d2b433 |
: m_id(_id), m_type(_type),
|
|
rpm-build |
d2b433 |
m_count(_count), m_data(_data),
|
|
rpm-build |
d2b433 |
m_loaded(false), m_dataptr(NULL),
|
|
rpm-build |
d2b433 |
m_container(_container)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
auto container_size = m_container.size();
|
|
rpm-build |
d2b433 |
auto unit_size = type_unit_size(static_cast<IFD::ExifTagType>(m_type));
|
|
rpm-build |
d2b433 |
if ((m_count * unit_size) > static_cast<size_t>(container_size)) {
|
|
rpm-build |
d2b433 |
LOGERR("Trying to have %u items in a container of %ld bytes\n",
|
|
rpm-build |
d2b433 |
m_count, container_size);
|
|
rpm-build |
d2b433 |
m_count = container_size / unit_size;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
IfdEntry::~IfdEntry()
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
if (m_dataptr) {
|
|
rpm-build |
d2b433 |
free(m_dataptr);
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
namespace {
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <class T>
|
|
rpm-build |
d2b433 |
void convert(Internals::IfdEntry* e, std::vector<MetaValue::value_t> & values)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
auto result = e->getArray<T>();
|
|
rpm-build |
d2b433 |
if (result.ok()) {
|
|
rpm-build |
d2b433 |
std::vector<T> v = result.unwrap();
|
|
rpm-build |
d2b433 |
values.insert(values.end(), v.cbegin(), v.cend());
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
// T is the Ifd primitive type. T2 is the target MetaValue type.
|
|
rpm-build |
d2b433 |
template <class T, class T2>
|
|
rpm-build |
d2b433 |
void convert(Internals::IfdEntry* e, std::vector<MetaValue::value_t> & values)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
auto result = e->getArray<T>();
|
|
rpm-build |
d2b433 |
if (result.ok()) {
|
|
rpm-build |
d2b433 |
std::vector<T> v = result.unwrap();
|
|
rpm-build |
d2b433 |
for(const auto & elem : v) {
|
|
rpm-build |
d2b433 |
values.push_back(T2(elem));
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
size_t IfdEntry::type_unit_size(IFD::ExifTagType _type)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
switch(_type) {
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_BYTE:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_SBYTE:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_ASCII:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_UNDEFINED:
|
|
rpm-build |
d2b433 |
return 1;
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_SHORT:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_SSHORT:
|
|
rpm-build |
d2b433 |
return 2;
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_LONG:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_SLONG:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_FLOAT:
|
|
rpm-build |
d2b433 |
return 4;
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_RATIONAL:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_SRATIONAL:
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_DOUBLE:
|
|
rpm-build |
d2b433 |
return 8;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
return 0;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
MetaValue* IfdEntry::make_meta_value()
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
std::vector<MetaValue::value_t> values;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
switch(type()) {
|
|
rpm-build |
d2b433 |
case Internals::IFD::EXIF_FORMAT_BYTE:
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
convert<uint8_t, uint32_t>(this, values);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
case Internals::IFD::EXIF_FORMAT_ASCII:
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
convert<std::string>(this, values);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
case Internals::IFD::EXIF_FORMAT_SHORT:
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
convert<uint16_t, uint32_t>(this, values);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
case Internals::IFD::EXIF_FORMAT_LONG:
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
convert<uint32_t>(this, values);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
case Internals::IFD::EXIF_FORMAT_SRATIONAL:
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
convert<Internals::IFD::SRational, double>(this, values);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
default:
|
|
rpm-build |
d2b433 |
LOGDBG1("unhandled type %d\n", type());
|
|
rpm-build |
d2b433 |
return NULL;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
return new MetaValue(values);
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
RawContainer::EndianType IfdEntry::endian() const
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
return m_container.endian();
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
bool IfdEntry::loadData(size_t unit_size)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
bool success = false;
|
|
rpm-build |
d2b433 |
size_t data_size = unit_size * m_count;
|
|
rpm-build |
d2b433 |
if (data_size <= 4) {
|
|
rpm-build |
d2b433 |
m_dataptr = NULL;
|
|
rpm-build |
d2b433 |
success = true;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
else {
|
|
rpm-build |
d2b433 |
off_t _offset;
|
|
rpm-build |
d2b433 |
if (endian() == RawContainer::ENDIAN_LITTLE) {
|
|
rpm-build |
d2b433 |
_offset = IfdTypeTrait<uint32_t>::EL((uint8_t*)&m_data, sizeof(uint32_t));
|
|
rpm-build |
d2b433 |
} else {
|
|
rpm-build |
d2b433 |
_offset = IfdTypeTrait<uint32_t>::BE((uint8_t*)&m_data, sizeof(uint32_t));
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
_offset += m_container.exifOffsetCorrection();
|
|
rpm-build |
d2b433 |
m_dataptr = (uint8_t*)realloc(m_dataptr, data_size);
|
|
rpm-build |
d2b433 |
success = (m_container.fetchData(m_dataptr,
|
|
rpm-build |
d2b433 |
_offset,
|
|
rpm-build |
d2b433 |
data_size) == data_size);
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
return success;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
uint32_t IfdEntry::getIntegerArrayItem(int idx)
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
uint32_t v = 0;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
try {
|
|
rpm-build |
d2b433 |
switch(type())
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_LONG:
|
|
rpm-build |
d2b433 |
v = IfdTypeTrait<uint32_t>::get(*this, idx);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_SHORT:
|
|
rpm-build |
d2b433 |
v = IfdTypeTrait<uint16_t>::get(*this, idx);
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
case IFD::EXIF_FORMAT_RATIONAL:
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
IFD::Rational r = IfdTypeTrait<IFD::Rational>::get(*this, idx);
|
|
rpm-build |
d2b433 |
if(r.denom == 0) {
|
|
rpm-build |
d2b433 |
v = 0;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
else {
|
|
rpm-build |
d2b433 |
v = r.num / r.denom;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
default:
|
|
rpm-build |
d2b433 |
break;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
catch(const std::exception & ex) {
|
|
rpm-build |
d2b433 |
LOGERR("Exception raised %s fetch integer value for %d\n", ex.what(), m_id);
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
return v;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
namespace IFD {
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
Rational::operator double() const
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
if(denom == 0) {
|
|
rpm-build |
d2b433 |
return INFINITY;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
return (double)num / (double)denom;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
SRational::operator double() const
|
|
rpm-build |
d2b433 |
{
|
|
rpm-build |
d2b433 |
if(denom == 0) {
|
|
rpm-build |
d2b433 |
return INFINITY;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
return (double)num / (double)denom;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const uint16_t IfdTypeTrait<uint8_t>::type = IFD::EXIF_FORMAT_BYTE;
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const size_t IfdTypeTrait<uint8_t>::size = 1;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const uint16_t IfdTypeTrait<uint16_t>::type = IFD::EXIF_FORMAT_SHORT;
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const size_t IfdTypeTrait<uint16_t>::size = 2;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const uint16_t IfdTypeTrait<IFD::Rational>::type = IFD::EXIF_FORMAT_RATIONAL;
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const size_t IfdTypeTrait<IFD::Rational>::size = 8;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const uint16_t IfdTypeTrait<IFD::SRational>::type = IFD::EXIF_FORMAT_SRATIONAL;
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const size_t IfdTypeTrait<IFD::SRational>::size = 8;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const uint16_t IfdTypeTrait<uint32_t>::type = IFD::EXIF_FORMAT_LONG;
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const size_t IfdTypeTrait<uint32_t>::size = 4;
|
|
rpm-build |
d2b433 |
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const uint16_t IfdTypeTrait<std::string>::type = IFD::EXIF_FORMAT_ASCII;
|
|
rpm-build |
d2b433 |
template <>
|
|
rpm-build |
d2b433 |
const size_t IfdTypeTrait<std::string>::size = 1;
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
}
|
|
rpm-build |
d2b433 |
/*
|
|
rpm-build |
d2b433 |
Local Variables:
|
|
rpm-build |
d2b433 |
mode:c++
|
|
rpm-build |
d2b433 |
c-file-style:"stroustrup"
|
|
rpm-build |
d2b433 |
c-file-offsets:((innamespace . 0))
|
|
rpm-build |
d2b433 |
tab-width:4
|
|
rpm-build |
d2b433 |
c-basic-offset:4
|
|
rpm-build |
d2b433 |
indent-tabs-mode:t
|
|
rpm-build |
d2b433 |
fill-column:80
|
|
rpm-build |
d2b433 |
End:
|
|
rpm-build |
d2b433 |
*/
|