libopenraw
rawfile.cpp
1 /*
2  * libopenraw - rawfile.cpp
3  *
4  * Copyright (C) 2008 Novell, Inc.
5  * Copyright (C) 2006-2008, 2010 Hubert Figuiere
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 
23 #include <cstring>
24 #include <cassert>
25 #include <map>
26 #include <string>
27 
28 #include <boost/algorithm/string.hpp>
29 #include <boost/bind.hpp>
30 #include <boost/scoped_ptr.hpp>
31 #include <boost/checked_delete.hpp>
32 
33 #include "trace.h"
34 
35 #include <libopenraw/metadata.h>
36 #include <libopenraw++/rawfile.h>
37 #include <libopenraw++/rawdata.h>
38 #include <libopenraw++/thumbnail.h>
39 
40 #include "io/file.h"
41 #include "io/memstream.h"
42 #include "cr2file.h"
43 #include "neffile.h"
44 #include "orffile.h"
45 #include "arwfile.h"
46 #include "peffile.h"
47 #include "crwfile.h"
48 #include "erffile.h"
49 #include "dngfile.h"
50 #include "mrwfile.h"
51 #include "metavalue.h"
52 #include "exception.h"
53 #include "demosaic.h"
54 
55 #include "rawfilefactory.h"
56 
57 using std::string;
58 using namespace Debug;
59 
60 namespace OpenRaw {
61 
62 using Internals::RawFileFactory;
63 
64 void init(void)
65 {
66  static RawFileFactory fctcr2(OR_RAWFILE_TYPE_CR2,
67  boost::bind(&Internals::Cr2File::factory, _1),
68  "cr2");
69  static RawFileFactory fctnef(OR_RAWFILE_TYPE_NEF,
70  boost::bind(&Internals::NEFFile::factory, _1),
71  "nef");
72  static RawFileFactory fctarw(OR_RAWFILE_TYPE_ARW,
73  boost::bind(&Internals::ARWFile::factory, _1),
74  "arw");
75  static RawFileFactory fctorf(OR_RAWFILE_TYPE_ORF,
76  boost::bind(&Internals::OrfFile::factory, _1),
77  "orf");
78  static RawFileFactory fctdng(OR_RAWFILE_TYPE_DNG,
79  boost::bind(&Internals::DNGFile::factory, _1),
80  "dng");
81  static RawFileFactory fctpef(OR_RAWFILE_TYPE_PEF,
82  boost::bind(&Internals::PEFFile::factory, _1),
83  "pef");
84  static RawFileFactory fctcrw(OR_RAWFILE_TYPE_CRW,
85  boost::bind(&Internals::CRWFile::factory, _1),
86  "crw");
87  static RawFileFactory fcterf(OR_RAWFILE_TYPE_ERF,
88  boost::bind(&Internals::ERFFile::factory, _1),
89  "erf");
90  static RawFileFactory fctmrw(OR_RAWFILE_TYPE_MRW,
91  boost::bind(&Internals::MRWFile::factory, _1),
92  "mrw");
93 }
94 
96 {
97 public:
98  Private(Type t)
99  : m_type(t),
100  m_type_id(OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NONE, OR_TYPEID_UNKNOWN)),
101  m_sizes(),
102  m_cam_ids(NULL)
103  {
104  }
105  ~Private()
106  {
107  std::map<int32_t, MetaValue*>::iterator iter;
108  for(iter = m_metadata.begin();
109  iter != m_metadata.end(); ++iter)
110  {
111  if(iter->second) {
112  delete iter->second;
113  }
114  }
115  }
117  Type m_type;
119  TypeId m_type_id;
121  std::vector<uint32_t> m_sizes;
122  std::map<int32_t, MetaValue*> m_metadata;
123  const camera_ids_t *m_cam_ids;
124 };
125 
126 
127 const char **RawFile::fileExtensions()
128 {
129  init();
130 
131  return RawFileFactory::fileExtensions();
132 }
133 
134 
135 RawFile *RawFile::newRawFile(const char*_filename, RawFile::Type _typeHint)
136 {
137  init();
138 
139  Type type;
140  if (_typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
141  type = identify(_filename);
142  }
143  else {
144  type = _typeHint;
145  }
146  Trace(DEBUG1) << "factory size " << RawFileFactory::table().size() << "\n";
147  RawFileFactory::Table::iterator iter = RawFileFactory::table().find(type);
148  if (iter == RawFileFactory::table().end()) {
149  Trace(WARNING) << "factory not found\n";
150  return NULL;
151  }
152  if (iter->second == NULL) {
153  Trace(WARNING) << "factory is NULL\n";
154  return NULL;
155  }
156  IO::Stream *f = new IO::File(_filename);
157  return iter->second(f);
158 }
159 
160 RawFile *RawFile::newRawFileFromMemory(const uint8_t *buffer,
161  uint32_t len,
162  RawFile::Type _typeHint)
163 {
164  init();
165  Type type;
166  if (_typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
167  ::or_error err = identifyBuffer(buffer, len, type);
168  if(err != OR_ERROR_NONE) {
169  Trace(ERROR) << "error identifying buffer\n";
170  return NULL;
171  }
172  }
173  else {
174  type = _typeHint;
175  }
176  RawFileFactory::Table::iterator iter = RawFileFactory::table().find(type);
177  if (iter == RawFileFactory::table().end()) {
178  Trace(WARNING) << "factory not found\n";
179  return NULL;
180  }
181  if (iter->second == NULL) {
182  Trace(WARNING) << "factory is NULL\n";
183  return NULL;
184  }
185  IO::Stream *f = new IO::MemStream((void*)buffer, len);
186  return iter->second(f);
187 }
188 
189 
190 RawFile::Type RawFile::identify(const char*_filename)
191 {
192  const char *e = ::strrchr(_filename, '.');
193  if (e == NULL) {
194  Trace(DEBUG1) << "Extension not found\n";
195  return OR_RAWFILE_TYPE_UNKNOWN;
196  }
197  std::string extension(e + 1);
198  if (extension.length() > 3) {
199  return OR_RAWFILE_TYPE_UNKNOWN;
200  }
201 
202  boost::to_lower(extension);
203 
204  RawFileFactory::Extensions & extensions = RawFileFactory::extensions();
205  RawFileFactory::Extensions::iterator iter = extensions.find(extension);
206  if (iter == extensions.end())
207  {
208  return OR_RAWFILE_TYPE_UNKNOWN;
209  }
210  return iter->second;
211 }
212 
213 ::or_error RawFile::identifyBuffer(const uint8_t* buff, size_t len,
214  RawFile::Type &_type)
215 {
216  _type = OR_RAWFILE_TYPE_UNKNOWN;
217  if(len <= 4) {
218  return OR_ERROR_BUF_TOO_SMALL;
219  }
220  if(memcmp(buff, "\0MRM", 4) == 0) {
221  _type = OR_RAWFILE_TYPE_MRW;
222  return OR_ERROR_NONE;
223  }
224  if(memcmp(buff, "II\x1a\0\0\0HEAPCCDR", 14) == 0) {
225  _type = OR_RAWFILE_TYPE_CRW;
226  return OR_ERROR_NONE;
227  }
228  if(memcmp(buff, "IIRO", 4) == 0) {
229  _type = OR_RAWFILE_TYPE_ORF;
230  return OR_ERROR_NONE;
231  }
232  if((memcmp(buff, "II\x2a\0", 4) == 0)
233  || (memcmp(buff, "MM\0\x2a", 4) == 0)) {
234  // TIFF based format
235  if(len >=12 ) {
236  if(memcmp(buff + 8, "CR\x2", 3) == 0) {
237  _type = OR_RAWFILE_TYPE_CR2;
238  return OR_ERROR_NONE;
239  }
240  }
241  if(len >= 8) {
242  IO::Stream *s = new IO::MemStream((void*)buff, len);
243  boost::scoped_ptr<Internals::TiffEpFile> f(new Internals::TiffEpFile(s, OR_RAWFILE_TYPE_TIFF));
244 
245  // Take into account DNG by checking the DNGVersion tag
246  const MetaValue *dng_version = f->getMetaValue(META_NS_TIFF | TIFF_TAG_DNG_VERSION);
247  if(dng_version) {
248  Trace(DEBUG1) << "found DNG versions\n";
249  _type = OR_RAWFILE_TYPE_DNG;
250  return OR_ERROR_NONE;
251  }
252 
253  const MetaValue *makev = f->getMetaValue(META_NS_TIFF | EXIF_TAG_MAKE);
254  if(makev){
255  std::string makes = makev->getString();
256  if(makes == "NIKON CORPORATION") {
257  _type = OR_RAWFILE_TYPE_NEF;
258  }
259  else if(makes == "SEIKO EPSON CORP."){
260  _type = OR_RAWFILE_TYPE_ERF;
261  }
262  else if(makes == "PENTAX Corporation ") {
263  _type = OR_RAWFILE_TYPE_PEF;
264  }
265  else if(makes == "SONY ") {
266  _type = OR_RAWFILE_TYPE_ARW;
267  }
268  else if(makes == "Canon") {
269  _type = OR_RAWFILE_TYPE_CR2;
270  }
271  }
272  }
273 
274  }
275  return OR_ERROR_NONE;
276 }
277 
278 RawFile::RawFile(IO::Stream *, RawFile::Type _type)
279  : d(new Private(_type))
280 {
281 
282 }
283 
284 
286 {
287  delete d;
288 }
289 
290 
291 RawFile::Type RawFile::type() const
292 {
293  return d->m_type;
294 }
295 
296 RawFile::TypeId RawFile::typeId()
297 {
298  if(d->m_type_id == 0) {
299  _identifyId();
300  }
301  return d->m_type_id;
302 }
303 
304 void RawFile::_setTypeId(RawFile::TypeId _type_id)
305 {
306  d->m_type_id = _type_id;
307 }
308 
309 const std::vector<uint32_t> & RawFile::listThumbnailSizes(void)
310 {
311  if (d->m_sizes.size() == 0) {
312  Trace(DEBUG1) << "_enumThumbnailSizes init\n";
313  bool ret = _enumThumbnailSizes(d->m_sizes);
314  if (!ret) {
315  Trace(DEBUG1) << "_enumThumbnailSizes failed\n";
316  }
317  }
318  return d->m_sizes;
319 }
320 
321 
322 ::or_error RawFile::getThumbnail(uint32_t tsize, Thumbnail & thumbnail)
323 {
324  ::or_error ret = OR_ERROR_NOT_FOUND;
325  uint32_t smallest_bigger = 0xffffffff;
326  uint32_t biggest_smaller = 0;
327  uint32_t found_size = 0;
328 
329  Trace(DEBUG1) << "requested size " << tsize << "\n";
330 
331  const std::vector<uint32_t> & sizes(listThumbnailSizes());
332 
333  std::vector<uint32_t>::const_iterator iter;
334 
335  for (iter = sizes.begin(); iter != sizes.end(); ++iter) {
336  Trace(DEBUG1) << "current iter is " << *iter << "\n";
337  if (*iter < tsize) {
338  if (*iter > biggest_smaller) {
339  biggest_smaller = *iter;
340  }
341  }
342  else if(*iter > tsize) {
343  if(*iter < smallest_bigger) {
344  smallest_bigger = *iter;
345  }
346  }
347  else { // *iter == tsize
348  found_size = tsize;
349  break;
350  }
351  }
352 
353  if (found_size == 0) {
354  found_size = (smallest_bigger != 0xffffffff ?
355  smallest_bigger : biggest_smaller);
356  }
357 
358  if (found_size != 0) {
359  Trace(DEBUG1) << "size " << found_size << " found\n";
360  ret = _getThumbnail(found_size, thumbnail);
361  }
362  else {
363  // no size found, let's fail gracefuly
364  Trace(DEBUG1) << "no size found\n";
365  ret = OR_ERROR_NOT_FOUND;
366  }
367 
368  return ret;
369 }
370 
371 
372 ::or_error RawFile::getRawData(RawData & rawdata, uint32_t options)
373 {
374  Trace(DEBUG1) << "getRawData()\n";
375  ::or_error ret = _getRawData(rawdata, options);
376  return ret;
377 }
378 
379 ::or_error RawFile::getRenderedImage(BitmapData & bitmapdata, uint32_t options)
380 {
381  RawData rawdata;
382  Trace(DEBUG1) << "options are " << options << "\n";
383  ::or_error ret = getRawData(rawdata, options);
384  if(ret == OR_ERROR_NONE) {
385  if(rawdata.dataType() != OR_DATA_TYPE_CFA) {
386  Trace(DEBUG1) << "wrong data type\n";
387  return OR_ERROR_INVALID_FORMAT;
388  }
389  uint32_t x,y;
390  or_cfa_pattern pattern;
391  uint16_t *src;
392  pattern = rawdata.cfaPattern();
393  x = rawdata.x();
394  y = rawdata.y();
395  bitmapdata.setDimensions(x,y);
396  bitmapdata.setDataType(OR_DATA_TYPE_PIXMAP_8RGB);
397  uint8_t *dst = (uint8_t *)bitmapdata.allocData(sizeof(uint8_t) * 3 * x * y);
398  /*
399  rawdata.linearize();
400  rawdata.subtractBlack();
401  rawdata.rescale();
402  rawdata.clip();
403  */
404  src = (uint16_t*)rawdata.data();
405 
406  /* figure out how the demosaic can be plugged for a different
407  * algorithm */
408  bimedian_demosaic(src, x, y, pattern, dst);
409  }
410  return ret;
411 }
412 
413 
415 {
416  int32_t idx = 0;
417  const MetaValue * value = getMetaValue(META_NS_TIFF
418  | EXIF_TAG_ORIENTATION);
419  if(value == NULL) {
420  return 0;
421  }
422  try {
423  idx = value->getInteger();
424  }
425  catch(const Internals::BadTypeException & e) {
426  Trace(DEBUG1) << "wrong type - " << e.what() << "\n";
427  }
428  return idx;
429 }
430 
431 const MetaValue *RawFile::getMetaValue(int32_t meta_index)
432 {
433  MetaValue *val = NULL;
434  std::map<int32_t, MetaValue*>::iterator iter = d->m_metadata.find(meta_index);
435  if(iter == d->m_metadata.end()) {
436  val = _getMetaValue(meta_index);
437  if(val != NULL) {
438  d->m_metadata[meta_index] = val;
439  }
440  }
441  else {
442  val = iter->second;
443  }
444  return val;
445 }
446 
447 
448 RawFile::TypeId RawFile::_typeIdFromModel(const std::string & model)
449 {
450  const struct camera_ids_t * p = d->m_cam_ids;
451  if(!p) {
452  return 0;
453  }
454  while(p->model) {
455  if(model == p->model) {
456  break;
457  }
458  p++;
459  }
460  return p->type_id;
461 }
462 
463 void RawFile::_setIdMap(const camera_ids_t *map)
464 {
465  d->m_cam_ids = map;
466 }
467 
468 }
469 
470 /*
471  Local Variables:
472  mode:c++
473  c-file-style:"stroustrup"
474  c-file-offsets:((innamespace . 0))
475  indent-tabs-mode:nil
476  fill-column:80
477  End:
478 */
479 
::or_error getThumbnail(uint32_t size, Thumbnail &thumbnail)
Definition: rawfile.cpp:322
DataType dataType() const
Definition: bitmapdata.cpp:87
Type type() const
Definition: rawfile.cpp:291
::or_error getRawData(RawData &rawdata, uint32_t options)
Definition: rawfile.cpp:372
::or_error getRenderedImage(BitmapData &bitmapdata, uint32_t options)
Definition: rawfile.cpp:379
virtual ::or_error _getRawData(RawData &data, uint32_t options)=0
void _setTypeId(TypeId _type_id)
Definition: rawfile.cpp:304
virtual ::or_error _enumThumbnailSizes(std::vector< uint32_t > &list)=0
virtual void setDimensions(uint32_t x, uint32_t y)
Definition: bitmapdata.cpp:148
TypeId typeId()
Definition: rawfile.cpp:296
virtual ::or_error _getThumbnail(uint32_t size, Thumbnail &thumbnail)=0
const std::vector< uint32_t > & listThumbnailSizes(void)
Definition: rawfile.cpp:309
void setDataType(DataType _type)
Definition: bitmapdata.cpp:92
std::vector< uint32_t > m_sizes
Definition: rawfile.cpp:121
virtual ~RawFile()
Definition: rawfile.cpp:285
int32_t getOrientation()
Definition: rawfile.cpp:414
base virtual class for IO
Definition: stream.h:40