libopenraw
cr2file.cpp
1 /*
2  * libopenraw - cr2file.cpp
3  *
4  * Copyright (C) 2006-2010 Hubert Figuiere
5  * Copyright (C) 2008 Novell, Inc.
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 <boost/scoped_ptr.hpp>
23 #include <boost/any.hpp>
24 #include <libopenraw/libopenraw.h>
25 #include <libopenraw++/thumbnail.h>
26 #include <libopenraw++/rawdata.h>
27 
28 #include "trace.h"
29 #include "io/file.h"
30 #include "io/memstream.h"
31 #include "ifdfilecontainer.h"
32 #include "ifd.h"
33 #include "cr2file.h"
34 #include "jfifcontainer.h"
35 #include "ljpegdecompressor.h"
36 #include "rawfilefactory.h"
37 
38 using namespace Debug;
39 
40 namespace OpenRaw {
41 
42  namespace Internals {
43  const IFDFile::camera_ids_t Cr2File::s_def[] = {
44  { "Canon EOS-1D Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
45  OR_TYPEID_CANON_1DMKII) },
46  { "Canon EOS-1D Mark III", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
47  OR_TYPEID_CANON_1DMKIII) },
48  { "Canon EOS-1D Mark IV", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
49  OR_TYPEID_CANON_1DMKIV) },
50  { "Canon EOS-1Ds Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
51  OR_TYPEID_CANON_1DSMKII) },
52  { "Canon EOS-1Ds Mark III", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
53  OR_TYPEID_CANON_1DSMKIII) },
54  { "Canon EOS 20D" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
55  OR_TYPEID_CANON_20D) },
56  { "Canon EOS 20Da", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
57  OR_TYPEID_CANON_20DA) },
58  { "Canon EOS 30D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
59  OR_TYPEID_CANON_30D) },
60  { "Canon EOS 350D DIGITAL", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
61  OR_TYPEID_CANON_350D) },
62  { "Canon EOS DIGITAL REBEL XT", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
63  OR_TYPEID_CANON_350D) },
64  { "Canon EOS 40D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
65  OR_TYPEID_CANON_40D) },
66  { "Canon EOS 400D DIGITAL", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
67  OR_TYPEID_CANON_400D) },
68  { "Canon EOS 450D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
69  OR_TYPEID_CANON_450D) },
70  { "Canon EOS 50D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
71  OR_TYPEID_CANON_50D) },
72  { "Canon EOS 500D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
73  OR_TYPEID_CANON_500D) },
74  { "Canon EOS 550D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
75  OR_TYPEID_CANON_550D) },
76  { "Canon EOS 60D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
77  OR_TYPEID_CANON_60D) },
78  { "Canon EOS 1000D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
79  OR_TYPEID_CANON_1000D) },
80  { "Canon EOS 5D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
81  OR_TYPEID_CANON_5D) },
82  { "Canon EOS 5D Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
83  OR_TYPEID_CANON_5DMKII) },
84  { "Canon EOS 7D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
85  OR_TYPEID_CANON_7D) },
86  { "Canon PowerShot G9", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
87  OR_TYPEID_CANON_G9) },
88  { "Canon PowerShot G10", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
89  OR_TYPEID_CANON_G11) },
90  { "Canon PowerShot G11", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
91  OR_TYPEID_CANON_G11) },
92  { 0, 0 }
93  };
94 
95  RawFile *Cr2File::factory(IO::Stream * s)
96  {
97  return new Cr2File(s);
98  }
99 
100  Cr2File::Cr2File(IO::Stream * s)
101  : IFDFile(s, OR_RAWFILE_TYPE_CR2)
102  {
103  _setIdMap(s_def);
104  }
105 
106  Cr2File::~Cr2File()
107  {
108  }
109 
110 
111  IFDDir::Ref Cr2File::_locateCfaIfd()
112  {
113  return m_container->setDirectory(3);
114  }
115 
116 
117  IFDDir::Ref Cr2File::_locateMainIfd()
118  {
119  return m_container->setDirectory(0);
120  }
121 
122  ::or_error Cr2File::_getRawData(RawData & data, uint32_t options)
123  {
124  ::or_error ret = OR_ERROR_NONE;
125  if(!m_cfaIfd) {
126  m_cfaIfd = _locateCfaIfd();
127  }
128  if(!m_cfaIfd) {
129  Trace(DEBUG1) << "cfa IFD not found\n";
130  return OR_ERROR_NOT_FOUND;
131  }
132 
133  Trace(DEBUG1) << "_getRawData()\n";
134  uint32_t offset = 0;
135  uint32_t byte_length = 0;
136  bool got_it;
137  got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
138  if(!got_it) {
139  Trace(DEBUG1) << "offset not found\n";
140  return OR_ERROR_NOT_FOUND;
141  }
142  got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
143  if(!got_it) {
144  Trace(DEBUG1) << "byte len not found\n";
145  return OR_ERROR_NOT_FOUND;
146  }
147  // get the "slicing", tag 0xc640 (3 SHORT)
148  std::vector<uint16_t> slices;
149  IFDEntry::Ref e = m_cfaIfd->getEntry(IFD::EXIF_TAG_CR2_SLICE);
150  if (e) {
151  e->getArray(slices);
152  Trace(DEBUG1) << "Found slice entry " << slices << "\n";
153  }
154 
155  if(!m_exifIfd) {
156  m_exifIfd = _locateExifIfd();
157  }
158  if (m_exifIfd) {
159  uint16_t x, y;
160  x = 0;
161  y = 0;
162  got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_X_DIMENSION, x);
163  if(!got_it) {
164  Trace(DEBUG1) << "X not found\n";
165  return OR_ERROR_NOT_FOUND;
166  }
167  got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_Y_DIMENSION, y);
168  if(!got_it) {
169  Trace(DEBUG1) << "Y not found\n";
170  return OR_ERROR_NOT_FOUND;
171  }
172 
173  void *p = data.allocData(byte_length);
174  size_t real_size = m_container->fetchData(p, offset,
175  byte_length);
176  if (real_size < byte_length) {
177  Trace(WARNING) << "Size mismatch for data: ignoring.\n";
178  }
179  data.setCfaPattern(OR_CFA_PATTERN_RGGB);
180  data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
181  data.setDimensions(x, y);
182  Trace(DEBUG1) << "In size is " << data.x()
183  << "x" << data.y() << "\n";
184  // decompress if we need
185  if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
186  boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
187  data.size()));
188  s->open(); // TODO check success
189  boost::scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
190  LJpegDecompressor decomp(s.get(), jfif.get());
191  // in fact on Canon CR2 files slices either do not exists
192  // or is 3.
193  if(slices.size() > 1) {
194  decomp.setSlices(slices);
195  }
196  RawData *dData = decomp.decompress();
197  if (dData != NULL) {
198  Trace(DEBUG1) << "Out size is " << dData->x()
199  << "x" << dData->y() << "\n";
200  // must re-set the cfaPattern
201  dData->setCfaPattern(data.cfaPattern());
202  data.swap(*dData);
203  delete dData;
204  }
205  }
206  }
207  else {
208  Trace(ERROR) << "unable to find ExifIFD\n";
209  ret = OR_ERROR_NOT_FOUND;
210  }
211  return ret;
212  }
213 
214 
215  }
216 }
IFDFileContainer * m_container
Definition: ifdfile.h:95
size_t fetchData(void *buf, const off_t offset, const size_t buf_size)
boost::shared_ptr< IFDEntry > Ref
Definition: ifdentry.h:122