00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <algorithm>
00023 #include <boost/bind.hpp>
00024 #include <boost/scoped_ptr.hpp>
00025
00026 #include <libopenraw/libopenraw.h>
00027 #include <libopenraw++/thumbnail.h>
00028 #include <libopenraw++/rawdata.h>
00029
00030 #include "debug.h"
00031 #include "io/file.h"
00032 #include "io/streamclone.h"
00033 #include "io/memstream.h"
00034 #include "crwfile.h"
00035 #include "ciffcontainer.h"
00036 #include "jfifcontainer.h"
00037 #include "crwdecompressor.h"
00038 #include "metavalue.h"
00039
00040 #include "rawfilefactory.h"
00041
00042 using namespace Debug;
00043 using boost::scoped_ptr;
00044
00045 namespace OpenRaw {
00046
00047 namespace Internals {
00048
00049 using namespace CIFF;
00050
00051 RawFile *CRWFile::factory(const char* _filename)
00052 {
00053 return new CRWFile(_filename);
00054 }
00055
00056 CRWFile::CRWFile(const char* _filename)
00057 : RawFile(_filename, OR_RAWFILE_TYPE_CRW),
00058 m_io(new IO::File(_filename)),
00059 m_container(new CIFFContainer(m_io)),
00060 m_x(0), m_y(0)
00061 {
00062
00063 }
00064
00065 CRWFile::~CRWFile()
00066 {
00067 delete m_container;
00068 delete m_io;
00069 }
00070
00071 ::or_error CRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00072 {
00073 ::or_error err = OR_ERROR_NOT_FOUND;
00074
00075 Heap::Ref heap = m_container->heap();
00076 if(!heap) {
00077
00078 return err;
00079 }
00080 const RecordEntry::List & records = heap->records();
00081 RecordEntry::List::const_iterator iter;
00082 iter = std::find_if(records.begin(), records.end(), boost::bind(
00083 &RecordEntry::isA, _1,
00084 static_cast<uint16_t>(TAG_JPEGIMAGE)));
00085 if (iter != records.end()) {
00086 Trace(DEBUG2) << "JPEG @" << (*iter).offset << "\n";
00087 m_x = m_y = 0;
00088
00089 scoped_ptr<IO::StreamClone> s(new IO::StreamClone(m_io, heap->offset()
00090 + (*iter).offset));
00091 scoped_ptr<JFIFContainer> jfif(new JFIFContainer(s.get(), 0));
00092
00093 jfif->getDimensions(m_x, m_y);
00094 Trace(DEBUG1) << "JPEG dimensions x=" << m_x
00095 << " y=" << m_y << "\n";
00096 list.push_back(std::max(m_x,m_y));
00097 err = OR_ERROR_NONE;
00098 }
00099
00100 return err;
00101 }
00102
00103 ::or_error CRWFile::_getThumbnail(uint32_t , Thumbnail & thumbnail)
00104 {
00105 ::or_error err = OR_ERROR_NOT_FOUND;
00106 Heap::Ref heap = m_container->heap();
00107 if(!heap) {
00108
00109 return err;
00110 }
00111
00112 const RecordEntry::List & records = heap->records();
00113 RecordEntry::List::const_iterator iter;
00114 iter = std::find_if(records.begin(), records.end(), boost::bind(
00115 &RecordEntry::isA, _1,
00116 static_cast<uint16_t>(TAG_JPEGIMAGE)));
00117 if (iter != records.end()) {
00118 Trace(DEBUG2) << "JPEG @" << (*iter).offset << "\n";
00119 size_t byte_size = (*iter).length;
00120 void *buf = thumbnail.allocData(byte_size);
00121 size_t real_size = (*iter).fetchData(heap.get(), buf, byte_size);
00122 if (real_size != byte_size) {
00123 Trace(WARNING) << "wrong size\n";
00124 }
00125 thumbnail.setDimensions(m_x, m_y);
00126 thumbnail.setDataType(OR_DATA_TYPE_JPEG);
00127 err = OR_ERROR_NONE;
00128 }
00129
00130 return err;
00131 }
00132
00133 ::or_error CRWFile::_getRawData(RawData & data, uint32_t options)
00134 {
00135 ::or_error err = OR_ERROR_NOT_FOUND;
00136 Heap::Ref props = m_container->getImageProps();
00137
00138 const ImageSpec * img_spec = m_container->getImageSpec();
00139 uint32_t x, y;
00140 x = y = 0;
00141 int32_t orientation = 0;
00142 if(img_spec) {
00143 x = img_spec->imageWidth;
00144 y = img_spec->imageHeight;
00145 orientation = img_spec->exifOrientation();
00146 }
00147
00148
00149 const CIFF::RecordEntry::List & propsRecs = props->records();
00150 CIFF::RecordEntry::List::const_iterator iter;
00151 iter = std::find_if(propsRecs.begin(), propsRecs.end(), boost::bind(
00152 &RecordEntry::isA, _1,
00153 static_cast<uint16_t>(TAG_EXIFINFORMATION)));
00154 if (iter == propsRecs.end()) {
00155 Trace(ERROR) << "Couldn't find the Exif information.\n";
00156 return err;
00157 }
00158
00159 Heap exifProps(iter->offset + props->offset(), iter->length, m_container);
00160
00161 const RecordEntry::List & exifPropsRecs = exifProps.records();
00162 iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(),
00163 boost::bind(
00164 &RecordEntry::isA, _1,
00165 static_cast<uint16_t>(TAG_DECODERTABLE)));
00166 if (iter == exifPropsRecs.end()) {
00167 Trace(ERROR) << "Couldn't find the decoder table.\n";
00168 return err;
00169 }
00170 Trace(DEBUG2) << "length = " << iter->length << "\n";
00171 Trace(DEBUG2) << "offset = " << exifProps.offset() + iter->offset << "\n";
00172 IO::Stream *file = m_container->file();
00173 file->seek(exifProps.offset() + iter->offset, SEEK_SET);
00174 uint32_t decoderTable;
00175 if(m_container->readUInt32(file, decoderTable)) {
00176 Trace(DEBUG2) << "decoder table = " << decoderTable << "\n";
00177 }
00178
00179
00180 uint16_t cfa_x, cfa_y;
00181 iter = std::find_if(exifPropsRecs.begin(), exifPropsRecs.end(), boost::bind(
00182 &RecordEntry::isA, _1,
00183 static_cast<uint16_t>(TAG_SENSORINFO)));
00184 if (iter == exifPropsRecs.end()) {
00185 Trace(ERROR) << "Couldn't find the sensor info.\n";
00186 return err;
00187 }
00188 Trace(DEBUG2) << "length = " << iter->length << "\n";
00189 Trace(DEBUG2) << "offset = " << exifProps.offset() + iter->offset << "\n";
00190
00191
00192 file->seek(exifProps.offset() + iter->offset + 2, SEEK_SET);
00193 if(!(m_container->readUInt16(file, cfa_x)
00194 && m_container->readUInt16(file, cfa_y))) {
00195 Trace(ERROR) << "Couldn't find the sensor size.\n";
00196 return err;
00197 }
00198
00199
00200 const CIFF::RecordEntry *entry = m_container->getRawDataRecord();
00201 if (entry) {
00202 CIFF::Heap::Ref heap = m_container->heap();
00203 Trace(DEBUG2) << "RAW @" << heap->offset() + entry->offset << "\n";
00204 size_t byte_size = entry->length;
00205 void *buf = data.allocData(byte_size);
00206 size_t real_size = entry->fetchData(heap.get(), buf, byte_size);
00207 if (real_size != byte_size) {
00208 Trace(WARNING) << "wrong size\n";
00209 }
00210 data.setDimensions(x, y);
00211 data.setCfaPattern(OR_CFA_PATTERN_RGGB);
00212 data.setDataType(OR_DATA_TYPE_COMPRESSED_CFA);
00213
00214
00215 if((options & OR_OPTIONS_DONT_DECOMPRESS) == 0) {
00216 boost::scoped_ptr<IO::Stream> s(new IO::MemStream(data.data(),
00217 data.size()));
00218 s->open();
00219
00220 CrwDecompressor decomp(s.get(), m_container);
00221
00222 decomp.setOutputDimensions(cfa_x, cfa_y);
00223 decomp.setDecoderTable(decoderTable);
00224 RawData *dData = decomp.decompress();
00225 if (dData != NULL) {
00226 Trace(DEBUG1) << "Out size is " << dData->x()
00227 << "x" << dData->y() << "\n";
00228 dData->setCfaPattern(data.cfaPattern());
00229 data.swap(*dData);
00230 delete dData;
00231 }
00232 }
00233 err = OR_ERROR_NONE;
00234 }
00235 return err;
00236 }
00237
00238 MetaValue *CRWFile::_getMetaValue(int32_t meta_index)
00239 {
00240 MetaValue * val = NULL;
00241
00242 switch(META_INDEX_MASKOUT(meta_index)) {
00243 case META_NS_TIFF:
00244 {
00245 const ImageSpec * img_spec = m_container->getImageSpec();
00246 if(img_spec) {
00247 val = new MetaValue(boost::any(
00248 static_cast<int32_t>(
00249 img_spec->exifOrientation())));
00250 }
00251 break;
00252 }
00253 case META_NS_EXIF:
00254 break;
00255 default:
00256 Trace(ERROR) << "Unknown Meta Namespace\n";
00257 break;
00258 }
00259
00260 return val;
00261 }
00262 }
00263 }