Blame lib/ifdentry.cpp

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
*/