libopenraw
olympusdecompressor.cpp
1 /*
2  * libopenraw - olympusdecompressor.cpp
3  *
4  * Copyright (C) 2011-2016 Hubert Figuiere
5  * Olympus Decompression copied from RawSpeed
6  * Copyright (C) 2009 Klaus Post
7  *
8  * This library is free software: you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation, either version 3 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see
20  * <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include <algorithm>
27 
28 #include "rawdata.hpp"
29 #include "olympusdecompressor.hpp"
30 #include "bititerator.hpp"
31 
32 namespace OpenRaw {
33 namespace Internals {
34 
35 static void decompressOlympus(const uint8_t* buffer, size_t size, uint8_t* data,
36  uint32_t w, uint32_t h);
37 
38 // decompression ported from RawSpeed.
39 static void decompressOlympus(const uint8_t* buffer, size_t size, uint8_t* data,
40  uint32_t w, uint32_t h)
41 {
42  int nbits, sign, low, high, i, wo0, n, nw0, wo1, nw1;
43  int acarry0[3], acarry1[3], pred, diff;
44 
45  int pitch = w * 2; //(((w * 2/*bpp*/) + 15) / 16) * 16; // TODO make that
46  //part of the outer datas
47 
48  /* Build a table to quickly look up "high" value */
49  char bittable[4096];
50  for (i = 0; i < 4096; i++) {
51  int b = i;
52  for (high = 0; high < 12; high++) {
53  if ((b >> (11 - high)) & 1) {
54  break;
55  }
56  }
57  bittable[i] = high;
58  }
59  wo0 = nw0 = wo1 = nw1 = 0;
60  buffer += 7;
61 
62  BitIterator bits(buffer, size - 7);
63 
64  for (uint32_t y = 0; y < h; y++) {
65  memset(acarry0, 0, sizeof acarry0);
66  memset(acarry1, 0, sizeof acarry1);
67  uint16_t* dest = (uint16_t*)&data[y * pitch];
68  for (uint32_t x = 0; x < w; x++) {
69  // bits.checkPos();
70  // bits.fill();
71  i = 2 * (acarry0[2] < 3);
72  for (nbits = 2 + i; (uint16_t)acarry0[0] >> (nbits + i); nbits++) {
73  }
74 
75  uint32_t b = bits.peek(15);
76  sign = (b >> 14) * -1;
77  low = (b >> 12) & 3;
78  high = bittable[b & 4095];
79  // Skip bits used above.
80  bits.skip(std::min(12 + 3, high + 1 + 3));
81 
82  if (high == 12) {
83  high = bits.get(16 - nbits) >> 1;
84  }
85 
86  acarry0[0] = (high << nbits) | bits.get(nbits);
87  diff = (acarry0[0] ^ sign) + acarry0[1];
88  acarry0[1] = (diff * 3 + acarry0[1]) >> 5;
89  acarry0[2] = acarry0[0] > 16 ? 0 : acarry0[2] + 1;
90 
91  if (y < 2 || x < 2) {
92  if (y < 2 && x < 2) {
93  pred = 0;
94  } else if (y < 2) {
95  pred = wo0;
96  } else {
97  pred = dest[-pitch + ((int)x)];
98  nw0 = pred;
99  }
100  dest[x] = pred + ((diff << 2) | low);
101  // Set predictor
102  wo0 = dest[x];
103  } else {
104  n = dest[-pitch + ((int)x)];
105  if (((wo0 < nw0) & (nw0 < n)) | ((n < nw0) & (nw0 < wo0))) {
106  if (abs(wo0 - nw0) > 32 || abs(n - nw0) > 32) {
107  pred = wo0 + n - nw0;
108  } else {
109  pred = (wo0 + n) >> 1;
110  }
111  } else {
112  pred = abs(wo0 - nw0) > abs(n - nw0) ? wo0 : n;
113  }
114 
115  dest[x] = pred + ((diff << 2) | low);
116  // Set predictors
117  wo0 = dest[x];
118  nw0 = n;
119  }
120  // _ASSERTE(0 == dest[x] >> 12) ;
121 
122  // ODD PIXELS
123  x += 1;
124  // bits.checkPos();
125  // bits.fill();
126  i = 2 * (acarry1[2] < 3);
127  for (nbits = 2 + i; (uint16_t)acarry1[0] >> (nbits + i); nbits++) {
128  }
129  b = bits.peek(15);
130  sign = (b >> 14) * -1;
131  low = (b >> 12) & 3;
132  high = bittable[b & 4095];
133  // Skip bits used above.
134  bits.skip(std::min(12 + 3, high + 1 + 3));
135 
136  if (high == 12) {
137  high = bits.get(16 - nbits) >> 1;
138  }
139 
140  acarry1[0] = (high << nbits) | bits.get(nbits);
141  diff = (acarry1[0] ^ sign) + acarry1[1];
142  acarry1[1] = (diff * 3 + acarry1[1]) >> 5;
143  acarry1[2] = acarry1[0] > 16 ? 0 : acarry1[2] + 1;
144 
145  if (y < 2 || x < 2) {
146  if (y < 2 && x < 2) {
147  pred = 0;
148  } else if (y < 2) {
149  pred = wo1;
150  } else {
151  pred = dest[-pitch + ((int)x)];
152  nw1 = pred;
153  }
154  dest[x] = pred + ((diff << 2) | low);
155  // Set predictor
156  wo1 = dest[x];
157  } else {
158  n = dest[-pitch + ((int)x)];
159  if (((wo1 < nw1) & (nw1 < n)) | ((n < nw1) & (nw1 < wo1))) {
160  if (abs(wo1 - nw1) > 32 || abs(n - nw1) > 32) {
161  pred = wo1 + n - nw1;
162  } else {
163  pred = (wo1 + n) >> 1;
164  }
165  } else {
166  pred = abs(wo1 - nw1) > abs(n - nw1) ? wo1 : n;
167  }
168 
169  dest[x] = pred + ((diff << 2) | low);
170 
171  // Set predictors
172  wo1 = dest[x];
173  nw1 = n;
174  }
175  // _ASSERTE(0 == dest[x] >> 12) ;
176  }
177  }
178 }
179 
181 {
182  RawDataPtr output(new RawData);
183 
184  output->allocData(m_w * m_h * 2);
185  decompressOlympus(m_buffer, m_size, (uint8_t*)output->data(), m_w, m_h);
186 
187  // hardcoded 12bits values
188  output->setBpc(12);
189  output->setWhiteLevel((1 << 12) - 1);
190 
191  return output;
192 }
193 
194 }
195 }
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
Definition: arwfile.cpp:30
virtual RawDataPtr decompress() override