crwfile.cpp

00001 /*
00002  * libopenraw - crwfile.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
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 <algorithm>
00023 #include <boost/bind.hpp>
00024 #include <boost/scoped_ptr.hpp>
00025 
00026 #include <libopenraw/libopenraw.h>
00027 #include <libopenraw++/thumbnail.h>
00028 #include <libopenraw++/rawdata.h>
00029 
00030 #include "debug.h"
00031 #include "io/file.h"
00032 #include "io/streamclone.h"
00033 #include "io/memstream.h"
00034 #include "crwfile.h"
00035 #include "ciffcontainer.h"
00036 #include "jfifcontainer.h"
00037 #include "crwdecompressor.h"
00038 #include "metavalue.h"
00039 
00040 #include "rawfilefactory.h"
00041 
00042 using namespace Debug;
00043 using boost::scoped_ptr;
00044 
00045 namespace OpenRaw {
00046 
00047     namespace Internals {
00048 
00049         using namespace CIFF;
00050 
00051         RawFile *CRWFile::factory(const char* _filename)
00052         {
00053             return new CRWFile(_filename);
00054         }
00055 
00056         CRWFile::CRWFile(const char* _filename)
00057             : RawFile(_filename, OR_RAWFILE_TYPE_CRW),
00058                 m_io(new IO::File(_filename)),
00059                 m_container(new CIFFContainer(m_io)),
00060                 m_x(0), m_y(0)
00061         {
00062 
00063         }
00064 
00065         CRWFile::~CRWFile()
00066         {
00067             delete m_container;
00068             delete m_io;
00069         }
00070 
00071         ::or_error CRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00072         {
00073             ::or_error err = OR_ERROR_NOT_FOUND;
00074 
00075             Heap::Ref heap = m_container->heap();
00076             if(!heap) {
00077                 // this is not a CIFF file.
00078                 return err;
00079             }
00080             const RecordEntry::List & records = heap->records();
00081             RecordEntry::List::const_iterator iter;
00082             iter = std::find_if(records.begin(), records.end(), boost::bind(
00083                                                         &RecordEntry::isA, _1, 
00084                                                         static_cast<uint16_t>(TAG_JPEGIMAGE)));
00085             if (iter != records.end()) {
00086                 Trace(DEBUG2) << "JPEG @" << (*iter).offset << "\n";
00087                 m_x = m_y = 0;
00088                 
00089                 scoped_ptr<IO::StreamClone> s(new IO::StreamClone(m_io, heap->offset()
00090                                                                   + (*iter).offset));
00091                 scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
00092 
00093                 jfif->getDimensions(m_x, m_y);
00094                 Trace(DEBUG1) << "JPEG dimensions x=" << m_x 
00095                                             << " y=" << m_y << "\n";
00096                 list.push_back(std::max(m_x,m_y));
00097                 err = OR_ERROR_NONE;
00098             }
00099 
00100             return err;
00101         }
00102 
00103         ::or_error CRWFile::_getThumbnail(uint32_t /*size*/, Thumbnail & thumbnail)
00104         {
00105             ::or_error err = OR_ERROR_NOT_FOUND;
00106             Heap::Ref heap = m_container->heap();
00107             if(!heap) {
00108                 // this is not a CIFF file.
00109                 return err;
00110             }
00111 
00112             const RecordEntry::List & records = heap->records();
00113             RecordEntry::List::const_iterator iter;
00114             iter = std::find_if(records.begin(), records.end(), boost::bind(
00115                                                         &RecordEntry::isA, _1, 
00116                                                         static_cast<uint16_t>(TAG_JPEGIMAGE)));
00117             if (iter != records.end()) {
00118                 Trace(DEBUG2) << "JPEG @" << (*iter).offset << "\n";
00119                 size_t byte_size = (*iter).length;
00120                 void *buf = thumbnail.allocData(byte_size);
00121                 size_t real_size = (*iter).fetchData(heap.get(), buf, byte_size);
00122                 if (real_size != byte_size) {
00123                     Trace(WARNING) << "wrong size\n";
00124                 }
00125                 thumbnail.setDimensions(m_x, m_y);
00126                 thumbnail.setDataType(OR_DATA_TYPE_JPEG);
00127                 err = OR_ERROR_NONE;
00128             }
00129 
00130             return err;
00131         }
00132 
00133         ::or_error CRWFile::_getRawData(RawData & data, uint32_t options)
00134         {
00135             ::or_error err = OR_ERROR_NOT_FOUND;
00136             Heap::Ref props = m_container->getImageProps();
00137 
00138             const ImageSpec * img_spec = m_container->getImageSpec();
00139             uint32_t x, y;
00140             x = y = 0;
00141             int32_t orientation = 0;
00142             if(img_spec) {
00143                 x = img_spec->imageWidth;
00144                 y = img_spec->imageHeight;
00145                 orientation = img_spec->exifOrientation();
00146             }
00147 
00148             // locate decoder table
00149             const CIFF::RecordEntry::List & propsRecs = props->records();
00150             CIFF::RecordEntry::List::const_iterator iter;
00151             iter = std::find_if(propsRecs.begin(), propsRecs.end(), boost::bind(
00152                                                         &RecordEntry::isA, _1, 
00153                                                         static_cast<uint16_t>(TAG_EXIFINFORMATION)));
00154             if (iter == propsRecs.end()) {
00155                 Trace(ERROR) << "Couldn't find the Exif information.\n";
00156                 return err;
00157             }
00158 
00159             Heap exifProps(iter->offset + props->offset(), iter->length, m_container);
00160 
00161             const RecordEntry::List & exifPropsRecs = exifProps.records();
00162             iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(), 
00163                                 boost::bind(
00164                                     &RecordEntry::isA, _1, 
00165                                     static_cast<uint16_t>(TAG_DECODERTABLE)));
00166             if (iter == exifPropsRecs.end()) {
00167                 Trace(ERROR) << "Couldn't find the decoder table.\n";
00168                 return err;
00169             }
00170             Trace(DEBUG2) << "length = " << iter->length << "\n";
00171             Trace(DEBUG2) << "offset = " << exifProps.offset() + iter->offset << "\n";
00172             IO::Stream *file = m_container->file();
00173             file->seek(exifProps.offset() + iter->offset, SEEK_SET);
00174             uint32_t decoderTable;
00175             if(m_container->readUInt32(file, decoderTable)) {
00176                 Trace(DEBUG2) << "decoder table = " << decoderTable << "\n";
00177             }
00178 
00179             // locate the CFA info
00180             uint16_t cfa_x, cfa_y;
00181             iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(), boost::bind(
00182                                                         &RecordEntry::isA, _1, 
00183                                                         static_cast<uint16_t>(TAG_SENSORINFO)));
00184             if (iter == exifPropsRecs.end()) {
00185                 Trace(ERROR) << "Couldn't find the sensor info.\n";
00186                 return err;
00187             }
00188             Trace(DEBUG2) << "length = " << iter->length << "\n";
00189             Trace(DEBUG2) << "offset = " << exifProps.offset() + iter->offset << "\n";
00190 
00191             // go figure what the +2 is. looks like it is the byte #
00192             file->seek(exifProps.offset() + iter->offset + 2, SEEK_SET);
00193             if(!(m_container->readUInt16(file, cfa_x) 
00194                      && m_container->readUInt16(file, cfa_y))) {
00195                 Trace(ERROR) << "Couldn't find the sensor size.\n";
00196                 return err;
00197             }
00198 
00199 
00200             const CIFF::RecordEntry *entry = m_container->getRawDataRecord();
00201             if (entry) {
00202                 CIFF::Heap::Ref heap = m_container->heap();
00203                 Trace(DEBUG2) << "RAW @" << heap->offset() + entry->offset << "\n";
00204                 size_t byte_size = entry->length;
00205                 void *buf = data.allocData(byte_size);
00206                 size_t real_size = entry->fetchData(heap.get(), buf, byte_size);
00207                 if (real_size != byte_size) {
00208                     Trace(WARNING) << "wrong size\n";
00209                 }
00210                 data.setDimensions(x, y);
00211                 data.setCfaPattern(OR_CFA_PATTERN_RGGB);
00212                 data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
00213 
00214                 // decompress if we need
00215                 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
00216                     boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
00217                                                                       data.size()));
00218                     s->open(); // TODO check success
00219                     
00220                     CrwDecompressor decomp(s.get(), m_container);
00221                     
00222                     decomp.setOutputDimensions(cfa_x, cfa_y);
00223                     decomp.setDecoderTable(decoderTable);
00224                     RawData *dData = decomp.decompress();
00225                     if (dData != NULL) {
00226                         Trace(DEBUG1) << "Out size is " << dData->x() 
00227                                                     << "x" << dData->y() << "\n";
00228                         dData->setCfaPattern(data.cfaPattern());
00229                         data.swap(*dData);
00230                         delete dData;
00231                     }
00232                 }
00233                 err = OR_ERROR_NONE;
00234             }
00235             return err;
00236         }
00237 
00238         MetaValue *CRWFile::_getMetaValue(int32_t meta_index)
00239         {
00240             MetaValue * val = NULL;
00241 
00242             switch(META_INDEX_MASKOUT(meta_index)) {
00243             case META_NS_TIFF:
00244             {
00245                 const ImageSpec * img_spec = m_container->getImageSpec();
00246                 if(img_spec) {
00247                     val = new MetaValue(boost::any(
00248                                             static_cast<int32_t>(
00249                                                 img_spec->exifOrientation())));
00250                 }
00251                 break;
00252             }
00253             case META_NS_EXIF:
00254                 break;
00255             default:
00256                 Trace(ERROR) << "Unknown Meta Namespace\n";
00257                 break;
00258             }
00259 
00260             return val;
00261         }
00262     }
00263 }

Generated on Tue Jun 17 11:47:19 2008 for libopenraw by  doxygen 1.5.6