libopenraw  0.3.7
makernotedir.cpp
1 /*
2  * libopenraw - makernotedir.cpp
3  *
4  * Copyright (C) 2010-2022 Hubert Figuière
5  *
6  * This library is free software: you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public License
8  * as published by the Free Software Foundation, either version 3 of
9  * the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <fcntl.h>
22 
23 #include <string.h>
24 
25 #include "makernotedir.hpp"
26 #include "io/stream.hpp"
27 #include "ifdfilecontainer.hpp"
28 #include "trace.hpp"
29 
30 namespace OpenRaw {
31 namespace Internals {
32 
33 namespace {
34 const TagTable empty_tag_names = {};
35 }
36 
37 /*
38  * For Makernote detection, see:
39  * http://owl.phy.queensu.ca/~phil/exiftool/makernote_types.html
40  * https://exiftool.org/makernote_types.html
41  * http://www.exiv2.org/makernote.html
42  */
43 MakerNoteDir::Ref
45  RawContainer& container, or_rawfile_type file_type)
46 {
47  LOGDBG1("createMakerNote()\n");
48 
49  // Canon MakerNote don't have an ID
50  if (file_type == OR_RAWFILE_TYPE_CR2
51  || file_type == OR_RAWFILE_TYPE_CR3
52  || file_type == OR_RAWFILE_TYPE_CRW) {
53 
54  return std::make_shared<MakerNoteDir>(
55  offset, container, 0, "Canon", mnote_canon_tag_names);
56  }
57 
58  // Sony RAW MakerNote don't have an ID
59  if (file_type == OR_RAWFILE_TYPE_ARW) {
60  return std::make_shared<MakerNoteDir>(
61  offset, container, 0, "Sony5", mnote_sony_tag_names);
62  }
63 
64  uint8_t data[18];
65  auto file = container.file();
66  file->seek(offset, SEEK_SET);
67  file->read(&data, 18);
68  // LOGDBG1("data %s\n", Debug::ascii_to_string(data, 18).c_str());
69  // LOGDBG1("data %s\n", Debug::bytes_to_string(data, 18).c_str());
70 
71  if (memcmp("Nikon\0", data, 6) == 0) {
72  if (data[6] == 1) {
73  return std::make_shared<MakerNoteDir>(
74  offset + 8, container, offset + 8, "Nikon2", mnote_nikon2_tag_names);
75  }
76  else if (data[6] == 2) {
77  // this one has an endian / TIFF header after the magic
78  return std::make_shared<MakerNoteDir>(
79  offset + 18, container, offset + 10, "Nikon", mnote_nikon_tag_names);
80  }
81  else {
82  return std::make_shared<MakerNoteDir>(
83  offset, container, offset, "", empty_tag_names);
84  }
85  }
86 
87  // Headerless Nikon.
88  if (file_type == OR_RAWFILE_TYPE_NEF) {
89  // Found on D1, D1X, D1H
90  return std::make_shared<MakerNoteDir>(
91  offset, container, offset, "Nikon (Headerless)", mnote_nikon_tag_names);
92  }
93 
94  if (memcmp("OLYMPUS\0", data, 8) == 0) {
95  return std::make_shared<MakerNoteDir>(
96  offset + 12, container, offset, "Olympus2", mnote_olympus_tag_names);
97  }
98 
99  if (memcmp("OM SYSTEM", data, 9) == 0) {
100  return std::make_shared<MakerNoteDir>(
101  offset + 16, container, offset, "Olympus2", mnote_olympus_tag_names);
102  }
103 
104  if (memcmp("OLYMP\0", data, 6) == 0) {
105  return std::make_shared<MakerNoteDir>(
106  offset + 8, container, 0, "Olympus", mnote_olympus_tag_names);
107  }
108  // EPSON R-D1, use Olympus
109  // XXX deal with endian.
110  if (memcmp("EPSON\0", data, 6) == 0) {
111  return std::make_shared<MakerNoteDir>(
112  offset + 8, container, 0, "Epson", mnote_olympus_tag_names);
113  }
114 
115  // Pentax Asahi Optical Corporation (pre Ricoh merger)
116  if (memcmp("AOC\0", data, 4) == 0) {
117  return std::make_shared<MakerNoteDir>(
118  offset + 6, container, 0, "Pentax", mnote_pentax_tag_names);
119  }
120  // Pentax post Ricoh merger
121  if (memcmp("PENTAX \0", data, 8) == 0) {
122  return std::make_shared<MakerNoteDir>(
123  offset + 10, container, offset, "Pentax", mnote_pentax_tag_names);
124  }
125 
126  if (memcmp("Panasonic\0", data, 10) == 0) {
127  return std::make_shared<MakerNoteDir>(
128  offset + 12, container, 0, "Panasonic", mnote_panasonic_tag_names);
129  }
130 
131  if (memcmp("Ricoh\0", data, 5) == 0) {
132  return std::make_shared<MakerNoteDir>(
133  offset + 8, container, 0, "Ricoh", mnote_ricoh_tag_names);
134  }
135 
136  if (memcmp("LEICA CAMERA AG\0", data, 16) == 0) {
137  if (file_type == OR_RAWFILE_TYPE_RW2) {
138  // Rebadged Panasonic
139  // Leica C-Lux
140  // Leica V-Lux 5
141  // Leica D-Lux 7
142  return std::make_shared<MakerNoteDir>(
143  offset + 18, container, 0, "Panasonic", mnote_panasonic_tag_names);
144  }
145  }
146 
147  if (memcmp("LEICA", data, 5) == 0) {
148  if (data[5] == 0 && data[6] == 0 && data[7] == 0) {
149  if (file_type == OR_RAWFILE_TYPE_RW2) {
150  // Panasonic
151  return std::make_shared<MakerNoteDir>(
152  offset + 8, container, 0, "Panasonic", mnote_panasonic_tag_names);
153  } else {
154  // Leica M8
155  return std::make_shared<MakerNoteDir>(
156  offset + 8, container, offset, "Leica2", mnote_leica2_tag_names);
157  }
158  }
159 
160  if (data[5] == 0 && data[7] == 0) {
161  switch (data[6]) {
162  case 0x08:
163  case 0x09: // Leica Q Typ 116 and SL (Type 601)
164  case 0x0a: // Leica Q3
165  return std::make_shared<MakerNoteDir>(
166  offset + 8, container, 0, "Leica5", mnote_leica5_tag_names);
167  case 0x01: // Leica X1
168  case 0x04: // Leica X VARIO
169  case 0x05: // Leica X2
170  case 0x06: // Leica T (Typ 701)
171  case 0x07: // Leica X (Typ 113)
172  case 0x10: // Leica X-U (Typ 113)
173  case 0x1a:
174  return std::make_shared<MakerNoteDir>(
175  offset + 8, container, offset, "Leica5", mnote_leica5_tag_names);
176  }
177  }
178 
179  // Leica M (Typ 240)
180  if (data[5] == 0x0 && data[6] == 0x02 && data[7] == 0xff) {
181  return std::make_shared<MakerNoteDir>(
182  offset + 8, container, 0, "Leica6", mnote_leica6_tag_names);
183  }
184 
185  // Leica M9/Monochrom
186  if (data[5] == '0' && data[6] == 0x03 && data[7] == 0) {
187  return std::make_shared<MakerNoteDir>(
188  offset + 8, container, offset, "Leica4", mnote_leica4_tag_names);
189  }
190 
191  // Leica M10
192  if (data[5] == 0 && data[6] == 0x02 && data[7] == 0) {
193  return std::make_shared<MakerNoteDir>(
194  offset + 8, container, 0, "Leica9", mnote_leica9_tag_names);
195  }
196  }
197 
198  if (memcmp("YI \0", data, 8) == 0) {
199  return std::make_shared<MakerNoteDir>(
200  offset + 12, container, offset, "Xiaoyi", mnote_xiaoyi_tag_names);
201  }
202 
203  if (memcmp("Apple iOS\0", data, 10) == 0) {
204  return std::make_shared<MakerNoteDir>(
205  offset + 14, container, offset, "Apple", mnote_apple_tag_names);
206  }
207 
208  if (memcmp("STMN", data, 4) == 0) {
209  if (data[8] == data[9] == data[10] == data[11] == 0) {
210  return std::make_shared<NonMakerNoteDir>(container, "Samsung1a");
211  } else {
212  return std::make_shared<NonMakerNoteDir>(container, "Samsung1b");
213  }
214  }
215 
216  if (memcmp("FUJIFILM", data, 8) == 0) {
217  auto mnote = std::make_shared<MakerNoteDir>(
218  offset + 12, container, offset, "Fujifilm", mnote_fujifilm_tag_names);
219  mnote->setEndian(RawContainer::ENDIAN_LITTLE);
220  return mnote;
221  }
222 
223  if (memcmp("SIGMA\0", data, 6) == 0) {
224  return std::make_shared<MakerNoteDir>(
225  offset + 10, container, 0, "Sigma", mnote_sigma_tag_names);
226  }
227 
228  if (memcmp("MLT0", data + 10, 4) == 0) {
229  return std::make_shared<MakerNoteDir>(
230  offset, container, offset, "Minolta", mnote_minolta_tag_names);
231  }
232 
233  return std::make_shared<MakerNoteDir>(offset, container, offset, "", empty_tag_names);
234 }
235 
236 MakerNoteDir::MakerNoteDir(RawContainer& _container, const std::string& id)
237  : IfdDir(0, _container, OR_IFD_MNOTE, empty_tag_names)
238  , m_id(id)
239 {
240 }
241 
242 MakerNoteDir::MakerNoteDir(IfdDir& ifd, const std::string& id, const TagTable& tag_table)
243  : MakerNoteDir(ifd.offset(), ifd.container(), ifd.offset(), id, tag_table)
244 {
245  setBaseOffset(0);
246 }
247 
248 MakerNoteDir::MakerNoteDir(off_t _offset,
249  RawContainer& _container,
250  off_t mnote_offset,
251  const std::string& id,
252  const TagTable& tag_table)
253  : IfdDir(_offset, _container, OR_IFD_MNOTE, tag_table)
254  , m_mnote_offset(mnote_offset)
255  , m_id(id)
256 {
257  setBaseOffset(mnote_offset);
258 }
259 
260 MakerNoteDir::~MakerNoteDir()
261 {
262 }
263 
265 {
266  auto entry = getEntry(id);
267  if (!entry) {
268  LOGDBG1("Coudln't get entry %u\n", id);
269  return Ref();
270  }
271 
272  uint32_t val_offset = 0;
273  // "INVALID" type entry (13) for some Olympus MakerNote
274  if (entry->type() == 13 || entry->type() == IFD::EXIF_FORMAT_LONG) {
275  val_offset = getEntryValue<uint32_t>(*entry, 0, true);
276  LOGDBG1("Custom IFD offset (uncorrected) = %u\n", val_offset);
277  val_offset += container().exifOffsetCorrection() + getMnoteOffset();
278  } else {
279  // Type is likely "UNDEFINED"
280  val_offset = entry->offset();
281  }
282  LOGDBG1("Custom IFD offset = %u\n", val_offset);
283 
284  auto ref = std::make_shared<IfdDir>(val_offset, container(), OR_IFD_OTHER);
285  ref->load();
286  return ref;
287 }
288 
289 }
290 }
291 
292 /*
293  Local Variables:
294  mode:c++
295  c-file-style:"stroustrup"
296  c-file-offsets:((innamespace . 0))
297  indent-tabs-mode:nil
298  fill-column:80
299  End:
300 */
An IFD directory.
Definition: ifddir.hpp:51
const RawContainer & container() const
The container for the IfdDir, const.
Definition: ifddir.hpp:108
void setBaseOffset(off_t base)
Set the base offset.
Definition: ifddir.hpp:91
IfdEntry::Ref getEntry(uint16_t id) const
Get the IfdEntry for the tag id.
Definition: ifddir.cpp:96
std::shared_ptr< IfdDir > Ref
Shared ptr of an IfdDir.
Definition: ifddir.hpp:56
off_t offset() const
Return the offset.
Definition: ifddir.hpp:106
IfdDir::Ref getIfdInEntry(uint16_t id)
static Ref createMakerNote(off_t offset, RawContainer &container, or_rawfile_type file_type)
Generic interface for the RAW file container.
or_rawfile_type
Types of RAW files.
Definition: consts.h:59
@ OR_IFD_OTHER
Generic.
Definition: consts.h:142
@ OR_IFD_MNOTE
MakerNote.
Definition: consts.h:148
@ OR_RAWFILE_TYPE_CRW
Definition: consts.h:62
@ OR_RAWFILE_TYPE_NEF
Definition: consts.h:63
@ 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_CR2
Definition: consts.h:61
Global namespace for libopenraw.
Definition: arwfile.cpp:29