RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
PrefixCodeVectorDecoder.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2017 Axel Waggershauser
5 Copyright (C) 2018 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#pragma once
23
24#include "adt/Invariant.h"
28#include <cassert>
29#include <cstdint>
30#include <tuple>
31#include <utility>
32#include <vector>
33
34namespace rawspeed {
35
36template <typename CodeTag>
38public:
39 using Tag = CodeTag;
41 using Traits = typename Base::Traits;
42
43 using Base::Base;
44
45private:
46 // Given this code len, which code id is the minimal?
47 std::vector<uint32_t> extrCodeIdForLen; // index is length of code
48
49protected:
50 template <typename BIT_STREAM>
51 std::pair<typename Base::CodeSymbol, int /*codeValue*/>
53 typename Base::CodeSymbol partial) const {
54 static_assert(
56 "This BitStreamer specialization is not marked as usable here");
57
58 // Read bits until either find the code or detect the incorrect code
59 while (partial.code_len < Base::maxCodeLength()) {
60 // Read one more bit
61 const bool bit = bs.getBitsNoFill(1);
62
63 partial.code <<= 1;
64 partial.code |= bit;
65 partial.code_len++;
66
67 // Given global ordering and the code length, we know the code id range.
68 for (auto codeId = extrCodeIdForLen[partial.code_len];
69 codeId < extrCodeIdForLen[1U + partial.code_len]; codeId++) {
70 const typename Base::CodeSymbol& symbol = Base::code.symbols[codeId];
71 invariant(partial.code_len == symbol.code_len);
72 if (symbol == partial) // yay, found?
73 return {symbol, Base::code.codeValues[codeId]};
74 }
75 }
76
77 ThrowRDE("bad Huffman code: %u (len: %u)", partial.code, partial.code_len);
78 }
79
80 template <typename BIT_STREAM>
81 std::pair<typename Base::CodeSymbol, int /*codeValue*/>
82 readSymbol(BIT_STREAM& bs) const {
83 // Start from completely unknown symbol.
84 typename Base::CodeSymbol partial;
85 partial.code_len = 0;
86 partial.code = 0;
87
88 return finishReadingPartialSymbol(bs, partial);
89 }
90
91public:
92 void setup(bool fullDecode_, bool fixDNGBug16_) {
93 AbstractPrefixCodeDecoder<CodeTag>::setup(fullDecode_, fixDNGBug16_);
94
95 extrCodeIdForLen.reserve(1U + Base::code.nCodesPerLength.size());
96 extrCodeIdForLen.resize(2); // for len 0 and 1, the min code id is always 0
97 for (auto codeLen = 1UL; codeLen < Base::code.nCodesPerLength.size();
98 codeLen++) {
99 auto minCodeId = extrCodeIdForLen.back();
100 minCodeId += Base::code.nCodesPerLength[codeLen];
101 extrCodeIdForLen.emplace_back(minCodeId);
102 }
103 assert(extrCodeIdForLen.size() == 1U + Base::code.nCodesPerLength.size());
104 }
105
106 template <typename BIT_STREAM>
107 typename Traits::CodeValueTy decodeCodeValue(BIT_STREAM& bs) const {
108 static_assert(
110 "This BitStreamer specialization is not marked as usable here");
112 return decode<BIT_STREAM, false>(bs);
113 }
114
115 template <typename BIT_STREAM> int decodeDifference(BIT_STREAM& bs) const {
116 static_assert(
118 "This BitStreamer specialization is not marked as usable here");
120 return decode<BIT_STREAM, true>(bs);
121 }
122
123 // The bool template paraeter is to enable two versions:
124 // one returning only the length of the of diff bits (see Hasselblad),
125 // one to return the fully decoded diff.
126 // All ifs depending on this bool will be optimized out by the compiler
127 template <typename BIT_STREAM, bool FULL_DECODE>
128 int decode(BIT_STREAM& bs) const {
129 static_assert(
131 "This BitStreamer specialization is not marked as usable here");
132 invariant(FULL_DECODE == Base::isFullDecode());
133
134 bs.fill(32);
135
136 typename Base::CodeSymbol symbol;
137 typename Traits::CodeValueTy codeValue;
138 std::tie(symbol, codeValue) = readSymbol(bs);
139
140 return Base::template processSymbol<BIT_STREAM, FULL_DECODE>(bs, symbol,
141 codeValue);
142 }
143};
144
145} // namespace rawspeed
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRDE(...)
assert(dim.area() >=area)
int processSymbol(BIT_STREAM &bs, CodeSymbol symbol, typename Traits::CodeValueTy codeValue) const
AbstractPrefixCodeTranscoder< CodeTag > Base
void setup(bool fullDecode_, bool fixDNGBug16_)
void setup(bool fullDecode_, bool fixDNGBug16_)
std::pair< typename Base::CodeSymbol, int > finishReadingPartialSymbol(BIT_STREAM &bs, typename Base::CodeSymbol partial) const
std::pair< typename Base::CodeSymbol, int > readSymbol(BIT_STREAM &bs) const
AbstractPrefixCodeDecoder< CodeTag > Base
Traits::CodeValueTy decodeCodeValue(BIT_STREAM &bs) const