rawfile.cpp

00001 /*
00002  * libopenraw - rawfile.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 
00023 #include <cstring>
00024 #include <cassert>
00025 #include <map>
00026 #include <string>
00027 
00028 #include <boost/algorithm/string.hpp>
00029 #include <boost/bind.hpp>
00030 #include <boost/scoped_ptr.hpp>
00031 #include <boost/checked_delete.hpp>
00032 
00033 #include "debug.h"
00034 
00035 #include <libopenraw/metadata.h>
00036 #include <libopenraw++/rawfile.h>
00037 #include <libopenraw++/rawdata.h>
00038 #include <libopenraw++/thumbnail.h>
00039 
00040 #include "io/file.h"
00041 #include "io/memstream.h"
00042 #include "cr2file.h"
00043 #include "neffile.h"
00044 #include "orffile.h"
00045 #include "arwfile.h"
00046 #include "peffile.h"
00047 #include "crwfile.h"
00048 #include "erffile.h"
00049 #include "dngfile.h"
00050 #include "mrwfile.h"
00051 #include "metavalue.h"
00052 #include "exception.h"
00053 #include "demosaic.h"
00054 
00055 #include "rawfilefactory.h"
00056 
00057 using std::string;
00058 using namespace Debug;
00059 
00060 namespace OpenRaw {
00061 
00062 using Internals::RawFileFactory;
00063 
00064 void init(void)
00065 {
00066     static RawFileFactory fctcr2(OR_RAWFILE_TYPE_CR2, 
00067                                  boost::bind(&Internals::Cr2File::factory, _1),
00068                                  "cr2");
00069     static RawFileFactory fctnef(OR_RAWFILE_TYPE_NEF, 
00070                                  boost::bind(&Internals::NEFFile::factory, _1),
00071                                  "nef");
00072     static RawFileFactory fctarw(OR_RAWFILE_TYPE_ARW, 
00073                                  boost::bind(&Internals::ARWFile::factory, _1),
00074                                  "arw");
00075     static RawFileFactory fctorf(OR_RAWFILE_TYPE_ORF, 
00076                                  boost::bind(&Internals::ORFFile::factory, _1),
00077                                  "orf");
00078     static RawFileFactory fctdng(OR_RAWFILE_TYPE_DNG, 
00079                                  boost::bind(&Internals::DNGFile::factory, _1),
00080                                  "dng");
00081     static RawFileFactory fctpef(OR_RAWFILE_TYPE_PEF, 
00082                                  boost::bind(&Internals::PEFFile::factory, _1),
00083                                  "pef");
00084     static RawFileFactory fctcrw(OR_RAWFILE_TYPE_CRW,
00085                                  boost::bind(&Internals::CRWFile::factory, _1),
00086                                  "crw");
00087     static RawFileFactory fcterf(OR_RAWFILE_TYPE_ERF,
00088                                  boost::bind(&Internals::ERFFile::factory, _1),
00089                                  "erf");
00090     static RawFileFactory fctmrw(OR_RAWFILE_TYPE_MRW,
00091                                  boost::bind(&Internals::MRWFile::factory, _1),
00092                                  "mrw");
00093 }
00094 
00095 class RawFile::Private 
00096 {
00097 public:
00098     Private(Type t)
00099         : m_type(t),
00100           m_type_id(OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_NONE, OR_TYPEID_UNKNOWN)),
00101           m_sizes(),
00102           m_cam_ids(NULL)
00103         {
00104         }
00105     ~Private()
00106         {
00107             std::map<int32_t, MetaValue*>::iterator iter;
00108             for(iter = m_metadata.begin();
00109                 iter != m_metadata.end(); ++iter)
00110             {
00111                 if(iter->second) {
00112                     delete iter->second;
00113                 }
00114             }
00115         }
00117     Type m_type;
00119     TypeId m_type_id;
00121     std::vector<uint32_t> m_sizes;
00122     std::map<int32_t, MetaValue*> m_metadata;
00123     const camera_ids_t *m_cam_ids;
00124 };
00125 
00126 
00127 const char **RawFile::fileExtensions()
00128 {
00129     init();
00130 
00131     return RawFileFactory::fileExtensions();
00132 }
00133 
00134 
00135 RawFile *RawFile::newRawFile(const char*_filename, RawFile::Type _typeHint)
00136 {
00137     init();
00138 
00139     Type type;
00140     if (_typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
00141         type = identify(_filename);
00142     }
00143     else {
00144         type = _typeHint;
00145     }
00146     Trace(DEBUG1) << "factory size " << RawFileFactory::table().size() << "\n";
00147     RawFileFactory::Table::iterator iter = RawFileFactory::table().find(type);
00148     if (iter == RawFileFactory::table().end()) {
00149         Trace(WARNING) << "factory not found\n";
00150         return NULL;
00151     }
00152     if (iter->second == NULL) {
00153         Trace(WARNING) << "factory is NULL\n";
00154         return NULL;
00155     }
00156     IO::Stream *f = new IO::File(_filename);
00157     return iter->second(f);
00158 }
00159 
00160 RawFile *RawFile::newRawFileFromMemory(const uint8_t *buffer, 
00161                                        uint32_t len, 
00162                                        RawFile::Type _typeHint)
00163 {
00164     init();
00165     Type type;
00166     if (_typeHint == OR_RAWFILE_TYPE_UNKNOWN) {
00167         ::or_error err = identifyBuffer(buffer, len, type);
00168         if(err != OR_ERROR_NONE) {
00169             Trace(ERROR) << "error identifying buffer\n";
00170             return NULL;
00171         }
00172     }
00173     else {
00174         type = _typeHint;
00175     }
00176     RawFileFactory::Table::iterator iter = RawFileFactory::table().find(type);
00177     if (iter == RawFileFactory::table().end()) {
00178         Trace(WARNING) << "factory not found\n";
00179         return NULL;
00180     }
00181     if (iter->second == NULL) {
00182         Trace(WARNING) << "factory is NULL\n";
00183         return NULL;
00184     }
00185     IO::Stream *f = new IO::MemStream((void*)buffer, len);
00186     return iter->second(f);
00187 }
00188 
00189 
00190 RawFile::Type RawFile::identify(const char*_filename)
00191 {
00192     const char *e = ::strrchr(_filename, '.');
00193     if (e == NULL) {
00194         Trace(DEBUG1) << "Extension not found\n";
00195         return OR_RAWFILE_TYPE_UNKNOWN;
00196     }
00197     std::string extension(e + 1);
00198     if (extension.length() > 3) {
00199         return OR_RAWFILE_TYPE_UNKNOWN;
00200     }
00201 
00202     boost::to_lower(extension);
00203 
00204     RawFileFactory::Extensions & extensions = RawFileFactory::extensions();
00205     RawFileFactory::Extensions::iterator iter = extensions.find(extension);
00206     if (iter == extensions.end())
00207     {
00208         return OR_RAWFILE_TYPE_UNKNOWN;
00209     }
00210     return iter->second;
00211 }
00212 
00213 ::or_error RawFile::identifyBuffer(const uint8_t* buff, size_t len,
00214                                    RawFile::Type &_type)
00215 {
00216     _type = OR_RAWFILE_TYPE_UNKNOWN;
00217     if(len <= 4) {
00218         return OR_ERROR_BUF_TOO_SMALL;
00219     }
00220     if(memcmp(buff, "\0MRM", 4) == 0) {
00221         _type = OR_RAWFILE_TYPE_MRW;
00222         return OR_ERROR_NONE;
00223     }
00224     if(memcmp(buff, "II\x1a\0\0\0HEAPCCDR", 14) == 0) {
00225         _type = OR_RAWFILE_TYPE_CRW;
00226         return OR_ERROR_NONE;
00227     }
00228     if(memcmp(buff, "IIRO", 4) == 0) {
00229         _type = OR_RAWFILE_TYPE_ORF;
00230         return OR_ERROR_NONE;
00231     }
00232     if((memcmp(buff, "II\x2a\0", 4) == 0) 
00233        || (memcmp(buff, "MM\0\x2a", 4) == 0)) {
00234         // TIFF based format
00235         if(len >=12 ) {
00236             if(memcmp(buff + 8, "CR\x2", 3) == 0) {
00237                 _type = OR_RAWFILE_TYPE_CR2;
00238                 return OR_ERROR_NONE;                
00239             }
00240         }
00241         if(len >= 8) {
00242             IO::Stream *s = new IO::MemStream((void*)buff, len);
00243             boost::scoped_ptr<Internals::TiffEpFile> f(new Internals::TiffEpFile(s, OR_RAWFILE_TYPE_TIFF));
00244             
00245             // Take into account DNG by checking the DNGVersion tag
00246             const MetaValue *dng_version = f->getMetaValue(META_NS_TIFF | TIFF_TAG_DNG_VERSION);
00247             if(dng_version) {
00248                 Trace(DEBUG1) << "found DNG versions\n";
00249                 _type = OR_RAWFILE_TYPE_DNG;
00250                 return OR_ERROR_NONE;
00251             }
00252 
00253             const MetaValue *makev = f->getMetaValue(META_NS_TIFF | EXIF_TAG_MAKE);
00254             if(makev){
00255                 std::string makes = makev->getString();
00256                 if(makes == "NIKON CORPORATION") {
00257                     _type = OR_RAWFILE_TYPE_NEF;
00258                 }
00259                 else if(makes == "SEIKO EPSON CORP."){
00260                     _type = OR_RAWFILE_TYPE_ERF;
00261                 }
00262                 else if(makes == "PENTAX Corporation ") {
00263                     _type = OR_RAWFILE_TYPE_PEF;                    
00264                 }
00265                 else if(makes == "SONY           ") {
00266                     _type = OR_RAWFILE_TYPE_ARW;                    
00267                 }
00268                 else if(makes == "Canon") {
00269                     _type = OR_RAWFILE_TYPE_CR2;
00270                 }
00271             }
00272         }
00273                         
00274     }
00275     return OR_ERROR_NONE;
00276 }
00277 
00278 RawFile::RawFile(IO::Stream *, RawFile::Type _type)
00279     : d(new Private(_type))
00280 {
00281         
00282 }
00283 
00284 
00285 RawFile::~RawFile()
00286 {
00287     delete d;
00288 }
00289 
00290 
00291 RawFile::Type RawFile::type() const
00292 {
00293     return d->m_type;
00294 }
00295 
00296 RawFile::TypeId RawFile::typeId()
00297 {
00298     if(d->m_type_id == 0) {
00299         _identifyId();
00300     }
00301     return d->m_type_id;
00302 }
00303 
00304 void RawFile::_setTypeId(RawFile::TypeId _type_id)
00305 {
00306     d->m_type_id = _type_id;
00307 }
00308 
00309 const std::vector<uint32_t> & RawFile::listThumbnailSizes(void)
00310 {
00311     if (d->m_sizes.size() == 0) {
00312         Trace(DEBUG1) << "_enumThumbnailSizes init\n";
00313         bool ret = _enumThumbnailSizes(d->m_sizes);
00314         if (!ret) {
00315             Trace(DEBUG1) << "_enumThumbnailSizes failed\n";
00316         }
00317     }
00318     return d->m_sizes;
00319 }
00320 
00321 
00322 ::or_error RawFile::getThumbnail(uint32_t tsize, Thumbnail & thumbnail)
00323 {
00324     ::or_error ret = OR_ERROR_NOT_FOUND;
00325     uint32_t smallest_bigger = 0xffffffff;
00326     uint32_t biggest_smaller = 0;
00327     uint32_t found_size = 0;
00328 
00329     Trace(DEBUG1) << "requested size " << tsize << "\n";
00330 
00331     const std::vector<uint32_t> & sizes(listThumbnailSizes());
00332 
00333     std::vector<uint32_t>::const_iterator iter;
00334 
00335     for (iter = sizes.begin(); iter != sizes.end(); ++iter) {
00336         Trace(DEBUG1) << "current iter is " << *iter << "\n";
00337         if (*iter < tsize) {
00338             if (*iter > biggest_smaller) {
00339                 biggest_smaller = *iter;
00340             }
00341         }
00342         else if(*iter > tsize) {
00343             if(*iter < smallest_bigger) {
00344                 smallest_bigger = *iter;
00345             }
00346         }
00347         else { // *iter == tsize
00348             found_size = tsize;
00349             break;
00350         }
00351     }
00352 
00353     if (found_size == 0) {
00354         found_size = (smallest_bigger != 0xffffffff ? 
00355                       smallest_bigger : biggest_smaller);
00356     }
00357 
00358     if (found_size != 0) {
00359         Trace(DEBUG1) << "size " << found_size << " found\n";
00360         ret = _getThumbnail(found_size, thumbnail);
00361     }
00362     else {
00363         // no size found, let's fail gracefuly
00364         Trace(DEBUG1) << "no size found\n";
00365         ret = OR_ERROR_NOT_FOUND;
00366     }
00367 
00368     return ret;
00369 }
00370 
00371 
00372 ::or_error RawFile::getRawData(RawData & rawdata, uint32_t options)
00373 {
00374     Trace(DEBUG1) << "getRawData()\n";
00375     ::or_error ret = _getRawData(rawdata, options);
00376     return ret;
00377 }   
00378 
00379 ::or_error RawFile::getRenderedImage(BitmapData & bitmapdata, uint32_t options)
00380 {
00381     RawData rawdata;
00382     ::or_error ret = getRawData(rawdata, options);
00383     if(ret == OR_ERROR_NONE) {
00384         uint32_t x,y;
00385         or_cfa_pattern pattern;
00386         uint16_t *src;
00387         pattern = rawdata.cfaPattern();
00388         x = rawdata.x();
00389         y = rawdata.y();
00390         bitmapdata.setDimensions(x,y);
00391         bitmapdata.setDataType(OR_DATA_TYPE_PIXMAP_8RGB);
00392         uint8_t *dst = (uint8_t *)bitmapdata.allocData(sizeof(uint8_t) * 3 * x * y);
00393         /*
00394         rawdata.linearize();
00395         rawdata.subtractBlack();
00396         rawdata.rescale();
00397         rawdata.clip();
00398         */
00399         src = (uint16_t*)rawdata.data();
00400 
00401         /* figure out how the demosaic can be plugged for a different 
00402          * algorithm */
00403         bimedian_demosaic(src, x, y, pattern, dst);
00404     }
00405     return ret;
00406 }
00407 
00408 
00409 int32_t RawFile::getOrientation()
00410 {
00411     int32_t idx = 0;
00412     const MetaValue * value = getMetaValue(META_NS_TIFF 
00413                                            | EXIF_TAG_ORIENTATION);
00414     if(value == NULL) {
00415         return 0;
00416     }
00417     try {
00418         idx = value->getInteger();
00419     }
00420     catch(const Internals::BadTypeException & e)    {
00421         Trace(DEBUG1) << "wrong type - " << e.what() << "\n";
00422     }
00423     return idx;
00424 }
00425     
00426 const MetaValue *RawFile::getMetaValue(int32_t meta_index)
00427 {
00428     MetaValue *val = NULL;
00429     std::map<int32_t, MetaValue*>::iterator iter = d->m_metadata.find(meta_index);
00430     if(iter == d->m_metadata.end()) {
00431         val = _getMetaValue(meta_index);
00432         if(val != NULL) {
00433             d->m_metadata[meta_index] = val;
00434         }
00435     }
00436     else {
00437         val = iter->second;
00438     }
00439     return val;
00440 }
00441 
00442 
00443 RawFile::TypeId RawFile::_typeIdFromModel(const std::string & model)
00444 {
00445     const struct camera_ids_t * p = d->m_cam_ids;
00446     if(!p) {
00447         return 0;
00448     }
00449     while(p->model) {
00450         if(model == p->model) {
00451             break;
00452         }
00453         p++;
00454     }
00455     return p->type_id;
00456 }
00457 
00458 void RawFile::_setIdMap(const camera_ids_t *map)
00459 {
00460     d->m_cam_ids = map;
00461 }
00462 
00463 }
00464 
00465 /*
00466   Local Variables:
00467   mode:c++
00468   c-file-style:"stroustrup"
00469   c-file-offsets:((innamespace . 0))
00470   indent-tabs-mode:nil
00471   fill-column:80
00472   End:
00473 */
00474 

Generated on Wed Aug 25 01:26:34 2010 for libopenraw by  doxygen 1.5.9