00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <boost/scoped_ptr.hpp>
00023 #include <boost/any.hpp>
00024 #include <libopenraw/libopenraw.h>
00025 #include <libopenraw++/thumbnail.h>
00026 #include <libopenraw++/rawdata.h>
00027
00028 #include "debug.h"
00029 #include "io/file.h"
00030 #include "io/memstream.h"
00031 #include "ifdfilecontainer.h"
00032 #include "ifd.h"
00033 #include "cr2file.h"
00034 #include "jfifcontainer.h"
00035 #include "ljpegdecompressor.h"
00036 #include "rawfilefactory.h"
00037
00038 using namespace Debug;
00039
00040 namespace OpenRaw {
00041
00042 namespace Internals {
00043 const IFDFile::camera_ids_t Cr2File::s_def[] = {
00044 { "Canon EOS-1D Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00045 OR_TYPEID_CANON_1DMKII) },
00046 { "Canon EOS-1D Mark III", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00047 OR_TYPEID_CANON_1DMKIII) },
00048 { "Canon EOS-1Ds Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00049 OR_TYPEID_CANON_1DSMKII) },
00050 { "Canon EOS-1Ds Mark III", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00051 OR_TYPEID_CANON_1DSMKIII) },
00052 { "Canon EOS 20D" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00053 OR_TYPEID_CANON_20D) },
00054 { "Canon EOS 20Da", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00055 OR_TYPEID_CANON_20DA) },
00056 { "Canon EOS 30D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00057 OR_TYPEID_CANON_30D) },
00058 { "Canon EOS 350D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00059 OR_TYPEID_CANON_350D) },
00060 { "Canon EOS 40D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00061 OR_TYPEID_CANON_40D) },
00062 { "Canon EOS 400D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00063 OR_TYPEID_CANON_400D) },
00064 { "Canon EOS 450D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00065 OR_TYPEID_CANON_450D) },
00066 { "Canon EOS 5D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00067 OR_TYPEID_CANON_5D) },
00068 { "Canon PowerShot G9", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON,
00069 OR_TYPEID_CANON_G9) },
00070 { 0, 0 }
00071 };
00072
00073 RawFile *Cr2File::factory(IO::Stream * s)
00074 {
00075 return new Cr2File(s);
00076 }
00077
00078 Cr2File::Cr2File(IO::Stream * s)
00079 : IFDFile(s, OR_RAWFILE_TYPE_CR2)
00080 {
00081 _setIdMap(s_def);
00082 }
00083
00084 Cr2File::~Cr2File()
00085 {
00086 }
00087
00088
00089 IFDDir::Ref Cr2File::_locateCfaIfd()
00090 {
00091 return m_container->setDirectory(3);
00092 }
00093
00094
00095 IFDDir::Ref Cr2File::_locateMainIfd()
00096 {
00097 return m_container->setDirectory(0);
00098 }
00099
00100 ::or_error Cr2File::_getRawData(RawData & data, uint32_t options)
00101 {
00102 ::or_error ret = OR_ERROR_NONE;
00103 if(!m_cfaIfd) {
00104 m_cfaIfd = _locateCfaIfd();
00105 }
00106 if(!m_cfaIfd) {
00107 Trace(DEBUG1) << "cfa IFD not found\n";
00108 return OR_ERROR_NOT_FOUND;
00109 }
00110
00111 Trace(DEBUG1) << "_getRawData()\n";
00112 uint32_t offset = 0;
00113 uint32_t byte_length = 0;
00114 bool got_it;
00115 got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00116 if(!got_it) {
00117 Trace(DEBUG1) << "offset not found\n";
00118 return OR_ERROR_NOT_FOUND;
00119 }
00120 got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
00121 if(!got_it) {
00122 Trace(DEBUG1) << "byte len not found\n";
00123 return OR_ERROR_NOT_FOUND;
00124 }
00125
00126 std::vector<uint16_t> slices;
00127 IFDEntry::Ref e = m_cfaIfd->getEntry(IFD::EXIF_TAG_CR2_SLICE);
00128 if (e) {
00129 e->getArray(slices);
00130 Trace(DEBUG1) << "Found slice entry " << slices << "\n";
00131 }
00132
00133 if(!m_exifIfd) {
00134 m_exifIfd = _locateExifIfd();
00135 }
00136 if (m_exifIfd) {
00137 uint16_t x, y;
00138 x = 0;
00139 y = 0;
00140 got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_X_DIMENSION, x);
00141 if(!got_it) {
00142 Trace(DEBUG1) << "X not found\n";
00143 return OR_ERROR_NOT_FOUND;
00144 }
00145 got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_Y_DIMENSION, y);
00146 if(!got_it) {
00147 Trace(DEBUG1) << "Y not found\n";
00148 return OR_ERROR_NOT_FOUND;
00149 }
00150
00151 void *p = data.allocData(byte_length);
00152 size_t real_size = m_container->fetchData(p, offset,
00153 byte_length);
00154 if (real_size < byte_length) {
00155 Trace(WARNING) << "Size mismatch for data: ignoring.\n";
00156 }
00157 data.setCfaPattern(OR_CFA_PATTERN_RGGB);
00158 data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
00159 data.setDimensions(x, y);
00160 Trace(DEBUG1) << "In size is " << data.x()
00161 << "x" << data.y() << "\n";
00162
00163 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
00164 boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
00165 data.size()));
00166 s->open();
00167 boost::scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
00168 LJpegDecompressor decomp(s.get(), jfif.get());
00169
00170
00171 if(slices.size() > 1) {
00172 decomp.setSlices(slices);
00173 }
00174 RawData *dData = decomp.decompress();
00175 if (dData != NULL) {
00176 Trace(DEBUG1) << "Out size is " << dData->x()
00177 << "x" << dData->y() << "\n";
00178
00179 dData->setCfaPattern(data.cfaPattern());
00180 data.swap(*dData);
00181 delete dData;
00182 }
00183 }
00184 }
00185 else {
00186 Trace(ERROR) << "unable to find ExifIFD\n";
00187 ret = OR_ERROR_NOT_FOUND;
00188 }
00189 return ret;
00190 }
00191
00192
00193 }
00194 }