cr2file.cpp

00001 /*
00002  * libopenraw - cr2file.cpp
00003  *
00004  * Copyright (C) 2006-2007 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
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of 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, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
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 
00044         RawFile *CR2File::factory(const char* _filename)
00045         {
00046             return new CR2File(_filename);
00047         }
00048 
00049         CR2File::CR2File(const char* _filename)
00050             : IFDFile(_filename, OR_RAWFILE_TYPE_CR2)
00051         {
00052 
00053         }
00054 
00055         CR2File::~CR2File()
00056         {
00057         }
00058 
00059 
00060         IFDDir::Ref  CR2File::_locateCfaIfd()
00061         {
00062             return m_container->setDirectory(3);
00063         }
00064 
00065         IFDDir::Ref  CR2File::_locateMainIfd()
00066         {
00067             return m_container->setDirectory(0);
00068         }
00069 
00070         ::or_error CR2File::_getRawData(RawData & data, uint32_t options)
00071         {
00072             ::or_error ret = OR_ERROR_NONE;
00073             if(!m_cfaIfd) {
00074                 m_cfaIfd = _locateCfaIfd();
00075             }
00076             if(!m_cfaIfd) {
00077                 Trace(DEBUG1) << "cfa IFD not found\n";
00078                 return OR_ERROR_NOT_FOUND;
00079             }
00080 
00081             Trace(DEBUG1) << "_getRawData()\n";
00082             uint32_t offset = 0;
00083             uint32_t byte_length = 0;
00084             bool got_it;
00085             got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00086             if(!got_it) {
00087                 Trace(DEBUG1) << "offset not found\n";
00088                 return OR_ERROR_NOT_FOUND;
00089             }
00090             got_it = m_cfaIfd->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
00091             if(!got_it) {
00092                 Trace(DEBUG1) << "byte len not found\n";
00093                 return OR_ERROR_NOT_FOUND;
00094             }
00095             // get the "slicing", tag 0xc640 (3 SHORT)
00096             std::vector<uint16_t> slices;
00097             IFDEntry::Ref e = m_cfaIfd->getEntry(IFD::EXIF_TAG_CR2_SLICE);
00098             if (e) {
00099                 e->getArray(slices);
00100                 Trace(DEBUG1) << "Found slice entry " << slices << "\n";
00101             }
00102 
00103             if(!m_exifIfd) {
00104                 m_exifIfd = _locateExifIfd();
00105             }
00106             if (m_exifIfd) {
00107                 uint16_t x, y;
00108                 x = 0;
00109                 y = 0;
00110                 got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_X_DIMENSION, x);
00111                 if(!got_it) {
00112                     Trace(DEBUG1) << "X not found\n";
00113                     return OR_ERROR_NOT_FOUND;
00114                 }
00115                 got_it = m_exifIfd->getValue(IFD::EXIF_TAG_PIXEL_Y_DIMENSION, y);
00116                 if(!got_it) {
00117                     Trace(DEBUG1) << "Y not found\n";
00118                     return OR_ERROR_NOT_FOUND;
00119                 }
00120                 
00121                 void *p = data.allocData(byte_length);
00122                 size_t real_size = m_container->fetchData(p, offset, 
00123                                                           byte_length);
00124                 if (real_size < byte_length) {
00125                     Trace(WARNING) << "Size mismatch for data: ignoring.\n";
00126                 }
00127                 data.setCfaPattern(OR_CFA_PATTERN_RGGB);
00128                 data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
00129                 data.setDimensions(x, y);
00130                 Trace(DEBUG1) << "In size is " << data.x() 
00131                               << "x" << data.y() << "\n";
00132                 // decompress if we need
00133                 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
00134                     boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
00135                                                                       data.size()));
00136                     s->open(); // TODO check success
00137                     boost::scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
00138                     LJpegDecompressor decomp(s.get(), jfif.get());
00139                     if(slices.size() > 1) {
00140                         decomp.setSlices(slices, 1); 
00141                     }
00142                     RawData *dData = decomp.decompress();
00143                     if (dData != NULL) {
00144                         Trace(DEBUG1) << "Out size is " << dData->x() 
00145                                                     << "x" << dData->y() << "\n";
00146                         // must re-set the cfaPattern
00147                         dData->setCfaPattern(data.cfaPattern());
00148                         data.swap(*dData);
00149                         delete dData;
00150                     }
00151                 }
00152             }
00153             else {
00154                 Trace(ERROR) << "unable to find ExifIFD\n";
00155                 ret = OR_ERROR_NOT_FOUND;
00156             }
00157             return ret;
00158         }
00159 
00160 
00161     }
00162 }

Generated on Sun Mar 23 09:28:21 2008 for libopenraw by  doxygen 1.5.5