libopenraw
|
00001 /* 00002 * libopenraw - cr2file.cpp 00003 * 00004 * Copyright (C) 2006-2008 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 "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 // get the "slicing", tag 0xc640 (3 SHORT) 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 // decompress if we need 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(); // TODO check success 00167 boost::scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0)); 00168 LJpegDecompressor decomp(s.get(), jfif.get()); 00169 // in fact on Canon CR2 files slices either do not exists 00170 // or is 3. 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 // must re-set the cfaPattern 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 }