mrwfile.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <iostream>
00024 #include <boost/scoped_array.hpp>
00025 #include <libopenraw/libopenraw.h>
00026 #include <libopenraw++/thumbnail.h>
00027 #include <libopenraw++/rawdata.h>
00028
00029 #include "debug.h"
00030 #include "io/stream.h"
00031 #include "io/file.h"
00032 #include "mrwcontainer.h"
00033 #include "ifd.h"
00034 #include "mrwfile.h"
00035 #include "unpack.h"
00036
00037 using namespace Debug;
00038
00039 namespace OpenRaw {
00040
00041
00042 namespace Internals {
00043
00044 RawFile *MRWFile::factory(const char* _filename)
00045 {
00046 return new MRWFile(_filename);
00047 }
00048
00049 MRWFile::MRWFile(const char* _filename)
00050 : IFDFile(_filename, OR_RAWFILE_TYPE_MRW, false)
00051 {
00052 m_container = new MRWContainer (m_io, 0);
00053 }
00054
00055 MRWFile::~MRWFile()
00056 {
00057 }
00058
00059 IFDDir::Ref MRWFile::_locateCfaIfd()
00060 {
00061
00062 if(!m_mainIfd) {
00063 m_mainIfd = _locateMainIfd();
00064 }
00065 return m_mainIfd;
00066 }
00067
00068
00069 IFDDir::Ref MRWFile::_locateMainIfd()
00070 {
00071 return m_container->setDirectory(0);
00072 }
00073
00074
00075 ::or_error MRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00076 {
00077 ::or_error err = OR_ERROR_NOT_FOUND;
00078 list.push_back (640);
00079 err = OR_ERROR_NONE;
00080 return err;
00081 }
00082
00083
00084 ::or_error MRWFile::_getThumbnail(uint32_t , Thumbnail & thumbnail)
00085 {
00086 IFDDir::Ref dir;
00087 IFDEntry::Ref maker_ent;
00088 IFDEntry::Ref thumb_ent;
00089 ::or_error ret = OR_ERROR_NOT_FOUND;
00090 MRWContainer *mc = (MRWContainer *)m_container;
00091
00092 dir = _locateExifIfd();
00093 if (!dir) {
00094 Trace(WARNING) << "EXIF dir not found\n";
00095 return ret;
00096 }
00097
00098 maker_ent = dir->getEntry(IFD::EXIF_TAG_MAKER_NOTE);
00099 if (!maker_ent) {
00100 Trace(WARNING) << "maker note offset entry not found\n";
00101 return ret;
00102 }
00103 uint32_t off = 0;
00104 off = maker_ent->offset();
00105
00106 IFDDir::Ref ref(new IFDDir(mc->ttw->offset() +
00107 MRW::DataBlockHeaderLength + off,
00108 *m_container));
00109 ref->load();
00110
00111 uint32_t tnail_offset = 0;
00112 uint32_t tnail_len = 0;
00113 thumb_ent = ref->getEntry(MRW::MRWTAG_THUMBNAIL);
00114 if (thumb_ent) {
00115 tnail_offset = thumb_ent->offset();
00116 tnail_len = thumb_ent->count();
00117 }
00118 else if(ref->getValue(MRW::MRWTAG_THUMBNAIL_OFFSET, tnail_offset)) {
00119 if(!ref->getValue(MRW::MRWTAG_THUMBNAIL_LENGTH, tnail_len)) {
00120 Trace(WARNING) << "thumbnail lenght entry not found\n";
00121 return ret;
00122 }
00123 }
00124 else
00125 {
00126 Trace(WARNING) << "thumbnail offset entry not found\n";
00127 return ret;
00128 }
00129
00130 Trace(DEBUG1) << "thumbnail offset found, "
00131 << " offset == " << tnail_offset << " count == "
00132 << tnail_len << "\n";
00133 void *p = thumbnail.allocData (tnail_len);
00134 size_t fetched = m_container->fetchData(p, mc->ttw->offset()
00135 + MRW::DataBlockHeaderLength
00136 + tnail_offset,
00137 tnail_len);
00138 if (fetched != tnail_len) {
00139 Trace(WARNING) << "Unable to fetch all thumbnail data: "
00140 << fetched << " not " << tnail_len
00141 << " bytes\n";
00142 }
00143
00144 ((unsigned char *)p)[0] = 0xFF;
00145
00146 thumbnail.setDataType (OR_DATA_TYPE_JPEG);
00147 thumbnail.setDimensions (640, 480);
00148 return OR_ERROR_NONE;
00149 }
00150
00151
00152 ::or_error MRWFile::_getRawData(RawData & data, uint32_t options)
00153 {
00154 MRWContainer *mc = (MRWContainer *)m_container;
00155
00156 if(!mc->prd) {
00157 return OR_ERROR_NOT_FOUND;
00158 }
00159
00160 uint16_t y = mc->prd->uint16_val (MRW::PRD_SENSOR_LENGTH);
00161 uint16_t x = mc->prd->uint16_val (MRW::PRD_SENSOR_WIDTH);
00162
00163 bool is_compressed = (mc->prd->uint8_val(MRW::PRD_STORAGE_TYPE) == 0x59);
00164
00165
00166
00167
00168 uint32_t finaldatalen = 2 * x * y;
00169 uint32_t datalen =
00170 (is_compressed ? x * y + ((x * y) >> 1) : finaldatalen);
00171
00172 if(options & OR_OPTIONS_DONT_DECOMPRESS) {
00173 finaldatalen = datalen;
00174 }
00175 if(is_compressed && (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00176 data.setDataType (OR_DATA_TYPE_COMPRESSED_CFA);
00177 }
00178 else {
00179 data.setDataType (OR_DATA_TYPE_CFA);
00180 }
00181 Trace(DEBUG1) << "datalen = " << datalen <<
00182 " final datalen = " << finaldatalen << "\n";
00183 void *p = data.allocData(finaldatalen);
00184 size_t fetched = 0;
00185 off_t offset = mc->pixelDataOffset();
00186 if(!is_compressed || (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00187 fetched = m_container->fetchData (p, offset, datalen);
00188 }
00189 else {
00190 Unpack unpack(x, y, IFD::COMPRESS_NONE);
00191 size_t blocksize = unpack.block_size();
00192 boost::scoped_array<uint8_t> block(new uint8_t[blocksize]);
00193 uint8_t * outdata = (uint8_t*)data.data();
00194 size_t outleft = finaldatalen;
00195 size_t got;
00196 do {
00197 Trace(DEBUG2) << "fatchData @offset " << offset << "\n";
00198 got = m_container->fetchData (block.get(),
00199 offset, blocksize);
00200 fetched += got;
00201 offset += got;
00202 Trace(DEBUG2) << "got " << got << "\n";
00203 if(got) {
00204 size_t out = unpack.unpack_be12to16(outdata, outleft,
00205 block.get(), got);
00206 outdata += out;
00207 outleft -= out;
00208 Trace(DEBUG2) << "unpacked " << out
00209 << " bytes from " << got << "\n";
00210 }
00211 } while((got != 0) && (fetched < datalen));
00212 }
00213 if (fetched < datalen) {
00214 Trace(WARNING) << "Fetched only " << fetched <<
00215 " of " << datalen << ": continuing anyway.\n";
00216 }
00217 uint16_t bpat = mc->prd->uint16_val (MRW::PRD_BAYER_PATTERN);
00218 or_cfa_pattern cfa_pattern = OR_CFA_PATTERN_NONE;
00219 switch(bpat)
00220 {
00221 case 0x0001:
00222 cfa_pattern = OR_CFA_PATTERN_RGGB;
00223 break;
00224 case 0x0004:
00225 cfa_pattern = OR_CFA_PATTERN_GBRG;
00226 break;
00227 default:
00228 break;
00229 }
00230 data.setCfaPattern(cfa_pattern);
00231 data.setDimensions (x, y);
00232
00233 return OR_ERROR_NONE;
00234 }
00235
00236 }
00237 }