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 const struct IFDFile::camera_ids_t MRWFile::s_def[] = {
00045 { "21860002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00046 OR_TYPEID_MINOLTA_MAXXUM_5D) },
00047 { "21810002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00048 OR_TYPEID_MINOLTA_MAXXUM_7D) },
00049 { "27730001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00050 OR_TYPEID_MINOLTA_DIMAGE5) },
00051 { "27660001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00052 OR_TYPEID_MINOLTA_DIMAGE7) },
00053 { "27790001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00054 OR_TYPEID_MINOLTA_DIMAGE7I) },
00055 { "27780001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00056 OR_TYPEID_MINOLTA_DIMAGE7HI) },
00057 { "27820001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00058 OR_TYPEID_MINOLTA_A1) },
00059 { "27200001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00060 OR_TYPEID_MINOLTA_A2) },
00061 { "27470002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
00062 OR_TYPEID_MINOLTA_A200) },
00063 { 0, 0 }
00064 };
00065
00066 RawFile *MRWFile::factory(IO::Stream *_f)
00067 {
00068 return new MRWFile(_f);
00069 }
00070
00071 MRWFile::MRWFile(IO::Stream* _f)
00072 : IFDFile(_f, OR_RAWFILE_TYPE_MRW, false)
00073 {
00074 _setIdMap(s_def);
00075 m_container = new MRWContainer (m_io, 0);
00076 }
00077
00078 MRWFile::~MRWFile()
00079 {
00080 }
00081
00082 IFDDir::Ref MRWFile::_locateCfaIfd()
00083 {
00084
00085 if(!m_mainIfd) {
00086 m_mainIfd = _locateMainIfd();
00087 }
00088 return m_mainIfd;
00089 }
00090
00091
00092 IFDDir::Ref MRWFile::_locateMainIfd()
00093 {
00094 return m_container->setDirectory(0);
00095 }
00096
00097
00098 void MRWFile::_identifyId()
00099 {
00100 MRWContainer *mc = (MRWContainer *)m_container;
00101 if(!m_mainIfd) {
00102 m_mainIfd = _locateMainIfd();
00103 }
00104
00105 if(mc->prd) {
00106 std::string version = mc->prd->string_val(MRW::PRD_VERSION);
00107 _setTypeId(_typeIdFromModel(version));
00108 }
00109 }
00110
00111
00112
00113 ::or_error MRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
00114 {
00115 ::or_error err = OR_ERROR_NOT_FOUND;
00116 list.push_back (640);
00117 err = OR_ERROR_NONE;
00118 return err;
00119 }
00120
00121
00122 ::or_error MRWFile::_getThumbnail(uint32_t , Thumbnail & thumbnail)
00123 {
00124 IFDDir::Ref dir;
00125 IFDEntry::Ref maker_ent;
00126 IFDEntry::Ref thumb_ent;
00127 ::or_error ret = OR_ERROR_NOT_FOUND;
00128 MRWContainer *mc = (MRWContainer *)m_container;
00129
00130 dir = _locateExifIfd();
00131 if (!dir) {
00132 Trace(WARNING) << "EXIF dir not found\n";
00133 return ret;
00134 }
00135
00136 maker_ent = dir->getEntry(IFD::EXIF_TAG_MAKER_NOTE);
00137 if (!maker_ent) {
00138 Trace(WARNING) << "maker note offset entry not found\n";
00139 return ret;
00140 }
00141 uint32_t off = 0;
00142 off = maker_ent->offset();
00143
00144 IFDDir::Ref ref(new IFDDir(mc->ttw->offset() +
00145 MRW::DataBlockHeaderLength + off,
00146 *m_container));
00147 ref->load();
00148
00149 uint32_t tnail_offset = 0;
00150 uint32_t tnail_len = 0;
00151 thumb_ent = ref->getEntry(MRW::MRWTAG_THUMBNAIL);
00152 if (thumb_ent) {
00153 tnail_offset = thumb_ent->offset();
00154 tnail_len = thumb_ent->count();
00155 }
00156 else if(ref->getValue(MRW::MRWTAG_THUMBNAIL_OFFSET, tnail_offset)) {
00157 if(!ref->getValue(MRW::MRWTAG_THUMBNAIL_LENGTH, tnail_len)) {
00158 Trace(WARNING) << "thumbnail lenght entry not found\n";
00159 return ret;
00160 }
00161 }
00162 else
00163 {
00164 Trace(WARNING) << "thumbnail offset entry not found\n";
00165 return ret;
00166 }
00167
00168 Trace(DEBUG1) << "thumbnail offset found, "
00169 << " offset == " << tnail_offset << " count == "
00170 << tnail_len << "\n";
00171 void *p = thumbnail.allocData (tnail_len);
00172 size_t fetched = m_container->fetchData(p, mc->ttw->offset()
00173 + MRW::DataBlockHeaderLength
00174 + tnail_offset,
00175 tnail_len);
00176 if (fetched != tnail_len) {
00177 Trace(WARNING) << "Unable to fetch all thumbnail data: "
00178 << fetched << " not " << tnail_len
00179 << " bytes\n";
00180 }
00181
00182 ((unsigned char *)p)[0] = 0xFF;
00183
00184 thumbnail.setDataType (OR_DATA_TYPE_JPEG);
00185 thumbnail.setDimensions (640, 480);
00186 return OR_ERROR_NONE;
00187 }
00188
00189
00190 ::or_error MRWFile::_getRawData(RawData & data, uint32_t options)
00191 {
00192 MRWContainer *mc = (MRWContainer *)m_container;
00193
00194 if(!mc->prd) {
00195 return OR_ERROR_NOT_FOUND;
00196 }
00197
00198 uint16_t y = mc->prd->uint16_val (MRW::PRD_SENSOR_LENGTH);
00199 uint16_t x = mc->prd->uint16_val (MRW::PRD_SENSOR_WIDTH);
00200 uint8_t bpc = mc->prd->uint8_val (MRW::PRD_PIXEL_SIZE);
00201
00202 bool is_compressed = (mc->prd->uint8_val(MRW::PRD_STORAGE_TYPE) == 0x59);
00203
00204
00205
00206
00207 uint32_t finaldatalen = 2 * x * y;
00208 uint32_t datalen =
00209 (is_compressed ? x * y + ((x * y) >> 1) : finaldatalen);
00210
00211 if(options & OR_OPTIONS_DONT_DECOMPRESS) {
00212 finaldatalen = datalen;
00213 }
00214 if(is_compressed && (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00215 data.setDataType (OR_DATA_TYPE_COMPRESSED_CFA);
00216 }
00217 else {
00218 data.setDataType (OR_DATA_TYPE_CFA);
00219 }
00220 data.setBpc(bpc);
00221
00222 data.setMax(0xf7d);
00223 Trace(DEBUG1) << "datalen = " << datalen <<
00224 " final datalen = " << finaldatalen << "\n";
00225 void *p = data.allocData(finaldatalen);
00226 size_t fetched = 0;
00227 off_t offset = mc->pixelDataOffset();
00228 if(!is_compressed || (options & OR_OPTIONS_DONT_DECOMPRESS)) {
00229 fetched = m_container->fetchData (p, offset, datalen);
00230 }
00231 else {
00232 Unpack unpack(x, IFD::COMPRESS_NONE);
00233 size_t blocksize = unpack.block_size();
00234 boost::scoped_array<uint8_t> block(new uint8_t[blocksize]);
00235 uint8_t * outdata = (uint8_t*)data.data();
00236 size_t got;
00237 do {
00238 Trace(DEBUG2) << "fatchData @offset " << offset << "\n";
00239 got = m_container->fetchData (block.get(),
00240 offset, blocksize);
00241 fetched += got;
00242 offset += got;
00243 Trace(DEBUG2) << "got " << got << "\n";
00244 if(got) {
00245 size_t out = unpack.unpack_be12to16(outdata,
00246 block.get(), got);
00247 outdata += out;
00248 Trace(DEBUG2) << "unpacked " << out
00249 << " bytes from " << got << "\n";
00250 }
00251 } while((got != 0) && (fetched < datalen));
00252 }
00253 if (fetched < datalen) {
00254 Trace(WARNING) << "Fetched only " << fetched <<
00255 " of " << datalen << ": continuing anyway.\n";
00256 }
00257 uint16_t bpat = mc->prd->uint16_val (MRW::PRD_BAYER_PATTERN);
00258 or_cfa_pattern cfa_pattern = OR_CFA_PATTERN_NONE;
00259 switch(bpat)
00260 {
00261 case 0x0001:
00262 cfa_pattern = OR_CFA_PATTERN_RGGB;
00263 break;
00264 case 0x0004:
00265 cfa_pattern = OR_CFA_PATTERN_GBRG;
00266 break;
00267 default:
00268 break;
00269 }
00270 data.setCfaPattern(cfa_pattern);
00271 data.setDimensions (x, y);
00272
00273 return OR_ERROR_NONE;
00274 }
00275
00276 }
00277 }