RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
PrefixCodeLookupDecoder.h
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2017 Axel Waggershauser
5 Copyright (C) 2017-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"
27#include "codes/HuffmanCode.h"
28#include "codes/PrefixCode.h"
30#include <cassert>
31#include <cstdint>
32#include <limits>
33#include <tuple>
34#include <utility>
35#include <vector>
36
37/*
38 * The following code is inspired by the IJG JPEG library.
39 *
40 * Copyright (C) 1991, 1992, Thomas G. Lane.
41 * Part of the Independent JPEG Group's software.
42 * See the file Copyright for more details.
43 *
44 * Copyright (c) 1993 Brian C. Smith, The Regents of the University
45 * of California
46 * All rights reserved.
47 *
48 * Copyright (c) 1994 Kongji Huang and Brian C. Smith.
49 * Cornell University
50 * All rights reserved.
51 *
52 * Permission to use, copy, modify, and distribute this software and its
53 * documentation for any purpose, without fee, and without written agreement is
54 * hereby granted, provided that the above copyright notice and the following
55 * two paragraphs appear in all copies of this software.
56 *
57 * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
58 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
59 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
60 * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61 *
62 * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
63 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
64 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
65 * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
66 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
67 */
68
69namespace rawspeed {
70
71template <typename CodeTag>
73public:
74 using Tag = CodeTag;
76 using Traits = typename Base::Traits;
77
78 // We only support true Huffman codes, not generic prefix codes.
80 : Base(std::move(hc).operator rawspeed::PrefixCode<CodeTag>()) {}
81
85
86protected:
87 // private fields calculated from codesPerBits and codeValues
88 // they are index '1' based, so we can directly lookup the value
89 // for code length l without decrementing
90 std::vector<typename Traits::CodeTy> maxCodeOL; // index is length of code
91 std::vector<typename Traits::CodeTy> codeOffsetOL; // index is length of code
92
93 static constexpr auto MaxCodeValue =
94 std::numeric_limits<typename Traits::CodeTy>::max();
95
96public:
97 void setup(bool fullDecode_, bool fixDNGBug16_) {
98 AbstractPrefixCodeDecoder<CodeTag>::setup(fullDecode_, fixDNGBug16_);
99
100 // Figure F.15: generate decoding tables
103 for (unsigned int numCodesSoFar = 0, codeLen = 1;
104 codeLen <= Base::maxCodeLength(); codeLen++) {
105 if (!Base::code.nCodesPerLength[codeLen])
106 continue;
108 Base::code.symbols[numCodesSoFar].code - numCodesSoFar);
109 assert(codeOffsetOL[codeLen] != MaxCodeValue);
110 numCodesSoFar += Base::code.nCodesPerLength[codeLen];
111 maxCodeOL[codeLen] = Base::code.symbols[numCodesSoFar - 1].code;
112 }
113 }
114
115 template <typename BIT_STREAM>
116 typename Traits::CodeValueTy decodeCodeValue(BIT_STREAM& bs) const {
117 static_assert(
119 "This BitStreamer specialization is not marked as usable here");
121 return decode<BIT_STREAM, false>(bs);
122 }
123
124 template <typename BIT_STREAM> int decodeDifference(BIT_STREAM& bs) const {
125 static_assert(
127 "This BitStreamer specialization is not marked as usable here");
129 return decode<BIT_STREAM, true>(bs);
130 }
131
132protected:
133 template <typename BIT_STREAM>
134 std::pair<typename Base::CodeSymbol, int /*codeValue*/>
136 typename Base::CodeSymbol partial) const {
137 static_assert(
139 "This BitStreamer specialization is not marked as usable here");
140 while (partial.code_len < Base::maxCodeLength() &&
141 (MaxCodeValue == maxCodeOL[partial.code_len] ||
142 partial.code > maxCodeOL[partial.code_len])) {
143 uint32_t temp = bs.getBitsNoFill(1);
144 partial.code =
145 implicit_cast<typename Traits::CodeTy>((partial.code << 1) | temp);
146 partial.code_len++;
147 }
148
149 // NOTE: when we are called from PrefixCodeLUTDecoder, the partial.code_len
150 // *could* be larger than the largest code lenght for this huffman table,
151 // which is a symptom of a corrupt code.
152 if (partial.code_len > Base::maxCodeLength() ||
153 partial.code > maxCodeOL[partial.code_len])
154 ThrowRDE("bad Huffman code: %u (len: %u)", partial.code,
155 partial.code_len);
156
157 assert(MaxCodeValue != codeOffsetOL[partial.code_len]);
158 assert(partial.code >= codeOffsetOL[partial.code_len]);
159 unsigned codeIndex = partial.code - codeOffsetOL[partial.code_len];
160 assert(codeIndex < Base::code.codeValues.size());
161
162 typename Traits::CodeValueTy codeValue = Base::code.codeValues[codeIndex];
163 return {partial, codeValue};
164 }
165
166 template <typename BIT_STREAM>
167 std::pair<typename Base::CodeSymbol, int /*codeValue*/>
168 readSymbol(BIT_STREAM& bs) const {
169 // Start from completely unknown symbol.
170 typename Base::CodeSymbol partial;
171 partial.code_len = 0;
172 partial.code = 0;
173
174 return finishReadingPartialSymbol(bs, partial);
175 }
176
177public:
178 // The bool template paraeter is to enable two versions:
179 // one returning only the length of the of diff bits (see Hasselblad),
180 // one to return the fully decoded diff.
181 // All ifs depending on this bool will be optimized out by the compiler
182 template <typename BIT_STREAM, bool FULL_DECODE>
183 int decode(BIT_STREAM& bs) const {
184 invariant(FULL_DECODE == Base::isFullDecode());
185 bs.fill(32);
186
187 typename Base::CodeSymbol symbol;
188 typename Traits::CodeValueTy codeValue;
189 std::tie(symbol, codeValue) = readSymbol(bs);
190
191 return Base::template processSymbol<BIT_STREAM, FULL_DECODE>(bs, symbol,
192 codeValue);
193 }
194};
195
196} // 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
void setup(bool fullDecode_, bool fixDNGBug16_)
std::pair< typename Base::CodeSymbol, int > finishReadingPartialSymbol(BIT_STREAM &bs, typename Base::CodeSymbol partial) const
Traits::CodeValueTy decodeCodeValue(BIT_STREAM &bs) const
PrefixCodeLookupDecoder(HuffmanCode< CodeTag > &&hc)
std::vector< typename Traits::CodeTy > codeOffsetOL
AbstractPrefixCodeDecoder< CodeTag > Base
PrefixCodeLookupDecoder(PrefixCode< CodeTag >)=delete
PrefixCodeLookupDecoder(PrefixCode< CodeTag > &&)=delete
PrefixCodeLookupDecoder(const PrefixCode< CodeTag > &)=delete
std::pair< typename Base::CodeSymbol, int > readSymbol(BIT_STREAM &bs) const
void setup(bool fullDecode_, bool fixDNGBug16_)
std::vector< typename Traits::CodeTy > maxCodeOL
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32