exiv2/src/rafimage.cpp
tbeu 6b1615840f Remove redundant check
V547 Expression 'bPrint' is always true. rafimage.cpp 112
V547 Expression 'bPrint' is always true. rafimage.cpp 125
V547 Expression 'bPrint' is always true. rafimage.cpp 136
V547 Expression 'bPrint' is always true. rafimage.cpp 147
V547 Expression 'bPrint' is always true. rafimage.cpp 158
V547 Expression 'bPrint' is always true. rafimage.cpp 169
V547 Expression 'bPrint' is always true. rafimage.cpp 190
V547 Expression 'bPrint' is always true. rafimage.cpp 213
V547 Expression 'bPrint' is always true. rafimage.cpp 236
V547 Expression 'bPrint' is always true. rafimage.cpp 252
V547 Expression 'bPrint' is always true. rafimage.cpp 262
V547 Expression 'bPrint' is always true. rafimage.cpp 272
2018-06-02 09:43:20 +02:00

353 lines
12 KiB
C++

// ***************************************************************** -*- C++ -*-
/*
* Copyright (C) 2004-2017 Andreas Huggel <ahuggel@gmx.net>
*
* This program is part of the Exiv2 distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
*/
/*
File: rafimage.cpp
Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
History: 05-Feb-07, ahu: created
Credits: See header file
*/
// *****************************************************************************
// included header files
#include "config.h"
#include "rafimage.hpp"
#include "tiffimage.hpp"
#include "image_int.hpp"
#include "image.hpp"
#include "basicio.hpp"
#include "error.hpp"
#include "futils.hpp"
// + standard includes
#include <string>
#include <cstring>
#include <iostream>
#include <cassert>
// *****************************************************************************
// class member definitions
namespace Exiv2 {
RafImage::RafImage(BasicIo::AutoPtr io, bool /*create*/)
: Image(ImageType::raf, mdExif | mdIptc | mdXmp, io)
{
} // RafImage::RafImage
std::string RafImage::mimeType() const
{
return "image/x-fuji-raf";
}
int RafImage::pixelWidth() const
{
Exiv2::ExifData::const_iterator widthIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension"));
if (widthIter != exifData_.end() && widthIter->count() > 0) {
return widthIter->toLong();
}
return 0;
}
int RafImage::pixelHeight() const
{
Exiv2::ExifData::const_iterator heightIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension"));
if (heightIter != exifData_.end() && heightIter->count() > 0) {
return heightIter->toLong();
}
return 0;
}
void RafImage::setExifData(const ExifData& /*exifData*/)
{
// Todo: implement me!
throw(Error(kerInvalidSettingForImage, "Exif metadata", "RAF"));
}
void RafImage::setIptcData(const IptcData& /*iptcData*/)
{
// Todo: implement me!
throw(Error(kerInvalidSettingForImage, "IPTC metadata", "RAF"));
}
void RafImage::setComment(const std::string& /*comment*/)
{
// not supported
throw(Error(kerInvalidSettingForImage, "Image comment", "RAF"));
}
void RafImage::printStructure(std::ostream& out, PrintStructureOption option, int depth) {
if (io_->open() != 0) {
throw Error(kerDataSourceOpenFailed, io_->path(), strError());
}
// Ensure this is the correct image type
if (!isRafType(*io_, true)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "RAF");
}
const bool bPrint = option==kpsBasic || option==kpsRecursive;
if ( bPrint ) {
io_->seek(0,BasicIo::beg); // rewind
{
out << Internal::indent(depth)
<< "STRUCTURE OF RAF FILE: "
<< io().path()
<< std::endl;
out << Internal::indent(depth)
<< Internal::stringFormat(" Length | Offset | Payload")
<< std::endl;
}
byte magicdata [17];
io_->read(magicdata, 16);
magicdata[16] = 0;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 16, 0)
<< "Magic number : "
<< std::string((char*)&magicdata)
<< std::endl;
}
byte data1 [5];
io_->read(data1, 4);
data1[4] = 0;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 16)
<< "data 1 : "
<< std::string((char*)&data1)
<< std::endl;
}
byte data2 [9];
io_->read(data2, 8);
data2[8] = 0;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 8, 20)
<< "data 2 : "
<< std::string((char*)&data2)
<< std::endl;
}
byte camdata [33];
io_->read(camdata, 32);
camdata[32] = 0;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 32, 28)
<< "camera : "
<< std::string((char*)&camdata)
<< std::endl;
}
byte dir_version [5];
io_->read(dir_version, 4);
dir_version[4] = 0;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 60)
<< "dir version : "
<< std::string((char*)&dir_version)
<< std::endl;
}
byte unknown [20];
io_->read(unknown, 20);
byte jpg_img_offset [4];
io_->read(jpg_img_offset, 4);
byte jpg_img_length [4];
io_->read(jpg_img_length, 4);
long jpg_img_off = Exiv2::getULong((const byte *) jpg_img_offset, bigEndian);
long jpg_img_len = Exiv2::getULong((const byte *) jpg_img_length, bigEndian);
std::stringstream j_off;
std::stringstream j_len;
j_off << jpg_img_off;
j_len << jpg_img_len;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 84)
<< "JPEG Image Offset : "
<< j_off.str()
<< std::endl;
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 88)
<< "JPEG Image Length : "
<< j_len.str()
<< std::endl;
}
byte cfa_header_offset [4];
io_->read(cfa_header_offset, 4);
byte cfa_header_length [4];
io_->read(cfa_header_length, 4);
long cfa_hdr_off = Exiv2::getULong((const byte *) cfa_header_offset, bigEndian);
long cfa_hdr_len = Exiv2::getULong((const byte *) cfa_header_length, bigEndian);
std::stringstream ch_off;
std::stringstream ch_len;
ch_off << cfa_hdr_off;
ch_len << cfa_hdr_len;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 92)
<< "CFA Header Offset : "
<< ch_off.str()
<< std::endl;
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 96)
<< "CFA Header Length : "
<< ch_len.str()
<< std::endl;
}
byte cfa_offset [4];
io_->read(cfa_offset, 4);
byte cfa_length [4];
io_->read(cfa_length, 4);
long cfa_off = Exiv2::getULong((const byte *) cfa_offset, bigEndian);
long cfa_len = Exiv2::getULong((const byte *) cfa_length, bigEndian);
std::stringstream c_off;
std::stringstream c_len;
c_off << cfa_off;
c_len << cfa_len;
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 100)
<< "CFA Offset : "
<< c_off.str()
<< std::endl;
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", 4, 104)
<< "CFA Length : "
<< c_len.str()
<< std::endl;
}
io_->seek(jpg_img_off, BasicIo::beg); // rewind
DataBuf payload(16); // header is different from chunks
io_->read(payload.pData_, payload.size_);
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", jpg_img_len, jpg_img_off)
<< "jpg image / exif : "
<< Internal::binaryToString(payload, payload.size_)
<< std::endl;
}
io_->seek(cfa_hdr_off, BasicIo::beg); // rewind
io_->read(payload.pData_, payload.size_);
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", cfa_hdr_len, cfa_hdr_off)
<< "CFA Header: "
<< Internal::binaryToString(payload, payload.size_)
<< std::endl;
}
io_->seek(cfa_off, BasicIo::beg); // rewind
io_->read(payload.pData_, payload.size_);
{
out << Internal::indent(depth)
<< Internal::stringFormat(" %8u | %8u | ", cfa_len, cfa_off)
<< "CFA : "
<< Internal::binaryToString(payload, payload.size_)
<< std::endl;
}
}
} // RafImage::printStructure
void RafImage::readMetadata()
{
#ifdef DEBUG
std::cerr << "Reading RAF file " << io_->path() << "\n";
#endif
if (io_->open() != 0) throw Error(kerDataSourceOpenFailed, io_->path(), strError());
IoCloser closer(*io_);
// Ensure that this is the correct image type
if (!isRafType(*io_, false)) {
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
throw Error(kerNotAnImage, "RAF");
}
clearMetadata();
io_->seek(84,BasicIo::beg);
byte jpg_img_offset [4];
io_->read(jpg_img_offset, 4);
byte jpg_img_length [4];
io_->read(jpg_img_length, 4);
long jpg_img_off = Exiv2::getULong((const byte *) jpg_img_offset, bigEndian);
long jpg_img_len = Exiv2::getULong((const byte *) jpg_img_length, bigEndian);
DataBuf buf(jpg_img_len - 12);
io_->seek(jpg_img_off + 12,BasicIo::beg);
io_->read(buf.pData_, buf.size_ - 12);
if (io_->error() || io_->eof()) throw Error(kerFailedToReadImageData);
io_->seek(0,BasicIo::beg); // rewind
ByteOrder bo = TiffParser::decode(exifData_,
iptcData_,
xmpData_,
buf.pData_,
buf.size_);
exifData_["Exif.Image2.JPEGInterchangeFormat"] = getULong(jpg_img_offset, bigEndian);
exifData_["Exif.Image2.JPEGInterchangeFormatLength"] = getULong(jpg_img_length, bigEndian);
setByteOrder(bo);
} // RafImage::readMetadata
void RafImage::writeMetadata()
{
//! Todo: implement me!
throw(Error(kerWritingImageFormatUnsupported, "RAF"));
} // RafImage::writeMetadata
// *************************************************************************
// free functions
Image::AutoPtr newRafInstance(BasicIo::AutoPtr io, bool create)
{
Image::AutoPtr image(new RafImage(io, create));
if (!image->good()) {
image.reset();
}
return image;
}
bool isRafType(BasicIo& iIo, bool advance)
{
const int32_t len = 8;
byte buf[len];
iIo.read(buf, len);
if (iIo.error() || iIo.eof()) {
return false;
}
int rc = memcmp(buf, "FUJIFILM", 8);
if (!advance || rc != 0) {
iIo.seek(-len, BasicIo::cur);
}
return rc == 0;
}
} // namespace Exiv2