libopenraw
rw2file.cpp
1 /*
2  * libopenraw - rw2file.cpp
3  *
4  * Copyright (C) 2011-2016 Hubert Figuiere
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 <stddef.h>
22 
23 #include <algorithm>
24 #include <cstdint>
25 #include <memory>
26 
27 #include <libopenraw/cameraids.h>
28 #include <libopenraw/debug.h>
29 
30 #include "rawdata.hpp"
31 #include "trace.hpp"
32 #include "io/streamclone.hpp"
33 #include "rw2file.hpp"
34 #include "rw2container.hpp"
35 #include "jfifcontainer.hpp"
36 #include "rawfile_private.hpp"
37 
38 using namespace Debug;
39 
40 namespace OpenRaw {
41 
42 namespace Internals {
43 
44 #define OR_MAKE_PANASONIC_TYPEID(camid) \
45  OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_PANASONIC,camid)
46 #define OR_MAKE_LEICA_TYPEID(camid) \
47  OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_LEICA,camid)
48 
49 /* taken from dcraw, by default */
50 static const BuiltinColourMatrix s_matrices[] = {
51  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF1), 15, 0xf92,
52  { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
53  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF2), 15, 0xfff,
54  { 7888,-1902,-1011,-8106,16085,2099,-2353,2866,7330 } },
55  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF3), 15, 0xfff,
56  { 9051,-2468,-1204,-5212,13276,2121,-1197,2510,6890 } },
57  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF5), 15, 0xfff,
58  { 8228,-2945,-660,-3938,11792,2430,-1094,2278,5793 } },
59  // Adobe DNG convert 7.4
60  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF6), 15, 0xfff,
61  { 8130,-2801,-946,-3520,11289,2552,-1314,2511,5791 } },
62  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GX1), 15, 0,
63  { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
64  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GX7), 15, 0,
65  { 7610,-2780,-576,-4614,12195,2733,-1375,2393,6490 } },
66  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ8), 0, 0xf7f,
67  { 8986,-2755,-802,-6341,13575,3077,-1476,2144,6379 } },
68  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ18), 0, 0,
69  { 9932,-3060,-935,-5809,13331,2753,-1267,2155,5575 } },
70  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ28), 15, 0xf96,
71  { 10109,-3488,-993,-5412,12812,2916,-1305,2140,5543 } },
72  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ200), 143, 0xfff,
73  { 8112,-2563,-740,-3730,11784,2197,-941,2075,4933 } },
74  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ30), 0, 0xf94,
75  { 10976,-4029,-1141,-7918,15491,2600,-1670,2071,8246 } },
76  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ50), 0, 0,
77  { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
78  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ100), 143, 0xfff,
79  { 16197,-6146,-1761,-2393,10765,1869,366,2238,5248 } },
80  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G1), 15, 0xf94,
81  { 8199,-2065,-1056,-8124,16156,2033,-2458,3022,7220 } },
82  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G2), 15, 0xf3c,
83  { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
84  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G3), 143, 0xfff,
85  { 6763,-1919,-863,-3868,11515,2684,-1216,2387,5879 } },
86  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G5), 143, 0xfff,
87  { 7798,-2562,-740,-3879,11584,2613,-1055,2248,5434 } },
88  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G10), 0, 0,
89  { 10113,-3400,-1114,-4765,12683,2317,-377,1437,6710 } },
90  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH1), 15, 0xf92,
91  { 6299,-1466,-532,-6535,13852,2969,-2331,3112,5984 } },
92  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH2), 15, 0xf95,
93  { 7780,-2410,-806,-3913,11724,2484,-1018,2390,5298 } },
94  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH3), 144, 0,
95  { 6559,-1752,-491,-3672,11407,2586,-962,1875,5130 } },
96  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH4), 15, 0,
97  { 7122,-2108,-512,-3155,11201,2231,-541,1423,5045 } },
98  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GM1), 15, 0,
99  { 6770,-1895,-744,-5232,13145,2303,-1664,2691,5703 } },
100  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX2), 0, 0,
101  { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
102  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX3), 15, 0,
103  { 8128,-2668,-655,-6134,13307,3161,-1782,2568,6083 } },
104  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX5), 143, 0,
105  { 10909,-4295,-948,-1333,9306,2399,22,1738,4582 } },
106  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX7), 143, 0,
107  { 10148,-3743,-991,-2837,11366,1659,-701,1893,4899 } },
108  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX100), 143, 0,
109  { 8844,-3538,-768,-3709,11762,2200,-698,1792,5220 } },
110  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_L1), 0, 0xf7f,
111  { 8054,-1885,-1025,-8349,16367,2040,-2805,3542,7629 } },
112  { OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_L10), 15, 0xf96,
113  { 8025,-1942,-1050,-7920,15904,2100,-2456,3005,7039 } },
114 
115  { OR_MAKE_LEICA_TYPEID(OR_TYPEID_LEICA_DIGILUX2), 0, 0,
116  { 11340,-4069,-1275,-7555,15266,2448,-2960,3426,7685 } },
117  { OR_MAKE_LEICA_TYPEID(OR_TYPEID_LEICA_DLUX_3), 0, 0,
118  { 8048,-2810,-623,-6450,13519,3272,-1700,2146,7049 } },
119  { OR_MAKE_LEICA_TYPEID(OR_TYPEID_LEICA_VLUX_1), 0, 0,
120  { 7906,-2709,-594,-6231,13351,3220,-1922,2631,6537 } },
121 
122  { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
123 };
124 
125 const IfdFile::camera_ids_t Rw2File::s_def[] = {
126  { "DMC-GF1", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF1) },
127  { "DMC-GF2", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF2) },
128  { "DMC-GF3", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF3) },
129  { "DMC-GF5", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF5) },
130  { "DMC-GF6", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GF6) },
131  { "DMC-GX1", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GX1) },
132  { "DMC-GX7", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GX7) },
133  { "DMC-FZ8", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ8) },
134  { "DMC-FZ18", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ18) },
135  { "DMC-FZ28", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ28) },
136  { "DMC-FZ30", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ30) },
137  { "DMC-FZ50", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ50) },
138  { "DMC-FZ100", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ100) },
139  { "DMC-FZ200", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_FZ200) },
140  { "DMC-G1", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G1) },
141  { "DMC-G2", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G2) },
142  { "DMC-G3", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G3) },
143  { "DMC-G5", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G5) },
144  { "DMC-G10", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_G10) },
145  { "DMC-GH1", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH1) },
146  { "DMC-GH2", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH2) },
147  { "DMC-GH3", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH3) },
148  { "DMC-GH4", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GH4) },
149  { "DMC-GM1", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GM1) },
150  { "DMC-GM5", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_GM5) },
151  { "DMC-LX2", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX2) },
152  { "DMC-LX3", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX3) },
153  { "DMC-LX5", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX5) },
154  { "DMC-LX7", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX7) },
155  { "DMC-LX100", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_LX100) },
156  { "DMC-L1", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_L1) },
157  { "DMC-L10", OR_MAKE_PANASONIC_TYPEID(OR_TYPEID_PANASONIC_L10) },
158 
159  { "DIGILUX 2", OR_MAKE_LEICA_TYPEID(OR_TYPEID_LEICA_DIGILUX2) },
160  { "D-LUX 3", OR_MAKE_LEICA_TYPEID(OR_TYPEID_LEICA_DLUX_3) },
161  { "V-LUX 1", OR_MAKE_LEICA_TYPEID(OR_TYPEID_LEICA_VLUX_1) },
162 
163  { 0, 0 }
164 };
165 
166 RawFile *Rw2File::factory(const IO::Stream::Ptr & s)
167 {
168  return new Rw2File(s);
169 }
170 
171 Rw2File::Rw2File(const IO::Stream::Ptr & s)
172  : IfdFile(s, OR_RAWFILE_TYPE_RW2, false)
173 {
174  _setIdMap(s_def);
175  _setMatrices(s_matrices);
176  m_container = new Rw2Container(m_io, 0);
177 }
178 
179 Rw2File::~Rw2File()
180 {
181 }
182 
183 
184 IfdDir::Ref Rw2File::_locateCfaIfd()
185 {
186  return mainIfd();
187 }
188 
189 
190 IfdDir::Ref Rw2File::_locateMainIfd()
191 {
192  return m_container->setDirectory(0);
193 }
194 
195 ::or_error Rw2File::_locateThumbnail(const IfdDir::Ref & dir,
196  std::vector<uint32_t> &list)
197 {
198  uint32_t offset = 0;
199  uint32_t size = 0;
200 
201  offset = _getJpegThumbnailOffset(dir, size);
202  if(size == 0) {
203  return OR_ERROR_NOT_FOUND;
204  }
205  Trace(DEBUG1) << "Jpeg offset: " << offset << "\n";
206 
207  uint32_t x = 0;
208  uint32_t y = 0;
209  ::or_data_type _type = OR_DATA_TYPE_JPEG;
210  IO::Stream::Ptr s(new IO::StreamClone(m_io, offset));
211  std::unique_ptr<JfifContainer> jfif(new JfifContainer(s, 0));
212  if (jfif->getDimensions(x,y)) {
213  Trace(DEBUG1) << "JPEG dimensions x=" << x
214  << " y=" << y << "\n";
215  }
216  if(_type != OR_DATA_TYPE_NONE) {
217  uint32_t dim = std::max(x, y);
218  _addThumbnail(dim, ThumbDesc(x, y, _type, offset, size));
219  list.push_back(dim);
220  }
221 
222  return OR_ERROR_NONE;
223 }
224 
225 uint32_t Rw2File::_getJpegThumbnailOffset(const IfdDir::Ref & dir, uint32_t & len)
226 {
227  IfdEntry::Ref e = dir->getEntry(IFD::RW2_TAG_JPEG_FROM_RAW);
228  if(!e) {
229  len = 0;
230  Trace(DEBUG1) << "JpegFromRaw not found\n";
231  return 0;
232  }
233  uint32_t offset = e->offset();
234  len = e->count();
235  return offset;
236 }
237 
238 
239 ::or_error Rw2File::_getRawData(RawData & data, uint32_t /*options*/)
240 {
241  ::or_error ret = OR_ERROR_NONE;
242  const IfdDir::Ref & _cfaIfd = cfaIfd();
243  if(!_cfaIfd) {
244  Trace(DEBUG1) << "cfa IFD not found\n";
245  return OR_ERROR_NOT_FOUND;
246  }
247 
248  Trace(DEBUG1) << "_getRawData()\n";
249  uint32_t offset = 0;
250  uint32_t byte_length = 0;
251  bool got_it;
252  // RW2 file
253  got_it = _cfaIfd->getIntegerValue(IFD::RW2_TAG_STRIP_OFFSETS, offset);
254  if(got_it) {
255  byte_length = m_container->file()->filesize() - offset;
256  }
257  else {
258  // RAW file alternative.
259  got_it = _cfaIfd->getIntegerValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
260  if(!got_it) {
261  Trace(DEBUG1) << "offset not found\n";
262  return OR_ERROR_NOT_FOUND;
263  }
264  got_it = _cfaIfd->getIntegerValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
265  if(!got_it) {
266  Trace(DEBUG1) << "byte len not found\n";
267  return OR_ERROR_NOT_FOUND;
268  }
269  }
270 
271  uint32_t x, y;
272  x = 0;
273  y = 0;
274  got_it = _cfaIfd->getIntegerValue(IFD::RW2_TAG_SENSOR_WIDTH, x);
275  if(!got_it) {
276  Trace(DEBUG1) << "X not found\n";
277  return OR_ERROR_NOT_FOUND;
278  }
279  got_it = _cfaIfd->getIntegerValue(IFD::RW2_TAG_SENSOR_HEIGHT, y);
280  if(!got_it) {
281  Trace(DEBUG1) << "Y not found\n";
282  return OR_ERROR_NOT_FOUND;
283  }
284 
285  // this is were things are complicated. The real size of the raw data
286  // is whatever is read (if compressed)
287  void *p = data.allocData(byte_length);
288  size_t real_size = m_container->fetchData(p, offset,
289  byte_length);
290 
291  if (real_size / (x * 8 / 7) == y) {
292  data.setDataType(OR_DATA_TYPE_COMPRESSED_RAW);
293  data.setCompression(PANA_RAW_COMPRESSION);
294  }
295  else if (real_size < byte_length) {
296  Trace(WARNING) << "Size mismatch for data: expected " << byte_length
297  << " got " << real_size << " ignoring.\n";
298  return OR_ERROR_NOT_FOUND;
299  }
300  else {
301  data.setDataType(OR_DATA_TYPE_RAW);
302  }
303  data.setCfaPatternType(OR_CFA_PATTERN_BGGR);
304 
305 
306  // they are not all RGGB.
307  // but I don't seem to see where this is encoded.
308  //
309  data.setDimensions(x, y);
310 
311  Trace(DEBUG1) << "In size is " << data.width()
312  << "x" << data.height() << "\n";
313  // get the sensor info
314  IfdEntry::Ref e = _cfaIfd->getEntry(IFD::RW2_TAG_SENSOR_LEFTBORDER);
315  x = e->getIntegerArrayItem(0);
316  e = _cfaIfd->getEntry(IFD::RW2_TAG_SENSOR_TOPBORDER);
317  y = e->getIntegerArrayItem(0);
318  e = _cfaIfd->getEntry(IFD::RW2_TAG_IMAGE_HEIGHT);
319  uint32_t h = e->getIntegerArrayItem(0);
320  e = _cfaIfd->getEntry(IFD::RW2_TAG_IMAGE_WIDTH);
321  uint32_t w = e->getIntegerArrayItem(0);
322 
323  data.setRoi(x, y, w, h);
324 
325  return ret;
326 }
327 
328 }
329 }
330 /*
331  Local Variables:
332  mode:c++
333  c-file-style:"stroustrup"
334  c-file-offsets:((innamespace . 0))
335  tab-width:2
336  c-basic-offset:2
337  indent-tabs-mode:nil
338  fill-column:80
339  End:
340 */
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
Definition: arwfile.cpp:30
std::shared_ptr< IfdEntry > Ref
Definition: ifdentry.hpp:178
Definition: trace.cpp:30