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 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 
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         const struct IFDFile::camera_ids_t MRWFile::s_def[] = {
00045             { "21860002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00046                                               OR_TYPEID_MINOLTA_MAXXUM_5D) },
00047             { "21810002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00048                                               OR_TYPEID_MINOLTA_MAXXUM_7D) },
00049             { "27730001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00050                                               OR_TYPEID_MINOLTA_DIMAGE5) },
00051             { "27660001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00052                                               OR_TYPEID_MINOLTA_DIMAGE7) },
00053             { "27790001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00054                                               OR_TYPEID_MINOLTA_DIMAGE7I) },
00055             { "27780001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00056                                               OR_TYPEID_MINOLTA_DIMAGE7HI) },
00057             { "27820001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00058                                               OR_TYPEID_MINOLTA_A1) },
00059             { "27200001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00060                                               OR_TYPEID_MINOLTA_A2) },
00061             { "27470002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00062                                               OR_TYPEID_MINOLTA_A200) },
00063             { 0, 0 }
00064         };
00065 
00066         RawFile *MRWFile::factory(IO::Stream *_f)
00067         {
00068             return new MRWFile(_f);
00069         }
00070 
00071         MRWFile::MRWFile(IO::Stream* _f)
00072             : IFDFile(_f, OR_RAWFILE_TYPE_MRW, false)
00073         {
00074             _setIdMap(s_def);
00075             m_container = new MRWContainer (m_io, 0);
00076         }
00077 
00078         MRWFile::~MRWFile()
00079         {
00080         }
00081 
00082         IFDDir::Ref  MRWFile::_locateCfaIfd()
00083         {
00084             // in MRW the CFA IFD is the main IFD
00085             if(!m_mainIfd) {
00086                 m_mainIfd = _locateMainIfd();
00087             }
00088             return m_mainIfd;
00089         }
00090 
00091 
00092         IFDDir::Ref  MRWFile::_locateMainIfd()
00093         {
00094             return m_container->setDirectory(0);
00095         }
00096 
00097 
00098         void MRWFile::_identifyId()
00099         {
00100             MRWContainer *mc = (MRWContainer *)m_container;
00101             if(!m_mainIfd) {
00102                 m_mainIfd = _locateMainIfd();
00103             }
00104 
00105             if(mc->prd) {
00106                 std::string version = mc->prd->string_val(MRW::PRD_VERSION);
00107                 _setTypeId(_typeIdFromModel(version));
00108             }
00109         }
00110 
00111     
00112         /* This code only knows about Dimage 5/7, in which the thumbnail position is special. */
00113         ::or_error MRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00114         {
00115             ::or_error err = OR_ERROR_NOT_FOUND;
00116             list.push_back (640);
00117             err = OR_ERROR_NONE;
00118             return err;
00119         }
00120 
00121         /* This code only knows about Dimage 5/7, in which the thumbnail position is special. */
00122         ::or_error MRWFile::_getThumbnail(uint32_t /*size*/, Thumbnail & thumbnail)
00123         {
00124             IFDDir::Ref dir;
00125             IFDEntry::Ref maker_ent;    /* Make note directory entry. */
00126             IFDEntry::Ref thumb_ent;    /* Thumbnail data directory entry. */
00127             ::or_error ret = OR_ERROR_NOT_FOUND;
00128             MRWContainer *mc = (MRWContainer *)m_container;
00129             
00130             dir = _locateExifIfd();
00131             if (!dir) {
00132                 Trace(WARNING) << "EXIF dir not found\n";
00133                 return ret;
00134             }
00135 
00136             maker_ent = dir->getEntry(IFD::EXIF_TAG_MAKER_NOTE);
00137             if (!maker_ent) {
00138                 Trace(WARNING) << "maker note offset entry not found\n";
00139                 return ret;
00140             }
00141             uint32_t off = 0;
00142             off = maker_ent->offset();
00143 
00144             IFDDir::Ref ref(new IFDDir(mc->ttw->offset() + 
00145                                        MRW::DataBlockHeaderLength + off, 
00146                                        *m_container));
00147             ref->load();
00148             
00149             uint32_t tnail_offset = 0;
00150             uint32_t tnail_len = 0;
00151             thumb_ent = ref->getEntry(MRW::MRWTAG_THUMBNAIL);
00152             if (thumb_ent) {
00153                 tnail_offset = thumb_ent->offset();
00154                 tnail_len = thumb_ent->count();
00155             }
00156             else if(ref->getValue(MRW::MRWTAG_THUMBNAIL_OFFSET, tnail_offset)) {
00157                 if(!ref->getValue(MRW::MRWTAG_THUMBNAIL_LENGTH, tnail_len)) {
00158                     Trace(WARNING) << "thumbnail lenght entry not found\n";
00159                     return ret;
00160                 }
00161             }
00162             else 
00163             {
00164                 Trace(WARNING) << "thumbnail offset entry not found\n";
00165                 return ret;
00166             }
00167             
00168             Trace(DEBUG1) << "thumbnail offset found, "
00169                           << " offset == " << tnail_offset  << " count == " 
00170                           << tnail_len << "\n";
00171             void *p = thumbnail.allocData (tnail_len);
00172             size_t fetched = m_container->fetchData(p, mc->ttw->offset() 
00173                                                     + MRW::DataBlockHeaderLength 
00174                                                     + tnail_offset, 
00175                                                     tnail_len);
00176             if (fetched != tnail_len) {
00177                 Trace(WARNING) << "Unable to fetch all thumbnail data: " 
00178                                << fetched << " not " << tnail_len 
00179                                << " bytes\n";
00180             }
00181             /* Need to patch first byte. */
00182             ((unsigned char *)p)[0] = 0xFF;
00183 
00184             thumbnail.setDataType (OR_DATA_TYPE_JPEG);
00185             thumbnail.setDimensions (640, 480);
00186             return OR_ERROR_NONE;
00187         }
00188 
00189 
00190         ::or_error MRWFile::_getRawData(RawData & data, uint32_t options) 
00191         { 
00192             MRWContainer *mc = (MRWContainer *)m_container;
00193 
00194             if(!mc->prd) {
00195                 return OR_ERROR_NOT_FOUND;
00196             }
00197             /* Obtain sensor dimensions from PRD block. */
00198             uint16_t y = mc->prd->uint16_val (MRW::PRD_SENSOR_LENGTH);
00199             uint16_t x = mc->prd->uint16_val (MRW::PRD_SENSOR_WIDTH);
00200             uint8_t bpc =  mc->prd->uint8_val (MRW::PRD_PIXEL_SIZE);
00201 
00202             bool is_compressed = (mc->prd->uint8_val(MRW::PRD_STORAGE_TYPE) == 0x59);
00203             /* Allocate space for and retrieve pixel data.
00204              * Currently only for cameras that don't compress pixel data.
00205              */
00206             /* Set pixel array parameters. */
00207             uint32_t finaldatalen = 2 * x * y;
00208             uint32_t datalen =
00209                 (is_compressed ? x * y + ((x * y) >> 1) : finaldatalen);
00210 
00211             if(options & OR_OPTIONS_DONT_DECOMPRESS) {
00212                 finaldatalen = datalen;
00213             }
00214             if(is_compressed && (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00215                 data.setDataType (OR_DATA_TYPE_COMPRESSED_CFA);
00216             }
00217             else {
00218                 data.setDataType (OR_DATA_TYPE_CFA);
00219             }
00220             data.setBpc(bpc);
00221             // this seems to be the hardcoded value.
00222             data.setMax(0xf7d);
00223             Trace(DEBUG1) << "datalen = " << datalen <<
00224                 " final datalen = " << finaldatalen << "\n";
00225             void *p = data.allocData(finaldatalen);
00226             size_t fetched = 0;
00227             off_t offset = mc->pixelDataOffset();
00228             if(!is_compressed || (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00229                 fetched = m_container->fetchData (p, offset, datalen);
00230             }
00231             else {
00232                 Unpack unpack(x, IFD::COMPRESS_NONE);
00233                 size_t blocksize = unpack.block_size();
00234                 boost::scoped_array<uint8_t> block(new uint8_t[blocksize]);
00235                 uint8_t * outdata = (uint8_t*)data.data();
00236                 size_t got;
00237                 do {
00238                     Trace(DEBUG2) << "fatchData @offset " << offset << "\n";
00239                     got = m_container->fetchData (block.get(), 
00240                                                   offset, blocksize);
00241                     fetched += got;
00242                     offset += got;
00243                     Trace(DEBUG2) << "got " << got << "\n";
00244                     if(got) {
00245                         size_t out = unpack.unpack_be12to16(outdata,
00246                                                             block.get(), got);
00247                         outdata += out;
00248                         Trace(DEBUG2) << "unpacked " << out
00249                                       << " bytes from " << got << "\n";
00250                     }
00251                 } while((got != 0) && (fetched < datalen));
00252             }
00253             if (fetched < datalen) {
00254                 Trace(WARNING) << "Fetched only " << fetched <<
00255                     " of " << datalen << ": continuing anyway.\n";
00256             }
00257             uint16_t bpat = mc->prd->uint16_val (MRW::PRD_BAYER_PATTERN);
00258             or_cfa_pattern cfa_pattern = OR_CFA_PATTERN_NONE;
00259             switch(bpat) 
00260             {
00261             case 0x0001:
00262                 cfa_pattern = OR_CFA_PATTERN_RGGB;
00263                 break;
00264             case 0x0004:
00265                 cfa_pattern = OR_CFA_PATTERN_GBRG;
00266                 break;
00267             default:
00268                 break;
00269             }
00270             data.setCfaPattern(cfa_pattern);
00271             data.setDimensions (x, y);
00272 
00273             return OR_ERROR_NONE; 
00274         }
00275 
00276     }
00277 }
Generated on Thu Jul 29 20:40:28 2010 for libopenraw by  doxygen 1.6.3