libopenraw
|
00001 /* 00002 * libopenraw - cr2file.cpp 00003 * 00004 * Copyright (C) 2006-2010 Hubert Figuiere 00005 * Copyright (C) 2008 Novell, Inc. 00006 * 00007 * This library is free software: you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License 00009 * as published by the Free Software Foundation, either version 3 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library. If not, see 00019 * <http://www.gnu.org/licenses/>. 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 "trace.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-1D Mark IV", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00049 OR_TYPEID_CANON_1DMKIV) }, 00050 { "Canon EOS-1Ds Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00051 OR_TYPEID_CANON_1DSMKII) }, 00052 { "Canon EOS-1Ds Mark III", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00053 OR_TYPEID_CANON_1DSMKIII) }, 00054 { "Canon EOS 20D" , OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00055 OR_TYPEID_CANON_20D) }, 00056 { "Canon EOS 20Da", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00057 OR_TYPEID_CANON_20DA) }, 00058 { "Canon EOS 30D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00059 OR_TYPEID_CANON_30D) }, 00060 { "Canon EOS 350D DIGITAL", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00061 OR_TYPEID_CANON_350D) }, 00062 { "Canon EOS DIGITAL REBEL XT", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00063 OR_TYPEID_CANON_350D) }, 00064 { "Canon EOS 40D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00065 OR_TYPEID_CANON_40D) }, 00066 { "Canon EOS 400D DIGITAL", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00067 OR_TYPEID_CANON_400D) }, 00068 { "Canon EOS 450D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00069 OR_TYPEID_CANON_450D) }, 00070 { "Canon EOS 50D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00071 OR_TYPEID_CANON_50D) }, 00072 { "Canon EOS 500D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00073 OR_TYPEID_CANON_500D) }, 00074 { "Canon EOS 550D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00075 OR_TYPEID_CANON_550D) }, 00076 { "Canon EOS 60D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00077 OR_TYPEID_CANON_60D) }, 00078 { "Canon EOS 1000D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00079 OR_TYPEID_CANON_1000D) }, 00080 { "Canon EOS 5D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00081 OR_TYPEID_CANON_5D) }, 00082 { "Canon EOS 5D Mark II", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00083 OR_TYPEID_CANON_5DMKII) }, 00084 { "Canon EOS 7D", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00085 OR_TYPEID_CANON_7D) }, 00086 { "Canon PowerShot G9", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00087 OR_TYPEID_CANON_G9) }, 00088 { "Canon PowerShot G10", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00089 OR_TYPEID_CANON_G11) }, 00090 { "Canon PowerShot G11", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_CANON, 00091 OR_TYPEID_CANON_G11) }, 00092 { 0, 0 } 00093 }; 00094 00095 RawFile *Cr2File::factory(IO::Stream * s) 00096 { 00097 return new Cr2File(s); 00098 } 00099 00100 Cr2File::Cr2File(IO::Stream * s) 00101 : IFDFile(s, OR_RAWFILE_TYPE_CR2) 00102 { 00103 _setIdMap(s_def); 00104 } 00105 00106 Cr2File::~Cr2File() 00107 { 00108 } 00109 00110 00111 IFDDir::Ref Cr2File::_locateCfaIfd() 00112 { 00113 return m_container->setDirectory(3); 00114 } 00115 00116 00117 IFDDir::Ref Cr2File::_locateMainIfd() 00118 { 00119 return m_container->setDirectory(0); 00120 } 00121 00122 ::or_error Cr2File::_getRawData(RawData & data, uint32_t options) 00123 { 00124 ::or_error ret = OR_ERROR_NONE; 00125 if(!m_cfaIfd) { 00126 m_cfaIfd = _locateCfaIfd(); 00127 } 00128 if(!m_cfaIfd) { 00129 Trace(DEBUG1) << "cfa IFD not found\n"; 00130 return OR_ERROR_NOT_FOUND; 00131 } 00132 00133 Trace(DEBUG1) << "_getRawData()\n"; 00134 uint32_t offset = 0; 00135 uint32_t byte_length = 0; 00136 bool got_it; 00137 got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset); 00138 if(!got_it) { 00139 Trace(DEBUG1) << "offset not found\n"; 00140 return OR_ERROR_NOT_FOUND; 00141 } 00142 got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length); 00143 if(!got_it) { 00144 Trace(DEBUG1) << "byte len not found\n"; 00145 return OR_ERROR_NOT_FOUND; 00146 } 00147 // get the "slicing", tag 0xc640 (3 SHORT) 00148 std::vector<uint16_t> slices; 00149 IFDEntry::Ref e = m_cfaIfd->getEntry(IFD::EXIF_TAG_CR2_SLICE); 00150 if (e) { 00151 e->getArray(slices); 00152 Trace(DEBUG1) << "Found slice entry " << slices << "\n"; 00153 } 00154 00155 if(!m_exifIfd) { 00156 m_exifIfd = _locateExifIfd(); 00157 } 00158 if (m_exifIfd) { 00159 uint16_t x, y; 00160 x = 0; 00161 y = 0; 00162 got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_X_DIMENSION, x); 00163 if(!got_it) { 00164 Trace(DEBUG1) << "X not found\n"; 00165 return OR_ERROR_NOT_FOUND; 00166 } 00167 got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_Y_DIMENSION, y); 00168 if(!got_it) { 00169 Trace(DEBUG1) << "Y not found\n"; 00170 return OR_ERROR_NOT_FOUND; 00171 } 00172 00173 void *p = data.allocData(byte_length); 00174 size_t real_size = m_container->fetchData(p, offset, 00175 byte_length); 00176 if (real_size < byte_length) { 00177 Trace(WARNING) << "Size mismatch for data: ignoring.\n"; 00178 } 00179 data.setCfaPattern(OR_CFA_PATTERN_RGGB); 00180 data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA); 00181 data.setDimensions(x, y); 00182 Trace(DEBUG1) << "In size is " << data.x() 00183 << "x" << data.y() << "\n"; 00184 // decompress if we need 00185 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) { 00186 boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(), 00187 data.size())); 00188 s->open(); // TODO check success 00189 boost::scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0)); 00190 LJpegDecompressor decomp(s.get(), jfif.get()); 00191 // in fact on Canon CR2 files slices either do not exists 00192 // or is 3. 00193 if(slices.size() > 1) { 00194 decomp.setSlices(slices); 00195 } 00196 RawData *dData = decomp.decompress(); 00197 if (dData != NULL) { 00198 Trace(DEBUG1) << "Out size is " << dData->x() 00199 << "x" << dData->y() << "\n"; 00200 // must re-set the cfaPattern 00201 dData->setCfaPattern(data.cfaPattern()); 00202 data.swap(*dData); 00203 delete dData; 00204 } 00205 } 00206 } 00207 else { 00208 Trace(ERROR) << "unable to find ExifIFD\n"; 00209 ret = OR_ERROR_NOT_FOUND; 00210 } 00211 return ret; 00212 } 00213 00214 00215 } 00216 }