RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
CrwDecompressor.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2009-2014 Klaus Post
5 Copyright (C) 2014 Pedro CĂ´rte-Real
6 Copyright (C) 2015-2018 Roman Lebedev
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
10 License as published by the Free Software Foundation; either
11 version 2 of 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, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21*/
22
24#include "adt/Array1DRef.h"
25#include "adt/Array2DRef.h"
26#include "adt/Bit.h"
27#include "adt/Casts.h"
28#include "adt/Invariant.h"
29#include "adt/Optional.h"
30#include "adt/Point.h"
33#include "codes/HuffmanCode.h"
35#include "common/RawImage.h"
37#include "io/Buffer.h"
38#include <array>
39#include <cstdint>
40#include <utility>
41
42using std::array;
43
44namespace rawspeed {
45
47 RawImage img, uint32_t dec_table, Array1DRef<const uint8_t> input_,
49 : mRaw(std::move(img)), mHuff(initHuffTables(dec_table)), input(input_),
50 lowbitInput(lowbitInput_) {
51 if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 ||
52 mRaw->getBpp() != sizeof(uint16_t))
53 ThrowRDE("Unexpected component count / data type");
54
55 const uint32_t width = mRaw->dim.x;
56 const uint32_t height = mRaw->dim.y;
57
58 if (width == 0 || height == 0 || width % 4 != 0 || width > 4104 ||
59 height > 3048 || (height * width) % 64 != 0)
60 ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
61
62 if (lowbitInput) {
63 // If there are low bits, the first part (size is calculable) is low bits
64 // Each block is 4 pairs of 2 bits, so we have 1 block per 4 pixels
65 const int lBlocks = 1 * height * width / 4;
66 invariant(lBlocks > 0);
67 if (lowbitInput->size() < lBlocks)
68 ThrowRDE("Unsufficient number of low bit blocks");
70 lowbitInput->getCrop(/*offset=*/0, /*size*/ lBlocks).getAsArray1DRef();
71 }
72}
73
75 const uint8_t* values) {
76 invariant(ncpl);
77
79 auto count = hc.setNCodesPerLength(Buffer(ncpl, 16));
81
82 PrefixCodeDecoder<> ht(std::move(hc));
83 ht.setup(/*fullDecode_=*/false, false);
84 return ht;
85}
86
88 if (table > 2)
89 ThrowRDE("Wrong table number: %u", table);
90
91 // NCodesPerLength
92 static const std::array<std::array<uint8_t, 16>, 3> first_tree_ncpl = {{
93 {0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
94 {0, 2, 2, 3, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0},
95 {0, 0, 6, 3, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
96 }};
97
98 static const std::array<std::array<uint8_t, 13>, 3> first_tree_codevalues = {{
99 {0x04, 0x03, 0x05, 0x06, 0x02, 0x07, 0x01, 0x08, 0x09, 0x00, 0x0a, 0x0b,
100 0xff},
101 {0x03, 0x02, 0x04, 0x01, 0x05, 0x00, 0x06, 0x07, 0x09, 0x08, 0x0a, 0x0b,
102 0xff},
103 {0x06, 0x05, 0x07, 0x04, 0x08, 0x03, 0x09, 0x02, 0x00, 0x0a, 0x01, 0x0b,
104 0xff},
105 }};
106
107 // NCodesPerLength
108 static const std::array<std::array<uint8_t, 16>, 3> second_tree_ncpl = {{
109 {0, 2, 2, 2, 1, 4, 2, 1, 2, 5, 1, 1, 0, 0, 0, 139},
110 {0, 2, 2, 1, 4, 1, 4, 1, 3, 3, 1, 0, 0, 0, 0, 140},
111 {0, 0, 6, 2, 1, 3, 3, 2, 5, 1, 2, 2, 8, 10, 0, 117},
112 }};
113
114 static const std::array<std::array<uint8_t, 164>, 3> second_tree_codevalues =
115 {{{0x03, 0x04, 0x02, 0x05, 0x01, 0x06, 0x07, 0x08, 0x12, 0x13, 0x11, 0x14,
116 0x09, 0x15, 0x22, 0x00, 0x21, 0x16, 0x0a, 0xf0, 0x23, 0x17, 0x24, 0x31,
117 0x32, 0x18, 0x19, 0x33, 0x25, 0x41, 0x34, 0x42, 0x35, 0x51, 0x36, 0x37,
118 0x38, 0x29, 0x79, 0x26, 0x1a, 0x39, 0x56, 0x57, 0x28, 0x27, 0x52, 0x55,
119 0x58, 0x43, 0x76, 0x59, 0x77, 0x54, 0x61, 0xf9, 0x71, 0x78, 0x75, 0x96,
120 0x97, 0x49, 0xb7, 0x53, 0xd7, 0x74, 0xb6, 0x98, 0x47, 0x48, 0x95, 0x69,
121 0x99, 0x91, 0xfa, 0xb8, 0x68, 0xb5, 0xb9, 0xd6, 0xf7, 0xd8, 0x67, 0x46,
122 0x45, 0x94, 0x89, 0xf8, 0x81, 0xd5, 0xf6, 0xb4, 0x88, 0xb1, 0x2a, 0x44,
123 0x72, 0xd9, 0x87, 0x66, 0xd4, 0xf5, 0x3a, 0xa7, 0x73, 0xa9, 0xa8, 0x86,
124 0x62, 0xc7, 0x65, 0xc8, 0xc9, 0xa1, 0xf4, 0xd1, 0xe9, 0x5a, 0x92, 0x85,
125 0xa6, 0xe7, 0x93, 0xe8, 0xc1, 0xc6, 0x7a, 0x64, 0xe1, 0x4a, 0x6a, 0xe6,
126 0xb3, 0xf1, 0xd3, 0xa5, 0x8a, 0xb2, 0x9a, 0xba, 0x84, 0xa4, 0x63, 0xe5,
127 0xc5, 0xf3, 0xd2, 0xc4, 0x82, 0xaa, 0xda, 0xe4, 0xf2, 0xca, 0x83, 0xa3,
128 0xa2, 0xc3, 0xea, 0xc2, 0xe2, 0xe3, 0xff, 0xff},
129 {0x02, 0x03, 0x01, 0x04, 0x05, 0x12, 0x11, 0x06, 0x13, 0x07, 0x08, 0x14,
130 0x22, 0x09, 0x21, 0x00, 0x23, 0x15, 0x31, 0x32, 0x0a, 0x16, 0xf0, 0x24,
131 0x33, 0x41, 0x42, 0x19, 0x17, 0x25, 0x18, 0x51, 0x34, 0x43, 0x52, 0x29,
132 0x35, 0x61, 0x39, 0x71, 0x62, 0x36, 0x53, 0x26, 0x38, 0x1a, 0x37, 0x81,
133 0x27, 0x91, 0x79, 0x55, 0x45, 0x28, 0x72, 0x59, 0xa1, 0xb1, 0x44, 0x69,
134 0x54, 0x58, 0xd1, 0xfa, 0x57, 0xe1, 0xf1, 0xb9, 0x49, 0x47, 0x63, 0x6a,
135 0xf9, 0x56, 0x46, 0xa8, 0x2a, 0x4a, 0x78, 0x99, 0x3a, 0x75, 0x74, 0x86,
136 0x65, 0xc1, 0x76, 0xb6, 0x96, 0xd6, 0x89, 0x85, 0xc9, 0xf5, 0x95, 0xb4,
137 0xc7, 0xf7, 0x8a, 0x97, 0xb8, 0x73, 0xb7, 0xd8, 0xd9, 0x87, 0xa7, 0x7a,
138 0x48, 0x82, 0x84, 0xea, 0xf4, 0xa6, 0xc5, 0x5a, 0x94, 0xa4, 0xc6, 0x92,
139 0xc3, 0x68, 0xb5, 0xc8, 0xe4, 0xe5, 0xe6, 0xe9, 0xa2, 0xa3, 0xe3, 0xc2,
140 0x66, 0x67, 0x93, 0xaa, 0xd4, 0xd5, 0xe7, 0xf8, 0x88, 0x9a, 0xd7, 0x77,
141 0xc4, 0x64, 0xe2, 0x98, 0xa5, 0xca, 0xda, 0xe8, 0xf3, 0xf6, 0xa9, 0xb2,
142 0xb3, 0xf2, 0xd2, 0x83, 0xba, 0xd3, 0xff, 0xff},
143 {0x04, 0x05, 0x03, 0x06, 0x02, 0x07, 0x01, 0x08, 0x09, 0x12, 0x13, 0x14,
144 0x11, 0x15, 0x0a, 0x16, 0x17, 0xf0, 0x00, 0x22, 0x21, 0x18, 0x23, 0x19,
145 0x24, 0x32, 0x31, 0x25, 0x33, 0x38, 0x37, 0x34, 0x35, 0x36, 0x39, 0x79,
146 0x57, 0x58, 0x59, 0x28, 0x56, 0x78, 0x27, 0x41, 0x29, 0x77, 0x26, 0x42,
147 0x76, 0x99, 0x1a, 0x55, 0x98, 0x97, 0xf9, 0x48, 0x54, 0x96, 0x89, 0x47,
148 0xb7, 0x49, 0xfa, 0x75, 0x68, 0xb6, 0x67, 0x69, 0xb9, 0xb8, 0xd8, 0x52,
149 0xd7, 0x88, 0xb5, 0x74, 0x51, 0x46, 0xd9, 0xf8, 0x3a, 0xd6, 0x87, 0x45,
150 0x7a, 0x95, 0xd5, 0xf6, 0x86, 0xb4, 0xa9, 0x94, 0x53, 0x2a, 0xa8, 0x43,
151 0xf5, 0xf7, 0xd4, 0x66, 0xa7, 0x5a, 0x44, 0x8a, 0xc9, 0xe8, 0xc8, 0xe7,
152 0x9a, 0x6a, 0x73, 0x4a, 0x61, 0xc7, 0xf4, 0xc6, 0x65, 0xe9, 0x72, 0xe6,
153 0x71, 0x91, 0x93, 0xa6, 0xda, 0x92, 0x85, 0x62, 0xf3, 0xc5, 0xb2, 0xa4,
154 0x84, 0xba, 0x64, 0xa5, 0xb3, 0xd2, 0x81, 0xe5, 0xd3, 0xaa, 0xc4, 0xca,
155 0xf2, 0xb1, 0xe4, 0xd1, 0x83, 0x63, 0xea, 0xc3, 0xe2, 0x82, 0xf1, 0xa3,
156 0xc2, 0xa1, 0xc1, 0xe3, 0xa2, 0xe1, 0xff, 0xff}}};
157
158 std::array<PrefixCodeDecoder<>, 2> mHuff = {
159 {makeDecoder(first_tree_ncpl[table].data(),
160 first_tree_codevalues[table].data()),
161 makeDecoder(second_tree_ncpl[table].data(),
162 second_tree_codevalues[table].data())}};
163
164 return mHuff;
165}
166
167inline void CrwDecompressor::decodeBlock(std::array<int16_t, 64>* diffBuf,
168 const crw_hts& mHuff,
169 BitStreamerJPEG& bs) {
170 invariant(diffBuf);
171
172 // decode the block
173 for (int i = 0; i < 64;) {
174 bs.fill(32);
175
176 const auto codeValue =
177 implicit_cast<uint8_t>(mHuff[i > 0].decodeCodeValue(bs));
178 const int len = codeValue & 0b1111;
179 const int index = codeValue >> 4;
180 invariant(len >= 0 && index >= 0);
181
182 if (len == 0 && index == 0 && i)
183 break;
184
185 if (len == 0xf && index == 0xf) {
186 ++i;
187 continue;
188 }
189
190 i += index;
191
192 if (len == 0) {
193 ++i;
194 continue;
195 }
196
197 int diff = bs.getBitsNoFill(len);
198
199 if (i >= 64)
200 break;
201
202 diff = PrefixCodeDecoder<>::extend(diff, len);
203
204 (*diffBuf)[i] = implicit_cast<int16_t>(diff);
205 ++i;
206 }
207}
208
209// FIXME: this function is horrible.
211 const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
212 invariant(out.width() > 0);
213 invariant(out.width() % 4 == 0);
214 invariant(out.height() > 0);
215
216 {
217 // Each block encodes 64 pixels
218
219 invariant((out.height() * out.width()) % 64 == 0);
220 const unsigned hBlocks = out.height() * out.width() / 64;
221 invariant(hBlocks > 0);
222
224
225 int carry = 0;
226 std::array<int, 2> base = {512, 512}; // starting predictors
227
228 int row = 0;
229 int col = 0;
230
231 for (unsigned block = 0; block < hBlocks; block++) {
232 array<int16_t, 64> diffBuf = {{}};
233 decodeBlock(&diffBuf, mHuff, bs);
234
235 // predict and output the block
236
237 diffBuf[0] += carry;
238 carry = diffBuf[0];
239
240 for (uint32_t k = 0; k < 64; ++k) {
241 if (col == out.width()) {
242 // new line. sadly, does not always happen when k == 0.
243 col = 0;
244 row++;
245 base = {512, 512}; // reinit.
246 }
247
248 base[k & 1] += diffBuf[k];
249
250 if (!isIntN(base[k & 1], 10))
251 ThrowRDE("Error decompressing");
252
253 out(row, col) = implicit_cast<uint16_t>(base[k & 1]);
254 ++col;
255 }
256 }
257 invariant(row == (out.height() - 1));
258 invariant(col == out.width());
259 }
260
261 // Add the uncompressed 2 low bits to the decoded 8 high bits
262 if (lowbitInput) {
263 Array2DRef lowbits(*lowbitInput, out.width() / 4, out.height(),
264 out.width() / 4);
265 for (int row = 0; row < out.height(); row++) {
266 for (int col = 0; col < out.width(); /* NOTE: col += 4 */) {
267 invariant(col % 4 == 0);
268 const uint8_t c = lowbits(row, col / 4);
269 // LSB-packed: p3 << 6 | p2 << 4 | p1 << 2 | p0 << 0
270
271 // We have read 8 bits, which is 4 pairs of 2 bits. So process 4 pixels.
272 for (uint32_t p = 0; p < 4; ++p, ++col) {
273 uint16_t& pixel = out(row, col);
274
275 uint16_t low = (c >> (2 * p)) & 0b11;
276 auto val = implicit_cast<uint16_t>((pixel << 2) | low);
277
278 if (out.width() == 2672 && val < 512)
279 val += 2; // No idea why this is needed
280
281 pixel = val;
282 }
283 }
284 }
285 }
286}
287
288} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRDE(...)
static int RAWSPEED_READNONE extend(uint32_t diff, uint32_t len)
int RAWSPEED_READONLY height() const
int RAWSPEED_READONLY width() const
uint32_t getBitsNoFill(int nbits)
void fill(int nbits=Cache::MaxGetBits)
std::array< PrefixCodeDecoder<>, 2 > crw_hts
CrwDecompressor(RawImage img, uint32_t dec_table_, Array1DRef< const uint8_t > input, Optional< Array1DRef< const uint8_t > > lowbitInput)
static void decodeBlock(std::array< int16_t, 64 > *diffBuf, const crw_hts &mHuff, BitStreamerJPEG &bs)
static crw_hts initHuffTables(uint32_t table)
Array1DRef< const uint8_t > input
static PrefixCodeDecoder makeDecoder(const uint8_t *ncpl, const uint8_t *values)
Optional< Array1DRef< const uint8_t > > lowbitInput
uint32_t setNCodesPerLength(Buffer data)
Definition HuffmanCode.h:99
void setCodeValues(Array1DRef< const typename Traits::CodeValueTy > data)
void setup(bool fullDecode_, bool fixDNGBug16_)
PrefixCodeLUTDecoder< CodeTag, PrefixCodeLookupDecoder< CodeTag > > PrefixCodeDecoder
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
constexpr bool RAWSPEED_READNONE isIntN(T value, unsigned int nBits)
Definition Bit.h:87