libopenraw  0.3.7
rawfile.cpp
1 /*
2  * libopenraw - rawfile.cpp
3  *
4  * Copyright (C) 2008 Novell, Inc.
5  * Copyright (C) 2006-2023 Hubert Figuière
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 #include <stddef.h>
23 #include <stdint.h>
24 
25 #include <cstring>
26 #include <functional>
27 #include <map>
28 #include <memory>
29 #include <mutex>
30 #include <string>
31 #include <utility>
32 #include <vector>
33 
34 #include <boost/algorithm/string.hpp>
35 
36 #include "trace.hpp"
37 
38 #include <libopenraw/cameraids.h>
39 #include <libopenraw/consts.h>
40 #include <libopenraw/debug.h>
41 #include <libopenraw/metadata.h>
42 
43 #include "metavalue.hpp"
44 #include "rawdata.hpp"
45 #include "rawfile.hpp"
46 #include "thumbnail.hpp"
47 #include "metadata.hpp"
48 
49 #include "arwfile.hpp"
50 #include "cr2file.hpp"
51 #include "cr3file.hpp"
52 #include "crwfile.hpp"
53 #include "dngfile.hpp"
54 #include "erffile.hpp"
55 #include "exception.hpp"
56 #include "io/file.hpp"
57 #include "io/memstream.hpp"
58 #include "io/stream.hpp"
59 #include "mrwfile.hpp"
60 #include "neffile.hpp"
61 #include "orffile.hpp"
62 #include "peffile.hpp"
63 #include "raffile.hpp"
64 #include "rawcontainer.hpp"
65 #include "rawfile_private.hpp"
66 #include "rw2file.hpp"
67 #include "tiffepfile.hpp"
68 
69 #include "rawfilefactory.hpp"
70 
71 using std::string;
72 using namespace Debug;
73 
74 namespace OpenRaw {
75 
76 class BitmapData;
77 
78 using Internals::RawFileFactory;
79 
80 static std::once_flag inited;
81 
82 /* This function is designed to be reentrant. */
83 void init(void)
84 {
85  std::call_once(inited, [] {
86  using namespace std::placeholders;
87 
88  RawFileFactory::registerType(OR_RAWFILE_TYPE_CR2,
89  std::bind(&Internals::Cr2File::factory, _1),
90  "cr2");
91  RawFileFactory::registerType(OR_RAWFILE_TYPE_NEF,
92  std::bind(&Internals::NefFile::factory, _1),
93  "nef");
94  RawFileFactory::registerType(OR_RAWFILE_TYPE_NRW,
95  std::bind(&Internals::NefFile::factory, _1),
96  "nrw");
97  RawFileFactory::registerType(OR_RAWFILE_TYPE_ARW,
98  std::bind(&Internals::ArwFile::factory, _1),
99  "arw");
100  RawFileFactory::registerType(OR_RAWFILE_TYPE_SR2,
101  std::bind(&Internals::ArwFile::factory, _1),
102  "sr2");
103  RawFileFactory::registerType(OR_RAWFILE_TYPE_ORF,
104  std::bind(&Internals::OrfFile::factory, _1),
105  "orf");
106  RawFileFactory::registerType(OR_RAWFILE_TYPE_DNG,
107  std::bind(&Internals::DngFile::factory, _1),
108  "dng");
109  RawFileFactory::registerType(OR_RAWFILE_TYPE_GPR,
110  std::bind(&Internals::DngFile::factory, _1),
111  "gpr");
112  RawFileFactory::registerType(OR_RAWFILE_TYPE_PEF,
113  std::bind(&Internals::PEFFile::factory, _1),
114  "pef");
115  RawFileFactory::registerType(OR_RAWFILE_TYPE_CRW,
116  std::bind(&Internals::CRWFile::factory, _1),
117  "crw");
118  RawFileFactory::registerType(OR_RAWFILE_TYPE_ERF,
119  std::bind(&Internals::ERFFile::factory, _1),
120  "erf");
121  RawFileFactory::registerType(OR_RAWFILE_TYPE_MRW,
122  std::bind(&Internals::MRWFile::factory, _1),
123  "mrw");
124  RawFileFactory::registerType(OR_RAWFILE_TYPE_RW2,
125  std::bind(&Internals::Rw2File::factory, _1),
126  "raw");
127  RawFileFactory::registerType(OR_RAWFILE_TYPE_RW2,
128  std::bind(&Internals::Rw2File::factory, _1),
129  "rw2");
130  RawFileFactory::registerType(OR_RAWFILE_TYPE_RW2,
131  std::bind(&Internals::Rw2File::factory, _1),
132  "rwl");
133  RawFileFactory::registerType(OR_RAWFILE_TYPE_RAF,
134  std::bind(&Internals::RafFile::factory, _1),
135  "raf");
136  RawFileFactory::registerType(OR_RAWFILE_TYPE_CR3,
137  std::bind(&Internals::Cr3File::factory, _1),
138  "cr3");
139  });
140 }
141 
143 public:
144  Private(Type t)
145  : m_type(t)
146  , m_type_id(
147  OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NONE, OR_TYPEID_UNKNOWN))
148  , m_sizes()
149  , m_cam_ids(NULL)
150  , m_matrices(NULL)
151  {
152  }
153  ~Private()
154  {
155  for (auto value : m_metadata) {
156  if (value.second) {
157  delete value.second;
158  }
159  }
160  }
164  TypeId m_type_id;
166  std::vector<uint32_t> m_sizes;
167  Internals::ThumbLocations m_thumbLocations;
168  std::map<int32_t, MetaValue*> m_metadata;
169  const camera_ids_t* m_cam_ids;
170  const Internals::BuiltinColourMatrix* m_matrices;
177  Internals::MakerNoteDir::Ref m_makerNoteIfd;
178 };
179 
180 const char** RawFile::fileExtensions()
181 {
182  init();
183 
184  return RawFileFactory::fileExtensions();
185 }
186 
187 RawFile* RawFile::newRawFile(const char* filename, RawFile::Type typeHint)
188 {
189  init();
190 
191  Type type;
192  if (typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
193  type = identify(filename);
194  if (type == OR_RAWFILE_TYPE_UNKNOWN) {
195  IO::Stream::Ptr f(new IO::File(filename));
196  f->open();
197  auto err = identifyIOBuffer(f, type);
198  if (err != OR_ERROR_NONE) {
199  LOGERR("identifyIOBuffer returned %u\n", err);
200  return nullptr;
201  }
202  }
203  }
204  else {
205  type = typeHint;
206  }
207  LOGDBG1("factory size %lu\n", (LSIZE)RawFileFactory::table().size());
208  auto iter = RawFileFactory::table().find(type);
209  if (iter == RawFileFactory::table().end()) {
210  LOGWARN("factory not found\n");
211  return NULL;
212  }
213  if (iter->second == NULL) {
214  LOGWARN("factory is NULL\n");
215  return NULL;
216  }
217  IO::Stream::Ptr f(new IO::File(filename));
218  return iter->second(f);
219 }
220 
221 RawFile* RawFile::newRawFileFromMemory(const uint8_t* buffer, uint32_t len,
222  RawFile::Type typeHint)
223 {
224  init();
225  Type type;
226  if (typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
227  ::or_error err = identifyBuffer(buffer, len, type);
228  if (err != OR_ERROR_NONE) {
229  LOGERR("error identifying buffer\n");
230  return NULL;
231  }
232  }
233  else {
234  type = typeHint;
235  }
236  auto iter = RawFileFactory::table().find(type);
237  if (iter == RawFileFactory::table().end()) {
238  LOGWARN("factory not found\n");
239  return NULL;
240  }
241  if (iter->second == nullptr) {
242  LOGWARN("factory is NULL\n");
243  return NULL;
244  }
245  IO::Stream::Ptr f(new IO::MemStream(buffer, len));
246  return iter->second(f);
247 }
248 
249 RawFile::Type RawFile::identify(const char* _filename)
250 {
251  const char* e = ::strrchr(_filename, '.');
252  if (e == NULL) {
253  LOGDBG1("Extension not found\n");
255  }
256  std::string extension(e + 1);
257  if (extension.length() > 3) {
259  }
260 
261  boost::to_lower(extension);
262 
263  const auto& extensions = RawFileFactory::extensions();
264  auto iter = extensions.find(extension);
265  if (iter == extensions.end()) {
267  }
268  return iter->second;
269 }
270 
272 RawFile::identifyBuffer(const uint8_t* buff, size_t len, RawFile::Type& _type)
273 {
274  IO::Stream::Ptr stream(new IO::MemStream(buff, len));
275  stream->open();
276  return identifyIOBuffer(stream, _type);
277 }
278 
280 RawFile::identifyIOBuffer(IO::Stream::Ptr& stream, RawFile::Type& _type)
281 {
282  off_t len = stream->filesize();
283 
284  constexpr size_t buffer_size = 16; // std::max(14, RAF_MAGIC_LEN)
285  uint8_t buff[buffer_size];
286 
287  // XXX check for error
288  stream->read(buff, buffer_size);
289 
290  _type = OR_RAWFILE_TYPE_UNKNOWN;
291  if (len <= 4) {
292  return OR_ERROR_BUF_TOO_SMALL;
293  }
294  if (memcmp(buff, "\0MRM", 4) == 0) {
295  _type = OR_RAWFILE_TYPE_MRW;
296  return OR_ERROR_NONE;
297  }
298  if (len >= 12 && (memcmp(buff + 4, "ftypcrx ", 8) == 0)) {
299  _type = OR_RAWFILE_TYPE_CR3;
300  return OR_ERROR_NONE;
301  }
302  if (len >= 14 && memcmp(buff, "II\x1a\0\0\0HEAPCCDR", 14) == 0) {
303  _type = OR_RAWFILE_TYPE_CRW;
304  return OR_ERROR_NONE;
305  }
306  if (memcmp(buff, "IIRO", 4) == 0) {
307  _type = OR_RAWFILE_TYPE_ORF;
308  return OR_ERROR_NONE;
309  }
310  if (memcmp(buff, "IIU\0", 4) == 0) {
311  _type = OR_RAWFILE_TYPE_RW2;
312  return OR_ERROR_NONE;
313  }
314  if (len >= RAF_MAGIC_LEN && memcmp(buff, RAF_MAGIC, RAF_MAGIC_LEN) == 0) {
315  _type = OR_RAWFILE_TYPE_RAF;
316  return OR_ERROR_NONE;
317  }
318  if ((memcmp(buff, "II\x2a\0", 4) == 0) ||
319  (memcmp(buff, "MM\0\x2a", 4) == 0)) {
320  // TIFF based format
321  if (len >= 12) {
322  if (memcmp(buff + 8, "CR\x2", 3) == 0) {
323  _type = OR_RAWFILE_TYPE_CR2;
324  return OR_ERROR_NONE;
325  }
326  }
327  if (len >= 8) {
328  stream->seek(0, SEEK_SET);
329  auto f = std::make_unique<Internals::TiffEpFile>(stream, OR_RAWFILE_TYPE_TIFF);
330 
331  // Take into account DNG by checking the DNGVersion tag
332  const MetaValue* dng_version =
333  f->getMetaValue(META_NS_TIFF | TIFF_TAG_DNG_VERSION);
334  if (dng_version) {
335  LOGDBG1("found DNG versions\n");
336  _type = OR_RAWFILE_TYPE_DNG;
337  return OR_ERROR_NONE;
338  }
339 
340  const MetaValue* makev =
341  f->getMetaValue(META_NS_TIFF | EXIF_TAG_MAKE);
342  if (makev) {
343  std::string makes = makev->getString(0);
344  if (makes.find("NIKON") == 0) {
345  _type = OR_RAWFILE_TYPE_NEF;
346  }
347  else if (makes == "SEIKO EPSON CORP.") {
348  _type = OR_RAWFILE_TYPE_ERF;
349  }
350  else if (makes == "PENTAX Corporation ") {
351  _type = OR_RAWFILE_TYPE_PEF;
352  }
353  else if (makes.find("SONY") == 0) {
354  _type = OR_RAWFILE_TYPE_ARW;
355  }
356  else if (makes == "Canon") {
357  _type = OR_RAWFILE_TYPE_CR2;
358  }
359  }
360  }
361  }
362  return OR_ERROR_NONE;
363 }
364 
365 RawFile::RawFile(RawFile::Type _type)
366  : d(new Private(_type))
367 {
368 }
369 
371 {
372  delete d;
373 }
374 
376 {
377  return d->m_type;
378 }
379 
380 RawFile::TypeId RawFile::typeId()
381 {
382  if (d->m_type_id == 0) {
383  _identifyId();
384  }
385  return d->m_type_id;
386 }
387 
388 RawFile::TypeId RawFile::vendorId()
389 {
390  const MetaValue* makev = getMetaValue(META_NS_TIFF | EXIF_TAG_MAKE);
391  const MetaValue* modelv = getMetaValue(META_NS_TIFF | EXIF_TAG_MODEL);
392  if (makev == nullptr) {
393  makev = getMetaValue(META_NS_TIFF | DNG_TAG_UNIQUE_CAMERA_MODEL);
394  }
395  if (makev != nullptr) {
396  std::string make = makev->getString(0);
397  std::string model;
398  if (modelv) {
399  model = modelv->getString(0);
400  }
401  return _typeIdFromMake(make, model) >> 16;
402  }
403  return OR_TYPEID_VENDOR_NONE;
404 }
405 
406 RawFile::TypeId RawFile::modelid_to_typeid(const std::map<uint32_t, RawFile::TypeId>& model_map,
407  uint32_t model_id)
408 {
409  auto iter = model_map.find(model_id);
410  if (iter != model_map.end()) {
411  return iter->second;
412  }
413  return 0;
414 }
415 
417  const Internals::ModelIdMap*&)
418 {
419  // By default there is none.
420  return false;
421 }
422 
423 RawFile::TypeId RawFile::_typeId() const
424 {
425  return d->m_type_id;
426 }
427 
428 void RawFile::_setTypeId(RawFile::TypeId _type_id)
429 {
430  d->m_type_id = _type_id;
431 }
432 
433 const std::vector<uint32_t>& RawFile::listThumbnailSizes(void)
434 {
435  if (d->m_sizes.empty()) {
436  LOGDBG1("_enumThumbnailSizes init\n");
438  if (ret != OR_ERROR_NONE) {
439  LOGDBG1("_enumThumbnailSizes failed\n");
440  }
441  }
442  return d->m_sizes;
443 }
444 
445 ::or_error RawFile::getThumbnail(uint32_t tsize, Thumbnail& thumbnail)
446 {
448  uint32_t smallest_bigger = 0xffffffff;
449  uint32_t biggest_smaller = 0;
450  uint32_t found_size = 0;
451 
452  LOGDBG1("requested size %u\n", tsize);
453 
454  auto sizes(listThumbnailSizes());
455 
456  for (auto s : sizes) {
457  LOGDBG1("current iter is %u\n", s);
458  if (s < tsize) {
459  if (s > biggest_smaller) {
460  biggest_smaller = s;
461  }
462  }
463  else if (s > tsize) {
464  if (s < smallest_bigger) {
465  smallest_bigger = s;
466  }
467  }
468  else { // s == tsize
469  found_size = tsize;
470  break;
471  }
472  }
473 
474  if (found_size == 0) {
475  found_size =
476  (smallest_bigger != 0xffffffff ? smallest_bigger : biggest_smaller);
477  }
478 
479  if (found_size != 0) {
480  LOGDBG1("size %u found\n", found_size);
481  ret = _getThumbnail(found_size, thumbnail);
482  }
483  else {
484  // no size found, let's fail gracefuly
485  LOGDBG1("no size found\n");
486  ret = OR_ERROR_NOT_FOUND;
487  }
488 
489  return ret;
490 }
491 
495 ::or_error RawFile::_getThumbnail(uint32_t size, Thumbnail& thumbnail)
496 {
498  auto iter = d->m_thumbLocations.find(size);
499  if (iter != d->m_thumbLocations.end()) {
500  const Internals::ThumbDesc& desc = iter->second;
501  thumbnail.setDataType(desc.type);
502  thumbnail.setDimensions(desc.x, desc.y);
503  if (desc.data) {
504  auto byte_length = desc.data->size();
505  void* p = thumbnail.allocData(byte_length);
506  ::memcpy(p, desc.data->data(), byte_length);
507  }
508  else {
509  uint32_t byte_length = desc.length;
510  uint32_t offset = desc.offset;
511 
512  LOGDBG1("Thumbnail at %u of %u bytes.\n", offset, byte_length);
513 
514  if (byte_length != 0) {
515  void* p = thumbnail.allocData(byte_length);
516  size_t real_size =
517  getContainer()->fetchData(p, offset, byte_length);
518  if (real_size < byte_length) {
519  LOGWARN("Size mismatch for data: got %lu expected %u "
520  "ignoring.\n",
521  (LSIZE)real_size, byte_length);
522  }
523  }
524  }
525  ret = OR_ERROR_NONE;
526  }
527 
528  return ret;
529 }
530 
531 void RawFile::_addThumbnail(uint32_t size, Internals::ThumbDesc&& desc)
532 {
533  d->m_thumbLocations[size] = std::move(desc);
534 }
535 
536 ::or_error RawFile::getRawData(RawData& rawdata, uint32_t options)
537 {
538  LOGDBG1("getRawData()\n");
539  ::or_error ret = _getRawData(rawdata, options);
540  if (ret != OR_ERROR_NONE) {
541  return ret;
542  }
543 
544  // if the colour matrix isn't copied already, do it now.
545  uint32_t matrix_size = 0;
546  if (!rawdata.getColourMatrix1(matrix_size) || !matrix_size) {
547  matrix_size = colourMatrixSize();
548  auto matrix = std::make_unique<double[]>(matrix_size);
549  if (getColourMatrix1(matrix.get(), matrix_size) == OR_ERROR_NONE) {
550  rawdata.setColourMatrix1(matrix.get(), matrix_size);
551  }
552  }
553 
554  return ret;
555 }
556 
557 ::or_error RawFile::getRenderedImage(BitmapData& bitmapdata, uint32_t options)
558 {
559  RawData rawdata;
560  LOGDBG1("options are %u\n", options);
561  ::or_error ret = getRawData(rawdata, options);
562  if (ret == OR_ERROR_NONE) {
563  ret = rawdata.getRenderedImage(bitmapdata, options);
564  }
565  return ret;
566 }
567 
569 {
570  uint32_t orientation = 0;
571  const MetaValue* value = getMetaValue(META_NS_TIFF | EXIF_TAG_ORIENTATION);
572  if (value == NULL) {
573  return 0;
574  }
575  try {
576  orientation = value->getUInteger(0);
577  }
578  catch (const Internals::BadTypeException& e) {
579  LOGDBG1("wrong type - %s\n", e.what());
580  }
581  return orientation;
582 }
583 
585 {
586  return 9;
587 }
588 
589 ::or_error RawFile::getColourMatrix1(double* matrix, uint32_t& size)
590 {
591  return _getColourMatrix(1, matrix, size);
592 }
593 
594 ::or_error RawFile::getColourMatrix2(double* matrix, uint32_t& size)
595 {
596  return _getColourMatrix(2, matrix, size);
597 }
598 
599 ::or_error RawFile::_getColourMatrix(uint32_t index, double* matrix,
600  uint32_t& size)
601 {
602  int32_t meta_index = 0;
603  switch (index) {
604  case 1:
605  meta_index = META_NS_TIFF | DNG_TAG_COLORMATRIX1;
606  break;
607  case 2:
608  meta_index = META_NS_TIFF | DNG_TAG_COLORMATRIX2;
609  break;
610  default:
611  size = 0;
612  return OR_ERROR_INVALID_PARAM;
613  }
614  const MetaValue* meta = getMetaValue(meta_index);
615 
616  if (!meta) {
617  if (index != 1) {
618  size = 0;
619  return OR_ERROR_INVALID_PARAM;
620  }
621  return _getBuiltinColourMatrix(d->m_matrices, typeId(), matrix, size);
622  }
623  uint32_t count = meta->getCount();
624  if (size < count) {
625  // return the expected size
626  size = count;
627  return OR_ERROR_BUF_TOO_SMALL;
628  }
629 
630  for (uint32_t i = 0; i < count; i++) {
631  matrix[i] = meta->getDouble(i);
632  }
633  size = count;
634 
635  return OR_ERROR_NONE;
636 }
637 
639 {
640  return _getCalibrationIlluminant(1);
641 }
642 
643 ExifLightsourceValue RawFile::getCalibrationIlluminant2()
644 {
645  return _getCalibrationIlluminant(2);
646 }
647 
649 {
651 }
652 
653 ExifLightsourceValue RawFile::_getCalibrationIlluminant(uint16_t index)
654 {
655  int32_t meta_index = 0;
656  switch (index) {
657  case 1:
658  meta_index = META_NS_TIFF | DNG_TAG_CALIBRATION_ILLUMINANT1;
659  break;
660  case 2:
661  meta_index = META_NS_TIFF | DNG_TAG_CALIBRATION_ILLUMINANT2;
662  break;
663  default:
664  return EV_LIGHTSOURCE_UNKNOWN;
665  }
666  const MetaValue* meta = getMetaValue(meta_index);
667 
668  if (!meta) {
669  return (index == 1) ? EV_LIGHTSOURCE_D65 : EV_LIGHTSOURCE_UNKNOWN;
670  }
671  return (ExifLightsourceValue)meta->getUInteger(0);
672 }
673 
674 // this one seems to be pretty much the same for all the
675 // IFD based raw files
677 {
678  const Internals::IfdDir::Ref & _mainIfd = mainIfd();
679  if (!_mainIfd) {
680  LOGERR("IfdFile::_locateExifIfd() main IFD not found\n");
681  return Internals::IfdDir::Ref();
682  }
683  return _mainIfd->getExifIFD();
684 }
685 
686 Internals::MakerNoteDir::Ref RawFile::_locateMakerNoteIfd()
687 {
688  const Internals::IfdDir::Ref & _exifIfd = exifIfd();
689  if (_exifIfd) {
690  // to not have a recursive declaration, getMakerNoteIfd() return an IfdDir.
691  return std::dynamic_pointer_cast<Internals::MakerNoteDir>(_exifIfd->getMakerNoteIfd(type()));
692  }
693  return Internals::MakerNoteDir::Ref();
694 }
695 
697 {
698  if (!d->m_cfaIfd) {
699  d->m_cfaIfd = _locateCfaIfd();
700  }
701  LOGASSERT(d->m_cfaIfd && d->m_cfaIfd->type() == OR_IFD_RAW ||
702  d->m_mainIfd && d->m_mainIfd->type() == OR_IFD_MAIN);
703  return d->m_cfaIfd;
704 }
705 
707 {
708  if (!d->m_mainIfd) {
709  d->m_mainIfd = _locateMainIfd();
710  }
711  LOGASSERT(d->m_mainIfd && d->m_mainIfd->type() == OR_IFD_MAIN);
712  return d->m_mainIfd;
713 }
714 
716 {
717  if (!d->m_exifIfd) {
718  d->m_exifIfd = _locateExifIfd();
719  }
720  LOGASSERT(d->m_exifIfd && d->m_exifIfd->type() == OR_IFD_EXIF);
721  return d->m_exifIfd;
722 }
723 
724 Internals::MakerNoteDir::Ref RawFile::makerNoteIfd()
725 {
726  if (!d->m_makerNoteIfd) {
728  }
729  LOGASSERT(!d->m_makerNoteIfd || d->m_makerNoteIfd->type() == OR_IFD_MNOTE);
730  return d->m_makerNoteIfd;
731 }
732 
733 const MetaValue* RawFile::getMetaValue(int32_t meta_index)
734 {
735  MetaValue* val = NULL;
736  auto iter = d->m_metadata.find(meta_index);
737  if (iter == d->m_metadata.end()) {
738  val = _getMetaValue(meta_index);
739  if (val != NULL) {
740  d->m_metadata[meta_index] = val;
741  }
742  }
743  else {
744  val = iter->second;
745  }
746  return val;
747 }
748 
749 MetadataIterator* RawFile::getMetadataIterator()
750 {
751  auto iter = new MetadataIterator(*this);
752 
753  return iter;
754 }
755 
756 
757 const RawFile::camera_ids_t* RawFile::_lookupCameraId(const camera_ids_t* map,
758  const std::string& value)
759 {
760  const camera_ids_t* p = map;
761  if (!p) {
762  return NULL;
763  }
764  while (p->model) {
765  if (value == p->model) {
766  return p;
767  }
768  p++;
769  }
770  return NULL;
771 }
772 
776 const RawFile::camera_ids_t* RawFile::lookupVendorId(const camera_ids_t* map,
777  const std::string& value)
778 {
779  const camera_ids_t* p = map;
780  if (!p) {
781  return NULL;
782  }
783  while (p->model) {
784  if (value.find(p->model) == 0) {
785  return p;
786  }
787  p++;
788  }
789  return NULL;
790 }
791 
792 RawFile::TypeId RawFile::_typeIdFromModel(const std::string& make,
793  const std::string& model)
794 {
795  const camera_ids_t* p = _lookupCameraId(d->m_cam_ids, model);
796  if (!p) {
797  return _typeIdFromMake(make, model);
798  }
799  return p->type_id;
800 }
801 
802 // About the order:
803 // We do a loose match (substring) of the "model" field against the Exif Make
804 // It's not a problem until Pentax and Ricoh merged.
805 // Where "PENTAX" Exif Make (Pentax) matches "PENTAX RICOH IMAGING" (Ricoh)
806 const RawFile::camera_ids_t RawFile::s_make[] = {
807  { "PENTAX RICOH IMAGING", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_RICOH, 0) },
808  { "RICOH IMAGING COMPANY, LTD.", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_RICOH, 0) },
809  { "Canon", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 0) },
810  { "NIKON", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NIKON, 0) },
811  { "LEICA", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_LEICA, 0) },
812  { "Leica", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_LEICA, 0) },
813  { "Panasonic", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_PANASONIC, 0) },
814  { "SONY", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_SONY, 0) },
815  { "OLYMPUS", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_OLYMPUS, 0) },
816  { "OM Digital Solutions", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_OLYMPUS, 0) },
817  { "PENTAX", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_PENTAX, 0) },
818  { "RICOH", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_RICOH, 0) },
819  { "SAMSUNG TECHWIN", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_SAMSUNG, 0) },
820  { "SEIKO EPSON CORP.", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_EPSON, 0) },
821  { "Konica Minolta Camera, Inc.", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA, 0) },
822  { "Minolta Co., Ltd.", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA, 0) },
823  { "KONICA MINOLTA", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA, 0) },
824  { "FUJIFILM", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_FUJIFILM, 0) },
825  { "Blackmagic", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_BLACKMAGIC, 0) },
826  { "SIGMA", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_SIGMA, 0) },
827  { "GoPro", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_GOPRO, 0) },
828  { "HASSELBLAD", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_HASSELBLAD, 0) },
829  { "Hasselblad", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_HASSELBLAD, 0) },
830  { "Apple", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_APPLE, 0) },
831  { "XIAOYI", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_XIAOYI, 0) },
832  { "ZEISS", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_ZEISS, 0) },
833  { "DJI", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_DJI, 0) },
834  { NULL, 0 }
835 };
836 
837 RawFile::TypeId RawFile::_typeIdFromMake(const std::string& make, const std::string& model)
838 {
839  const camera_ids_t* p = lookupVendorId(s_make, make);
840  if (!p) {
841  return 0;
842  }
843  if (p->type_id == OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_RICOH, 0)) {
844  // Ricoh bought Pentax and now it is a mess.
845  // If the model contain "PENTAX" it's a Pentax.
846  if (model.find("PENTAX") != std::string::npos) {
847  return OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_PENTAX, 0);
848  }
849  }
850  return p->type_id;
851 }
852 
853 void RawFile::_setIdMap(const camera_ids_t* map)
854 {
855  d->m_cam_ids = map;
856 }
857 
858 const Internals::BuiltinColourMatrix* RawFile::_getMatrices() const
859 {
860  return d->m_matrices;
861 }
862 
863 void RawFile::_setMatrices(const Internals::BuiltinColourMatrix* matrices)
864 {
865  d->m_matrices = matrices;
866 }
867 
868 /*
869  * Will return OR_ERROR_NOT_IMPLEMENTED if the builtin levels
870  * aren't found.
871  */
872 ::or_error RawFile::_getBuiltinLevels(const Internals::BuiltinColourMatrix* m,
873  TypeId type_id, uint16_t& black,
874  uint16_t& white)
875 {
876  if (!m) {
878  }
879  while (m->camera) {
880  if (m->camera == type_id) {
881  black = m->black;
882  white = m->white;
883  return OR_ERROR_NONE;
884  }
885  ++m;
886  }
888 }
889 
890 /*
891  * Will return OR_ERROR_NOT_IMPLEMENTED if the builtin matrix
892  * isn't found.
893  */
894 ::or_error RawFile::_getBuiltinColourMatrix(
895  const Internals::BuiltinColourMatrix* m, TypeId type_id, double* matrix,
896  uint32_t& size)
897 {
898  if (!m) {
900  }
901  if (size < 9) {
902  return OR_ERROR_BUF_TOO_SMALL;
903  }
904 
905  while (m->camera) {
906  if (m->camera == type_id) {
907  for (int i = 0; i < 9; i++) {
908  matrix[i] = static_cast<double>(m->matrix[i]) / 10000.0;
909  }
910  size = 9;
911  return OR_ERROR_NONE;
912  }
913  ++m;
914  }
915  size = 0;
917 }
918 }
919 
920 /*
921  Local Variables:
922  mode:c++
923  c-file-style:"stroustrup"
924  c-file-offsets:((innamespace . 0))
925  indent-tabs-mode:nil
926  fill-column:80
927  End:
928 */
Represent some bitmap data.
Definition: bitmapdata.hpp:30
void setDataType(DataType _type)
Set the data type.
Definition: bitmapdata.cpp:91
virtual void setDimensions(uint32_t x, uint32_t y)
Set the pixel dimensions of the bitmap.
Definition: bitmapdata.cpp:157
File IO stream.
Definition: file.hpp:39
Memory based stream to read memory like a file IO.
Definition: memstream.hpp:40
std::shared_ptr< Stream > Ptr
Definition: stream.hpp:47
std::shared_ptr< IfdDir > Ref
Shared ptr of an IfdDir.
Definition: ifddir.hpp:56
size_t fetchData(void *buf, off_t offset, size_t buf_size) const
Fetch the data chunk from the file.
std::unique_ptr< BitmapData > data
Metadata value.
Definition: metavalue.hpp:35
Iterator for the metadata.
Definition: metadata.hpp:34
Represent camera raw data.
Definition: rawdata.hpp:38
const double * getColourMatrix1(uint32_t &size) const
Definition: rawdata.cpp:248
::or_error getRenderedImage(BitmapData &bitmapdata, uint32_t options)
Definition: rawdata.cpp:131
Internals::IfdDir::Ref m_cfaIfd
Definition: rawfile.cpp:171
std::vector< uint32_t > m_sizes
Definition: rawfile.cpp:166
Internals::IfdDir::Ref m_mainIfd
Definition: rawfile.cpp:172
Internals::MakerNoteDir::Ref m_makerNoteIfd
Definition: rawfile.cpp:177
Internals::IfdDir::Ref m_exifIfd
Definition: rawfile.cpp:176
RAW file.
Definition: rawfile.hpp:66
virtual ::or_error _getRawData(RawData &data, uint32_t options)=0
Get the RAW data.
virtual ::or_error _getThumbnail(uint32_t size, Thumbnail &thumbnail)
Get the thumbnail of exact size.
Definition: rawfile.cpp:495
virtual Internals::MakerNoteDir::Ref _locateMakerNoteIfd()
Locate the MakerNote IFD.
Definition: rawfile.cpp:686
::or_error getThumbnail(uint32_t size, Thumbnail &thumbnail)
Get the thumbnail from the raw file.
Definition: rawfile.cpp:445
virtual Internals::IfdDir::Ref _locateCfaIfd()=0
Locate the IFD for the raw data.
TypeId typeId()
The RAW file type ID. Identify it if needed.
Definition: rawfile.cpp:380
virtual bool vendorCameraIdLocation(Internals::IfdDir::Ref &ifd, uint16_t &index, const Internals::ModelIdMap *&model_map)
Get the vendor camera ID location.
Definition: rawfile.cpp:416
void _setTypeId(TypeId _type_id)
Set the file type id.
Definition: rawfile.cpp:428
Internals::IfdDir::Ref exifIfd()
Get the Exif IFD.
Definition: rawfile.cpp:715
virtual Internals::IfdDir::Ref _locateExifIfd()
Locate the Exif IFD.
Definition: rawfile.cpp:676
::or_error getRawData(RawData &rawdata, uint32_t options)
Get the RAW data.
Definition: rawfile.cpp:536
uint32_t colourMatrixSize()
Definition: rawfile.cpp:584
virtual ::or_error _getColourMatrix(uint32_t index, double *matrix, uint32_t &size)
Get the colour matrix.
Definition: rawfile.cpp:599
virtual Internals::IfdDir::Ref _locateMainIfd()=0
Locate the main IFD.
virtual ::or_error _enumThumbnailSizes(std::vector< uint32_t > &list)=0
Enumerate the thumbnail sizes.
uint32_t getOrientation()
Get the orientation of the image, using Exif enums.
Definition: rawfile.cpp:568
Internals::MakerNoteDir::Ref makerNoteIfd()
Get the MakerNote IFD.
Definition: rawfile.cpp:724
::or_error getColourMatrix1(double *matrix, uint32_t &size)
Get colour matrix.
Definition: rawfile.cpp:589
virtual Internals::RawContainer * getContainer() const =0
Get the container.
virtual ~RawFile()
Destructor.
Definition: rawfile.cpp:370
virtual MetaValue * _getMetaValue(int32_t)=0
Implementation for getMetaValue()
virtual void _identifyId()=0
Identify the file and set the ID internally.
const std::vector< uint32_t > & listThumbnailSizes(void)
List the available thumbnail sizes.
Definition: rawfile.cpp:433
::or_error getRenderedImage(BitmapData &bitmapdata, uint32_t options)
Get the rendered image.
Definition: rawfile.cpp:557
Internals::IfdDir::Ref mainIfd()
Get the main IFD.
Definition: rawfile.cpp:706
ExifLightsourceValue getCalibrationIlluminant1()
Get the calibration illuminant that match the colour matrix.
Definition: rawfile.cpp:638
Internals::IfdDir::Ref cfaIfd()
Get the IFD containing the CFA.
Definition: rawfile.cpp:696
TypeId _typeId() const
Just get the type id value. No identification. You might want to use typeId() in the general case.
Definition: rawfile.cpp:423
const MetaValue * getMetaValue(int32_t meta_index)
Get a metadata value.
Definition: rawfile.cpp:733
static RawFile::TypeId modelid_to_typeid(const std::map< uint32_t, RawFile::TypeId > &model_map, uint32_t model_id)
Helper to get the TypeId from the map.
Definition: rawfile.cpp:406
virtual or_colour_matrix_origin getColourMatrixOrigin() const
Get the origin of the colour matrix for the RAW file.
Definition: rawfile.cpp:648
Type type() const
Accessor for the type.
Definition: rawfile.cpp:375
Represent a thumbnail.
Definition: thumbnail.hpp:32
#define RAF_MAGIC
The RAF MAGIC string.
Definition: raffile.hpp:38
#define RAF_MAGIC_LEN
The length of the MAGIC strinng.
Definition: raffile.hpp:40
@ META_NS_TIFF
Definition: metadata.h:52
#define OR_MAKE_FILE_TYPEID(vendor, camera)
Make a or_rawfile_typeid with a vendor and camera.
Definition: consts.h:133
or_rawfile_type
Types of RAW files.
Definition: consts.h:59
or_colour_matrix_origin
Where the colour matrix comes from. Typically DNG is provided. The others are built-in.
Definition: consts.h:121
or_error
Error codes returned by libopenraw.
Definition: consts.h:42
@ OR_IFD_RAW
RAW data.
Definition: consts.h:150
@ OR_IFD_MNOTE
MakerNote.
Definition: consts.h:148
@ OR_IFD_MAIN
Main (like in TIFF)
Definition: consts.h:144
@ OR_IFD_EXIF
Exif metadata.
Definition: consts.h:146
@ OR_RAWFILE_TYPE_MRW
Definition: consts.h:64
@ OR_RAWFILE_TYPE_DNG
Definition: consts.h:66
@ OR_RAWFILE_TYPE_GPR
Definition: consts.h:75
@ OR_RAWFILE_TYPE_TIFF
Definition: consts.h:70
@ OR_RAWFILE_TYPE_NRW
Definition: consts.h:71
@ OR_RAWFILE_TYPE_RAF
Definition: consts.h:73
@ OR_RAWFILE_TYPE_CRW
Definition: consts.h:62
@ OR_RAWFILE_TYPE_ERF
Definition: consts.h:69
@ OR_RAWFILE_TYPE_NEF
Definition: consts.h:63
@ OR_RAWFILE_TYPE_SR2
Definition: consts.h:76
@ OR_RAWFILE_TYPE_CR3
Definition: consts.h:74
@ OR_RAWFILE_TYPE_ARW
Definition: consts.h:65
@ OR_RAWFILE_TYPE_RW2
Definition: consts.h:72
@ OR_RAWFILE_TYPE_PEF
Definition: consts.h:68
@ OR_RAWFILE_TYPE_UNKNOWN
Definition: consts.h:60
@ OR_RAWFILE_TYPE_ORF
Definition: consts.h:67
@ OR_RAWFILE_TYPE_CR2
Definition: consts.h:61
@ OR_COLOUR_MATRIX_BUILTIN
Definition: consts.h:123
@ OR_ERROR_BUF_TOO_SMALL
Definition: consts.h:44
@ OR_ERROR_NOT_IMPLEMENTED
Definition: consts.h:52
@ OR_ERROR_INVALID_PARAM
Definition: consts.h:49
@ OR_ERROR_NONE
Definition: consts.h:43
@ OR_ERROR_NOT_FOUND
Definition: consts.h:48
std::map< uint32_t, ::or_rawfile_typeid > ModelIdMap
Definition: rawfile.hpp:54
Global namespace for libopenraw.
Definition: arwfile.cpp:29