RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
PrefixCodeTreeDecoder.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"
25#include "adt/Optional.h"
30#include <cassert>
31#include <tuple>
32#include <utility>
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:
47
48protected:
49 template <typename BIT_STREAM>
50 std::pair<typename Base::CodeSymbol, int /*codeValue*/>
52 typename Base::CodeSymbol initialPartial) const {
53 typename Base::CodeSymbol partial;
54 partial.code = 0;
55 partial.code_len = 0;
56
57 const auto* top = &(tree.root->getAsBranch());
58
59 auto walkBinaryTree = [&partial, &top](bool bit)
60 -> Optional<std::pair<typename Base::CodeSymbol, int /*codeValue*/>> {
61 partial.code <<= 1;
62 partial.code |= bit;
63 partial.code_len++;
64
65 // NOTE: The order *IS* important! Left to right, zero to one!
66 const auto& newNode = top->buds[bit];
67
68 if (!newNode) {
69 // Got nothing in this direction.
70 ThrowRDE("bad Huffman code: %u (len: %u)", partial.code,
71 partial.code_len);
72 }
73
74 if (static_cast<typename decltype(tree)::Node::Type>(*newNode) ==
75 decltype(tree)::Node::Type::Leaf) {
76 // Ok, great, hit a Leaf. This is it.
77 return {{partial, newNode->getAsLeaf().value}};
78 }
79
80 // Else, this is a branch, continue looking.
81 top = &(newNode->getAsBranch());
82 return std::nullopt;
83 };
84
85 // First, translate pre-existing code bits.
86 for (unsigned bit : initialPartial.getBitsMSB()) {
87 if (auto sym = walkBinaryTree(bit))
88 return *sym;
89 }
90
91 // Read bits until either find the code or detect the incorrect code
92 while (true) {
93 invariant(partial.code_len <= Traits::MaxCodeLenghtBits);
94
95 // Read one more bit
96 const bool bit = bs.getBitsNoFill(1);
97
98 if (auto sym = walkBinaryTree(bit))
99 return *sym;
100 }
101
102 // We have either returned the found symbol, or thrown on incorrect symbol.
103 __builtin_unreachable();
104 }
105
106 template <typename BIT_STREAM>
107 std::pair<typename Base::CodeSymbol, int /*codeValue*/>
108 readSymbol(BIT_STREAM& bs) const {
109 static_assert(
111 "This BitStreamer specialization is not marked as usable here");
112
113 // Start from completely unknown symbol.
114 typename Base::CodeSymbol partial;
115 partial.code_len = 0;
116 partial.code = 0;
117
118 return finishReadingPartialSymbol(bs, partial);
119 }
120
121public:
122 void setup(bool fullDecode_, bool fixDNGBug16_) {
123 AbstractPrefixCodeDecoder<CodeTag>::setup(fullDecode_, fixDNGBug16_);
124
125 assert(Base::code.symbols.size() == Base::code.codeValues.size());
126 for (unsigned codeIndex = 0; codeIndex != Base::code.symbols.size();
127 ++codeIndex)
128 tree.add(Base::code.symbols[codeIndex], Base::code.codeValues[codeIndex]);
129 }
130
131 template <typename BIT_STREAM>
132 typename Traits::CodeValueTy decodeCodeValue(BIT_STREAM& bs) const {
133 static_assert(
135 "This BitStreamer specialization is not marked as usable here");
137 return decode<BIT_STREAM, false>(bs);
138 }
139
140 template <typename BIT_STREAM> int decodeDifference(BIT_STREAM& bs) const {
141 static_assert(
143 "This BitStreamer specialization is not marked as usable here");
145 return decode<BIT_STREAM, true>(bs);
146 }
147
148 // The bool template paraeter is to enable two versions:
149 // one returning only the length of the of diff bits (see Hasselblad),
150 // one to return the fully decoded diff.
151 // All ifs depending on this bool will be optimized out by the compiler
152 template <typename BIT_STREAM, bool FULL_DECODE>
153 int decode(BIT_STREAM& bs) const {
154 static_assert(
156 "This BitStreamer specialization is not marked as usable here");
157 invariant(FULL_DECODE == Base::isFullDecode());
158
159 bs.fill(32);
160
161 typename Base::CodeSymbol symbol;
162 typename Traits::CodeValueTy codeValue;
163 std::tie(symbol, codeValue) = readSymbol(bs);
164
165 return Base::template processSymbol<BIT_STREAM, FULL_DECODE>(bs, symbol,
166 codeValue);
167 }
168};
169
170} // 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_)
Traits::CodeValueTy decodeCodeValue(BIT_STREAM &bs) const
int decodeDifference(BIT_STREAM &bs) const
BinaryPrefixTree< CodeTag > tree
void setup(bool fullDecode_, bool fixDNGBug16_)
std::pair< typename Base::CodeSymbol, int > readSymbol(BIT_STREAM &bs) const
AbstractPrefixCodeDecoder< CodeTag > Base
std::pair< typename Base::CodeSymbol, int > finishReadingPartialSymbol(BIT_STREAM &bs, typename Base::CodeSymbol initialPartial) const