libopenraw  0.3.7
rawdata.cpp
1 /*
2  * libopenraw - rawdata.cpp
3  *
4  * Copyright (C) 2007-2019 Hubert Figuiere
5  * Copyright (C) 2008 Novell, Inc.
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 #include <stddef.h>
23 #include <string.h>
24 #include <algorithm>
25 #include <cassert>
26 #include <cstdint>
27 #include <vector>
28 
29 #include <libopenraw/consts.h>
30 #include <libopenraw/debug.h>
31 
32 #include "bitmapdata.hpp"
33 #include "rawdata.hpp"
34 #include "mosaicinfo.hpp"
35 #include "rawfile.hpp"
36 #include "render/bimedian_demosaic.hpp"
37 #include "render/grayscale.hpp"
38 #include "trace.hpp"
39 
40 namespace OpenRaw {
41 
42 static const int MAX_MATRIX_SIZE = 12;
43 
45 public:
46  RawData *self;
47  uint16_t blackLevel, whiteLevel;
49  uint32_t activeAreaX;
50  uint32_t activeAreaY;
51  uint32_t activeAreaW;
52  uint32_t activeAreaH;
53  ExifPhotometricInterpretation photometricInterpretation;
54  const MosaicInfo* mosaic_info; // IMMUTABLE
55  uint32_t compression;
56  uint8_t *pos;
57  size_t offset;
58  size_t row_offset;
59  uint8_t slice;
60  uint32_t sliceWidth;
61  uint32_t sliceOffset;
63  std::vector<uint16_t> slices;
65  double colourMatrix[MAX_MATRIX_SIZE];
66  uint32_t colourMatrixCount;
67  double colourMatrix2[MAX_MATRIX_SIZE];
68  uint32_t colourMatrix2Count;
69 
70  Private(RawData *_self)
71  : self(_self)
72  , blackLevel(0), whiteLevel(0)
73  , activeAreaX(0), activeAreaY(0), activeAreaW(0), activeAreaH(0)
74  , photometricInterpretation(EV_PI_CFA)
75  , mosaic_info(MosaicInfo::twoByTwoPattern(OR_CFA_PATTERN_NONE))
76  , compression(0)
77  , pos(NULL), offset(0)
78  , row_offset(0)
79  , slice(0), sliceWidth(0)
80  , sliceOffset(0), slices()
81  , colourMatrixCount(0)
82  , colourMatrix2Count(0)
83  {
84  memset(colourMatrix, 0, sizeof(colourMatrix));
85  memset(colourMatrix2, 0, sizeof(colourMatrix2));
86  }
87  void advance(size_t s);
88  void nextSlice();
89  void nextRow();
90 private:
91  Private(const Private &);
92  Private & operator=(const Private &);
93 };
94 
95 
96 RawData *
97 RawData::getAndExtractRawData(const char* filename, uint32_t options,
98  or_error & err)
99 {
100  err = OR_ERROR_NONE;
101  RawData *rawdata = NULL;
102 
103  RawFile *file = RawFile::newRawFile(filename);
104  if (file) {
105  rawdata = new RawData();
106  err = file->getRawData(*rawdata, options);
107  delete file;
108  }
109  else {
110  err = OR_ERROR_CANT_OPEN; // file error
111  }
112  return rawdata;
113 }
114 
115 
116 RawData::RawData()
117  : BitmapData(),
118  d(new RawData::Private(this))
119 {
120 
121 }
122 
123 
124 RawData::~RawData()
125 {
126  delete d;
127 }
128 
129 // rendering
130 
131 ::or_error RawData::getRenderedImage(BitmapData & bitmapdata, uint32_t /*options*/)
132 {
133  uint32_t _x, _y, out_x, out_y;
134  uint16_t *src;
135 
136  if(dataType() != OR_DATA_TYPE_RAW) {
137  LOGDBG1("wrong data type\n");
139  }
140  if(d->photometricInterpretation != EV_PI_CFA &&
141  d->photometricInterpretation != EV_PI_LINEAR_RAW) {
142  LOGDBG1("only CFA or LinearRaw are supported.\n");
144  }
145 
146  _x = width();
147  _y = height();
148 
149  /*
150  rawdata.linearize();
151  rawdata.subtractBlack();
152  rawdata.rescale();
153  rawdata.clip();
154  */
155  src = (uint16_t*)data();
156 
157  or_error err = OR_ERROR_NONE;
158 
159  if (d->photometricInterpretation == EV_PI_CFA) {
161  auto mosaic_info = mosaicInfo();
162  if (mosaic_info) {
163  pattern = mosaic_info->patternType();
164  }
165  /* figure out how the demosaic can be plugged for a different
166  * algorithm */
168  uint16_t *dst = (uint16_t *)bitmapdata.allocData(sizeof(uint16_t) * 3 * _x * _y);
169  err = bimedian_demosaic(src, _x, _y, pattern, dst, out_x, out_y);
170  bitmapdata.setDimensions(out_x, out_y);
171 
172  // correct colour using the colour matrices
173  // TODO
174  }
175  else {
177  uint16_t *dst = (uint16_t *)bitmapdata.allocData(sizeof(uint16_t)
178  * 3 * _x * _y);
179 
180  err = grayscale_to_rgb(src, _x, _y, dst);
181  bitmapdata.setDimensions(_x, _y);
182  }
183 
184  return err;
185 }
186 
187 // other
188 
189 uint16_t RawData::blackLevel() const
190 {
191  return d->blackLevel;
192 }
193 
194 uint16_t RawData::whiteLevel() const
195 {
196  return d->whiteLevel;
197 }
198 
199 void RawData::setBlackLevel(uint16_t m)
200 {
201  d->blackLevel = m;
202 }
203 
204 void RawData::setWhiteLevel(uint16_t m)
205 {
206  d->whiteLevel = m;
207 }
208 
209 uint32_t RawData::activeAreaX() const
210 {
211  return d->activeAreaX;
212 }
213 
214 uint32_t RawData::activeAreaY() const
215 {
216  return d->activeAreaY;
217 }
218 
219 uint32_t RawData::activeAreaWidth() const
220 {
221  return d->activeAreaW;
222 }
223 
224 uint32_t RawData::activeAreaHeight() const
225 {
226  return d->activeAreaH;
227 }
228 
229 void RawData::setActiveArea(uint32_t x, uint32_t y, uint32_t w, uint32_t h)
230 {
231  d->activeAreaX = x;
232  d->activeAreaY = y;
233  d->activeAreaW = w;
234  d->activeAreaH = h;
235 }
236 
237 void RawData::setPhotometricInterpretation(ExifPhotometricInterpretation pi)
238 {
239  d->photometricInterpretation = pi;
240 }
241 
242 ExifPhotometricInterpretation RawData::getPhotometricInterpretation() const
243 {
244  return d->photometricInterpretation;
245 }
246 
247 
248 const double* RawData::getColourMatrix1(uint32_t & matrixSize) const
249 {
250  matrixSize = d->colourMatrixCount;
251  return d->colourMatrix;
252 }
253 
254 void RawData::setColourMatrix1(const double* matrix, uint32_t matrixSize)
255 {
256  if(matrixSize > MAX_MATRIX_SIZE) {
257  matrixSize = MAX_MATRIX_SIZE;
258  }
259  for(uint32_t i = 0; i < matrixSize; i++) {
260  d->colourMatrix[i] = matrix[i];
261  }
262  d->colourMatrixCount = matrixSize;
263 }
264 
265 const double* RawData::getColourMatrix2(uint32_t & matrixSize) const
266 {
267  matrixSize = d->colourMatrix2Count;
268  return d->colourMatrix2;
269 }
270 
271 void RawData::setColourMatrix2(const double* matrix, uint32_t matrixSize)
272 {
273  if(matrixSize > MAX_MATRIX_SIZE) {
274  matrixSize = MAX_MATRIX_SIZE;
275  }
276  for(uint32_t i = 0; i < matrixSize; i++) {
277  d->colourMatrix2[i] = matrix[i];
278  }
279  d->colourMatrix2Count = matrixSize;
280 }
281 
282 void RawData::swap(RawData & with)
283 {
284  BitmapData::swap(with);
285  std::swap(this->d, with.d);
286 }
287 
288 void * RawData::allocData(const size_t s)
289 {
290  void * p = BitmapData::allocData(s);
291  d->pos = (uint8_t*)p;
292  d->offset = 0;
293  return p;
294 }
295 
296 
297 void RawData::setDimensions(uint32_t x, uint32_t y)
298 {
300  // set activate area if not set, of if the new dimensions are smaller.
301  if (d->activeAreaW == 0) {
302  d->activeAreaW = x;
303  } else if (d->activeAreaW + d->activeAreaX > x) {
304  d->activeAreaW = x - d->activeAreaX;
305  }
306  if (d->activeAreaH == 0) {
307  d->activeAreaH = y;
308  } else if (d->activeAreaH + d->activeAreaY > y) {
309  d->activeAreaH = y - d->activeAreaY;
310  }
311  if (d->slices.size()) {
312  d->sliceWidth = d->slices[0];
313  }
314  else {
315  d->sliceWidth = x;
316  }
317 }
318 
319 void RawData::setSlices(const std::vector<uint16_t> & slices)
320 {
321  d->slices = slices;
322  if(slices.size()) {
323  d->sliceWidth = slices[0];
324  }
325  else {
326  d->sliceWidth = width();
327  }
328 }
329 
330 void RawData::setCfaPatternType(or_cfa_pattern t)
331 {
332  d->mosaic_info = MosaicInfo::twoByTwoPattern(t);
333 }
334 
336 {
337  return d->mosaic_info;
338 }
339 
340 void RawData::setMosaicInfo(const MosaicInfo* mosaic_info)
341 {
342  d->mosaic_info = mosaic_info;
343 }
344 
345 void RawData::setCompression(uint32_t t)
346 {
347  d->compression = t;
348 }
349 
350 uint32_t RawData::compression() const
351 {
352  return d->compression;
353 }
354 
356 {
357  assert(d->pos);
358  assert(d->offset < size());
359  *(d->pos) = c & 0xff;
360  *(d->pos + 1) = (c >> 8) & 0xff;
361  d->advance(sizeof(c));
362  return *this;
363 }
364 
365 void RawData::Private::nextRow()
366 {
367  uint32_t w = self->width() * 2;
368  uint32_t row = offset / w;
369  row++;
370  if (row == self->height()) {
371  // on the last
372  nextSlice();
373  row = 0;
374  }
375  offset = row * w + sliceOffset * 2;
376  pos = (uint8_t*)(self->data()) + offset;
377  row_offset = offset;
378 }
379 
380 void RawData::Private::nextSlice()
381 {
382  if(slices.size() > slice) {
383  sliceOffset += slices[slice];
384  slice++;
385  }
386  if(slices.size() > slice) {
387  sliceWidth = slices[slice];
388  }
389  else {
390  sliceWidth = 0;
391  }
392 }
393 
394 void RawData::Private::advance(size_t s)
395 {
396  if(offset + s - row_offset >= sliceWidth * 2) {
397  nextRow();
398  }
399  else {
400  pos += s;
401  offset += s;
402  }
403 }
404 
405 }
406 /*
407  Local Variables:
408  mode:c++
409  c-file-style:"stroustrup"
410  c-file-offsets:((innamespace . 0))
411  indent-tabs-mode:nil
412  fill-column:80
413  End:
414 */
415 
Represent some bitmap data.
Definition: bitmapdata.hpp:30
void setDataType(DataType _type)
Set the data type.
Definition: bitmapdata.cpp:91
uint32_t width() const
Width of the image data.
Definition: bitmapdata.cpp:137
uint32_t height() const
Height of the image data.
Definition: bitmapdata.cpp:142
void swap(BitmapData &with)
Swap the two objects data.
Definition: bitmapdata.cpp:81
size_t size() const
Get the size of the data.
Definition: bitmapdata.cpp:120
virtual void setDimensions(uint32_t x, uint32_t y)
Set the pixel dimensions of the bitmap.
Definition: bitmapdata.cpp:157
DataType dataType() const
Get the data type.
Definition: bitmapdata.cpp:86
Info on the mosaic for the Colour Filter Array.
Definition: mosaicinfo.hpp:33
static const MosaicInfo * twoByTwoPattern(::or_cfa_pattern)
Factory to return a singleton instance of the right pattern.
Definition: mosaicinfo.cpp:84
double colourMatrix[MAX_MATRIX_SIZE]
Definition: rawdata.cpp:65
Represent camera raw data.
Definition: rawdata.hpp:38
void swap(RawData &with)
Definition: rawdata.cpp:282
const double * getColourMatrix1(uint32_t &size) const
Definition: rawdata.cpp:248
uint32_t activeAreaX() const
Definition: rawdata.cpp:209
RawData & append(uint16_t c)
Definition: rawdata.cpp:355
const MosaicInfo * mosaicInfo() const
Definition: rawdata.cpp:335
::or_error getRenderedImage(BitmapData &bitmapdata, uint32_t options)
Definition: rawdata.cpp:131
const double * getColourMatrix2(uint32_t &size) const
Definition: rawdata.cpp:265
virtual void setDimensions(uint32_t x, uint32_t y) override
Set the pixel dimensions of the bitmap.
Definition: rawdata.cpp:297
RAW file.
Definition: rawfile.hpp:66
::or_error getRawData(RawData &rawdata, uint32_t options)
Get the RAW data.
Definition: rawfile.cpp:536
static RawFile * newRawFile(const char *_filename, Type typeHint=OR_RAWFILE_TYPE_UNKNOWN)
Factory method to create the proper RawFile instance.
Definition: rawfile.cpp:187
or_cfa_pattern
CFA pattern types.
Definition: consts.h:94
or_error
Error codes returned by libopenraw.
Definition: consts.h:42
@ OR_CFA_PATTERN_NONE
Definition: consts.h:95
@ OR_DATA_TYPE_PIXMAP_16RGB
Definition: consts.h:83
@ OR_DATA_TYPE_RAW
Definition: consts.h:87
@ OR_ERROR_CANT_OPEN
Definition: consts.h:46
@ OR_ERROR_NONE
Definition: consts.h:43
@ OR_ERROR_INVALID_FORMAT
Definition: consts.h:50
Global namespace for libopenraw.
Definition: arwfile.cpp:29