libopenraw
orffile.cpp
1/*
2 * libopenraw - orffile.cpp
3 *
4 * Copyright (C) 2006-2017 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 <algorithm>
22#include <cstdint>
23#include <memory>
24
25#include <libopenraw/debug.h>
26#include <libopenraw/cameraids.h>
27#include <libopenraw/consts.h>
28
29#include "cfapattern.hpp"
30#include "rawdata.hpp"
31#include "rawfile.hpp"
32
33#include "ifdfilecontainer.hpp"
34#include "makernotedir.hpp"
35
36#include "trace.hpp"
37#include "orffile.hpp"
38#include "ifd.hpp"
39#include "ifddir.hpp"
40#include "ifdentry.hpp"
41#include "orfcontainer.hpp"
42#include "olympusdecompressor.hpp"
43#include "rawfile_private.hpp"
44#include "io/streamclone.hpp"
45#include "jfifcontainer.hpp"
46
47using namespace Debug;
48
49namespace OpenRaw {
50namespace Internals {
51
52#define OR_MAKE_OLYMPUS_TYPEID(camid) \
53 OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_OLYMPUS,camid)
54
55/* taken from dcraw, by default */
56static const BuiltinColourMatrix s_matrices[] = {
57 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E1),
58 0,
59 0,
60 { 11846,-4767,-945,-7027,15878,1089,-2699,4122,8311 } },
61 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E10),
62 0,
63 0xffc,
64 { 12745,-4500,-1416,-6062,14542,1580,-1934,2256,6603 } },
65 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E3),
66 0,
67 0xf99,
68 { 9487,-2875,-1115,-7533,15606,2010,-1618,2100,7389 } },
69 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E5),
70 0,
71 0,
72 { 11200,-3783,-1325,-4576,12593,2206,-695,1742,7504 } },
73 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E300),
74 0,
75 0,
76 { 7828,-1761,-348,-5788,14071,1830,-2853,4518,6557 } },
77 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E330),
78 0,
79 0,
80 { 8961,-2473,-1084,-7979,15990,2067,-2319,3035,8249 } },
81 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E400),
82 0,
83 0,
84 { 6169,-1483,-21,-7107,14761,2536,-2904,3580,8568 } },
85 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E410),
86 0,
87 0xf6a,
88 { 8856,-2582,-1026,-7761,15766,2082,-2009,2575,7469 } },
89 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E500),
90 0,
91 0,
92 { 8136,-1968,-299,-5481,13742,1871,-2556,4205,6630 } },
93 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E510),
94 0,
95 0xf6a,
96 { 8785,-2529,-1033,-7639,15624,2112,-1783,2300,7817 } },
97 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E620),
98 0,
99 0xfaf,
100 { 8453,-2198,-1092,-7609,15681,2008,-1725,2337,7824 } },
101 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP350),
102 0,
103 0,
104 { 12078,-4836,-1069,-6671,14306,2578,-786,939,7418 } },
105 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP500),
106 0,
107 0xfff,
108 { 9493,-3415,-666,-5211,12334,3260,-1548,2262,6482 } },
109 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP510),
110 0,
111 0xffe,
112 { 10593,-3607,-1010,-5881,13127,3084,-1200,1805,6721 } },
113 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP550),
114 0,
115 0xffe,
116 { 11597,-4006,-1049,-5432,12799,2957,-1029,1750,6516 } },
117 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EP1),
118 0,
119 0xffd,
120 { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
121 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EP2),
122 0,
123 0xffd,
124 { 8343,-2050,-1021,-7715,15705,2103,-1831,2380,8235 } },
125 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EP3),
126 0,
127 0,
128 { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
129 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL1),
130 0,
131 0,
132 { 11408,-4289,-1215,-4286,12385,2118,-387,1467,7787 } },
133 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL2),
134 0,
135 0,
136 { 15030,-5552,-1806,-3987,12387,1767,-592,1670,7023 } },
137 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL3),
138 0,
139 0,
140 { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
141 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL5),
142 0,
143 0xfcb,
144 { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
145 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL6),
146 0,
147 0xfcb,
148 { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
149 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL7),
150 0,
151 0xfcb,
152 { 9197,-3190,-659,-2606,10830,2039,-458,1250,5458 } },
153 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL8),
154 0,
155 0xfcb,
156 { 9197, -3190, -659, -2606, 10830, 2039, -458, 1250, 5458 } },
157 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL9),
158 0,
159 0xfcb,
160 { 8380, -2630, -639, -2887, 10725, 2496, -627, 1427, 5438 } },
161 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPM1),
162 0,
163 0,
164 { 7575,-2159,-571,-3722,11341,2725,-1434,2819,6271 } },
165 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPM2),
166 0,
167 0,
168 { 8380,-2630,-639,-2887,10725,2496,-627,1427,5438 } },
169 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_XZ1),
170 0,
171 0,
172 { 10901,-4095,-1074,-1141,9208,2293,-62,1417,5158 } },
173 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_XZ10),
174 0,
175 0,
176 { 9777, -3483, -925, -2886, 11297, 1800, -602, 1663, 5134 } },
177 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_XZ2),
178 0,
179 0,
180 { 9777,-3483,-925,-2886,11297,1800,-602,1663,5134 } },
181 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM5),
182 0,
183 0xfe1,
184 { 8380, -2630, -639, -2887, 725, 2496, -627, 1427, 5438 } },
185 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM5II),
186 0,
187 0,
188 { 9422, -3258, -711, -2655, 10898, 2015, -512, 1354, 5512 } },
189 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM1),
190 0,
191 0,
192 { 7687, -1984, -606, -4327, 11928, 2721, -1381, 2339, 6452 } },
193 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM10),
194 0,
195 0,
196 { 8380, -2630, -639, -2887, 10725, 2496, -627, 1427, 5438 } },
197 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM10II), // Identical to MarkI
198 0,
199 0,
200 { 8380, -2630, -639, -2887, 10725, 2496, -627, 1427, 5438 } },
201 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_STYLUS1),
202 0,
203 0,
204 { 8360, -2420, -880, -3928, 12353, 1739, -1381, 2416, 5173 } },
205 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_PEN_F),
206 0,
207 0,
208 { 9476, -3182, -765, -2613, 10958, 1893, -449, 1315, 5268 } },
209 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SH2),
210 0,
211 0,
212 { 10156, -3425, -1077, -2611, 11177, 1624, -385, 1592, 5080 } },
213 { OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_TG4),
214 0,
215 0,
216 { 11426, -4159, -1126, -2066, 10678, 1593, -120, 1327, 4998 } },
217
218 { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
219
220};
221
222const struct IfdFile::camera_ids_t OrfFile::s_def[] = {
223 { "E-1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E1) },
224 { "E-10 " , OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E10) },
225 { "E-3 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E3) },
226 { "E-5 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E5) },
227 { "E-300 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E300) },
228 { "E-330 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E330) },
229 { "E-400 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E400) },
230 { "E-410 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E410) },
231 { "E-500 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E500) },
232 { "E-510 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E510) },
233 { "E-620 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_E620) },
234 { "SP350" , OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP350) },
235 { "SP500UZ" , OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP500) },
236 { "SP510UZ" , OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP510) },
237 { "SP550UZ ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SP550) },
238 { "E-P1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EP1) },
239 { "E-P2 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EP2) },
240 { "E-P3 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EP3) },
241 { "E-PL1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL1) },
242 { "E-PL2 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL2) },
243 { "E-PL3 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL3) },
244 { "E-PL5 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL5) },
245 { "E-PL6 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL6) },
246 { "E-PL7 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL7) },
247 { "E-PL8 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL8) },
248 { "E-PL9 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPL9) },
249 { "E-PM1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPM1) },
250 { "E-PM2 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EPM2) },
251 { "XZ-1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_XZ1) },
252 { "XZ-10 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_XZ10) },
253 { "XZ-2 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_XZ2) },
254 { "E-M5 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM5) },
255 { "E-M5MarkII ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM5II) },
256 { "E-M1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM1) },
257 { "E-M1MarkII ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM1II) },
258 { "E-M10 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM10) },
259 { "E-M10MarkII ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_EM10II) },
260 { "STYLUS1 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_STYLUS1) },
261 { "PEN-F ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_PEN_F) },
262 { "SH-2 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_SH2) },
263 { "TG-4 ", OR_MAKE_OLYMPUS_TYPEID(OR_TYPEID_OLYMPUS_TG4) },
264 { 0, 0 }
265};
266
267RawFile *OrfFile::factory(const IO::Stream::Ptr &s)
268{
269 return new OrfFile(s);
270}
271
272OrfFile::OrfFile(const IO::Stream::Ptr &s)
273 : IfdFile(s, OR_RAWFILE_TYPE_ORF, false)
274{
275 _setIdMap(s_def);
276 _setMatrices(s_matrices);
277 m_container = new OrfContainer(m_io, 0);
278}
279
280OrfFile::~OrfFile()
281{
282}
283
284IfdDir::Ref OrfFile::_locateCfaIfd()
285{
286 // in ORF the CFA IFD is the main IFD
287 return mainIfd();
288}
289
290
291IfdDir::Ref OrfFile::_locateMainIfd()
292{
293 return m_container->setDirectory(0);
294}
295
296::or_error OrfFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
297{
298 auto err = OR_ERROR_NOT_FOUND;
299
301
302 auto exif = exifIfd();
303 if (!exif) {
304 return err;
305 }
306
307 auto ifd = exif->getMakerNoteIfd();
308 if (!ifd) {
309 return err;
310 }
311 auto makerNote = std::dynamic_pointer_cast<MakerNoteDir>(ifd);
312 if (!makerNote) {
313 return err;
314 }
315
316 auto e = makerNote->getEntry(0x100);
317 if (e) {
318 auto val_offset = e->offset();
319
320 val_offset += makerNote->getMnoteOffset();
321
322 LOGDBG1("fetching JPEG\n");
323 IO::Stream::Ptr s(
324 std::make_shared<IO::StreamClone>(m_io, val_offset));
325 std::unique_ptr<JfifContainer> jfif(new JfifContainer(s, 0));
326
327 uint32_t x, y;
328 x = y = 0;
329 jfif->getDimensions(x, y);
330 LOGDBG1("JPEG dimensions x=%d y=%d\n", x, y);
331
332 uint32_t dim = std::max(x, y);
333 if (dim) {
334 _addThumbnail(dim, ThumbDesc(x, y, OR_DATA_TYPE_JPEG,
335 val_offset, e->count()));
336 list.push_back(dim);
337 err = OR_ERROR_NONE;
338 }
339 }
340
341 return err;
342}
343
344::or_error OrfFile::_getRawData(RawData & data, uint32_t options)
345{
346 ::or_error err;
347 const IfdDir::Ref & _cfaIfd = cfaIfd();
348 err = _getRawDataFromDir(data, _cfaIfd);
349 if(err == OR_ERROR_NONE) {
350 // ORF files seems to be marked as uncompressed even if they are.
351 uint32_t x = data.width();
352 uint32_t y = data.height();
353 uint32_t compression = 0;
354 if(data.size() < x * y * 2) {
355 compression = ORF_COMPRESSION;
356 data.setCompression(ORF_COMPRESSION);
357 data.setDataType(OR_DATA_TYPE_COMPRESSED_RAW);
358 }
359 else {
360 compression = data.compression();
361 }
362 switch(compression) {
363 case ORF_COMPRESSION:
364 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
365 OlympusDecompressor decomp((const uint8_t*)data.data(),
366 data.size(), m_container, x, y);
367 RawDataPtr dData = decomp.decompress();
368 if (dData) {
369 dData->setCfaPatternType(data.cfaPattern()->patternType());
370 data.swap(*dData);
371 data.setDataType(OR_DATA_TYPE_RAW);
372 data.setDimensions(x, y);
373 }
374 }
375 break;
376 default:
377 break;
378 }
379 }
380 return err;
381}
382
383uint32_t OrfFile::_translateCompressionType(IFD::TiffCompress tiffCompression)
384{
385 if(tiffCompression == IFD::COMPRESS_CUSTOM) {
386 return ORF_COMPRESSION;
387 }
388 return (uint32_t)tiffCompression;
389}
390
391}
392}
393/*
394 Local Variables:
395 mode:c++
396 c-file-style:"stroustrup"
397 c-file-offsets:((innamespace . 0))
398 indent-tabs-mode:nil
399 fill-column:80
400 End:
401*/
void setDataType(DataType _type)
size_t size() const
::or_cfa_pattern patternType() const
generic IFD based raw file.
Definition ifdfile.hpp:48
virtual::or_error _enumThumbnailSizes(std::vector< uint32_t > &list) override
Definition ifdfile.cpp:112
IfdFileContainer * m_container
Definition ifdfile.hpp:90
::or_error _getRawDataFromDir(RawData &data, const IfdDir::Ref &dir)
Definition ifdfile.cpp:510
const IfdDir::Ref & cfaIfd()
Definition ifdfile.cpp:332
::or_error _enumThumbnailSizes(std::vector< uint32_t > &list) override
Definition orffile.cpp:296
virtual::or_error _getRawData(RawData &data, uint32_t options) override
Definition orffile.cpp:344
virtual uint32_t _translateCompressionType(IFD::TiffCompress tiffCompression) override
Definition orffile.cpp:383
void swap(RawData &with)
Definition rawdata.cpp:245
const CfaPattern * cfaPattern() const
Definition rawdata.cpp:287
virtual void setDimensions(uint32_t x, uint32_t y) override
Definition rawdata.cpp:260
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard....
Definition arwfile.cpp:30