29 #include <libopenraw/debug.h> 30 #include <libopenraw/metadata.h> 31 #include <libopenraw/cameraids.h> 33 #include "rawdata.hpp" 34 #include "metavalue.hpp" 35 #include "cfapattern.hpp" 36 #include "rawfile.hpp" 38 #include "io/streamclone.hpp" 39 #include "io/memstream.hpp" 40 #include "crwfile.hpp" 41 #include "ciffcontainer.hpp" 42 #include "jfifcontainer.hpp" 43 #include "crwdecompressor.hpp" 44 #include "rawfile_private.hpp" 46 using namespace Debug;
54 #define OR_MAKE_CANON_TYPEID(camid) \ 55 OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,camid) 58 static const BuiltinColourMatrix s_matrices[] = {
59 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_D30), 0, 0,
60 { 9805,-2689,-1312,-5803,13064,3068,-2438,3075,8775 } },
61 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_D60), 0, 0xfa0,
62 { 6188,-1341,-890,-7168,14489,2937,-2640,3228,8483 } },
63 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_10D), 0, 0xfa0,
64 { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
65 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_300D), 0, 0xfa0,
66 { 8197,-2000,-1118,-6714,14335,2592,-2536,3178,8266 } },
69 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G2), 0, 0,
70 { 9087,-2693,-1049,-6715,14382,2537,-2291,2819,7790 } },
71 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G3), 0, 0,
72 { 9212,-2781,-1073,-6573,14189,2605,-2300,2844,7664 } },
73 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G5), 0, 0,
74 { 9757,-2872,-933,-5972,13861,2301,-1622,2328,7212 } },
75 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G6), 0, 0,
76 { 9877,-3775,-871,-7613,14807,3072,-1448,1305,7485 } },
77 { OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_PRO1), 0, 0,
78 { 10062,-3522,-999,-7643,15117,2730,-765,817,7323 } },
79 { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0 } }
82 const RawFile::camera_ids_t CRWFile::s_def[] = {
83 {
"Canon EOS D30" , OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_D30) },
84 {
"Canon EOS D60" , OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_D60) },
85 {
"Canon EOS 10D" , OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_10D) },
86 {
"Canon EOS 300D DIGITAL", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_300D) },
87 {
"Canon PowerShot G1", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G1) },
88 {
"Canon PowerShot G2", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G2) },
89 {
"Canon PowerShot G3", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G3) },
90 {
"Canon PowerShot G5", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G5) },
91 {
"Canon PowerShot G6", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G6) },
92 {
"Canon PowerShot G7", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_G7) },
93 {
"Canon PowerShot Pro1", OR_MAKE_CANON_TYPEID(OR_TYPEID_CANON_PRO1) },
97 RawFile *CRWFile::factory(
const IO::Stream::Ptr &s)
99 return new CRWFile(s);
102 CRWFile::CRWFile(
const IO::Stream::Ptr &s)
103 : RawFile(OR_RAWFILE_TYPE_CRW),
105 m_container(new CIFFContainer(m_io)),
109 _setMatrices(s_matrices);
119 ::or_error err = OR_ERROR_NOT_FOUND;
121 Heap::Ref heap = m_container->heap();
126 const RecordEntry::List & records = heap->records();
127 RecordEntry::List::const_iterator iter;
128 iter = std::find_if(records.cbegin(), records.cend(), std::bind(
130 static_cast<uint16_t>(TAG_JPEGIMAGE)));
131 if (iter != records.end()) {
132 LOGDBG2(
"JPEG @%u\n", (*iter).offset);
134 uint32_t offset = heap->offset() + (*iter).offset;
136 std::unique_ptr<JfifContainer> jfif(
new JfifContainer(s, 0));
138 jfif->getDimensions(m_x, m_y);
139 LOGDBG1(
"JPEG dimensions x=%d y=%d\n", m_x, m_y);
140 uint32_t dim = std::max(m_x,m_y);
141 _addThumbnail(dim,
ThumbDesc(m_x, m_y, OR_DATA_TYPE_JPEG, offset, (*iter).length));
156 ::or_error err = OR_ERROR_NOT_FOUND;
157 Heap::Ref props = m_container->getImageProps();
160 return OR_ERROR_NOT_FOUND;
162 const ImageSpec * img_spec = m_container->getImageSpec();
166 x = img_spec->imageWidth;
167 y = img_spec->imageHeight;
171 const CIFF::RecordEntry::List & propsRecs = props->records();
172 auto iter = std::find_if(propsRecs.cbegin(), propsRecs.cend(), std::bind(
174 static_cast<uint16_t>(TAG_EXIFINFORMATION)));
175 if (iter == propsRecs.end()) {
176 LOGERR(
"Couldn't find the Exif information.\n");
177 return OR_ERROR_NOT_FOUND;
180 Heap exifProps(iter->offset + props->offset(), iter->length, m_container);
182 const RecordEntry::List & exifPropsRecs = exifProps.records();
183 iter = std::find_if(exifPropsRecs.cbegin(), exifPropsRecs.cend(),
186 static_cast<uint16_t>(TAG_DECODERTABLE)));
187 if (iter == exifPropsRecs.end()) {
188 LOGERR(
"Couldn't find the decoder table.\n");
191 LOGDBG2(
"length = %d\n", iter->length);
192 LOGDBG2(
"offset = %ld\n", exifProps.offset() + iter->offset);
193 auto file = m_container->file();
194 file->seek(exifProps.offset() + iter->offset, SEEK_SET);
198 LOGERR(
"Couldn't find decoder table\n");
199 return OR_ERROR_NOT_FOUND;
202 uint32_t decoderTable = result.unwrap();
203 LOGDBG2(
"decoder table = %u\n", decoderTable);
206 iter = std::find_if(exifPropsRecs.cbegin(), exifPropsRecs.cend(), std::bind(
208 static_cast<uint16_t>(TAG_SENSORINFO)));
209 if (iter == exifPropsRecs.end()) {
210 LOGERR(
"Couldn't find the sensor info.\n");
213 LOGDBG2(
"length = %u\n", iter->length);
214 LOGDBG2(
"offset = %ld\n", exifProps.offset() + iter->offset);
217 file->seek(exifProps.offset() + iter->offset + 2, SEEK_SET);
221 if(cfa_x.empty() || cfa_y.empty()) {
222 LOGERR(
"Couldn't find the sensor size.\n");
223 return OR_ERROR_NOT_FOUND;
229 CIFF::Heap::Ref heap = m_container->heap();
230 LOGDBG2(
"RAW @%ld\n", heap->offset() + entry->offset);
231 size_t byte_size = entry->length;
232 void *buf = data.allocData(byte_size);
233 size_t real_size = entry->
fetchData(heap.get(), buf, byte_size);
234 if (real_size != byte_size) {
235 LOGWARN(
"wrong size\n");
238 data.setCfaPatternType(OR_CFA_PATTERN_RGGB);
242 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
249 decomp.setOutputDimensions(cfa_x.unwrap(), cfa_y.unwrap());
250 decomp.setDecoderTable(decoderTable);
251 RawDataPtr dData = decomp.decompress();
253 LOGDBG1(
"Out size is %dx%d\n", dData->width(), dData->height());
263 MetaValue *CRWFile::_getMetaValue(int32_t meta_index)
267 switch(META_INDEX_MASKOUT(meta_index)) {
270 uint32_t index = META_NS_MASKOUT(meta_index);
272 case EXIF_TAG_ORIENTATION:
274 const ImageSpec * img_spec = m_container->getImageSpec();
276 val =
new MetaValue(static_cast<uint32_t>(
277 img_spec->exifOrientation()));
284 if (index == EXIF_TAG_MAKE && !m_make.empty()) {
288 if (index == EXIF_TAG_MODEL && !m_model.empty()) {
293 CIFF::Heap::Ref heap = m_container->getCameraProps();
295 auto propsRecs = heap->records();
297 = std::find_if(propsRecs.cbegin(), propsRecs.cend(),
299 return e.isA(static_cast<uint16_t>(CIFF::TAG_RAWMAKEMODEL));
301 if (iter == propsRecs.end()) {
302 LOGERR(
"Couldn't find the image info.\n");
306 size_t sz = iter->length;
310 iter->fetchData(heap.get(),
316 m_make = std::string(buf, p - buf);
320 if (index == EXIF_TAG_MODEL) {
323 else if (index == EXIF_TAG_MAKE) {
326 LOGDBG1(
"Make %s\n", m_make.c_str());
327 LOGDBG1(
"Model %s\n", m_model.c_str());
340 LOGERR(
"Unknown Meta Namespace\n");
347 void CRWFile::_identifyId()
352 MetaValue * v = _getMetaValue(META_NS_TIFF | EXIF_TAG_MODEL);
354 model = v->getString(0);
357 v = _getMetaValue(META_NS_TIFF | EXIF_TAG_MAKE);
359 make = v->getString(0);
362 _setTypeId(_typeIdFromModel(make, model));
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
size_t fetchData(Heap *heap, void *buf, size_t size) const
cloned stream. Allow reading from a different offset
Option< uint32_t > readUInt32(const IO::Stream::Ptr &f)
::or_cfa_pattern patternType() const
virtual ::or_error _getRawData(RawData &data, uint32_t options) override
const CfaPattern * cfaPattern() const
bool isA(uint16_t _typeCode) const
void setDataType(DataType _type)
Option< uint16_t > readUInt16(const IO::Stream::Ptr &f)
virtual RawContainer * getContainer() const override
virtual void setDimensions(uint32_t x, uint32_t y) override
virtual ::or_error _enumThumbnailSizes(std::vector< uint32_t > &list) override