00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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 {
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
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
00395
00396
00397
00398
00399 src = (uint16_t*)rawdata.data();
00400
00401
00402
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
00467
00468
00469
00470
00471
00472
00473
00474