1 /*
2     RawSpeed - RAW file decoder.
3 
4     Copyright (C) 2018 Stefan Löffler
5     Copyright (C) 2018-2019 Roman Lebedev
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
9     License as published by the Free Software Foundation; either
10     version 2 of 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, write to the Free Software
19     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
22 /*
23   This is a decompressor for VC-5 raw compression algo, as used in GoPro raws.
24   This implementation is similar to that one of the official reference
25   implementation of the https://github.com/gopro/gpr project, and is producing
26   bitwise-identical output as compared with the Adobe DNG Converter
27   implementation.
28  */
29 
30 #include "rawspeedconfig.h" // for HAVE_OPENMP
31 #include "decompressors/VC5Decompressor.h"
32 #include "common/Array2DRef.h"            // for Array2DRef
33 #include "common/Common.h"                // for clampBits, roundUpDivision
34 #include "common/Optional.h"              // for Optional
35 #include "common/Point.h"                 // for iPoint2D
36 #include "common/RawspeedException.h"     // for RawspeedException
37 #include "common/SimpleLUT.h"             // for SimpleLUT, SimpleLUT<>::va...
38 #include "decoders/RawDecoderException.h" // for ThrowRDE
39 #include "io/Endianness.h"                // for Endianness, Endianness::big
40 #include <cassert>                        // for assert
41 #include <cmath>                          // for pow
42 #include <initializer_list>               // for initializer_list
43 #include <limits>                         // for numeric_limits
44 #include <string>                         // for string
45 #include <utility>                        // for move
46 
47 namespace {
48 
49 // Definitions needed by table17.inc
50 // Taken from
51 // https://github.com/gopro/gpr/blob/a513701afce7b03173213a2f67dfd9dd28fa1868/source/lib/vc5_decoder/vlc.h
52 struct RLV {
53   uint_fast8_t size; //!< Size of code word in bits
54   uint32_t bits;     //!< Code word bits right justified
55   uint16_t count;    //!< Run length
56   uint16_t value;    //!< Run value (unsigned)
57 };
58 #define RLVTABLE(n)                                                            \
59   struct {                                                                     \
60     const uint32_t length;                                                     \
61     const RLV entries[n];                                                      \
62   } constexpr
63 #include "gopro/vc5/table17.inc"
64 
decompand(int16_t val)65 constexpr int16_t decompand(int16_t val) {
66   double c = val;
67   // Invert companding curve
68   c += (c * c * c * 768) / (255. * 255. * 255.);
69   if (c > std::numeric_limits<int16_t>::max())
70     return std::numeric_limits<int16_t>::max();
71   if (c < std::numeric_limits<int16_t>::min())
72     return std::numeric_limits<int16_t>::min();
73   return c;
74 }
75 
76 #ifndef NDEBUG
__anonc96cba220202() 77 const int ignore = []() {
78   for (const RLV& entry : table17.entries) {
79     assert(((-decompand(entry.value)) == decompand(-int16_t(entry.value))) &&
80            "negation of decompanded value is the same as decompanding of "
81            "negated value");
82   }
83   return 0;
84 }();
85 #endif
86 
__anonc96cba220302() 87 const std::array<RLV, table17.length> decompandedTable17 = []() {
88   std::array<RLV, table17.length> d;
89   for (auto i = 0U; i < table17.length; i++) {
90     d[i] = table17.entries[i];
91     d[i].value = decompand(table17.entries[i].value);
92   }
93   return d;
94 }();
95 
96 } // namespace
97 
98 #define PRECISION_MIN 8
99 #define PRECISION_MAX 16
100 
101 #define MARKER_BAND_END 1
102 
103 namespace rawspeed {
104 
setBandValid(const int band)105 void VC5Decompressor::Wavelet::setBandValid(const int band) {
106   mDecodedBandMask |= (1 << band);
107 }
108 
isBandValid(const int band) const109 bool VC5Decompressor::Wavelet::isBandValid(const int band) const {
110   return mDecodedBandMask & (1 << band);
111 }
112 
allBandsValid() const113 bool VC5Decompressor::Wavelet::allBandsValid() const {
114   return mDecodedBandMask == static_cast<uint32_t>((1 << numBands) - 1);
115 }
116 
117 Array2DRef<const int16_t>
bandAsArray2DRef(const unsigned int iBand) const118 VC5Decompressor::Wavelet::bandAsArray2DRef(const unsigned int iBand) const {
119   return {bands[iBand]->data.data(), width, height};
120 }
121 
122 namespace {
123 const auto convolute = [](int row, int col, std::array<int, 4> muls,
124                           const Array2DRef<const int16_t> high, auto lowGetter,
__anonc96cba220502(int row, int col, std::array<int, 4> muls, const Array2DRef<const int16_t> high, auto lowGetter, int DescaleShift = 0) 125                           int DescaleShift = 0) {
126   auto highCombined = muls[0] * high(row, col);
127   auto lowsCombined = [muls, lowGetter]() {
128     int lows = 0;
129     for (int i = 0; i < 3; i++)
130       lows += muls[1 + i] * lowGetter(i);
131     return lows;
132   }();
133   // Round up 'lows' up
134   lowsCombined += 4;
135   // And finally 'average' them.
136   auto lowsRounded = lowsCombined >> 3;
137   auto total = highCombined + lowsRounded;
138   // Descale it.
139   total <<= DescaleShift;
140   // And average it.
141   total >>= 1;
142   return total;
143 };
144 
145 struct ConvolutionParams {
146   struct First {
147     static constexpr std::array<int, 4> mul_even = {+1, +11, -4, +1};
148     static constexpr std::array<int, 4> mul_odd = {-1, +5, +4, -1};
149     static constexpr int coord_shift = 0;
150   };
151   static constexpr First First{};
152 
153   struct Middle {
154     static constexpr std::array<int, 4> mul_even = {+1, +1, +8, -1};
155     static constexpr std::array<int, 4> mul_odd = {-1, -1, +8, +1};
156     static constexpr int coord_shift = -1;
157   };
158   static constexpr Middle Middle{};
159 
160   struct Last {
161     static constexpr std::array<int, 4> mul_even = {+1, -1, +4, +5};
162     static constexpr std::array<int, 4> mul_odd = {-1, +1, -4, +11};
163     static constexpr int coord_shift = -2;
164   };
165   static constexpr Last Last{};
166 };
167 
168 constexpr std::array<int, 4> ConvolutionParams::First::mul_even;
169 constexpr std::array<int, 4> ConvolutionParams::First::mul_odd;
170 
171 constexpr std::array<int, 4> ConvolutionParams::Middle::mul_even;
172 constexpr std::array<int, 4> ConvolutionParams::Middle::mul_odd;
173 
174 constexpr std::array<int, 4> ConvolutionParams::Last::mul_even;
175 constexpr std::array<int, 4> ConvolutionParams::Last::mul_odd;
176 
177 } // namespace
178 
reconstructPass(const Array2DRef<int16_t> dst,const Array2DRef<const int16_t> high,const Array2DRef<const int16_t> low) const179 void VC5Decompressor::Wavelet::reconstructPass(
180     const Array2DRef<int16_t> dst, const Array2DRef<const int16_t> high,
181     const Array2DRef<const int16_t> low) const noexcept {
182   auto process = [low, high, dst](auto segment, int row, int col) {
183     auto lowGetter = [&row, &col, low](int delta) {
184       return low(row + decltype(segment)::coord_shift + delta, col);
185     };
186     auto convolution = [&row, &col, high, lowGetter](std::array<int, 4> muls) {
187       return convolute(row, col, muls, high, lowGetter, /*DescaleShift*/ 0);
188     };
189 
190     int even = convolution(decltype(segment)::mul_even);
191     int odd = convolution(decltype(segment)::mul_odd);
192 
193     dst(2 * row, col) = static_cast<int16_t>(even);
194     dst(2 * row + 1, col) = static_cast<int16_t>(odd);
195   };
196 
197   // Vertical reconstruction
198 #ifdef HAVE_OPENMP
199 #pragma omp for schedule(static)
200 #endif
201   for (int row = 0; row < height; ++row) {
202     if (row == 0) {
203       // 1st row
204       for (int col = 0; col < width; ++col)
205         process(ConvolutionParams::First, row, col);
206     } else if (row + 1 < height) {
207       // middle rows
208       for (int col = 0; col < width; ++col)
209         process(ConvolutionParams::Middle, row, col);
210     } else {
211       // last row
212       for (int col = 0; col < width; ++col)
213         process(ConvolutionParams::Last, row, col);
214     }
215   }
216 }
217 
combineLowHighPass(const Array2DRef<int16_t> dst,const Array2DRef<const int16_t> low,const Array2DRef<const int16_t> high,int descaleShift,bool clampUint=false) const218 void VC5Decompressor::Wavelet::combineLowHighPass(
219     const Array2DRef<int16_t> dst, const Array2DRef<const int16_t> low,
220     const Array2DRef<const int16_t> high, int descaleShift,
221     bool clampUint = false) const noexcept {
222   auto process = [low, high, descaleShift, clampUint, dst](auto segment,
223                                                            int row, int col) {
224     auto lowGetter = [&row, &col, low](int delta) {
225       return low(row, col + decltype(segment)::coord_shift + delta);
226     };
227     auto convolution = [&row, &col, high, lowGetter,
228                         descaleShift](std::array<int, 4> muls) {
229       return convolute(row, col, muls, high, lowGetter, descaleShift);
230     };
231 
232     int even = convolution(decltype(segment)::mul_even);
233     int odd = convolution(decltype(segment)::mul_odd);
234 
235     if (clampUint) {
236       even = clampBits(even, 14);
237       odd = clampBits(odd, 14);
238     }
239     dst(row, 2 * col) = static_cast<int16_t>(even);
240     dst(row, 2 * col + 1) = static_cast<int16_t>(odd);
241   };
242 
243   // Horizontal reconstruction
244 #ifdef HAVE_OPENMP
245 #pragma omp for schedule(static)
246 #endif
247   for (int row = 0; row < dst.height; ++row) {
248     // First col
249     int col = 0;
250     process(ConvolutionParams::First, row, col);
251     // middle cols
252     for (col = 1; col + 1 < width; ++col) {
253       process(ConvolutionParams::Middle, row, col);
254     }
255     // last col
256     process(ConvolutionParams::Last, row, col);
257   }
258 }
259 
processLow(const Wavelet & wavelet)260 void VC5Decompressor::Wavelet::ReconstructableBand::processLow(
261     const Wavelet& wavelet) noexcept {
262   Array2DRef<int16_t> lowpass;
263 #ifdef HAVE_OPENMP
264 #pragma omp single copyprivate(lowpass)
265 #endif
266   lowpass = Array2DRef<int16_t>::create(&lowpass_storage, wavelet.width,
267                                         2 * wavelet.height);
268 
269   const Array2DRef<const int16_t> highlow = wavelet.bandAsArray2DRef(2);
270   const Array2DRef<const int16_t> lowlow = wavelet.bandAsArray2DRef(0);
271 
272   // Reconstruct the "immediates", the actual low pass ...
273   wavelet.reconstructPass(lowpass, highlow, lowlow);
274 }
275 
processHigh(const Wavelet & wavelet)276 void VC5Decompressor::Wavelet::ReconstructableBand::processHigh(
277     const Wavelet& wavelet) noexcept {
278   Array2DRef<int16_t> highpass;
279 #ifdef HAVE_OPENMP
280 #pragma omp single copyprivate(highpass)
281 #endif
282   highpass = Array2DRef<int16_t>::create(&highpass_storage, wavelet.width,
283                                          2 * wavelet.height);
284 
285   const Array2DRef<const int16_t> highhigh = wavelet.bandAsArray2DRef(3);
286   const Array2DRef<const int16_t> lowhigh = wavelet.bandAsArray2DRef(1);
287 
288   wavelet.reconstructPass(highpass, highhigh, lowhigh);
289 }
290 
combine(const Wavelet & wavelet)291 void VC5Decompressor::Wavelet::ReconstructableBand::combine(
292     const Wavelet& wavelet) noexcept {
293   int16_t descaleShift = (wavelet.prescale == 2 ? 2 : 0);
294 
295   Array2DRef<int16_t> dest;
296 #ifdef HAVE_OPENMP
297 #pragma omp single copyprivate(dest)
298 #endif
299   dest =
300       Array2DRef<int16_t>::create(&data, 2 * wavelet.width, 2 * wavelet.height);
301 
302   const Array2DRef<int16_t> lowpass(lowpass_storage.data(), wavelet.width,
303                                     2 * wavelet.height);
304   const Array2DRef<int16_t> highpass(highpass_storage.data(), wavelet.width,
305                                      2 * wavelet.height);
306 
307   // And finally, combine the low pass, and high pass.
308   wavelet.combineLowHighPass(dest, lowpass, highpass, descaleShift, clampUint);
309 }
310 
decode(const Wavelet & wavelet)311 void VC5Decompressor::Wavelet::ReconstructableBand::decode(
312     const Wavelet& wavelet) noexcept {
313   assert(wavelet.allBandsValid());
314   assert(data.empty());
315   processLow(wavelet);
316   processHigh(wavelet);
317   combine(wavelet);
318 }
319 
VC5Decompressor(ByteStream bs,const RawImage & img)320 VC5Decompressor::VC5Decompressor(ByteStream bs, const RawImage& img)
321     : mRaw(img), mBs(std::move(bs)) {
322   if (!mRaw->dim.hasPositiveArea())
323     ThrowRDE("Bad image dimensions.");
324 
325   if (mRaw->dim.x % mVC5.patternWidth != 0)
326     ThrowRDE("Width %u is not a multiple of %u", mRaw->dim.x,
327              mVC5.patternWidth);
328 
329   if (mRaw->dim.y % mVC5.patternHeight != 0)
330     ThrowRDE("Height %u is not a multiple of %u", mRaw->dim.y,
331              mVC5.patternHeight);
332 
333   // Initialize wavelet sizes.
334   for (Channel& channel : channels) {
335     channel.width = mRaw->dim.x / mVC5.patternWidth;
336     channel.height = mRaw->dim.y / mVC5.patternHeight;
337 
338     uint16_t waveletWidth = channel.width;
339     uint16_t waveletHeight = channel.height;
340     for (Wavelet& wavelet : channel.wavelets) {
341       // Pad dimensions as necessary and divide them by two for the next wavelet
342       for (auto* dimension : {&waveletWidth, &waveletHeight})
343         *dimension = roundUpDivision(*dimension, 2);
344       wavelet.width = waveletWidth;
345       wavelet.height = waveletHeight;
346     }
347   }
348 
349   if (img->whitePoint <= 0 || img->whitePoint > int(((1U << 16U) - 1U)))
350     ThrowRDE("Bad white level %i", img->whitePoint);
351 
352   outputBits = 0;
353   for (int wp = img->whitePoint; wp != 0; wp >>= 1)
354     ++outputBits;
355   assert(outputBits <= 16);
356 
357   parseVC5();
358 }
359 
initVC5LogTable()360 void VC5Decompressor::initVC5LogTable() {
361   mVC5LogTable = decltype(mVC5LogTable)(
362       [outputBits = outputBits](unsigned i, unsigned tableSize) {
363         // The vanilla "inverse log" curve for decoding.
364         auto normalizedCurve = [](auto normalizedI) {
365           return (std::pow(113.0, normalizedI) - 1) / 112.0;
366         };
367 
368         auto normalizeI = [tableSize](auto x) { return x / (tableSize - 1.0); };
369         auto denormalizeY = [maxVal = std::numeric_limits<uint16_t>::max()](
370                                 auto y) { return maxVal * y; };
371         // Adjust for output whitelevel bitdepth.
372         auto rescaleY = [outputBits](auto y) {
373           auto scale = 16 - outputBits;
374           return y >> scale;
375         };
376 
377         const auto naiveY = denormalizeY(normalizedCurve(normalizeI(i)));
378         const auto intY = static_cast<unsigned int>(naiveY);
379         const auto rescaledY = rescaleY(intY);
380         return rescaledY;
381       });
382 }
383 
parseVC5()384 void VC5Decompressor::parseVC5() {
385   mBs.setByteOrder(Endianness::big);
386 
387   assert(mRaw->dim.x > 0);
388   assert(mRaw->dim.y > 0);
389 
390   // All VC-5 data must start with "VC-%" (0x56432d35)
391   if (mBs.getU32() != 0x56432d35)
392     ThrowRDE("not a valid VC-5 datablock");
393 
394   bool done = false;
395   while (!done) {
396     auto tag = static_cast<VC5Tag>(mBs.getU16());
397     uint16_t val = mBs.getU16();
398 
399     bool optional = matches(tag, VC5Tag::Optional);
400     if (optional)
401       tag = -tag;
402 
403     switch (tag) {
404     case VC5Tag::ChannelCount:
405       if (val != numChannels)
406         ThrowRDE("Bad channel count %u, expected %u", val, numChannels);
407       break;
408     case VC5Tag::ImageWidth:
409       if (val != mRaw->dim.x)
410         ThrowRDE("Image width mismatch: %u vs %u", val, mRaw->dim.x);
411       break;
412     case VC5Tag::ImageHeight:
413       if (val != mRaw->dim.y)
414         ThrowRDE("Image height mismatch: %u vs %u", val, mRaw->dim.y);
415       break;
416     case VC5Tag::LowpassPrecision:
417       if (val < PRECISION_MIN || val > PRECISION_MAX)
418         ThrowRDE("Invalid precision %i", val);
419       mVC5.lowpassPrecision = val;
420       break;
421     case VC5Tag::ChannelNumber:
422       if (val >= numChannels)
423         ThrowRDE("Bad channel number (%u)", val);
424       mVC5.iChannel = val;
425       break;
426     case VC5Tag::ImageFormat:
427       if (val != mVC5.imgFormat)
428         ThrowRDE("Image format %i is not 4(RAW)", val);
429       break;
430     case VC5Tag::SubbandCount:
431       if (val != numSubbands)
432         ThrowRDE("Unexpected subband count %u, expected %u", val, numSubbands);
433       break;
434     case VC5Tag::MaxBitsPerComponent:
435       if (val != VC5_LOG_TABLE_BITWIDTH) {
436         ThrowRDE("Bad bits per componend %u, not %u", val,
437                  VC5_LOG_TABLE_BITWIDTH);
438       }
439       break;
440     case VC5Tag::PatternWidth:
441       if (val != mVC5.patternWidth)
442         ThrowRDE("Bad pattern width %u, not %u", val, mVC5.patternWidth);
443       break;
444     case VC5Tag::PatternHeight:
445       if (val != mVC5.patternHeight)
446         ThrowRDE("Bad pattern height %u, not %u", val, mVC5.patternHeight);
447       break;
448     case VC5Tag::SubbandNumber:
449       if (val >= numSubbands)
450         ThrowRDE("Bad subband number %u", val);
451       mVC5.iSubband = val;
452       break;
453     case VC5Tag::Quantization:
454       mVC5.quantization = static_cast<int16_t>(val);
455       break;
456     case VC5Tag::ComponentsPerSample:
457       if (val != mVC5.cps)
458         ThrowRDE("Bad component per sample count %u, not %u", val, mVC5.cps);
459       break;
460     case VC5Tag::PrescaleShift:
461       // FIXME: something is wrong. We get this before VC5Tag::ChannelNumber.
462       // Defaulting to 'mVC5.iChannel=0' seems to work *for existing samples*.
463       for (int iWavelet = 0; iWavelet < numWaveletLevels; ++iWavelet) {
464         auto& channel = channels[mVC5.iChannel];
465         auto& wavelet = channel.wavelets[iWavelet];
466         wavelet.prescale =
467             extractHighBits(val, 2 * iWavelet, /*effectiveBitwidth=*/14) & 0x03;
468       }
469       break;
470     default: { // A chunk.
471       unsigned int chunkSize = 0;
472       if (matches(tag, VC5Tag::LARGE_CHUNK)) {
473         chunkSize = static_cast<unsigned int>(
474             ((static_cast<std::underlying_type<VC5Tag>::type>(tag) & 0xff)
475              << 16) |
476             (val & 0xffff));
477       } else if (matches(tag, VC5Tag::SMALL_CHUNK)) {
478         chunkSize = (val & 0xffff);
479       }
480 
481       if (is(tag, VC5Tag::LargeCodeblock)) {
482         parseLargeCodeblock(mBs.getStream(chunkSize, 4));
483         break;
484       }
485 
486       // And finally, we got here if we didn't handle this tag/maybe-chunk.
487 
488       // Magic, all the other 'large' chunks are actually optional,
489       // and don't specify any chunk bytes-to-be-skipped.
490       if (matches(tag, VC5Tag::LARGE_CHUNK)) {
491         optional = true;
492         chunkSize = 0;
493       }
494 
495       if (!optional) {
496         ThrowRDE("Unknown (unhandled) non-optional Tag 0x%04hx",
497                  static_cast<std::underlying_type<VC5Tag>::type>(tag));
498       }
499 
500       if (chunkSize)
501         mBs.skipBytes(chunkSize, 4);
502 
503       break;
504     }
505     }
506 
507     done = true;
508     for (int iChannel = 0; iChannel < numChannels && done; ++iChannel) {
509       Wavelet& wavelet = channels[iChannel].wavelets[0];
510       if (!wavelet.allBandsValid())
511         done = false;
512     }
513   }
514 }
515 
LowPassBand(const Wavelet & wavelet,ByteStream bs_,uint16_t lowpassPrecision_)516 VC5Decompressor::Wavelet::LowPassBand::LowPassBand(const Wavelet& wavelet,
517                                                    ByteStream bs_,
518                                                    uint16_t lowpassPrecision_)
519     : AbstractDecodeableBand(std::move(bs_)),
520       lowpassPrecision(lowpassPrecision_) {
521   // Low-pass band is a uncompressed version of the image, hugely downscaled.
522   // It consists of width * height pixels, `lowpassPrecision` each.
523   // We can easily check that we have sufficient amount of bits to decode it.
524   const auto waveletArea = iPoint2D(wavelet.width, wavelet.height).area();
525   const auto bitsTotal = waveletArea * lowpassPrecision;
526   const auto bytesTotal = roundUpDivision(bitsTotal, 8);
527   bs = bs.getStream(bytesTotal); // And clamp the size while we are at it.
528 }
529 
decode(const Wavelet & wavelet)530 void VC5Decompressor::Wavelet::LowPassBand::decode(const Wavelet& wavelet) {
531   const auto dst =
532       Array2DRef<int16_t>::create(&data, wavelet.width, wavelet.height);
533 
534   BitPumpMSB bits(bs);
535   for (auto row = 0; row < dst.height; ++row) {
536     for (auto col = 0; col < dst.width; ++col)
537       dst(row, col) = static_cast<int16_t>(bits.getBits(lowpassPrecision));
538   }
539 }
540 
decode(const Wavelet & wavelet)541 void VC5Decompressor::Wavelet::HighPassBand::decode(const Wavelet& wavelet) {
542   auto dequantize = [quant = quant](int16_t val) -> int16_t {
543     return val * quant;
544   };
545 
546   Array2DRef<int16_t>::create(&data, wavelet.width, wavelet.height);
547 
548   BitPumpMSB bits(bs);
549   // decode highpass band
550   int pixelValue = 0;
551   unsigned int count = 0;
552   int nPixels = wavelet.width * wavelet.height;
553   for (int iPixel = 0; iPixel < nPixels;) {
554     getRLV(&bits, &pixelValue, &count);
555     for (; count > 0; --count) {
556       if (iPixel >= nPixels)
557         ThrowRDE("Buffer overflow");
558       data[iPixel] = dequantize(pixelValue);
559       ++iPixel;
560     }
561   }
562   getRLV(&bits, &pixelValue, &count);
563   static_assert(decompand(MARKER_BAND_END) == MARKER_BAND_END, "passthrough");
564   if (pixelValue != MARKER_BAND_END || count != 0)
565     ThrowRDE("EndOfBand marker not found");
566 }
567 
parseLargeCodeblock(const ByteStream & bs)568 void VC5Decompressor::parseLargeCodeblock(const ByteStream& bs) {
569   static const auto subband_wavelet_index = []() {
570     std::array<int, numSubbands> wavelets;
571     int wavelet = 0;
572     for (auto i = wavelets.size() - 1; i > 0;) {
573       for (auto t = 0; t < numWaveletLevels; t++) {
574         wavelets[i] = wavelet;
575         i--;
576       }
577       if (i > 0)
578         wavelet++;
579     }
580     wavelets.front() = wavelet;
581     return wavelets;
582   }();
583   static const auto subband_band_index = []() {
584     std::array<int, numSubbands> bands;
585     bands.front() = 0;
586     for (auto i = 1U; i < bands.size();) {
587       for (int t = 1; t <= numWaveletLevels;) {
588         bands[i] = t;
589         t++;
590         i++;
591       }
592     }
593     return bands;
594   }();
595 
596   if (!mVC5.iSubband.hasValue())
597     ThrowRDE("Did not see VC5Tag::SubbandNumber yet");
598 
599   const int idx = subband_wavelet_index[mVC5.iSubband.getValue()];
600   const int band = subband_band_index[mVC5.iSubband.getValue()];
601 
602   auto& wavelets = channels[mVC5.iChannel].wavelets;
603 
604   Wavelet& wavelet = wavelets[idx];
605   if (wavelet.isBandValid(band)) {
606     ThrowRDE("Band %u for wavelet %u on channel %u was already seen", band, idx,
607              mVC5.iChannel);
608   }
609 
610   std::unique_ptr<Wavelet::AbstractBand>& dstBand = wavelet.bands[band];
611   if (mVC5.iSubband.getValue() == 0) {
612     assert(band == 0);
613     // low-pass band, only one, for the smallest wavelet, per channel per image
614     if (!mVC5.lowpassPrecision.hasValue())
615       ThrowRDE("Did not see VC5Tag::LowpassPrecision yet");
616     dstBand = std::make_unique<Wavelet::LowPassBand>(
617         wavelet, bs, mVC5.lowpassPrecision.getValue());
618     mVC5.lowpassPrecision.reset();
619   } else {
620     if (!mVC5.quantization.hasValue())
621       ThrowRDE("Did not see VC5Tag::Quantization yet");
622     dstBand = std::make_unique<Wavelet::HighPassBand>(
623         bs, mVC5.quantization.getValue());
624     mVC5.quantization.reset();
625   }
626   wavelet.setBandValid(band);
627 
628   // If this wavelet is fully specified, mark the low-pass band of the
629   // next lower wavelet as specified.
630   if (idx > 0 && wavelet.allBandsValid()) {
631     Wavelet& nextWavelet = wavelets[idx - 1];
632     assert(!nextWavelet.isBandValid(0));
633     nextWavelet.bands[0] = std::make_unique<Wavelet::ReconstructableBand>();
634     nextWavelet.setBandValid(0);
635   }
636 
637   mVC5.iSubband.reset();
638 }
639 
prepareBandDecodingPlan()640 void VC5Decompressor::prepareBandDecodingPlan() {
641   assert(allDecodeableBands.empty());
642   allDecodeableBands.reserve(numSubbandsTotal);
643   // All the high-pass bands for all wavelets,
644   // in this specific order of decreasing worksize.
645   for (int waveletLevel = 0; waveletLevel < numWaveletLevels; waveletLevel++) {
646     for (auto channelId = 0; channelId < numChannels; channelId++) {
647       for (int bandId = 1; bandId <= numHighPassBands; bandId++) {
648         auto& channel = channels[channelId];
649         auto& wavelet = channel.wavelets[waveletLevel];
650         auto* band = wavelet.bands[bandId].get();
651         auto* decodeableHighPassBand =
652             dynamic_cast<Wavelet::HighPassBand*>(band);
653         allDecodeableBands.emplace_back(decodeableHighPassBand, wavelet);
654       }
655     }
656   }
657   // The low-pass bands at the end. I'm guessing they should be fast to
658   // decode.
659   for (Channel& channel : channels) {
660     // Low-pass band of the smallest wavelet.
661     Wavelet& smallestWavelet = channel.wavelets.back();
662     auto* decodeableLowPassBand =
663         dynamic_cast<Wavelet::LowPassBand*>(smallestWavelet.bands[0].get());
664     allDecodeableBands.emplace_back(decodeableLowPassBand, smallestWavelet);
665   }
666   assert(allDecodeableBands.size() == numSubbandsTotal);
667 }
668 
prepareBandReconstruction()669 void VC5Decompressor::prepareBandReconstruction() {
670   assert(reconstructionSteps.empty());
671   reconstructionSteps.reserve(numLowPassBandsTotal);
672   // For every channel, recursively reconstruct the low-pass bands.
673   for (auto& channel : channels) {
674     // Reconstruct the intermediate lowpass bands.
675     for (int waveletLevel = numWaveletLevels - 1; waveletLevel > 0;
676          waveletLevel--) {
677       Wavelet* wavelet = &(channel.wavelets[waveletLevel]);
678       Wavelet& nextWavelet = channel.wavelets[waveletLevel - 1];
679 
680       auto* band = dynamic_cast<Wavelet::ReconstructableBand*>(
681           nextWavelet.bands[0].get());
682       reconstructionSteps.emplace_back(wavelet, band);
683     }
684     // Finally, reconstruct the final lowpass band.
685     Wavelet* wavelet = &(channel.wavelets.front());
686     reconstructionSteps.emplace_back(wavelet, &(channel.band));
687   }
688   assert(reconstructionSteps.size() == numLowPassBandsTotal);
689 }
690 
prepareDecodingPlan()691 void VC5Decompressor::prepareDecodingPlan() {
692   prepareBandDecodingPlan();
693   prepareBandReconstruction();
694 }
695 
decodeThread(bool * exceptionThrown) const696 void VC5Decompressor::decodeThread(bool* exceptionThrown) const noexcept {
697   // Decode all the existing bands. May fail.
698   decodeBands(exceptionThrown);
699 
700   // Proceed only if decoding did not fail.
701   if (*exceptionThrown)
702     return;
703 
704   // And now, reconstruct the low-pass bands.
705   reconstructLowpassBands();
706 
707   // And finally!
708   combineFinalLowpassBands();
709 }
710 
decode(unsigned int offsetX,unsigned int offsetY,unsigned int width,unsigned int height)711 void VC5Decompressor::decode(unsigned int offsetX, unsigned int offsetY,
712                              unsigned int width, unsigned int height) {
713   if (offsetX || offsetY || mRaw->dim != iPoint2D(width, height))
714     ThrowRDE("VC5Decompressor expects to fill the whole image, not some tile.");
715 
716   initVC5LogTable();
717 
718   prepareDecodingPlan();
719 
720   bool exceptionThrown = false;
721 #ifdef HAVE_OPENMP
722 #pragma omp parallel default(none) shared(exceptionThrown)                     \
723     num_threads(rawspeed_get_number_of_processor_cores())
724 #endif
725   decodeThread(&exceptionThrown);
726 
727   std::string firstErr;
728   if (mRaw->isTooManyErrors(1, &firstErr)) {
729     assert(exceptionThrown);
730     ThrowRDE("Too many errors encountered. Giving up. First Error:\n%s",
731              firstErr.c_str());
732   } else {
733     assert(!exceptionThrown);
734   }
735 }
736 
decodeBands(bool * exceptionThrown) const737 void VC5Decompressor::decodeBands(bool* exceptionThrown) const noexcept {
738 #ifdef HAVE_OPENMP
739 #pragma omp for schedule(dynamic, 1)
740 #endif
741   for (auto decodeableBand = allDecodeableBands.begin();
742        decodeableBand < allDecodeableBands.end(); ++decodeableBand) {
743     try {
744       decodeableBand->band->decode(decodeableBand->wavelet);
745     } catch (RawspeedException& err) {
746       // Propagate the exception out of OpenMP magic.
747       mRaw->setError(err.what());
748 #ifdef HAVE_OPENMP
749 #pragma omp atomic write
750 #endif
751       *exceptionThrown = true;
752 #ifdef HAVE_OPENMP
753 #pragma omp cancel for
754 #endif
755     }
756   }
757 }
758 
reconstructLowpassBands() const759 void VC5Decompressor::reconstructLowpassBands() const noexcept {
760   for (const ReconstructionStep& step : reconstructionSteps) {
761     step.band.decode(step.wavelet);
762 
763 #ifdef HAVE_OPENMP
764 #pragma omp single nowait
765 #endif
766     step.wavelet.clear(); // we no longer need it.
767   }
768 }
769 
combineFinalLowpassBands() const770 void VC5Decompressor::combineFinalLowpassBands() const noexcept {
771   const Array2DRef<uint16_t> out(mRaw->getU16DataAsUncroppedArray2DRef());
772 
773   const int width = out.width / 2;
774   const int height = out.height / 2;
775 
776   const Array2DRef<const int16_t> lowbands0 = Array2DRef<const int16_t>(
777       channels[0].band.data.data(), channels[0].width, channels[0].height);
778   const Array2DRef<const int16_t> lowbands1 = Array2DRef<const int16_t>(
779       channels[1].band.data.data(), channels[1].width, channels[1].height);
780   const Array2DRef<const int16_t> lowbands2 = Array2DRef<const int16_t>(
781       channels[2].band.data.data(), channels[2].width, channels[2].height);
782   const Array2DRef<const int16_t> lowbands3 = Array2DRef<const int16_t>(
783       channels[3].band.data.data(), channels[3].width, channels[3].height);
784 
785   // Convert to RGGB output
786 #ifdef HAVE_OPENMP
787 #pragma omp for schedule(static) collapse(2)
788 #endif
789   for (int row = 0; row < height; ++row) {
790     for (int col = 0; col < width; ++col) {
791       const int mid = 2048;
792 
793       int gs = lowbands0(row, col);
794       int rg = lowbands1(row, col) - mid;
795       int bg = lowbands2(row, col) - mid;
796       int gd = lowbands3(row, col) - mid;
797 
798       int r = gs + 2 * rg;
799       int b = gs + 2 * bg;
800       int g1 = gs + gd;
801       int g2 = gs - gd;
802 
803       out(2 * row + 0, 2 * col + 0) = static_cast<uint16_t>(mVC5LogTable[r]);
804       out(2 * row + 0, 2 * col + 1) = static_cast<uint16_t>(mVC5LogTable[g1]);
805       out(2 * row + 1, 2 * col + 0) = static_cast<uint16_t>(mVC5LogTable[g2]);
806       out(2 * row + 1, 2 * col + 1) = static_cast<uint16_t>(mVC5LogTable[b]);
807     }
808   }
809 }
810 
getRLV(BitPumpMSB * bits,int * value,unsigned int * count)811 inline void VC5Decompressor::getRLV(BitPumpMSB* bits, int* value,
812                                     unsigned int* count) {
813   unsigned int iTab;
814 
815   static constexpr auto maxBits = 1 + table17.entries[table17.length - 1].size;
816 
817   // Ensure the maximum number of bits are cached to make peekBits() as fast as
818   // possible.
819   bits->fill(maxBits);
820   for (iTab = 0; iTab < table17.length; ++iTab) {
821     if (decompandedTable17[iTab].bits ==
822         bits->peekBitsNoFill(decompandedTable17[iTab].size))
823       break;
824   }
825   if (iTab >= table17.length)
826     ThrowRDE("Code not found in codebook");
827 
828   bits->skipBitsNoFill(decompandedTable17[iTab].size);
829   *value = decompandedTable17[iTab].value;
830   *count = decompandedTable17[iTab].count;
831   if (*value != 0) {
832     if (bits->getBitsNoFill(1))
833       *value = -(*value);
834   }
835 }
836 
837 } // namespace rawspeed
838