libopenraw
mrwfile.cpp
1 /*
2  * libopenraw - mrwfile.cpp
3  *
4  * Copyright (C) 2006,2008 Hubert Figuiere
5  * Copyright (C) 2008 Bradley Broom
6  *
7  * This library is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation, either version 3 of
10  * the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see
19  * <http://www.gnu.org/licenses/>.
20  */
21 
22 
23 #include <iostream>
24 #include <boost/scoped_array.hpp>
25 #include <libopenraw/libopenraw.h>
26 #include <libopenraw++/thumbnail.h>
27 #include <libopenraw++/rawdata.h>
28 
29 #include "trace.h"
30 #include "io/stream.h"
31 #include "io/file.h"
32 #include "mrwcontainer.h"
33 #include "ifd.h"
34 #include "mrwfile.h"
35 #include "unpack.h"
36 
37 using namespace Debug;
38 
39 namespace OpenRaw {
40 
41 
42  namespace Internals {
43 
44  const struct IFDFile::camera_ids_t MRWFile::s_def[] = {
45  { "21860002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
46  OR_TYPEID_MINOLTA_MAXXUM_5D) },
47  { "21810002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
48  OR_TYPEID_MINOLTA_MAXXUM_7D) },
49  { "27730001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
50  OR_TYPEID_MINOLTA_DIMAGE5) },
51  { "27660001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
52  OR_TYPEID_MINOLTA_DIMAGE7) },
53  { "27790001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
54  OR_TYPEID_MINOLTA_DIMAGE7I) },
55  { "27780001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
56  OR_TYPEID_MINOLTA_DIMAGE7HI) },
57  { "27820001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
58  OR_TYPEID_MINOLTA_A1) },
59  { "27200001", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
60  OR_TYPEID_MINOLTA_A2) },
61  { "27470002", OR_MAKE_FILE_TYPEID(OR_TYPEID_VENDOR_MINOLTA,
62  OR_TYPEID_MINOLTA_A200) },
63  { 0, 0 }
64  };
65 
66  RawFile *MRWFile::factory(IO::Stream *_f)
67  {
68  return new MRWFile(_f);
69  }
70 
71  MRWFile::MRWFile(IO::Stream* _f)
72  : IFDFile(_f, OR_RAWFILE_TYPE_MRW, false)
73  {
74  _setIdMap(s_def);
75  m_container = new MRWContainer (m_io, 0);
76  }
77 
78  MRWFile::~MRWFile()
79  {
80  }
81 
82  IFDDir::Ref MRWFile::_locateCfaIfd()
83  {
84  // in MRW the CFA IFD is the main IFD
85  if(!m_mainIfd) {
86  m_mainIfd = _locateMainIfd();
87  }
88  return m_mainIfd;
89  }
90 
91 
92  IFDDir::Ref MRWFile::_locateMainIfd()
93  {
94  return m_container->setDirectory(0);
95  }
96 
97 
98  void MRWFile::_identifyId()
99  {
100  MRWContainer *mc = (MRWContainer *)m_container;
101  if(!m_mainIfd) {
102  m_mainIfd = _locateMainIfd();
103  }
104 
105  if(mc->prd) {
106  std::string version = mc->prd->string_val(MRW::PRD_VERSION);
107  _setTypeId(_typeIdFromModel(version));
108  }
109  }
110 
111 
112  /* This code only knows about Dimage 5/7, in which the thumbnail position is special. */
113  ::or_error MRWFile::_enumThumbnailSizes(std::vector<uint32_t> &list)
114  {
115  ::or_error err = OR_ERROR_NOT_FOUND;
116  list.push_back (640);
117  err = OR_ERROR_NONE;
118  return err;
119  }
120 
121  /* This code only knows about Dimage 5/7, in which the thumbnail position is special. */
122  ::or_error MRWFile::_getThumbnail(uint32_t /*size*/, Thumbnail & thumbnail)
123  {
124  IFDDir::Ref dir;
125  IFDEntry::Ref maker_ent; /* Make note directory entry. */
126  IFDEntry::Ref thumb_ent; /* Thumbnail data directory entry. */
127  ::or_error ret = OR_ERROR_NOT_FOUND;
129 
130  dir = _locateExifIfd();
131  if (!dir) {
132  Trace(WARNING) << "EXIF dir not found\n";
133  return ret;
134  }
135 
136  maker_ent = dir->getEntry(IFD::EXIF_TAG_MAKER_NOTE);
137  if (!maker_ent) {
138  Trace(WARNING) << "maker note offset entry not found\n";
139  return ret;
140  }
141  uint32_t off = 0;
142  off = maker_ent->offset();
143 
144  IFDDir::Ref ref(new IFDDir(mc->ttw->offset() +
145  MRW::DataBlockHeaderLength + off,
146  *m_container));
147  ref->load();
148 
149  uint32_t tnail_offset = 0;
150  uint32_t tnail_len = 0;
151  thumb_ent = ref->getEntry(MRW::MRWTAG_THUMBNAIL);
152  if (thumb_ent) {
153  tnail_offset = thumb_ent->offset();
154  tnail_len = thumb_ent->count();
155  }
156  else if(ref->getValue(MRW::MRWTAG_THUMBNAIL_OFFSET, tnail_offset)) {
157  if(!ref->getValue(MRW::MRWTAG_THUMBNAIL_LENGTH, tnail_len)) {
158  Trace(WARNING) << "thumbnail lenght entry not found\n";
159  return ret;
160  }
161  }
162  else
163  {
164  Trace(WARNING) << "thumbnail offset entry not found\n";
165  return ret;
166  }
167 
168  Trace(DEBUG1) << "thumbnail offset found, "
169  << " offset == " << tnail_offset << " count == "
170  << tnail_len << "\n";
171  void *p = thumbnail.allocData (tnail_len);
172  size_t fetched = m_container->fetchData(p, mc->ttw->offset()
173  + MRW::DataBlockHeaderLength
174  + tnail_offset,
175  tnail_len);
176  if (fetched != tnail_len) {
177  Trace(WARNING) << "Unable to fetch all thumbnail data: "
178  << fetched << " not " << tnail_len
179  << " bytes\n";
180  }
181  /* Need to patch first byte. */
182  ((unsigned char *)p)[0] = 0xFF;
183 
184  thumbnail.setDataType (OR_DATA_TYPE_JPEG);
185  thumbnail.setDimensions (640, 480);
186  return OR_ERROR_NONE;
187  }
188 
189 
190  ::or_error MRWFile::_getRawData(RawData & data, uint32_t options)
191  {
193 
194  if(!mc->prd) {
195  return OR_ERROR_NOT_FOUND;
196  }
197  /* Obtain sensor dimensions from PRD block. */
198  uint16_t y = mc->prd->uint16_val (MRW::PRD_SENSOR_LENGTH);
199  uint16_t x = mc->prd->uint16_val (MRW::PRD_SENSOR_WIDTH);
200  uint8_t bpc = mc->prd->uint8_val (MRW::PRD_PIXEL_SIZE);
201 
202  bool is_compressed = (mc->prd->uint8_val(MRW::PRD_STORAGE_TYPE) == 0x59);
203  /* Allocate space for and retrieve pixel data.
204  * Currently only for cameras that don't compress pixel data.
205  */
206  /* Set pixel array parameters. */
207  uint32_t finaldatalen = 2 * x * y;
208  uint32_t datalen =
209  (is_compressed ? x * y + ((x * y) >> 1) : finaldatalen);
210 
211  if(options & OR_OPTIONS_DONT_DECOMPRESS) {
212  finaldatalen = datalen;
213  }
214  if(is_compressed && (options & OR_OPTIONS_DONT_DECOMPRESS)) {
215  data.setDataType (OR_DATA_TYPE_COMPRESSED_CFA);
216  }
217  else {
218  data.setDataType (OR_DATA_TYPE_CFA);
219  }
220  data.setBpc(bpc);
221  // this seems to be the hardcoded value.
222  data.setMax(0xf7d);
223  Trace(DEBUG1) << "datalen = " << datalen <<
224  " final datalen = " << finaldatalen << "\n";
225  void *p = data.allocData(finaldatalen);
226  size_t fetched = 0;
227  off_t offset = mc->pixelDataOffset();
228  if(!is_compressed || (options & OR_OPTIONS_DONT_DECOMPRESS)) {
229  fetched = m_container->fetchData (p, offset, datalen);
230  }
231  else {
232  Unpack unpack(x, IFD::COMPRESS_NONE);
233  size_t blocksize = unpack.block_size();
234  boost::scoped_array<uint8_t> block(new uint8_t[blocksize]);
235  uint8_t * outdata = (uint8_t*)data.data();
236  size_t got;
237  do {
238  Trace(DEBUG2) << "fatchData @offset " << offset << "\n";
239  got = m_container->fetchData (block.get(),
240  offset, blocksize);
241  fetched += got;
242  offset += got;
243  Trace(DEBUG2) << "got " << got << "\n";
244  if(got) {
245  size_t out = unpack.unpack_be12to16(outdata,
246  block.get(), got);
247  outdata += out;
248  Trace(DEBUG2) << "unpacked " << out
249  << " bytes from " << got << "\n";
250  }
251  } while((got != 0) && (fetched < datalen));
252  }
253  if (fetched < datalen) {
254  Trace(WARNING) << "Fetched only " << fetched <<
255  " of " << datalen << ": continuing anyway.\n";
256  }
257  uint16_t bpat = mc->prd->uint16_val (MRW::PRD_BAYER_PATTERN);
258  or_cfa_pattern cfa_pattern = OR_CFA_PATTERN_NONE;
259  switch(bpat)
260  {
261  case 0x0001:
262  cfa_pattern = OR_CFA_PATTERN_RGGB;
263  break;
264  case 0x0004:
265  cfa_pattern = OR_CFA_PATTERN_GBRG;
266  break;
267  default:
268  break;
269  }
270  data.setCfaPattern(cfa_pattern);
271  data.setDimensions (x, y);
272 
273  return OR_ERROR_NONE;
274  }
275 
276  }
277 }
virtual ::or_error _getThumbnail(uint32_t size, Thumbnail &thumbnail)
Definition: mrwfile.cpp:122
IFDFileContainer * m_container
Definition: ifdfile.h:95
size_t fetchData(void *buf, const off_t offset, const size_t buf_size)
virtual void setDimensions(uint32_t x, uint32_t y)
Definition: rawdata.cpp:132
void _setTypeId(TypeId _type_id)
Definition: rawfile.cpp:304
virtual void setDimensions(uint32_t x, uint32_t y)
Definition: bitmapdata.cpp:148
void setBpc(uint32_t _bpc)
Definition: bitmapdata.cpp:154
virtual ::or_error _enumThumbnailSizes(std::vector< uint32_t > &list)
Definition: mrwfile.cpp:113
void setDataType(DataType _type)
Definition: bitmapdata.cpp:92
size_t unpack_be12to16(uint8_t *dest, const uint8_t *src, size_t size)
Definition: unpack.cpp:56
base virtual class for IO
Definition: stream.h:40
boost::shared_ptr< IFDEntry > Ref
Definition: ifdentry.h:122
virtual ::or_error _getRawData(RawData &data, uint32_t options)
Definition: mrwfile.cpp:190