00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <algorithm>
00023 #include <utility>
00024 #include <boost/bind.hpp>
00025 #include <boost/scoped_ptr.hpp>
00026
00027 #include <libopenraw/libopenraw.h>
00028 #include <libopenraw++/thumbnail.h>
00029 #include <libopenraw++/rawdata.h>
00030
00031 #include "debug.h"
00032 #include "io/file.h"
00033 #include "io/streamclone.h"
00034 #include "io/memstream.h"
00035 #include "crwfile.h"
00036 #include "ciffcontainer.h"
00037 #include "jfifcontainer.h"
00038 #include "crwdecompressor.h"
00039 #include "metavalue.h"
00040
00041 #include "rawfilefactory.h"
00042
00043 using namespace Debug;
00044 using boost::scoped_ptr;
00045
00046 namespace OpenRaw {
00047
00048 namespace Internals {
00049
00050 using namespace CIFF;
00051
00052 const RawFile::camera_ids_t CRWFile::s_def[] = {
00053 { "Canon EOS D30" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00054 OR_TYPEID_CANON_D30) },
00055 { "Canon EOS D60" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00056 OR_TYPEID_CANON_D60) },
00057 { "Canon EOS 10D" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00058 OR_TYPEID_CANON_10D) },
00059 { "Canon EOS 300D DIGITAL", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00060 OR_TYPEID_CANON_300D) },
00061 { "Canon PowerShot G1", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00062 OR_TYPEID_CANON_G1) },
00063 { "Canon PowerShot G2", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00064 OR_TYPEID_CANON_G2) },
00065 { "Canon PowerShot G3", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00066 OR_TYPEID_CANON_G3) },
00067 { "Canon PowerShot G5", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00068 OR_TYPEID_CANON_G5) },
00069 { "Canon PowerShot G6", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00070 OR_TYPEID_CANON_G6) },
00071 { "Canon PowerShot G7", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00072 OR_TYPEID_CANON_G7) },
00073 { "Canon PowerShot Pro1", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00074 OR_TYPEID_CANON_PRO1) },
00075 { 0, 0 }
00076 };
00077
00078 RawFile *CRWFile::factory(IO::Stream *s)
00079 {
00080 return new CRWFile(s);
00081 }
00082
00083 CRWFile::CRWFile(IO::Stream *s)
00084 : RawFile(s, OR_RAWFILE_TYPE_CRW),
00085 m_io(s),
00086 m_container(new CIFFContainer(m_io)),
00087 m_x(0), m_y(0)
00088 {
00089 _setIdMap(s_def);
00090 }
00091
00092 CRWFile::~CRWFile()
00093 {
00094 delete m_container;
00095 delete m_io;
00096 }
00097
00098 ::or_error CRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00099 {
00100 ::or_error err = OR_ERROR_NOT_FOUND;
00101
00102 Heap::Ref heap = m_container->heap();
00103 if(!heap) {
00104
00105 return err;
00106 }
00107 const RecordEntry::List & records = heap->records();
00108 RecordEntry::List::const_iterator iter;
00109 iter = std::find_if(records.begin(), records.end(), boost::bind(
00110 &RecordEntry::isA, _1,
00111 static_cast<uint16_t>(TAG_JPEGIMAGE)));
00112 if (iter != records.end()) {
00113 Trace(DEBUG2) << "JPEG @" << (*iter).offset << "\n";
00114 m_x = m_y = 0;
00115
00116 scoped_ptr<IO::StreamClone> s(new IO::StreamClone(m_io, heap->offset()
00117 + (*iter).offset));
00118 scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
00119
00120 jfif->getDimensions(m_x, m_y);
00121 Trace(DEBUG1) << "JPEG dimensions x=" << m_x
00122 << " y=" << m_y << "\n";
00123 list.push_back(std::max(m_x,m_y));
00124 err = OR_ERROR_NONE;
00125 }
00126
00127 return err;
00128 }
00129
00130 ::or_error CRWFile::_getThumbnail(uint32_t , Thumbnail & thumbnail)
00131 {
00132 ::or_error err = OR_ERROR_NOT_FOUND;
00133 Heap::Ref heap = m_container->heap();
00134 if(!heap) {
00135
00136 return err;
00137 }
00138
00139 const RecordEntry::List & records = heap->records();
00140 RecordEntry::List::const_iterator iter;
00141 iter = std::find_if(records.begin(), records.end(), boost::bind(
00142 &RecordEntry::isA, _1,
00143 static_cast<uint16_t>(TAG_JPEGIMAGE)));
00144 if (iter != records.end()) {
00145 Trace(DEBUG2) << "JPEG @" << (*iter).offset << "\n";
00146 size_t byte_size = (*iter).length;
00147 void *buf = thumbnail.allocData(byte_size);
00148 size_t real_size = (*iter).fetchData(heap.get(), buf, byte_size);
00149 if (real_size != byte_size) {
00150 Trace(WARNING) << "wrong size\n";
00151 }
00152 thumbnail.setDimensions(m_x, m_y);
00153 thumbnail.setDataType(OR_DATA_TYPE_JPEG);
00154 err = OR_ERROR_NONE;
00155 }
00156
00157 return err;
00158 }
00159
00160 ::or_error CRWFile::_getRawData(RawData & data, uint32_t options)
00161 {
00162 ::or_error err = OR_ERROR_NOT_FOUND;
00163 Heap::Ref props = m_container->getImageProps();
00164
00165 if(!props) {
00166 return OR_ERROR_NOT_FOUND;
00167 }
00168 const ImageSpec * img_spec = m_container->getImageSpec();
00169 uint32_t x, y;
00170 x = y = 0;
00171 int32_t orientation = 0;
00172 if(img_spec) {
00173 x = img_spec->imageWidth;
00174 y = img_spec->imageHeight;
00175 orientation = img_spec->exifOrientation();
00176 }
00177
00178
00179 const CIFF::RecordEntry::List & propsRecs = props->records();
00180 CIFF::RecordEntry::List::const_iterator iter;
00181 iter = std::find_if(propsRecs.begin(), propsRecs.end(), boost::bind(
00182 &RecordEntry::isA, _1,
00183 static_cast<uint16_t>(TAG_EXIFINFORMATION)));
00184 if (iter == propsRecs.end()) {
00185 Trace(ERROR) << "Couldn't find the Exif information.\n";
00186 return err;
00187 }
00188
00189 Heap exifProps(iter->offset + props->offset(), iter->length, m_container);
00190
00191 const RecordEntry::List & exifPropsRecs = exifProps.records();
00192 iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(),
00193 boost::bind(
00194 &RecordEntry::isA, _1,
00195 static_cast<uint16_t>(TAG_DECODERTABLE)));
00196 if (iter == exifPropsRecs.end()) {
00197 Trace(ERROR) << "Couldn't find the decoder table.\n";
00198 return err;
00199 }
00200 Trace(DEBUG2) << "length = " << iter->length << "\n";
00201 Trace(DEBUG2) << "offset = " << exifProps.offset() + iter->offset << "\n";
00202 IO::Stream *file = m_container->file();
00203 file->seek(exifProps.offset() + iter->offset, SEEK_SET);
00204 uint32_t decoderTable;
00205 if(m_container->readUInt32(file, decoderTable)) {
00206 Trace(DEBUG2) << "decoder table = " << decoderTable << "\n";
00207 }
00208
00209
00210 uint16_t cfa_x, cfa_y;
00211 iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(), boost::bind(
00212 &RecordEntry::isA, _1,
00213 static_cast<uint16_t>(TAG_SENSORINFO)));
00214 if (iter == exifPropsRecs.end()) {
00215 Trace(ERROR) << "Couldn't find the sensor info.\n";
00216 return err;
00217 }
00218 Trace(DEBUG2) << "length = " << iter->length << "\n";
00219 Trace(DEBUG2) << "offset = " << exifProps.offset() + iter->offset << "\n";
00220
00221
00222 file->seek(exifProps.offset() + iter->offset + 2, SEEK_SET);
00223 if(!(m_container->readUInt16(file, cfa_x)
00224 && m_container->readUInt16(file, cfa_y))) {
00225 Trace(ERROR) << "Couldn't find the sensor size.\n";
00226 return err;
00227 }
00228
00229
00230 const CIFF::RecordEntry *entry = m_container->getRawDataRecord();
00231 if (entry) {
00232 CIFF::Heap::Ref heap = m_container->heap();
00233 Trace(DEBUG2) << "RAW @" << heap->offset() + entry->offset << "\n";
00234 size_t byte_size = entry->length;
00235 void *buf = data.allocData(byte_size);
00236 size_t real_size = entry->fetchData(heap.get(), buf, byte_size);
00237 if (real_size != byte_size) {
00238 Trace(WARNING) << "wrong size\n";
00239 }
00240 data.setDimensions(x, y);
00241 data.setCfaPattern(OR_CFA_PATTERN_RGGB);
00242 data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
00243
00244
00245 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
00246 boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
00247 data.size()));
00248 s->open();
00249
00250 CrwDecompressor decomp(s.get(), m_container);
00251
00252 decomp.setOutputDimensions(cfa_x, cfa_y);
00253 decomp.setDecoderTable(decoderTable);
00254 RawData *dData = decomp.decompress();
00255 if (dData != NULL) {
00256 Trace(DEBUG1) << "Out size is " << dData->x()
00257 << "x" << dData->y() << "\n";
00258 dData->setCfaPattern(data.cfaPattern());
00259 data.swap(*dData);
00260 delete dData;
00261 }
00262 }
00263 err = OR_ERROR_NONE;
00264 }
00265 return err;
00266 }
00267
00268 MetaValue *CRWFile::_getMetaValue(int32_t meta_index)
00269 {
00270 MetaValue * val = NULL;
00271
00272 switch(META_INDEX_MASKOUT(meta_index)) {
00273 case META_NS_TIFF:
00274 {
00275 switch(META_NS_MASKOUT(meta_index)) {
00276 case EXIF_TAG_ORIENTATION:
00277 {
00278 const ImageSpec * img_spec = m_container->getImageSpec();
00279 if(img_spec) {
00280 val = new MetaValue(static_cast<uint32_t>(
00281 img_spec->exifOrientation()));
00282 }
00283 break;
00284 }
00285 case EXIF_TAG_MODEL:
00286 {
00287 CIFF::Heap::Ref heap = m_container->getCameraProps();
00288 if(heap) {
00289 const CIFF::RecordEntry::List & propsRecs = heap->records();
00290 CIFF::RecordEntry::List::const_iterator iter;
00291 iter = std::find_if(propsRecs.begin(), propsRecs.end(),
00292 boost::bind(
00293 &CIFF::RecordEntry::isA, _1,
00294 static_cast<uint16_t>(CIFF::TAG_RAWMAKEMODEL)));
00295 if (iter == propsRecs.end()) {
00296 Trace(ERROR) << "Couldn't find the image info.\n";
00297 }
00298 else {
00299 char buf[256];
00300 size_t sz = iter->length;
00301 if(sz > 256) {
00302 sz = 256;
00303 }
00304 size_t sz2;
00305 std::string model;
00306 sz2 = iter->fetchData(heap.get(), (void*)buf, sz);
00307 char *p = buf;
00308 while(*p) {
00309 p++;
00310 }
00311 p++;
00312 model = p;
00313 val = new MetaValue(model);
00314 Trace(DEBUG1) << "Model " << model << "\n";
00315 }
00316 }
00317
00318
00319 break;
00320 }
00321 }
00322 break;
00323 }
00324 case META_NS_EXIF:
00325 break;
00326 default:
00327 Trace(ERROR) << "Unknown Meta Namespace\n";
00328 break;
00329 }
00330
00331 return val;
00332 }
00333
00334 void CRWFile::_identifyId()
00335 {
00336 MetaValue * v = _getMetaValue(META_NS_TIFF | EXIF_TAG_MODEL);
00337 if(v) {
00338 std::string model;
00339 try {
00340 model = v->getString();
00341 _setTypeId(_typeIdFromModel(model));
00342 }
00343 catch(...)
00344 {
00345 }
00346 delete v;
00347 }
00348 }
00349
00350 }
00351 }
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361