libopenraw
|
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