libopenraw  0.3.7
cr3file.cpp
1 /* -*- mode:c++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil; -*- */
2 /*
3  * libopenraw - cr3file.cpp
4  *
5  * Copyright (C) 2018-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 <cstdint>
23 #include <memory>
24 #include <stddef.h>
25 #include <vector>
26 
27 #include <libopenraw/cameraids.h>
28 #include <libopenraw/consts.h>
29 #include <libopenraw/debug.h>
30 
31 #include "cr3file.hpp"
32 #include "isomediacontainer.hpp"
33 #include "canon.hpp"
34 #include "rawdata.hpp"
35 #include "rawfile_private.hpp"
36 #include "bitmapdata.hpp"
37 #include "trace.hpp"
38 
39 using namespace Debug;
40 
41 namespace OpenRaw {
42 namespace Internals {
43 
44 #define OR_MAKE_CANON_TYPEID(camid) \
45  OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, camid)
46 
47 /* all relative to the D65 calibration illuminant */
48 static const BuiltinColourMatrix s_matrices[] = {
49  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M200),
50  0,
51  0,
52  { 10463, -2173, -1437, -4856, 12635, 2482, -1216, 2915, 7237 } },
53  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M50),
54  0,
55  0,
56  { 8532, -701, -1167, -4095, 11879, 2508, -797, 2424, 7010 } },
57  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M50MKII),
58  0,
59  0,
60  { 10463, -2173, -1437, -4856, 12635, 2482, -1216, 2915, 7237 } },
61  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M6MKII),
62  0,
63  0,
64  { 11498, -3759, -1516, -5073, 12954, 2349, -892, 1867, 6118 } },
65  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_90D),
66  0,
67  0,
68  { 11498, -3759, -1516, -5073, 12954, 2349, -892, 1867, 6118 } },
69  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R),
70  0,
71  0,
72  { 6446, -366, -864, -4436, 12204, 2513, -952, 2496, 6348 } },
73  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_RP),
74  0,
75  0,
76  { 8608, -2097, -1178, -5425, 13265, 2383, -1149, 2238, 5680 } },
77  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R3),
78  0,
79  0,
80  { 9423, -2839, -1195, -4532, 12377, 2415, -483, 1374, 5276 } },
81  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R5),
82  0,
83  0,
84  { 9766, -2953, -1254, -4276, 12116, 2433, -437, 1336, 5131 } },
85  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R50),
86  0,
87  0,
88  { 9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913 } },
89  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R6),
90  0,
91  0,
92  { 8293, -1611, -1132, -4759, 12711, 2275, -1013, 2415, 5509 } },
93  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R6MKII),
94  0,
95  0,
96  { 9539, -2795, -1224, -4175, 11998, 2458, -465, 1755, 6048 } },
97  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R7),
98  0,
99  0,
100  { 10424, -3138, -1300, -4221, 11938, 2584, -547, 1658, 6183 } },
101  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R8),
102  0,
103  0,
104  { 9539, -2795, -1224, -4175, 11998, 2458, -465, 1755, 6048 } },
105  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R10),
106  0,
107  0,
108  { 9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913 } },
109  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_SX70_HS),
110  0,
111  0,
112  { 18285, -8907, -1951, -1845, 10688, 1323, 364, 1101, 5139 } },
113  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_250D),
114  0,
115  0,
116  { 9079, -1923, -1236, -4677, 12454, 2492, -922, 2319, 5565 } },
117  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_850D),
118  0,
119  0,
120  { 9079, -1923, -1236, -4677, 12454, 2492, -922, 2319, 5565 } },
121  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G5XMKII),
122  0,
123  0,
124  { 11629, -5713, -914, -2706, 11090, 1842, -206, 1225, 5515 } },
125  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G7XMKIII),
126  0,
127  0,
128  { 11629, -5713, -914, -2706, 11090, 1842, -206, 1225, 5515 } },
129  { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DXMKIII),
130  0,
131  0,
132  { 8971, -2022, -1242, -5405, 13249, 2380, -1280, 2483, 6072 } },
133  { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
134 };
135 
136 const RawFile::camera_ids_t Cr3File::s_def[] = {
137  { "Canon EOS M50", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M50) },
138  { "Canon EOS M200", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M200) },
139  { "Canon EOS R", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R) },
140  { "Canon EOS RP", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_RP) },
141  { "Canon EOS R3", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R3) },
142  { "Canon EOS R5", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R5) },
143  { "Canon EOS R6", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R6) },
144  { "Canon EOS R6 m2", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R6MKII) },
145  { "Canon EOS R7", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R7) },
146  { "Canon EOS R8", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R8) },
147  { "Canon EOS R10", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R10) },
148  { "Canon EOS R50", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_R50) },
149  { "Canon EOS 250D", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_250D) },
150  { "Canon EOS Rebel SL3", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_250D) },
151  { "Canon EOS 850D", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_850D) },
152  { "Canon EOS Rebel T8i", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_850D) },
153  { "Canon PowerShot SX70 HS", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_SX70_HS) },
154  { "Canon PowerShot G5 X Mark II", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G5XMKII) },
155  { "Canon PowerShot G7 X Mark III", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G7XMKIII) },
156  { "Canon EOS-1D X Mark III", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_1DXMKIII) },
157  { "Canon EOS M6 Mark II", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_EOS_M6MKII) },
158  { "Canon EOS 90D", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_90D) },
159  { 0, 0 }
160 };
161 
162 RawFile *Cr3File::factory(const IO::Stream::Ptr &s)
163 {
164  return new Cr3File(s);
165 }
166 
167 Cr3File::Cr3File(const IO::Stream::Ptr &s)
168  : RawFile(OR_RAWFILE_TYPE_CR3)
169  , m_io(s)
170  , m_container(new IsoMediaContainer(s))
171 {
172  _setIdMap(s_def);
173  _setMatrices(s_matrices);
174 }
175 
176 Cr3File::~Cr3File()
177 {
178  delete m_container;
179 }
180 
181 RawContainer *Cr3File::getContainer() const
182 {
183  return m_container;
184 }
185 
186 ::or_error Cr3File::_getRawData(RawData &data, uint32_t options)
187 {
188  auto track = m_container->get_track(2);
189  if (!track || (*track).track_type != MP4PARSE_TRACK_TYPE_VIDEO) {
190  LOGERR("%u Not a video track\n", 2);
191  return OR_ERROR_NOT_FOUND;
192  }
193  auto raw_track = m_container->get_raw_track(2);
194  if (!raw_track || (*raw_track).is_jpeg) {
195  LOGERR("%u not the RAW data track\n", 2);
196  return OR_ERROR_NOT_FOUND;
197  }
198 
199  if ((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
200  LOGWARN("Can't provide decompressed data yet. Ignoring.\n");
201  }
202 
204  data.setDimensions((*raw_track).image_width, (*raw_track).image_height);
205  // get the sensor info
206  IfdDir::Ref makerNote = makerNoteIfd();
207  auto sensorInfo = canon_get_sensorinfo(makerNote);
208  if (sensorInfo) {
209  data.setActiveArea((*sensorInfo)[0], (*sensorInfo)[1],
210  (*sensorInfo)[2], (*sensorInfo)[3]);
211  }
212 
213  auto byte_length = (*raw_track).size;
214  void* p = data.allocData(byte_length);
215  size_t real_size = m_container->fetchData(p, (*raw_track).offset,
216  byte_length);
217  if (real_size < byte_length) {
218  LOGWARN("Size mismatch for data: ignoring.\n");
219  }
220  return OR_ERROR_NONE;
221 }
222 
223 ::or_error Cr3File::_enumThumbnailSizes(std::vector<uint32_t> &list)
224 {
225  auto err = OR_ERROR_NOT_FOUND;
226  auto craw_header = m_container->get_craw_header();
227  if (craw_header) {
228  uint32_t x = (*craw_header).thumb_w;
229  uint32_t y = (*craw_header).thumb_h;
230  auto dim = std::max(x, y);
231  if (dim) {
232  list.push_back(dim);
233  auto data = std::make_unique<BitmapData>();
234  data->setDimensions(x, y);
235  data->setDataType(OR_DATA_TYPE_JPEG);
236  void* p = data->allocData((*craw_header).thumbnail.length);
237  ::memcpy(p, (*craw_header).thumbnail.data, (*craw_header).thumbnail.length);
238  _addThumbnail(dim, ThumbDesc(x, y, OR_DATA_TYPE_JPEG, std::move(data)));
239  err = OR_ERROR_NONE;
240  }
241  }
242  auto track_count = m_container->count_tracks();
243  for (uint32_t i = 0; i < track_count; i++) {
244  auto track = m_container->get_track(i);
245  if (!track || (*track).track_type != MP4PARSE_TRACK_TYPE_VIDEO) {
246  LOGDBG1("%u Not a video track\n", i);
247  continue;
248  }
249  auto raw_track = m_container->get_raw_track(i);
250  if (!raw_track || !(*raw_track).is_jpeg) {
251  LOGDBG1("%u not a RAW data track\n", i);
252  continue;
253  }
254  auto dim = std::max((*raw_track).image_width,
255  (*raw_track).image_height);
256  LOGDBG1("Dimension %u\n", dim);
257  list.push_back(dim);
258  _addThumbnail(dim, ThumbDesc((*raw_track).image_width,
259  (*raw_track).image_height,
260  OR_DATA_TYPE_JPEG, (*raw_track).offset,
261  (*raw_track).size));
262  err = OR_ERROR_NONE;
263  }
264 
265  auto desc = m_container->get_preview_desc();
266  if (desc) {
267  auto dim = std::max((*desc).x, (*desc).y);
268  list.push_back(dim);
269  _addThumbnail(dim, desc.value());
270  err = OR_ERROR_NONE;
271  }
272 
273  return err;
274 }
275 
276 
277 IfdDir::Ref Cr3File::findIfd(uint32_t idx)
278 {
279  if (idx >= m_ifds.size()) {
280  LOGERR("Invalid ifd index %u\n", idx);
281  return IfdDir::Ref();
282  }
283 
284  auto ifd = m_ifds[idx];
285 
286  if (!ifd) {
287  ifd = m_container->get_metadata_block(idx);
288  if (!ifd) {
289  LOGERR("cr3: can't find meta block 0\n");
290  return IfdDir::Ref();
291  }
292  }
293 
294  return ifd->setDirectory(0);
295 }
296 
297 IfdDir::Ref Cr3File::_locateMainIfd()
298 {
299  auto ifd = findIfd(0);
300  if (ifd) {
301  ifd->setType(OR_IFD_MAIN);
302  }
303  return ifd;
304 }
305 
306 IfdDir::Ref Cr3File::_locateExifIfd()
307 {
308  auto ifd = findIfd(1);
309  if (ifd) {
310  ifd->setType(OR_IFD_EXIF);
311  }
312  return ifd;
313 }
314 
315 MakerNoteDir::Ref Cr3File::_locateMakerNoteIfd()
316 {
317  auto ifd = findIfd(2);
318  if (ifd) {
319  auto mnote = std::make_shared<MakerNoteDir>(*ifd, "Canon", mnote_canon_tag_names);
320  mnote->load();
321  return mnote;
322  }
323  return std::dynamic_pointer_cast<MakerNoteDir>(ifd);
324 }
325 
326 MetaValue* Cr3File::_getMetaValue(int32_t meta_index)
327 {
328  MetaValue *val = nullptr;
329  IfdDir::Ref ifd;
330  // I wish I had an HaveIFD "trait" for this.
331  // This is almost IfdFile::_getMetaValue()
332  if (META_INDEX_MASKOUT(meta_index) == META_NS_TIFF) {
333  ifd = mainIfd();
334  } else if (META_INDEX_MASKOUT(meta_index) == META_NS_EXIF) {
335  ifd = exifIfd();
336  } else {
337  LOGERR("Unknown Meta Namespace\n");
338  }
339  if(ifd) {
340  LOGDBG1("Meta value for %u\n", META_NS_MASKOUT(meta_index));
341 
342  IfdEntry::Ref e = ifd->getEntry(META_NS_MASKOUT(meta_index));
343  if(e) {
344  val = ifd->makeMetaValue(*e);
345  }
346  }
347 
348  return val;
349 }
350 
351 void Cr3File::_identifyId()
352 {
353  // XXX TODO this code seems be very common with IfdFile
354  // There is a camera model ID in the MakerNote tag 0x0010.
355  // Use this at first.
356  auto mn = makerNoteIfd();
357  if (mn) {
358  auto id = mn->getValue<uint32_t>(IFD::MNOTE_CANON_MODEL_ID);
359  if (id) {
360  auto id_value = id.value();
361  auto type_id = modelid_to_typeid(canon_modelid_map, id_value);
362  if (type_id != 0) {
363  _setTypeId(type_id);
364  return;
365  }
366  LOGERR("model ID %x not found\n", id_value);
367  } else {
368  LOGERR("model ID not found\n");
369  }
370  } else {
371  LOGERR("model ID not found (missing MakerNote)\n");
372  }
373 }
374 
375 }
376 }
void setDataType(DataType _type)
Set the data type.
Definition: bitmapdata.cpp:91
std::shared_ptr< IfdDir > Ref
Shared ptr of an IfdDir.
Definition: ifddir.hpp:56
std::shared_ptr< IfdEntry > Ref
IfdEntry reference (ie shared pointer)
Definition: ifdentry.hpp:202
Generic interface for the RAW file container.
Metadata value.
Definition: metavalue.hpp:35
Represent camera raw data.
Definition: rawdata.hpp:38
virtual void setDimensions(uint32_t x, uint32_t y) override
Set the pixel dimensions of the bitmap.
Definition: rawdata.cpp:297
Option< std::array< uint32_t, 4 > > canon_get_sensorinfo(const IfdDir::Ref &ifddir)
Get the sensor info from and IfdDir.
Definition: canon.cpp:178
const ModelIdMap canon_modelid_map
The model ID map for Canon cameras.
Definition: canon.cpp:35
#define META_NS_MASKOUT(x)
Mask the namespace out.
Definition: metadata.h:56
#define META_INDEX_MASKOUT(x)
Mask the index out.
Definition: metadata.h:58
@ META_NS_TIFF
Definition: metadata.h:52
@ META_NS_EXIF
Definition: metadata.h:51
or_error
Error codes returned by libopenraw.
Definition: consts.h:42
@ OR_DATA_TYPE_JPEG
Definition: consts.h:84
@ OR_DATA_TYPE_COMPRESSED_RAW
Definition: consts.h:88
@ OR_OPTIONS_DONT_DECOMPRESS
Definition: consts.h:114
@ OR_IFD_MAIN
Main (like in TIFF)
Definition: consts.h:144
@ OR_IFD_EXIF
Exif metadata.
Definition: consts.h:146
@ OR_RAWFILE_TYPE_CR3
Definition: consts.h:74
@ OR_ERROR_NONE
Definition: consts.h:43
@ OR_ERROR_NOT_FOUND
Definition: consts.h:48
Global namespace for libopenraw.
Definition: arwfile.cpp:29