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

Generated on Sat Aug 15 16:52:19 2009 for libopenraw by  doxygen 1.5.9