34#include <boost/algorithm/string.hpp>
38#include <libopenraw/metadata.h>
39#include <libopenraw/cameraids.h>
40#include <libopenraw/consts.h>
41#include <libopenraw/debug.h>
45#include "thumbnail.hpp"
46#include "metavalue.hpp"
48#include "io/stream.hpp"
50#include "io/memstream.hpp"
51#include "rawcontainer.hpp"
52#include "tiffepfile.hpp"
64#include "exception.hpp"
65#include "rawfile_private.hpp"
67#include "rawfilefactory.hpp"
80 using namespace std::placeholders;
83 std::bind(&Internals::Cr2File::factory, _1),
86 std::bind(&Internals::NefFile::factory, _1),
89 std::bind(&Internals::NefFile::factory, _1),
92 std::bind(&Internals::ArwFile::factory, _1),
95 std::bind(&Internals::OrfFile::factory, _1),
98 std::bind(&Internals::DngFile::factory, _1),
101 std::bind(&Internals::PEFFile::factory, _1),
104 std::bind(&Internals::CRWFile::factory, _1),
107 std::bind(&Internals::ERFFile::factory, _1),
110 std::bind(&Internals::MRWFile::factory, _1),
113 std::bind(&Internals::Rw2File::factory, _1),
116 std::bind(&Internals::Rw2File::factory, _1),
119 std::bind(&Internals::Rw2File::factory, _1),
122 std::bind(&Internals::RafFile::factory, _1),
131 m_type_id(OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NONE, OR_TYPEID_UNKNOWN)),
139 for(
auto value : m_metadata)
152 Internals::ThumbLocations m_thumbLocations;
153 std::map<int32_t, MetaValue*> m_metadata;
172 if (_typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
173 type = identify(_filename);
181 LOGWARN(
"factory not found\n");
184 if (iter->second == NULL) {
185 LOGWARN(
"factory is NULL\n");
188 IO::Stream::Ptr f(
new IO::File(_filename));
189 return iter->second(f);
194 RawFile::Type _typeHint)
198 if (_typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
199 ::or_error err = identifyBuffer(buffer, len,
type);
200 if(err != OR_ERROR_NONE) {
201 LOGERR(
"error identifying buffer\n");
210 LOGWARN(
"factory not found\n");
213 if (iter->second ==
nullptr) {
214 LOGWARN(
"factory is NULL\n");
218 return iter->second(f);
222RawFile::Type RawFile::identify(
const char*_filename)
224 const char *e = ::strrchr(_filename,
'.');
226 LOGDBG1(
"Extension not found\n");
227 return OR_RAWFILE_TYPE_UNKNOWN;
229 std::string extension(e + 1);
230 if (extension.length() > 3) {
231 return OR_RAWFILE_TYPE_UNKNOWN;
234 boost::to_lower(extension);
237 auto iter = extensions.find(extension);
238 if (iter == extensions.end())
240 return OR_RAWFILE_TYPE_UNKNOWN;
245::or_error RawFile::identifyBuffer(
const uint8_t* buff,
size_t len,
246 RawFile::Type &_type)
248 _type = OR_RAWFILE_TYPE_UNKNOWN;
250 return OR_ERROR_BUF_TOO_SMALL;
252 if(memcmp(buff,
"\0MRM", 4) == 0) {
253 _type = OR_RAWFILE_TYPE_MRW;
254 return OR_ERROR_NONE;
256 if(memcmp(buff,
"II\x1a\0\0\0HEAPCCDR", 14) == 0) {
257 _type = OR_RAWFILE_TYPE_CRW;
258 return OR_ERROR_NONE;
260 if(memcmp(buff,
"IIRO", 4) == 0) {
261 _type = OR_RAWFILE_TYPE_ORF;
262 return OR_ERROR_NONE;
264 if(memcmp(buff,
"IIU\0", 4) == 0) {
265 _type = OR_RAWFILE_TYPE_RW2;
266 return OR_ERROR_NONE;
268 if(memcmp(buff, RAF_MAGIC, RAF_MAGIC_LEN) == 0) {
269 _type = OR_RAWFILE_TYPE_RAF;
270 return OR_ERROR_NONE;
272 if((memcmp(buff,
"II\x2a\0", 4) == 0)
273 || (memcmp(buff,
"MM\0\x2a", 4) == 0)) {
276 if(memcmp(buff + 8,
"CR\x2", 3) == 0) {
277 _type = OR_RAWFILE_TYPE_CR2;
278 return OR_ERROR_NONE;
282 IO::Stream::Ptr s(
new IO::MemStream((
void*)buff, len));
283 std::unique_ptr<Internals::TiffEpFile> f(
new Internals::TiffEpFile(s, OR_RAWFILE_TYPE_TIFF));
286 const MetaValue *dng_version = f->getMetaValue(META_NS_TIFF | TIFF_TAG_DNG_VERSION);
288 LOGDBG1(
"found DNG versions\n");
289 _type = OR_RAWFILE_TYPE_DNG;
290 return OR_ERROR_NONE;
293 const MetaValue *makev = f->getMetaValue(META_NS_TIFF | EXIF_TAG_MAKE);
295 std::string makes = makev->getString(0);
296 if(makes ==
"NIKON CORPORATION") {
297 _type = OR_RAWFILE_TYPE_NEF;
299 else if(makes ==
"SEIKO EPSON CORP."){
300 _type = OR_RAWFILE_TYPE_ERF;
302 else if(makes ==
"PENTAX Corporation ") {
303 _type = OR_RAWFILE_TYPE_PEF;
305 else if(makes ==
"SONY ") {
306 _type = OR_RAWFILE_TYPE_ARW;
308 else if(makes ==
"Canon") {
309 _type = OR_RAWFILE_TYPE_CR2;
315 return OR_ERROR_NONE;
318RawFile::RawFile(RawFile::Type _type)
337 if(d->m_type_id == 0) {
350 d->m_type_id = _type_id;
355 if (d->m_sizes.empty()) {
356 LOGDBG1(
"_enumThumbnailSizes init\n");
358 if (ret != OR_ERROR_NONE) {
359 LOGDBG1(
"_enumThumbnailSizes failed\n");
368 ::or_error ret = OR_ERROR_NOT_FOUND;
369 uint32_t smallest_bigger = 0xffffffff;
370 uint32_t biggest_smaller = 0;
371 uint32_t found_size = 0;
373 LOGDBG1(
"requested size %u\n", tsize);
377 for (
auto s : sizes) {
378 LOGDBG1(
"current iter is %u\n", s);
380 if (s > biggest_smaller) {
385 if(s < smallest_bigger) {
395 if (found_size == 0) {
396 found_size = (smallest_bigger != 0xffffffff ?
397 smallest_bigger : biggest_smaller);
400 if (found_size != 0) {
401 LOGDBG1(
"size %u found\n", found_size);
406 LOGDBG1(
"no size found\n");
407 ret = OR_ERROR_NOT_FOUND;
418 ::or_error ret = OR_ERROR_NOT_FOUND;
419 auto iter = d->m_thumbLocations.find(size);
420 if(iter != d->m_thumbLocations.end())
424 uint32_t byte_length= desc.length;
425 uint32_t offset = desc.
offset;
427 LOGDBG1(
"Thumbnail at %u of %u bytes.\n", offset, byte_length);
429 if (byte_length != 0) {
430 void *p = thumbnail.allocData(byte_length);
433 if (real_size < byte_length) {
434 LOGWARN(
"Size mismatch for data: got %lu expected %u ignoring.\n",
435 real_size, byte_length);
448 d->m_thumbLocations[size] = desc;
453 LOGDBG1(
"getRawData()\n");
455 if (ret != OR_ERROR_NONE) {
460 uint32_t matrix_size = 0;
463 double *matrix =
new double[matrix_size];
465 rawdata.setColourMatrix1(matrix, matrix_size);
476 LOGDBG1(
"options are %u\n", options);
477 ::or_error ret =
getRawData(rawdata, options);
478 if(ret == OR_ERROR_NONE) {
488 const MetaValue * value = getMetaValue(META_NS_TIFF
489 | EXIF_TAG_ORIENTATION);
494 idx = value->getInteger(0);
497 LOGDBG1(
"wrong type - %s\n", e.what());
512::or_error RawFile::getColourMatrix2(
double* matrix, uint32_t & size)
519 int32_t meta_index = 0;
522 meta_index = META_NS_TIFF | DNG_TAG_COLORMATRIX1;
525 meta_index = META_NS_TIFF | DNG_TAG_COLORMATRIX2;
529 return OR_ERROR_INVALID_PARAM;
531 const MetaValue* meta = getMetaValue(meta_index);
536 return OR_ERROR_INVALID_PARAM;
538 return _getBuiltinColourMatrix(d->m_matrices,
typeId(), matrix, size);
540 uint32_t count = meta->getCount();
544 return OR_ERROR_BUF_TOO_SMALL;
547 for(uint32_t i = 0; i < count; i++) {
548 matrix[i] = meta->getDouble(i);
552 return OR_ERROR_NONE;
557 return _getCalibrationIlluminant(1);
560ExifLightsourceValue RawFile::getCalibrationIlluminant2()
562 return _getCalibrationIlluminant(2);
565ExifLightsourceValue RawFile::_getCalibrationIlluminant(uint16_t index)
567 int32_t meta_index = 0;
570 meta_index = META_NS_TIFF | DNG_TAG_CALIBRATION_ILLUMINANT1;
573 meta_index = META_NS_TIFF | DNG_TAG_CALIBRATION_ILLUMINANT2;
576 return EV_LIGHTSOURCE_UNKNOWN;
578 const MetaValue* meta = getMetaValue(meta_index);
581 return (index == 1) ? EV_LIGHTSOURCE_D65 : EV_LIGHTSOURCE_UNKNOWN;
583 return (ExifLightsourceValue)meta->getInteger(0);
586const MetaValue *RawFile::getMetaValue(int32_t meta_index)
588 MetaValue *val = NULL;
589 auto iter = d->m_metadata.find(meta_index);
590 if(iter == d->m_metadata.end()) {
591 val = _getMetaValue(meta_index);
593 d->m_metadata[meta_index] = val;
604RawFile::_lookupCameraId(
const camera_ids_t * map,
const std::string& value)
611 if(value == p->model) {
619RawFile::TypeId RawFile::_typeIdFromModel(
const std::string & make,
620 const std::string & model)
622 const camera_ids_t * p = _lookupCameraId(d->m_cam_ids, model);
624 return _typeIdFromMake(make);
630 {
"Canon", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 0) },
631 {
"NIKON CORPORATION", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 0) },
632 {
"LEICA CAMERA AG ", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_LEICA, 0) },
633 {
"Leica Camera AG", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_LEICA, 0) },
634 {
"Panasonic", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_PANASONIC, 0) },
636 {
"Minolta", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA, 0) },
637 {
"FujiFilm", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_FUJIFILM, 0) },
643RawFile::_typeIdFromMake(
const std::string& make)
652void RawFile::_setIdMap(
const camera_ids_t *map)
658RawFile::_getMatrices()
const
660 return d->m_matrices;
665 d->m_matrices = matrices;
671 uint16_t & black, uint16_t & white)
674 return OR_ERROR_NOT_FOUND;
677 if(m->camera == type_id) {
680 return OR_ERROR_NONE;
684 return OR_ERROR_NOT_FOUND;
694 return OR_ERROR_NOT_FOUND;
697 return OR_ERROR_BUF_TOO_SMALL;
701 if(m->camera == type_id) {
702 for(
int i = 0; i < 9; i++) {
703 matrix[i] =
static_cast<double>(m->matrix[i]) / 10000.0;
706 return OR_ERROR_NONE;
711 return OR_ERROR_NOT_FOUND;
void setDataType(DataType _type)
virtual void setDimensions(uint32_t x, uint32_t y)
size_t fetchData(void *buf, off_t offset, size_t buf_size)
const double * getColourMatrix1(uint32_t &size) const
::or_error getRenderedImage(BitmapData &bitmapdata, uint32_t options)
static const char ** fileExtensions()
static Extensions & extensions()
std::vector< uint32_t > m_sizes
virtual::or_error _enumThumbnailSizes(std::vector< uint32_t > &list)=0
virtual::or_error _getThumbnail(uint32_t size, Thumbnail &thumbnail)
::or_error getThumbnail(uint32_t size, Thumbnail &thumbnail)
void _setTypeId(TypeId _type_id)
::or_error getRawData(RawData &rawdata, uint32_t options)
uint32_t colourMatrixSize()
virtual::or_error _getColourMatrix(uint32_t index, double *matrix, uint32_t &size)
::or_error getColourMatrix1(double *matrix, uint32_t &size)
virtual Internals::RawContainer * getContainer() const =0
static RawFile * newRawFile(const char *_filename, Type _typeHint=OR_RAWFILE_TYPE_UNKNOWN)
const std::vector< uint32_t > & listThumbnailSizes(void)
::or_error getRenderedImage(BitmapData &bitmapdata, uint32_t options)
ExifLightsourceValue getCalibrationIlluminant1()
virtual::or_error _getRawData(RawData &data, uint32_t options)=0
static const char ** fileExtensions()
static RawFile * newRawFileFromMemory(const uint8_t *buffer, uint32_t len, Type _typeHint=OR_RAWFILE_TYPE_UNKNOWN)
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard....