ifdfile.cpp

00001 /*
00002  * libopenraw - ifdfile.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 <numeric>
00024 #include <boost/scoped_ptr.hpp>
00025 #include <boost/scoped_array.hpp>
00026 
00027 #include <libopenraw++/thumbnail.h>
00028 #include <libopenraw++/rawdata.h>
00029 
00030 #include "debug.h"
00031 #include "io/stream.h"
00032 #include "io/streamclone.h"
00033 #include "io/file.h"
00034 #include "ifd.h"
00035 #include "ifdfile.h"
00036 #include "ifdfilecontainer.h"
00037 #include "jfifcontainer.h"
00038 #include "neffile.h" // I wonder if this is smart as it break the abstraction.
00039 #include "metavalue.h"
00040 #include "unpack.h"
00041 
00042 using namespace Debug;
00043 using boost::scoped_ptr;
00044 
00045 
00046 namespace OpenRaw {
00047     namespace Internals {
00048 
00049 
00050         IFDFile::IFDFile(const char *_filename, Type _type, 
00051                          bool instantiateContainer)
00052             : RawFile(_filename, _type),
00053                 m_thumbLocations(),
00054                 m_io(new IO::File(_filename)),
00055                 m_container(NULL)
00056         {
00057             if(instantiateContainer) {
00058                 m_container = new IFDFileContainer(m_io, 0);
00059             }
00060         }
00061 
00062         IFDFile::~IFDFile()
00063         {
00064             delete m_container;
00065             delete m_io;
00066         }
00067 
00068         // this one seems to be pretty much the same for all the
00069         // IFD based raw files
00070         IFDDir::Ref  IFDFile::_locateExifIfd()
00071         {
00072             m_mainIfd = _locateMainIfd();
00073             if (!m_mainIfd) {
00074                 Trace(ERROR) << "IFDFile::_locateExifIfd() "
00075                     "main IFD not found\n";
00076                 return IFDDir::Ref();
00077             }
00078             return m_mainIfd->getExifIFD();
00079         }
00080 
00081 
00082         ::or_error IFDFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00083         {
00084             ::or_error err = OR_ERROR_NONE;
00085 
00086             Trace(DEBUG1) << "_enumThumbnailSizes()\n";
00087             std::vector<IFDDir::Ref> & dirs = m_container->directories();
00088             std::vector<IFDDir::Ref>::iterator iter; 
00089             
00090             Trace(DEBUG1) << "num of dirs " << dirs.size() << "\n";
00091             for(iter = dirs.begin(); iter != dirs.end(); ++iter)
00092             {
00093                 IFDDir::Ref & dir = *iter;
00094                 dir->load();
00095                 or_error ret = _locateThumbnail(dir, list);
00096                 if (ret == OR_ERROR_NONE)
00097                 {
00098                     Trace(DEBUG1) << "Found " << list.back() << " pixels\n";
00099                 }
00100                 std::vector<IFDDir::Ref> subdirs;
00101                 if(dir->getSubIFDs(subdirs)) {
00102                     Trace(DEBUG1) << "Iterating subdirs\n";
00103                     std::vector<IFDDir::Ref>::iterator iter2; 
00104                     for(iter2 = subdirs.begin(); iter2 != subdirs.end(); 
00105                         ++iter2)
00106                     {
00107                         IFDDir::Ref & dir2 = *iter2;
00108                         dir2->load();
00109                         ret = _locateThumbnail(dir2, list);
00110                         if (ret == OR_ERROR_NONE)
00111                         {
00112                             Trace(DEBUG1) << "Found " << list.back() << " pixels\n";
00113                         }
00114                     }
00115                 }
00116             }
00117             if (list.size() <= 0) {
00118                 err = OR_ERROR_NOT_FOUND;
00119             }
00120             return err;
00121         }
00122 
00123 
00124         ::or_error IFDFile::_locateThumbnail(const IFDDir::Ref & dir,
00125                                                                      std::vector<uint32_t> &list)
00126         {
00127             ::or_error ret = OR_ERROR_NOT_FOUND;
00128             bool got_it;
00129             uint32_t x = 0;
00130             uint32_t y = 0;
00131             ::or_data_type _type = OR_DATA_TYPE_NONE;
00132             uint32_t subtype = 0;
00133 
00134             Trace(DEBUG1) << "_locateThumbnail\n";
00135 
00136             got_it = dir->getValue(IFD::EXIF_TAG_NEW_SUBFILE_TYPE, subtype);
00137             Trace(DEBUG1) << "subtype " << subtype  << "\n";
00138             if(!got_it) {
00139                 if(!m_cfaIfd) {
00140                     m_cfaIfd = _locateCfaIfd();
00141                 }
00142                 if(m_cfaIfd == dir) {
00143                     return OR_ERROR_NOT_FOUND;
00144                 }
00145                 else {
00146                     subtype = 1;
00147                 }
00148             }
00149             if (subtype == 1) {
00150 
00151                 uint16_t photom_int = 0;
00152                 got_it = dir->getValue(IFD::EXIF_TAG_PHOTOMETRIC_INTERPRETATION, 
00153                                                                         photom_int);
00154 
00155                 if (got_it) {
00156                     Trace(DEBUG1) << "photometric int " << photom_int  << "\n";
00157                 }
00158                 // photometric interpretation is RGB
00159                 if (!got_it || (photom_int == 2)) {
00160 
00161                     got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x);
00162                     got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y);
00163 
00164                     uint16_t compression = 0;
00165                     got_it = dir->getValue(IFD::EXIF_TAG_COMPRESSION, compression);
00166                     
00167                     uint32_t offset = 0;
00168                     got_it = dir->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00169                     if (!got_it || (compression == 6) || (compression == 7)) {
00170                         if(!got_it) {
00171                             got_it = dir->getValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT,
00172                                                    offset);
00173                         }
00174                         if (got_it) {
00175                             // workaround for CR2 files where 8RGB data is marked
00176                             // as JPEG. Check the real data size.
00177                             uint32_t byte_count;
00178                             if(x && y && dir->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_count)) {
00179                                 if(byte_count >= (x * y * 3)) {
00180                                     _type = OR_DATA_TYPE_PIXMAP_8RGB;
00181                                 }
00182                                 else {
00183                                     _type = OR_DATA_TYPE_JPEG;
00184                                 }
00185                             }
00186                             else {
00187                                 _type = OR_DATA_TYPE_JPEG;
00188                                 Trace(DEBUG1) << "looking for JPEG at " << offset << "\n";
00189                                 if (x == 0 || y == 0) {
00190                                     scoped_ptr<IO::StreamClone> s(new IO::StreamClone(m_io, offset));
00191                                     scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
00192                                     if (jfif->getDimensions(x,y)) {
00193                                         Trace(DEBUG1) << "JPEG dimensions x=" << x 
00194                                                       << " y=" << y << "\n";
00195                                     }
00196                                     else {
00197                                         _type = OR_DATA_TYPE_NONE;
00198                                         Trace(WARNING) << "Couldn't get JPEG "
00199                                             "dimensions.\n";
00200                                     }
00201                                 }
00202                                 else {
00203                                     Trace(DEBUG1) << "JPEG (supposed) dimensions x=" << x 
00204                                                   << " y=" << y << "\n";
00205                                 }
00206                             }
00207 
00208                         }
00209                     }
00210                     else {
00211                         Trace(DEBUG1) << "found strip offsets\n";
00212                         if (x != 0 && y != 0) {
00213                             _type = OR_DATA_TYPE_PIXMAP_8RGB;
00214                         }
00215                     }
00216                     if(_type != OR_DATA_TYPE_NONE) {
00217                         uint32_t dim = std::max(x, y);
00218                         m_thumbLocations[dim] = IFDThumbDesc(x, y, _type, dir);
00219                         list.push_back(dim);
00220                         ret = OR_ERROR_NONE;
00221                     }
00222                 }
00223                 else if (photom_int == 6) {
00224                     Trace(WARNING) << "Unsupported YCbCr photometric "
00225                         "interpretation.\n";
00226                 }
00227             }
00228 
00229             return ret;
00230         }
00231 
00232 
00233         ::or_error IFDFile::_getThumbnail(uint32_t size, Thumbnail & thumbnail)
00234         {
00235             ::or_error ret = OR_ERROR_NOT_FOUND;
00236             ThumbLocations::iterator iter = m_thumbLocations.find(size);
00237             if(iter != m_thumbLocations.end()) 
00238             {
00239                 bool got_it;
00240 
00241                 IFDThumbDesc & desc = iter->second;
00242                 thumbnail.setDataType(desc.type);
00243                 uint32_t byte_length= 0; 
00244                 uint32_t offset = 0;
00245                 uint32_t x = desc.x;
00246                 uint32_t y = desc.y;
00247 
00248                 switch(desc.type)
00249                 {
00250                 case OR_DATA_TYPE_JPEG:
00251                     got_it = desc.ifddir
00252                         ->getValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
00253                                                      byte_length);
00254                     if(got_it) {
00255                         got_it = desc.ifddir
00256                             ->getValue(IFD::EXIF_TAG_JPEG_INTERCHANGE_FORMAT,
00257                                        offset);
00258                     }
00259                     else {
00260                         // some case it is STRIP_OFFSETS for JPEG
00261                         got_it = desc.ifddir
00262                             ->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00263                         got_it = desc.ifddir
00264                             ->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
00265                     }
00266                     break;
00267                 case OR_DATA_TYPE_PIXMAP_8RGB:
00268                     got_it = desc.ifddir
00269                         ->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00270                     got_it = desc.ifddir
00271                         ->getValue(IFD::EXIF_TAG_STRIP_BYTE_COUNTS, byte_length);
00272 
00273                     got_it = desc.ifddir
00274                         ->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x);
00275                     got_it = desc.ifddir
00276                         ->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y);
00277                     break;
00278                 default:
00279                     break;
00280                 }
00281                 if (byte_length != 0) {
00282                     void *p = thumbnail.allocData(byte_length);
00283                     size_t real_size = m_container->fetchData(p, offset, 
00284                                                                                                         byte_length);
00285                     if (real_size < byte_length) {
00286                         Trace(WARNING) << "Size mismatch for data: ignoring.\n";
00287                     }
00288 
00289                     thumbnail.setDimensions(x, y);
00290                     ret = OR_ERROR_NONE;
00291                 }
00292             }
00293 
00294             return ret;
00295         }
00296 
00297 
00298         MetaValue *IFDFile::_getMetaValue(int32_t meta_index)
00299         {
00300             MetaValue * val = NULL;
00301             IFDDir::Ref ifd;
00302             if(META_INDEX_MASKOUT(meta_index) == META_NS_TIFF) {
00303                 if(!m_mainIfd) {
00304                     m_mainIfd = _locateMainIfd();
00305                 }
00306                 ifd = m_mainIfd;
00307             }
00308             else if(META_INDEX_MASKOUT(meta_index) == META_NS_EXIF) {
00309                 if(!m_exifIfd) {
00310                     m_exifIfd = _locateExifIfd();
00311                 }
00312                 ifd = m_exifIfd;
00313             }
00314             else {
00315                 Trace(ERROR) << "Unknown Meta Namespace\n";
00316             }
00317             if(ifd) {
00318                 Trace(DEBUG1) << "Meta value for " 
00319                               << META_NS_MASKOUT(meta_index) << "\n";
00320                 uint16_t n = 0;
00321                 bool got_it = ifd->getValue(META_NS_MASKOUT(meta_index), n);
00322                 if(got_it){
00323                     Trace(DEBUG1) << "found value\n";
00324                     val = new MetaValue(boost::any(static_cast<int32_t>(n)));
00325                 }               
00326             }
00327             return val;
00328         }
00329 
00330 
00331         namespace {
00332 
00333         RawData::CfaPattern 
00334         _convertArrayToCfaPattern(const std::vector<uint8_t> &cfaPattern)
00335         {
00336             RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NON_RGB22;
00337             if(cfaPattern.size() != 4) {
00338                 Trace(WARNING) << "Unsupported bayer pattern\n";
00339             }
00340             else {
00341                 Trace(DEBUG2) << "patter is = " << cfaPattern[0] << ", "
00342                               << cfaPattern[1] << ", " << cfaPattern[2] 
00343                               << ", " << cfaPattern[3] << "\n";
00344                 switch(cfaPattern[0]) {
00345                 case IFD::CFA_RED:
00346                     switch(cfaPattern[1]) {
00347                     case IFD::CFA_GREEN:
00348                         if((cfaPattern[2] == IFD::CFA_GREEN) 
00349                            && (cfaPattern[3] == IFD::CFA_BLUE)) 
00350                         {
00351                             cfa_pattern = OR_CFA_PATTERN_RGGB;
00352                         }
00353                         break;
00354                     }
00355                     break;
00356                 case IFD::CFA_GREEN:
00357                     switch(cfaPattern[1]) {
00358                     case IFD::CFA_RED:
00359                         if((cfaPattern[2] == 2) 
00360                            && (cfaPattern[3] == IFD::CFA_GREEN)) 
00361                         {
00362                             cfa_pattern = OR_CFA_PATTERN_GRBG;
00363                         }
00364                         break;
00365                     case 2:
00366                         if((cfaPattern[2] == IFD::CFA_RED) 
00367                            && (cfaPattern[3] == IFD::CFA_GREEN)) 
00368                         {
00369                             cfa_pattern = OR_CFA_PATTERN_GBRG;
00370                         }
00371                         break;
00372                     }
00373                     break;
00374                 case IFD::CFA_BLUE:
00375                     switch(cfaPattern[1]) {
00376                     case IFD::CFA_GREEN:
00377                         if((cfaPattern[2] == IFD::CFA_GREEN) 
00378                            && (cfaPattern[3] == IFD::CFA_RED)) 
00379                         {
00380                             cfa_pattern = OR_CFA_PATTERN_BGGR;
00381                         }
00382                         break;
00383                     }
00384                     break;
00385                 }
00386                 //
00387             }
00388             return cfa_pattern;
00389         }
00390 
00391         RawData::CfaPattern _convertNewCfaPattern(const IFDEntry::Ref & e)
00392         {
00393             RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NONE;
00394             if(!e || (e->count() < 4)) {
00395                 return cfa_pattern;
00396             }
00397 
00398             uint16_t hdim = IFDTypeTrait<uint16_t>::get(*e, 0, true);
00399             uint16_t vdim = IFDTypeTrait<uint16_t>::get(*e, 1, true);
00400             if(hdim != 2 && vdim != 2) {
00401                 cfa_pattern = OR_CFA_PATTERN_NON_RGB22;
00402             }
00403             else {
00404                 std::vector<uint8_t> cfaPattern;
00405                 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 4, true));
00406                 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 5, true));
00407                 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 6, true));
00408                 cfaPattern.push_back(IFDTypeTrait<uint8_t>::get(*e, 7, true));
00409                 cfa_pattern = _convertArrayToCfaPattern(cfaPattern);
00410             }
00411             return cfa_pattern;
00412         }
00413 
00414 
00416         RawData::CfaPattern _convertCfaPattern(const IFDEntry::Ref & e)
00417         {
00418             std::vector<uint8_t> cfaPattern;
00419             RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NONE;
00420             
00421             e->getArray(cfaPattern);
00422             if(!cfaPattern.empty()) {
00423                 cfa_pattern = _convertArrayToCfaPattern(cfaPattern);
00424             }
00425             return cfa_pattern;
00426         }
00427 
00433         static RawData::CfaPattern _getCfaPattern(const IFDDir::Ref & dir)
00434         {
00435             Trace(DEBUG1) << __FUNCTION__ << "\n";
00436             RawData::CfaPattern cfa_pattern = OR_CFA_PATTERN_NONE;
00437             try {
00438                 IFDEntry::Ref e = dir->getEntry(IFD::EXIF_TAG_CFA_PATTERN);
00439                 if(e) {
00440                     cfa_pattern = _convertCfaPattern(e);
00441                 }
00442                 else {
00443                     e = dir->getEntry(IFD::EXIF_TAG_NEW_CFA_PATTERN);
00444                     if(e)  {
00445                         cfa_pattern = _convertNewCfaPattern(e);
00446                     }
00447                 }
00448             }
00449             catch(...)
00450             {
00451                 Trace(ERROR) << "Exception in _getCfaPattern().\n";
00452             }
00453             return cfa_pattern;
00454         }
00455 
00456         } // end anon namespace
00457 
00458         ::or_error IFDFile::_getRawDataFromDir(RawData & data, IFDDir::Ref & dir)
00459         {
00460             ::or_error ret = OR_ERROR_NONE;
00461             
00462             uint16_t bpc = 0;
00463             uint32_t offset = 0;
00464             uint32_t byte_length = 0;
00465             bool got_it;
00466             uint32_t x, y;
00467             x = 0;
00468             y = 0;
00469 
00470             got_it = dir->getValue(IFD::EXIF_TAG_BITS_PER_SAMPLE, bpc);
00471             if(!got_it) {
00472                 Trace(ERROR) << "unable to guess Bits per sample\n";
00473             }
00474 
00475             got_it = dir->getValue(IFD::EXIF_TAG_STRIP_OFFSETS, offset);
00476             if(got_it) {
00477                 IFDEntry::Ref e = dir->getEntry(IFD::EXIF_TAG_STRIP_BYTE_COUNTS);
00478                 if(e) {
00479                     std::vector<uint32_t> counts;
00480                     e->getArray(counts);
00481                     Trace(DEBUG1) << "counting tiles\n";
00482                     byte_length = std::accumulate(counts.begin(), counts.end(), 0);
00483                 }
00484                 else {
00485                     Trace(DEBUG1) << "byte len not found\n";
00486                     return OR_ERROR_NOT_FOUND;
00487                 }
00488             }
00489             else {
00490                 // the tile are individual JPEGS....
00491                 // TODO extract all of them.
00492                 IFDEntry::Ref e = dir->getEntry(IFD::TIFF_TAG_TILE_OFFSETS);
00493                 if(e) {
00494                     std::vector<uint32_t> offsets;
00495                     e->getArray(offsets);
00496                     if(offsets.size() > 1) {
00497                         offset = offsets[0];
00498                     }
00499                     else {
00500                         Trace(DEBUG1) << "tile offsets empty\n";
00501                         return OR_ERROR_NOT_FOUND;                      
00502                     }
00503                 }
00504                 else {
00505                     Trace(DEBUG1) << "tile offsets not found\n";
00506                     return OR_ERROR_NOT_FOUND;                      
00507                 }
00508                 e = dir->getEntry(IFD::TIFF_TAG_TILE_BYTECOUNTS);
00509                 if(e) {
00510                     std::vector<uint32_t> counts;
00511                     e->getArray(counts);
00512                     Trace(DEBUG1) << "counting tiles\n";
00513                     byte_length = std::accumulate(counts.begin(), counts.end(), 0);
00514                 }
00515                 else {
00516                     Trace(DEBUG1) << "tile byte counts not found\n";
00517                     return OR_ERROR_NOT_FOUND;                      
00518                 }
00519             }
00520             got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_WIDTH, x);
00521             if(!got_it) {
00522                 Trace(DEBUG1) << "X not found\n";
00523                 return OR_ERROR_NOT_FOUND;
00524             }
00525             got_it = dir->getIntegerValue(IFD::EXIF_TAG_IMAGE_LENGTH, y);
00526             if(!got_it) {
00527                 Trace(DEBUG1) << "Y not found\n";
00528                 return OR_ERROR_NOT_FOUND;
00529             }
00530 
00531             uint32_t compression = 0;
00532             got_it = dir->getIntegerValue(IFD::EXIF_TAG_COMPRESSION, compression);
00533             if(!got_it)
00534             {
00535                 Trace(DEBUG1) << "Compression type not found\n";
00536             }
00537             BitmapData::DataType data_type = OR_DATA_TYPE_NONE;
00538 
00539             switch(compression) 
00540             {
00541             case IFD::COMPRESS_NONE:
00542                 data_type = OR_DATA_TYPE_CFA;
00543                 break;
00544             case IFD::COMPRESS_NIKON_PACK:
00545                 data_type = OR_DATA_TYPE_CFA;
00546                 break;
00547             case IFD::COMPRESS_NIKON_QUANTIZED:
00548                 // must check whether it is really compressed
00549                 // only for D100
00550                 if( !NEFFile::isCompressed(*m_container, offset) ) {
00551                     compression = IFD::COMPRESS_NIKON_PACK;
00552                     data_type = OR_DATA_TYPE_CFA;
00553                     // this is a hack. we should check if 
00554                     // we have a D100 instead, but that case is already
00555                     // a D100 corner case. WILL BREAK on compressed files.
00556                     // according to dcraw we must increase the size by 6.
00557                     x += 6;
00558                     break;
00559                 }
00560             default:
00561                 data_type = OR_DATA_TYPE_COMPRESSED_CFA;
00562                 break;
00563             }
00564 
00565             Trace(DEBUG1) << "RAW Compression is " << compression << "\n";
00566             
00567             RawData::CfaPattern cfa_pattern = _getCfaPattern(dir);
00568             if(cfa_pattern == OR_CFA_PATTERN_NONE) {
00569                 // some file have it in the exif IFD instead.
00570                 if(!m_exifIfd) {
00571                     m_exifIfd = _locateExifIfd();
00572                 }
00573                 cfa_pattern = _getCfaPattern(m_exifIfd);
00574             }
00575 
00576 
00577             if((bpc == 12) && (compression == 1) 
00578                && (byte_length == (x * y * 2))) 
00579             {
00580                 bpc = 16;
00581             }
00582             if((bpc == 16) || (data_type == OR_DATA_TYPE_COMPRESSED_CFA)) {
00583                 void *p = data.allocData(byte_length);
00584                 size_t real_size = m_container->fetchData(p, offset, 
00585                                                           byte_length);
00586                 if (real_size < byte_length) {
00587                     Trace(WARNING) << "Size mismatch for data: ignoring.\n";
00588                 }
00589             }
00590             else if((bpc == 12) || (bpc == 8)) {
00591                 size_t fetched = 0;
00592                 Unpack unpack(x, y, compression);
00593                 const size_t blocksize = (bpc == 8 ? x : unpack.block_size());
00594                 Trace(DEBUG1) << "Block size = " << blocksize << "\n";
00595                 Trace(DEBUG1) << "dimensions (x, y) " << x << ", "
00596                               << y << "\n";
00597                 boost::scoped_array<uint8_t> block(new uint8_t[blocksize]);
00598                 size_t outleft = x * y * 2;
00599                 uint8_t * outdata = (uint8_t*)data.allocData(outleft);
00600                 size_t got;
00601                 Trace(DEBUG1) << "offset of RAW data = " << offset << "\n";
00602                 do {
00603                     got = m_container->fetchData (block.get(), 
00604                                                   offset, blocksize);
00605                     fetched += got;
00606                     offset += got;
00607                     if(got) {
00608                         if(bpc == 12) {
00609                             size_t out = unpack.unpack_be12to16(outdata, 
00610                                                                 outleft, 
00611                                                                 block.get(), 
00612                                                                 got);
00613                             outdata += out;
00614                             outleft -= out;
00615                         }
00616                         else {
00617                             // outdata point to uint16_t
00618                             std::copy(block.get(), block.get()+got,
00619                                       (uint16_t*)outdata);
00620                             outdata += (got << 1);
00621                         }
00622                     }
00623                 } while((got != 0) && (fetched < byte_length));
00624             }
00625             else {
00626                 Trace(ERROR) << "Unsupported bpc " << bpc << "\n";
00627             }
00628             data.setCfaPattern(cfa_pattern);
00629             data.setDataType(data_type);
00630             data.setCompression(data_type == OR_DATA_TYPE_COMPRESSED_CFA 
00631                                 ? compression : 1);
00632             data.setDimensions(x, y);
00633             
00634             return ret;
00635         }
00636 
00637     }
00638 }

Generated on Sat Nov 7 19:23:17 2009 for libopenraw by  doxygen 1.5.8