Blame lib/mrwcontainer.cpp

rpm-build d2b433
/*
rpm-build d2b433
 * libopenraw - mrwcontainer.cpp
rpm-build d2b433
 *
rpm-build d2b433
 * Copyright (C) 2006-2017 Hubert Figuière
rpm-build d2b433
 * Copyright (C) 2008 Bradley Broom
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
#include <fcntl.h>
rpm-build d2b433
#include <stddef.h>
rpm-build d2b433
rpm-build d2b433
#include <libopenraw/debug.h>
rpm-build d2b433
rpm-build d2b433
#include "trace.hpp"
rpm-build d2b433
#include "mrwcontainer.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
namespace MRW {
rpm-build d2b433
rpm-build d2b433
DataBlock::DataBlock(off_t start, MRWContainer *_container)
rpm-build d2b433
    : m_start(start), m_container(_container), m_loaded(false)
rpm-build d2b433
{
rpm-build d2b433
    LOGDBG2("> DataBlock start == %ld\n", start);
rpm-build d2b433
    if (m_container->fetchData(m_name, m_start, 4) != 4) {
rpm-build d2b433
        // FIXME: Handle error
rpm-build d2b433
        LOGWARN("  Error reading block name %ld\n", start);
rpm-build d2b433
        return;
rpm-build d2b433
    }
rpm-build d2b433
    auto result = m_container->readInt32(m_container->file());
rpm-build d2b433
    if (result.empty()) {
rpm-build d2b433
        // FIXME: Handle error
rpm-build d2b433
        LOGWARN("  Error reading block length %ld\n", start);
rpm-build d2b433
        return;
rpm-build d2b433
    }
rpm-build d2b433
    m_length = result.unwrap();
rpm-build d2b433
    LOGDBG1("  DataBlock %s, length %d at %ld\n", name().c_str(), m_length, m_start);
rpm-build d2b433
    LOGDBG2("< DataBlock\n");
rpm-build d2b433
    m_loaded = true;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
Option<int8_t>
rpm-build d2b433
DataBlock::int8_val(off_t off)
rpm-build d2b433
{
rpm-build d2b433
    MRWContainer *mc = m_container;
rpm-build d2b433
    mc->file()->seek(m_start + DataBlockHeaderLength + off, SEEK_SET);
rpm-build d2b433
    return mc->readInt8(mc->file());
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
Option<uint8_t>
rpm-build d2b433
DataBlock::uint8_val(off_t off)
rpm-build d2b433
{
rpm-build d2b433
    MRWContainer *mc = m_container;
rpm-build d2b433
    mc->file()->seek(m_start + DataBlockHeaderLength + off, SEEK_SET);
rpm-build d2b433
    return  mc->readUInt8(mc->file());
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
Option<uint16_t>
rpm-build d2b433
DataBlock::uint16_val(off_t off)
rpm-build d2b433
{
rpm-build d2b433
    MRWContainer *mc = m_container;
rpm-build d2b433
    mc->file()->seek(m_start + DataBlockHeaderLength + off, SEEK_SET);
rpm-build d2b433
    return mc->readUInt16(mc->file());
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
Option<std::string>
rpm-build d2b433
DataBlock::string_val(off_t off)
rpm-build d2b433
{
rpm-build d2b433
    char buf[9];
rpm-build d2b433
    size_t s;
rpm-build d2b433
    MRWContainer *mc = m_container;
rpm-build d2b433
    s = mc->fetchData(buf, m_start + DataBlockHeaderLength + off, 8);
rpm-build d2b433
    if (s != 8) {
rpm-build d2b433
        return Option<std::string>();
rpm-build d2b433
    }
rpm-build d2b433
    buf[8] = 0;
rpm-build d2b433
    return Option<std::string>(buf);
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
MRWContainer::MRWContainer(const IO::Stream::Ptr &_file, off_t _offset)
rpm-build d2b433
    : IfdFileContainer(_file, _offset)
rpm-build d2b433
{
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
MRWContainer::~MRWContainer()
rpm-build d2b433
{
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
IfdFileContainer::EndianType MRWContainer::isMagicHeader(const char *p, int len)
rpm-build d2b433
{
rpm-build d2b433
    if (len < 4) {
rpm-build d2b433
        // we need at least 4 bytes to check
rpm-build d2b433
        return ENDIAN_NULL;
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    if ((p[0] == 0x00) && (p[1] == 'M') && (p[2] == 'R') && (p[3] == 'M')) {
rpm-build d2b433
rpm-build d2b433
        LOGDBG1("Identified MRW file\n");
rpm-build d2b433
rpm-build d2b433
        return ENDIAN_BIG;
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    LOGDBG1("Unidentified MRW file\n");
rpm-build d2b433
rpm-build d2b433
    return ENDIAN_NULL;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
bool MRWContainer::locateDirsPreHook()
rpm-build d2b433
{
rpm-build d2b433
    char version[9];
rpm-build d2b433
    off_t position;
rpm-build d2b433
rpm-build d2b433
    LOGDBG1("> MRWContainer::locateDirsPreHook()\n");
rpm-build d2b433
    m_endian = ENDIAN_BIG;
rpm-build d2b433
rpm-build d2b433
    /* MRW file always starts with an MRM datablock. */
rpm-build d2b433
    mrm = std::make_shared<MRW::DataBlock>(m_offset, this);
rpm-build d2b433
    if (mrm->name() != "MRM") {
rpm-build d2b433
        LOGWARN("MRW file begins not with MRM block, "
rpm-build d2b433
                "but with unrecognized DataBlock :: name == %s\n",
rpm-build d2b433
                mrm->name().c_str());
rpm-build d2b433
        return false;
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /* Subblocks are contained within the MRM block. Scan them and create
rpm-build d2b433
     * appropriate block descriptors.
rpm-build d2b433
     */
rpm-build d2b433
    position = mrm->offset() + MRW::DataBlockHeaderLength;
rpm-build d2b433
    while (position < pixelDataOffset()) {
rpm-build d2b433
        auto ref = std::make_shared<MRW::DataBlock>(position, this);
rpm-build d2b433
        LOGDBG1("Loaded DataBlock :: name == %s\n", ref->name().c_str());
rpm-build d2b433
        if (!ref || !ref->loaded()) {
rpm-build d2b433
            break;
rpm-build d2b433
        }
rpm-build d2b433
        if (ref->name() == "PRD") {
rpm-build d2b433
            if (prd) {
rpm-build d2b433
                LOGWARN("File contains duplicate DataBlock :: name == %s\n",
rpm-build d2b433
                        ref->name().c_str());
rpm-build d2b433
            }
rpm-build d2b433
            prd = ref;
rpm-build d2b433
        } else if (ref->name() == "TTW") {
rpm-build d2b433
            if (ttw) {
rpm-build d2b433
                LOGWARN("File contains duplicate DataBlock :: name == %s\n",
rpm-build d2b433
                        ref->name().c_str());
rpm-build d2b433
            }
rpm-build d2b433
            ttw = ref;
rpm-build d2b433
        } else if (ref->name() == "WBG") {
rpm-build d2b433
            if (wbg) {
rpm-build d2b433
                LOGWARN("File contains duplicate DataBlock :: name == %s\n",
rpm-build d2b433
                        ref->name().c_str());
rpm-build d2b433
            }
rpm-build d2b433
            wbg = ref;
rpm-build d2b433
        } else if (ref->name() == "RIF") {
rpm-build d2b433
            if (rif) {
rpm-build d2b433
                LOGWARN("File contains duplicate DataBlock :: name == %s\n",
rpm-build d2b433
                        ref->name().c_str());
rpm-build d2b433
            }
rpm-build d2b433
            rif = ref;
rpm-build d2b433
        } else if (ref->name() != "PAD") {
rpm-build d2b433
            LOGWARN("File contains unrecognized DataBlock :: name == %s\n",
rpm-build d2b433
                    ref->name().c_str());
rpm-build d2b433
        }
rpm-build d2b433
        position = ref->offset() + MRW::DataBlockHeaderLength + ref->length();
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /* Check that we found all the expected data blocks. */
rpm-build d2b433
    if (!prd) {
rpm-build d2b433
        LOGWARN("File does NOT contain expected DataBlock :: name == PRD\n");
rpm-build d2b433
        return false;
rpm-build d2b433
    }
rpm-build d2b433
    if (!ttw) {
rpm-build d2b433
        LOGWARN("File does NOT contain expected DataBlock :: name == TTW\n");
rpm-build d2b433
        return false;
rpm-build d2b433
    }
rpm-build d2b433
    if (!wbg) {
rpm-build d2b433
        LOGWARN("File does NOT contain expected DataBlock :: name == WBG\n");
rpm-build d2b433
        return false;
rpm-build d2b433
    }
rpm-build d2b433
    if (!rif) {
rpm-build d2b433
        LOGWARN("File does NOT contain expected DataBlock :: name == RIF\n");
rpm-build d2b433
        return false;
rpm-build d2b433
    }
rpm-build d2b433
rpm-build d2b433
    /* Extract the file version string. */
rpm-build d2b433
    if (fetchData(version,
rpm-build d2b433
                  prd->offset() + MRW::DataBlockHeaderLength + MRW::PRD_VERSION,
rpm-build d2b433
                  8) != 8) {
rpm-build d2b433
        // FIXME: Handle error
rpm-build d2b433
        LOGDBG1("  Error reading version string\n");
rpm-build d2b433
    }
rpm-build d2b433
    version[8] = '\0';
rpm-build d2b433
    m_version = std::string(version);
rpm-build d2b433
    LOGDBG1("  MRW file version == %s\n", m_version.c_str());
rpm-build d2b433
rpm-build d2b433
    /* For the benefit of our parent class, set the container offset to the
rpm-build d2b433
     * beginning of
rpm-build d2b433
     * the TIFF data (the contents of the TTW data block), and seek there.
rpm-build d2b433
     */
rpm-build d2b433
    m_offset = ttw->offset() + MRW::DataBlockHeaderLength;
rpm-build d2b433
rpm-build d2b433
    // TODO: Not sure exactly here the origin of this.
rpm-build d2b433
    // But it doesn't work.
rpm-build d2b433
    //  if((version[2] != '7') || (version[3] != '3')) {
rpm-build d2b433
    setExifOffsetCorrection(m_offset);
rpm-build d2b433
    LOGDBG1("setting correction to %ld\n", m_offset);
rpm-build d2b433
    //  }
rpm-build d2b433
rpm-build d2b433
    m_file->seek(m_offset, SEEK_SET);
rpm-build d2b433
    LOGDBG1("< MRWContainer\n");
rpm-build d2b433
rpm-build d2b433
    return true;
rpm-build d2b433
}
rpm-build d2b433
rpm-build d2b433
}
rpm-build d2b433
}