24 #include <boost/bind.hpp>
25 #include <boost/scoped_ptr.hpp>
27 #include <libopenraw/libopenraw.h>
28 #include <libopenraw++/thumbnail.h>
29 #include <libopenraw++/rawdata.h>
33 #include "io/streamclone.h"
34 #include "io/memstream.h"
36 #include "ciffcontainer.h"
37 #include "jfifcontainer.h"
38 #include "crwdecompressor.h"
39 #include "metavalue.h"
41 #include "rawfilefactory.h"
43 using namespace Debug;
44 using boost::scoped_ptr;
52 const RawFile::camera_ids_t CRWFile::s_def[] = {
53 {
"Canon EOS D30" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
54 OR_TYPEID_CANON_D30) },
55 {
"Canon EOS D60" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
56 OR_TYPEID_CANON_D60) },
57 {
"Canon EOS 10D" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
58 OR_TYPEID_CANON_10D) },
59 {
"Canon EOS 300D DIGITAL", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
60 OR_TYPEID_CANON_300D) },
61 {
"Canon PowerShot G1", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
62 OR_TYPEID_CANON_G1) },
63 {
"Canon PowerShot G2", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
64 OR_TYPEID_CANON_G2) },
65 {
"Canon PowerShot G3", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
66 OR_TYPEID_CANON_G3) },
67 {
"Canon PowerShot G5", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
68 OR_TYPEID_CANON_G5) },
69 {
"Canon PowerShot G6", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
70 OR_TYPEID_CANON_G6) },
71 {
"Canon PowerShot G7", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
72 OR_TYPEID_CANON_G7) },
73 {
"Canon PowerShot Pro1", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
74 OR_TYPEID_CANON_PRO1) },
78 RawFile *CRWFile::factory(IO::Stream *s)
80 return new CRWFile(s);
83 CRWFile::CRWFile(IO::Stream *s)
84 : RawFile(s, OR_RAWFILE_TYPE_CRW),
86 m_container(new CIFFContainer(m_io)),
100 ::or_error err = OR_ERROR_NOT_FOUND;
102 Heap::Ref heap = m_container->heap();
107 const RecordEntry::List & records = heap->records();
108 RecordEntry::List::const_iterator iter;
109 iter = std::find_if(records.begin(), records.end(), boost::bind(
111 static_cast<uint16_t>(TAG_JPEGIMAGE)));
112 if (iter != records.end()) {
113 Trace(DEBUG2) <<
"JPEG @" << (*iter).offset <<
"\n";
118 scoped_ptr<JFIFContainer> jfif(
new JFIFContainer(s.get(), 0));
120 jfif->getDimensions(m_x, m_y);
121 Trace(DEBUG1) <<
"JPEG dimensions x=" << m_x
122 <<
" y=" << m_y <<
"\n";
123 list.push_back(std::max(m_x,m_y));
132 ::or_error err = OR_ERROR_NOT_FOUND;
133 Heap::Ref heap = m_container->heap();
139 const RecordEntry::List & records = heap->records();
140 RecordEntry::List::const_iterator iter;
141 iter = std::find_if(records.begin(), records.end(), boost::bind(
143 static_cast<uint16_t>(TAG_JPEGIMAGE)));
144 if (iter != records.end()) {
145 Trace(DEBUG2) <<
"JPEG @" << (*iter).offset <<
"\n";
146 size_t byte_size = (*iter).length;
147 void *buf = thumbnail.allocData(byte_size);
148 size_t real_size = (*iter).fetchData(heap.get(), buf, byte_size);
149 if (real_size != byte_size) {
150 Trace(WARNING) <<
"wrong size\n";
162 ::or_error err = OR_ERROR_NOT_FOUND;
163 Heap::Ref props = m_container->getImageProps();
166 return OR_ERROR_NOT_FOUND;
168 const ImageSpec * img_spec = m_container->getImageSpec();
171 int32_t orientation = 0;
173 x = img_spec->imageWidth;
174 y = img_spec->imageHeight;
175 orientation = img_spec->exifOrientation();
179 const CIFF::RecordEntry::List & propsRecs = props->records();
180 CIFF::RecordEntry::List::const_iterator iter;
181 iter = std::find_if(propsRecs.begin(), propsRecs.end(), boost::bind(
183 static_cast<uint16_t>(TAG_EXIFINFORMATION)));
184 if (iter == propsRecs.end()) {
185 Trace(ERROR) <<
"Couldn't find the Exif information.\n";
189 Heap exifProps(iter->offset + props->offset(), iter->length, m_container);
191 const RecordEntry::List & exifPropsRecs = exifProps.records();
192 iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(),
195 static_cast<uint16_t>(TAG_DECODERTABLE)));
196 if (iter == exifPropsRecs.end()) {
197 Trace(ERROR) <<
"Couldn't find the decoder table.\n";
200 Trace(DEBUG2) <<
"length = " << iter->length <<
"\n";
201 Trace(DEBUG2) <<
"offset = " << exifProps.offset() + iter->offset <<
"\n";
203 file->
seek(exifProps.offset() + iter->offset, SEEK_SET);
204 uint32_t decoderTable;
205 if(m_container->
readUInt32(file, decoderTable)) {
206 Trace(DEBUG2) <<
"decoder table = " << decoderTable <<
"\n";
210 uint16_t cfa_x, cfa_y;
211 iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(), boost::bind(
213 static_cast<uint16_t>(TAG_SENSORINFO)));
214 if (iter == exifPropsRecs.end()) {
215 Trace(ERROR) <<
"Couldn't find the sensor info.\n";
218 Trace(DEBUG2) <<
"length = " << iter->length <<
"\n";
219 Trace(DEBUG2) <<
"offset = " << exifProps.offset() + iter->offset <<
"\n";
222 file->
seek(exifProps.offset() + iter->offset + 2, SEEK_SET);
225 Trace(ERROR) <<
"Couldn't find the sensor size.\n";
232 CIFF::Heap::Ref heap = m_container->heap();
233 Trace(DEBUG2) <<
"RAW @" << heap->offset() + entry->offset <<
"\n";
234 size_t byte_size = entry->length;
235 void *buf = data.allocData(byte_size);
236 size_t real_size = entry->
fetchData(heap.get(), buf, byte_size);
237 if (real_size != byte_size) {
238 Trace(WARNING) <<
"wrong size\n";
241 data.setCfaPattern(OR_CFA_PATTERN_RGGB);
245 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
246 boost::scoped_ptr<IO::Stream> s(
new IO::MemStream(data.data(),
252 decomp.setOutputDimensions(cfa_x, cfa_y);
253 decomp.setDecoderTable(decoderTable);
254 RawData *dData = decomp.decompress();
256 Trace(DEBUG1) <<
"Out size is " << dData->x()
257 <<
"x" << dData->y() <<
"\n";
258 dData->setCfaPattern(data.cfaPattern());
268 MetaValue *CRWFile::_getMetaValue(int32_t meta_index)
272 switch(META_INDEX_MASKOUT(meta_index)) {
275 switch(META_NS_MASKOUT(meta_index)) {
276 case EXIF_TAG_ORIENTATION:
278 const ImageSpec * img_spec = m_container->getImageSpec();
280 val =
new MetaValue(static_cast<uint32_t>(
281 img_spec->exifOrientation()));
287 CIFF::Heap::Ref heap = m_container->getCameraProps();
289 const CIFF::RecordEntry::List & propsRecs = heap->records();
290 CIFF::RecordEntry::List::const_iterator iter;
291 iter = std::find_if(propsRecs.begin(), propsRecs.end(),
294 static_cast<uint16_t>(CIFF::TAG_RAWMAKEMODEL)));
295 if (iter == propsRecs.end()) {
296 Trace(ERROR) <<
"Couldn't find the image info.\n";
300 size_t sz = iter->length;
306 sz2 = iter->fetchData(heap.get(), (
void*)buf, sz);
313 val =
new MetaValue(model);
314 Trace(DEBUG1) <<
"Model " << model <<
"\n";
327 Trace(ERROR) <<
"Unknown Meta Namespace\n";
334 void CRWFile::_identifyId()
336 MetaValue * v = _getMetaValue(META_NS_TIFF | EXIF_TAG_MODEL);
340 model = v->getString();
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
virtual void setDimensions(uint32_t x, uint32_t y)
bool readUInt16(IO::Stream *f, uint16_t &v)
void _setTypeId(TypeId _type_id)
cloned stream. Allow reading from a different offset
virtual void setDimensions(uint32_t x, uint32_t y)
bool isA(uint16_t _typeCode) const
virtual ::or_error _getThumbnail(uint32_t size, Thumbnail &thumbnail)
virtual int seek(off_t offset, int whence)=0
void setDataType(DataType _type)
virtual ::or_error _getRawData(RawData &data, uint32_t options)
size_t fetchData(Heap *heap, void *buf, size_t size) const
virtual ::or_error _enumThumbnailSizes(std::vector< uint32_t > &list)
base virtual class for IO
bool readUInt32(IO::Stream *f, uint32_t &v)