mrwfile.cpp

00001 /*
00002  * libopenraw - mrwfile.cpp
00003  *
00004  * Copyright (C) 2006,2008 Hubert Figuiere
00005  * Copyright (C) 2008 Bradley Broom
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 
00023 #include <iostream>
00024 #include <boost/scoped_array.hpp>
00025 #include <libopenraw/libopenraw.h>
00026 #include <libopenraw++/thumbnail.h>
00027 #include <libopenraw++/rawdata.h>
00028 
00029 #include "debug.h"
00030 #include "io/stream.h"
00031 #include "io/file.h"
00032 #include "mrwcontainer.h"
00033 #include "ifd.h"
00034 #include "mrwfile.h"
00035 #include "unpack.h"
00036 
00037 using namespace Debug;
00038 
00039 namespace OpenRaw {
00040 
00041 
00042     namespace Internals {
00043 
00044         RawFile *MRWFile::factory(const char* _filename)
00045         {
00046             return new MRWFile(_filename);
00047         }
00048 
00049         MRWFile::MRWFile(const char* _filename)
00050             : IFDFile(_filename, OR_RAWFILE_TYPE_MRW, false)
00051         {
00052             m_container = new MRWContainer (m_io, 0);
00053         }
00054 
00055         MRWFile::~MRWFile()
00056         {
00057         }
00058 
00059         IFDDir::Ref  MRWFile::_locateCfaIfd()
00060         {
00061             // in MRW the CFA IFD is the main IFD
00062             if(!m_mainIfd) {
00063                 m_mainIfd = _locateMainIfd();
00064             }
00065             return m_mainIfd;
00066         }
00067 
00068 
00069         IFDDir::Ref  MRWFile::_locateMainIfd()
00070         {
00071             return m_container->setDirectory(0);
00072         }
00073         
00074         /* This code only knows about Dimage 5/7, in which the thumbnail position is special. */
00075         ::or_error MRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00076         {
00077             ::or_error err = OR_ERROR_NOT_FOUND;
00078             list.push_back (640);
00079             err = OR_ERROR_NONE;
00080             return err;
00081         }
00082 
00083         /* This code only knows about Dimage 5/7, in which the thumbnail position is special. */
00084         ::or_error MRWFile::_getThumbnail(uint32_t /*size*/, Thumbnail & thumbnail)
00085         {
00086             IFDDir::Ref dir;
00087             IFDEntry::Ref maker_ent;    /* Make note directory entry. */
00088             IFDEntry::Ref thumb_ent;    /* Thumbnail data directory entry. */
00089             ::or_error ret = OR_ERROR_NOT_FOUND;
00090             MRWContainer *mc = (MRWContainer *)m_container;
00091             
00092             dir = _locateExifIfd();
00093             if (!dir) {
00094                 Trace(WARNING) << "EXIF dir not found\n";
00095                 return ret;
00096             }
00097 
00098             maker_ent = dir->getEntry(IFD::EXIF_TAG_MAKER_NOTE);
00099             if (!maker_ent) {
00100                 Trace(WARNING) << "maker note offset entry not found\n";
00101                 return ret;
00102             }
00103             uint32_t off = 0;
00104             off = maker_ent->offset();
00105 
00106             IFDDir::Ref ref(new IFDDir(mc->ttw->offset() + 
00107                                        MRW::DataBlockHeaderLength + off, 
00108                                        *m_container));
00109             ref->load();
00110             
00111             uint32_t tnail_offset = 0;
00112             uint32_t tnail_len = 0;
00113             thumb_ent = ref->getEntry(MRW::MRWTAG_THUMBNAIL);
00114             if (thumb_ent) {
00115                 tnail_offset = thumb_ent->offset();
00116                 tnail_len = thumb_ent->count();
00117             }
00118             else if(ref->getValue(MRW::MRWTAG_THUMBNAIL_OFFSET, tnail_offset)) {
00119                 if(!ref->getValue(MRW::MRWTAG_THUMBNAIL_LENGTH, tnail_len)) {
00120                     Trace(WARNING) << "thumbnail lenght entry not found\n";
00121                     return ret;
00122                 }
00123             }
00124             else 
00125             {
00126                 Trace(WARNING) << "thumbnail offset entry not found\n";
00127                 return ret;
00128             }
00129             
00130             Trace(DEBUG1) << "thumbnail offset found, "
00131                           << " offset == " << tnail_offset  << " count == " 
00132                           << tnail_len << "\n";
00133             void *p = thumbnail.allocData (tnail_len);
00134             size_t fetched = m_container->fetchData(p, mc->ttw->offset() 
00135                                                     + MRW::DataBlockHeaderLength 
00136                                                     + tnail_offset, 
00137                                                     tnail_len);
00138             if (fetched != tnail_len) {
00139                 Trace(WARNING) << "Unable to fetch all thumbnail data: " 
00140                                << fetched << " not " << tnail_len 
00141                                << " bytes\n";
00142             }
00143             /* Need to patch first byte. */
00144             ((unsigned char *)p)[0] = 0xFF;
00145 
00146             thumbnail.setDataType (OR_DATA_TYPE_JPEG);
00147             thumbnail.setDimensions (640, 480);
00148             return OR_ERROR_NONE;
00149         }
00150 
00151 
00152         ::or_error MRWFile::_getRawData(RawData & data, uint32_t options) 
00153         { 
00154             MRWContainer *mc = (MRWContainer *)m_container;
00155 
00156             if(!mc->prd) {
00157                 return OR_ERROR_NOT_FOUND;
00158             }
00159             /* Obtain sensor dimensions from PRD block. */
00160             uint16_t y = mc->prd->uint16_val (MRW::PRD_SENSOR_LENGTH);
00161             uint16_t x = mc->prd->uint16_val (MRW::PRD_SENSOR_WIDTH);
00162             
00163             bool is_compressed = (mc->prd->uint8_val(MRW::PRD_STORAGE_TYPE) == 0x59);
00164             /* Allocate space for and retrieve pixel data.
00165              * Currently only for cameras that don't compress pixel data.
00166              */
00167             /* Set pixel array parameters. */
00168             uint32_t finaldatalen = 2 * x * y;
00169             uint32_t datalen =
00170                 (is_compressed ? x * y + ((x * y) >> 1) : finaldatalen);
00171 
00172             if(options & OR_OPTIONS_DONT_DECOMPRESS) {
00173                 finaldatalen = datalen;
00174             }
00175             if(is_compressed && (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00176                 data.setDataType (OR_DATA_TYPE_COMPRESSED_CFA);
00177             }
00178             else {
00179                 data.setDataType (OR_DATA_TYPE_CFA);
00180             }
00181             Trace(DEBUG1) << "datalen = " << datalen <<
00182                 " final datalen = " << finaldatalen << "\n";
00183             void *p = data.allocData(finaldatalen);
00184             size_t fetched = 0;
00185             off_t offset = mc->pixelDataOffset();
00186             if(!is_compressed || (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00187                 fetched = m_container->fetchData (p, offset, datalen);
00188             }
00189             else {
00190                 Unpack unpack(x, y, IFD::COMPRESS_NONE);
00191                 size_t blocksize = unpack.block_size();
00192                 boost::scoped_array<uint8_t> block(new uint8_t[blocksize]);
00193                 uint8_t * outdata = (uint8_t*)data.data();
00194                 size_t outleft = finaldatalen;
00195                 size_t got;
00196                 do {
00197                     Trace(DEBUG2) << "fatchData @offset " << offset << "\n";
00198                     got = m_container->fetchData (block.get(), 
00199                                                   offset, blocksize);
00200                     fetched += got;
00201                     offset += got;
00202                     Trace(DEBUG2) << "got " << got << "\n";
00203                     if(got) {
00204                         size_t out = unpack.unpack_be12to16(outdata, outleft, 
00205                                                             block.get(), got);
00206                         outdata += out;
00207                         outleft -= out;
00208                         Trace(DEBUG2) << "unpacked " << out
00209                                       << " bytes from " << got << "\n";
00210                     }
00211                 } while((got != 0) && (fetched < datalen));
00212             }
00213             if (fetched < datalen) {
00214                 Trace(WARNING) << "Fetched only " << fetched <<
00215                     " of " << datalen << ": continuing anyway.\n";
00216             }
00217             uint16_t bpat = mc->prd->uint16_val (MRW::PRD_BAYER_PATTERN);
00218             or_cfa_pattern cfa_pattern = OR_CFA_PATTERN_NONE;
00219             switch(bpat) 
00220             {
00221             case 0x0001:
00222                 cfa_pattern = OR_CFA_PATTERN_RGGB;
00223                 break;
00224             case 0x0004:
00225                 cfa_pattern = OR_CFA_PATTERN_GBRG;
00226                 break;
00227             default:
00228                 break;
00229             }
00230             data.setCfaPattern(cfa_pattern);
00231             data.setDimensions (x, y);
00232 
00233             return OR_ERROR_NONE; 
00234         }
00235 
00236     }
00237 }

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