cr2file.cpp

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 }
Generated on Thu Jul 29 20:43:09 2010 for libopenraw by  doxygen 1.6.3