Line | Count | Source (jump to first uncovered line) |
1 | | // Good, Fast Wavelet Codec "GFWX" v1 |
2 | | // ---------------------------------- |
3 | | // December 1, 2015 [patched on Oct 20, 2017] |
4 | | // Author: Graham Fyffe <gfyffe@gmail.com> or <fyffe@google.com>, and Google, Inc. |
5 | | // Website: www.gfwx.org |
6 | | // Features: |
7 | | // - FAST |
8 | | // - compression ratio similar to JPEG 2000 |
9 | | // - under 1000 lines of code, with no external libraries |
10 | | // - 100% lossless at max quality |
11 | | // - low quality looks interpolated instead of blocky |
12 | | // - progressive decoding with optional downsampling |
13 | | // - supports uint8_t, int8_t, uint16_t, int16_t |
14 | | // - supports 1 to 65536 interleaved channels |
15 | | // - supports 1 to 65536 non-interleaved layers |
16 | | // - optional Bayer mode to compress Bayer data more |
17 | | // - optional chroma downsampling, even in Bayer mode |
18 | | // - optional user-programmable color/channel transform |
19 | | // - optional slightly less fast mode to compress more |
20 | | // - imageData can be any class with a pointer-like interface |
21 | | // - thoroughly tested using several pictures of cats |
22 | | // |
23 | | // GFWX is released under the 3-clause BSD license: |
24 | | // |
25 | | // Copyright (c) 2015, University of Southern California. All rights reserved. Redistribution and use in source and binary forms, |
26 | | // with or without modification, are permitted provided that the following conditions are met: |
27 | | // |
28 | | // 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. |
29 | | // |
30 | | // 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in |
31 | | // the documentation and/or other materials provided with the distribution. |
32 | | // |
33 | | // 3. Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from |
34 | | // this software without specific prior written permission. |
35 | | // |
36 | | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
38 | | // COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
39 | | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
40 | | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
41 | | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
42 | | |
43 | | #pragma once |
44 | | #include <algorithm> |
45 | | #include <cstddef> |
46 | | #include <cstdint> |
47 | | #include <cstdlib> |
48 | | #include <limits> |
49 | | #include <type_traits> |
50 | | #include <utility> |
51 | | #include <vector> |
52 | | #if defined(_OPENMP) && defined(_MSC_VER) |
53 | | #define OMP_PARALLEL_FOR(X) __pragma(omp parallel for schedule(dynamic, X)) |
54 | | #elif defined(_OPENMP) |
55 | | #include <omp.h> |
56 | | #define STR(X) #X |
57 | | #define STRINGIFY(X) STR(X) |
58 | | #define TWO_ARGUMENTS(X,Y,Z) X(Y, Z) |
59 | | #define OMP_PARALLEL_FOR(X) _Pragma(STRINGIFY(TWO_ARGUMENTS(omp parallel for schedule, dynamic, X))) |
60 | | #else |
61 | | #define OMP_PARALLEL_FOR(X) |
62 | | #endif |
63 | | |
64 | | namespace GFWX |
65 | | { |
66 | | enum |
67 | | { |
68 | | QualityMax = 1024, // compress with QualityMax for 100% lossless, or less than QualityMax for lossy |
69 | | ThreadIterations = 64, // OMP settings tuned on my machine with large images |
70 | | BitDepthAuto = 0, BlockDefault = 7, BlockMax = 30, |
71 | | FilterLinear = 0, FilterCubic = 1, QuantizationScalar = 0, EncoderTurbo = 0, EncoderFast = 1, EncoderContextual = 2, |
72 | | IntentGeneric = 0, IntentMono = 1, IntentBayerRGGB = 2, IntentBayerBGGR = 3, IntentBayerGRBG = 4, IntentBayerGBRG = 5, IntentBayerGeneric = 6, |
73 | | IntentRGB = 7, IntentRGBA = 8, IntentRGBApremult = 9, IntentBGR = 10, IntentBGRA = 11, IntentBGRApremult = 12, IntentCMYK = 13, |
74 | | ResultOk = 0, ErrorOverflow = -1, ErrorMalformed = -2, ErrorTypeMismatch = -3 |
75 | | }; |
76 | | |
77 | | struct Header // use the empty constructor to fetch headers before decompressing, and use the parameterized constructor when compressing |
78 | | { |
79 | | int sizex, sizey, layers, channels, bitDepth, quality, chromaScale, blockSize, filter, quantization, encoder, intent, version, isSigned; |
80 | 15 | Header() {} |
81 | | Header(int sizex, int sizey, int layers, int channels, int bitDepth, |
82 | | int quality, int chromaScale, int blockSize, int filter, int quantization, int encoder, int intent) |
83 | 3.04k | : sizex(sizex), sizey(sizey), layers(layers), channels(channels), bitDepth(bitDepth), quality(std::max(1, std::min(int(QualityMax), quality))), |
84 | 3.04k | chromaScale(std::max(1, std::min(256, chromaScale))), blockSize(std::min(30, std::max(2, blockSize))), filter(std::min(255, filter)), |
85 | 3.04k | quantization(std::min(255, quantization)), encoder(std::min(255, encoder)), intent(std::min(255, intent)) {} |
86 | | size_t bufferSize() const |
87 | 23 | { |
88 | 23 | size_t const part1 = static_cast<size_t>(sizex) * sizey; |
89 | 23 | size_t const part2 = static_cast<size_t>(channels) * layers * ((bitDepth + 7) / 8); |
90 | 23 | return std::log(part1) + std::log(part2) > std::log(std::numeric_limits<size_t>::max() - 1) ? 0 : part1 * part2; |
91 | 23 | } |
92 | | }; |
93 | | |
94 | | template<typename T> struct Image // handy wrapper for 2D image data |
95 | | { |
96 | | T * data; |
97 | | int sizex, sizey; |
98 | 3.51M | Image(T * data, int sizex, int sizey) : data(data), sizex(sizex), sizey(sizey) {} |
99 | 740M | T * operator[] (int y) { return data + static_cast<size_t>(y) * sizex; } |
100 | | }; |
101 | | |
102 | | struct Bits // handy wrapper for treating an array of unsigned ints as a bit stream |
103 | | { |
104 | | uint32_t * buffer, * bufferEnd; |
105 | | uint32_t writeCache; |
106 | | int indexBits; // -1 indicates buffer overflow |
107 | 16.2k | Bits(uint32_t * buffer, uint32_t * bufferEnd) : buffer(buffer), bufferEnd(bufferEnd), writeCache(0), indexBits(0) {} |
108 | | uint32_t getBits(int bits) |
109 | 9.80M | { |
110 | 9.80M | int newBits = indexBits + bits; |
111 | 9.80M | if (buffer == bufferEnd) |
112 | 63.4k | return indexBits = -1; // signify overflow |
113 | 9.73M | uint32_t x = *buffer << indexBits; |
114 | 9.73M | if (newBits >= 32) |
115 | 483k | { |
116 | 483k | ++ buffer; |
117 | 483k | if ((newBits -= 32) > 0) |
118 | 7.15k | { |
119 | 7.15k | if (buffer == bufferEnd) |
120 | 1 | return indexBits = -1; // signify overflow |
121 | 7.15k | x |= *buffer >> (32 - indexBits); |
122 | 7.15k | } |
123 | 483k | } |
124 | 9.73M | indexBits = newBits; |
125 | 9.73M | return x >> (32 - bits); |
126 | 9.73M | } |
127 | | void putBits(uint32_t x, int bits) |
128 | 58.1M | { |
129 | 58.1M | int newBits = indexBits + bits; |
130 | 58.1M | if (buffer == bufferEnd) |
131 | 10.7M | newBits = -1; // signify overflow |
132 | 47.3M | else if (newBits < 32) |
133 | 36.1M | (writeCache <<= bits) |= x; |
134 | 11.1M | else if (bits == 32 && newBits == 32) |
135 | 13.8k | { |
136 | 13.8k | newBits = 0; |
137 | 13.8k | *(buffer ++) = x; |
138 | 13.8k | } |
139 | 11.1M | else |
140 | 11.1M | { |
141 | 11.1M | newBits -= 32; |
142 | 11.1M | *(buffer ++) = (writeCache << (bits - newBits)) | (x >> newBits); |
143 | 11.1M | writeCache = x; |
144 | 11.1M | } |
145 | 58.1M | indexBits = newBits; |
146 | 58.1M | } |
147 | | uint32_t getZeros(uint32_t maxZeros) |
148 | 5.33M | { |
149 | 5.33M | int newBits = indexBits; |
150 | 5.33M | if (buffer == bufferEnd) |
151 | 99.3k | return indexBits = -1; // signify overflow |
152 | 5.23M | uint32_t b = *buffer; |
153 | 5.23M | uint32_t x = 0; |
154 | 6.69M | while (true) |
155 | 6.69M | { |
156 | 6.69M | if (newBits == 31) |
157 | 194k | { |
158 | 194k | ++ buffer; |
159 | 194k | if ((b & 1u) || (++ x == maxZeros)) |
160 | 155k | { |
161 | 155k | indexBits = 0; |
162 | 155k | return x; |
163 | 155k | } |
164 | 39.7k | if (buffer == bufferEnd) |
165 | 0 | return indexBits = -1; // signify overflow |
166 | 39.7k | b = *buffer; |
167 | 39.7k | newBits = 0; |
168 | 39.7k | continue; |
169 | 39.7k | } |
170 | 6.49M | if (((b << newBits) & (1u << 31)) || (++ x == maxZeros)) |
171 | 5.08M | { |
172 | 5.08M | indexBits = newBits + 1; |
173 | 5.08M | return x; |
174 | 5.08M | } |
175 | 1.41M | ++ newBits; |
176 | 1.41M | } |
177 | 5.23M | } |
178 | | void flushWriteWord() // [NOTE] does not clear overflow |
179 | 3.50M | { |
180 | 3.50M | putBits(0, (32 - indexBits) % 32); |
181 | 3.50M | } |
182 | | void flushReadWord() // [NOTE] does not clear overflow |
183 | 11 | { |
184 | 11 | if (indexBits <= 0) |
185 | 5 | return; |
186 | 6 | ++ buffer; |
187 | 6 | indexBits = 0; |
188 | 6 | } |
189 | | }; |
190 | | |
191 | | template<int pot> void unsignedCode(uint32_t x, Bits & stream) // limited length power-of-two Golomb-Rice code |
192 | 43.9M | { |
193 | 43.9M | uint32_t const y = x >> (pot); |
194 | 43.9M | if (y >= 12) |
195 | 13.2M | { |
196 | 13.2M | stream.putBits(0, 12); // escape to larger code |
197 | 13.2M | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); |
198 | 13.2M | } |
199 | 30.6M | else |
200 | 30.6M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary |
201 | 43.9M | } void GFWX::unsignedCode<2>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 725k | { | 193 | 725k | uint32_t const y = x >> (pot); | 194 | 725k | if (y >= 12) | 195 | 68.1k | { | 196 | 68.1k | stream.putBits(0, 12); // escape to larger code | 197 | 68.1k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 68.1k | } | 199 | 656k | else | 200 | 656k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 725k | } |
void GFWX::unsignedCode<6>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 68.1k | { | 193 | 68.1k | uint32_t const y = x >> (pot); | 194 | 68.1k | if (y >= 12) | 195 | 10.7k | { | 196 | 10.7k | stream.putBits(0, 12); // escape to larger code | 197 | 10.7k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 10.7k | } | 199 | 57.3k | else | 200 | 57.3k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 68.1k | } |
void GFWX::unsignedCode<10>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 10.7k | { | 193 | 10.7k | uint32_t const y = x >> (pot); | 194 | 10.7k | if (y >= 12) | 195 | 888 | { | 196 | 888 | stream.putBits(0, 12); // escape to larger code | 197 | 888 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 888 | } | 199 | 9.90k | else | 200 | 9.90k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 10.7k | } |
void GFWX::unsignedCode<14>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 888 | { | 193 | 888 | uint32_t const y = x >> (pot); | 194 | 888 | if (y >= 12) | 195 | 36 | { | 196 | 36 | stream.putBits(0, 12); // escape to larger code | 197 | 36 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 36 | } | 199 | 852 | else | 200 | 852 | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 888 | } |
void GFWX::unsignedCode<18>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 36 | { | 193 | 36 | uint32_t const y = x >> (pot); | 194 | 36 | if (y >= 12) | 195 | 0 | { | 196 | 0 | stream.putBits(0, 12); // escape to larger code | 197 | 0 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 0 | } | 199 | 36 | else | 200 | 36 | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 36 | } |
Unexecuted instantiation: void GFWX::unsignedCode<22>(unsigned int, GFWX::Bits&) Unexecuted instantiation: void GFWX::unsignedCode<24>(unsigned int, GFWX::Bits&) void GFWX::unsignedCode<1>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 14.1M | { | 193 | 14.1M | uint32_t const y = x >> (pot); | 194 | 14.1M | if (y >= 12) | 195 | 5.34M | { | 196 | 5.34M | stream.putBits(0, 12); // escape to larger code | 197 | 5.34M | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 5.34M | } | 199 | 8.76M | else | 200 | 8.76M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 14.1M | } |
void GFWX::unsignedCode<5>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 5.34M | { | 193 | 5.34M | uint32_t const y = x >> (pot); | 194 | 5.34M | if (y >= 12) | 195 | 2.24M | { | 196 | 2.24M | stream.putBits(0, 12); // escape to larger code | 197 | 2.24M | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 2.24M | } | 199 | 3.09M | else | 200 | 3.09M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 5.34M | } |
void GFWX::unsignedCode<9>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 2.24M | { | 193 | 2.24M | uint32_t const y = x >> (pot); | 194 | 2.24M | if (y >= 12) | 195 | 11.4k | { | 196 | 11.4k | stream.putBits(0, 12); // escape to larger code | 197 | 11.4k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 11.4k | } | 199 | 2.23M | else | 200 | 2.23M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 2.24M | } |
void GFWX::unsignedCode<13>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 11.4k | { | 193 | 11.4k | uint32_t const y = x >> (pot); | 194 | 11.4k | if (y >= 12) | 195 | 70 | { | 196 | 70 | stream.putBits(0, 12); // escape to larger code | 197 | 70 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 70 | } | 199 | 11.3k | else | 200 | 11.3k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 11.4k | } |
void GFWX::unsignedCode<17>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 70 | { | 193 | 70 | uint32_t const y = x >> (pot); | 194 | 70 | if (y >= 12) | 195 | 0 | { | 196 | 0 | stream.putBits(0, 12); // escape to larger code | 197 | 0 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 0 | } | 199 | 70 | else | 200 | 70 | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 70 | } |
Unexecuted instantiation: void GFWX::unsignedCode<21>(unsigned int, GFWX::Bits&) void GFWX::unsignedCode<3>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 1.05M | { | 193 | 1.05M | uint32_t const y = x >> (pot); | 194 | 1.05M | if (y >= 12) | 195 | 126k | { | 196 | 126k | stream.putBits(0, 12); // escape to larger code | 197 | 126k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 126k | } | 199 | 926k | else | 200 | 926k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 1.05M | } |
void GFWX::unsignedCode<7>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 126k | { | 193 | 126k | uint32_t const y = x >> (pot); | 194 | 126k | if (y >= 12) | 195 | 12.0k | { | 196 | 12.0k | stream.putBits(0, 12); // escape to larger code | 197 | 12.0k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 12.0k | } | 199 | 114k | else | 200 | 114k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 126k | } |
void GFWX::unsignedCode<11>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 12.0k | { | 193 | 12.0k | uint32_t const y = x >> (pot); | 194 | 12.0k | if (y >= 12) | 195 | 178 | { | 196 | 178 | stream.putBits(0, 12); // escape to larger code | 197 | 178 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 178 | } | 199 | 11.8k | else | 200 | 11.8k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 12.0k | } |
void GFWX::unsignedCode<15>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 178 | { | 193 | 178 | uint32_t const y = x >> (pot); | 194 | 178 | if (y >= 12) | 195 | 0 | { | 196 | 0 | stream.putBits(0, 12); // escape to larger code | 197 | 0 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 0 | } | 199 | 178 | else | 200 | 178 | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 178 | } |
Unexecuted instantiation: void GFWX::unsignedCode<19>(unsigned int, GFWX::Bits&) Unexecuted instantiation: void GFWX::unsignedCode<23>(unsigned int, GFWX::Bits&) void GFWX::unsignedCode<4>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 12.6M | { | 193 | 12.6M | uint32_t const y = x >> (pot); | 194 | 12.6M | if (y >= 12) | 195 | 4.77M | { | 196 | 4.77M | stream.putBits(0, 12); // escape to larger code | 197 | 4.77M | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 4.77M | } | 199 | 7.84M | else | 200 | 7.84M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 12.6M | } |
void GFWX::unsignedCode<8>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 4.77M | { | 193 | 4.77M | uint32_t const y = x >> (pot); | 194 | 4.77M | if (y >= 12) | 195 | 77.5k | { | 196 | 77.5k | stream.putBits(0, 12); // escape to larger code | 197 | 77.5k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 77.5k | } | 199 | 4.69M | else | 200 | 4.69M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 4.77M | } |
void GFWX::unsignedCode<12>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 77.5k | { | 193 | 77.5k | uint32_t const y = x >> (pot); | 194 | 77.5k | if (y >= 12) | 195 | 97 | { | 196 | 97 | stream.putBits(0, 12); // escape to larger code | 197 | 97 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 97 | } | 199 | 77.4k | else | 200 | 77.4k | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 77.5k | } |
void GFWX::unsignedCode<16>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 97 | { | 193 | 97 | uint32_t const y = x >> (pot); | 194 | 97 | if (y >= 12) | 195 | 0 | { | 196 | 0 | stream.putBits(0, 12); // escape to larger code | 197 | 0 | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 0 | } | 199 | 97 | else | 200 | 97 | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 97 | } |
Unexecuted instantiation: void GFWX::unsignedCode<20>(unsigned int, GFWX::Bits&) void GFWX::unsignedCode<0>(unsigned int, GFWX::Bits&) Line | Count | Source | 192 | 2.73M | { | 193 | 2.73M | uint32_t const y = x >> (pot); | 194 | 2.73M | if (y >= 12) | 195 | 572k | { | 196 | 572k | stream.putBits(0, 12); // escape to larger code | 197 | 572k | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); | 198 | 572k | } | 199 | 2.15M | else | 200 | 2.15M | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary | 201 | 2.73M | } |
|
202 | | |
203 | | template<int pot> uint32_t unsignedDecode(Bits & stream) |
204 | 5.33M | { |
205 | 5.33M | uint32_t x = stream.getZeros(12); |
206 | 5.33M | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. |
207 | 5.33M | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; |
208 | 5.33M | } unsigned int GFWX::unsignedDecode<2>(GFWX::Bits&) Line | Count | Source | 204 | 5.03M | { | 205 | 5.03M | uint32_t x = stream.getZeros(12); | 206 | 5.03M | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 5.03M | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 5.03M | } |
unsigned int GFWX::unsignedDecode<6>(GFWX::Bits&) Line | Count | Source | 204 | 1.00k | { | 205 | 1.00k | uint32_t x = stream.getZeros(12); | 206 | 1.00k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.00k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.00k | } |
unsigned int GFWX::unsignedDecode<10>(GFWX::Bits&) Line | Count | Source | 204 | 956 | { | 205 | 956 | uint32_t x = stream.getZeros(12); | 206 | 956 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 956 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 956 | } |
unsigned int GFWX::unsignedDecode<14>(GFWX::Bits&) Line | Count | Source | 204 | 926 | { | 205 | 926 | uint32_t x = stream.getZeros(12); | 206 | 926 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 926 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 926 | } |
unsigned int GFWX::unsignedDecode<18>(GFWX::Bits&) Line | Count | Source | 204 | 914 | { | 205 | 914 | uint32_t x = stream.getZeros(12); | 206 | 914 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 914 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 914 | } |
unsigned int GFWX::unsignedDecode<22>(GFWX::Bits&) Line | Count | Source | 204 | 911 | { | 205 | 911 | uint32_t x = stream.getZeros(12); | 206 | 911 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 911 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 911 | } |
unsigned int GFWX::unsignedDecode<26>(GFWX::Bits&) Line | Count | Source | 204 | 909 | { | 205 | 909 | uint32_t x = stream.getZeros(12); | 206 | 909 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 909 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 909 | } |
unsigned int GFWX::unsignedDecode<30>(GFWX::Bits&) Line | Count | Source | 204 | 907 | { | 205 | 907 | uint32_t x = stream.getZeros(12); | 206 | 907 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 907 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 907 | } |
unsigned int GFWX::unsignedDecode<34>(GFWX::Bits&) Line | Count | Source | 204 | 907 | { | 205 | 907 | uint32_t x = stream.getZeros(12); | 206 | 907 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 907 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 907 | } |
unsigned int GFWX::unsignedDecode<38>(GFWX::Bits&) Line | Count | Source | 204 | 901 | { | 205 | 901 | uint32_t x = stream.getZeros(12); | 206 | 901 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 901 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 901 | } |
unsigned int GFWX::unsignedDecode<42>(GFWX::Bits&) Line | Count | Source | 204 | 899 | { | 205 | 899 | uint32_t x = stream.getZeros(12); | 206 | 899 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 899 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 899 | } |
unsigned int GFWX::unsignedDecode<46>(GFWX::Bits&) Line | Count | Source | 204 | 898 | { | 205 | 898 | uint32_t x = stream.getZeros(12); | 206 | 898 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 898 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 898 | } |
unsigned int GFWX::unsignedDecode<50>(GFWX::Bits&) Line | Count | Source | 204 | 895 | { | 205 | 895 | uint32_t x = stream.getZeros(12); | 206 | 895 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 895 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 895 | } |
unsigned int GFWX::unsignedDecode<54>(GFWX::Bits&) Line | Count | Source | 204 | 895 | { | 205 | 895 | uint32_t x = stream.getZeros(12); | 206 | 895 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 895 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 895 | } |
unsigned int GFWX::unsignedDecode<58>(GFWX::Bits&) Line | Count | Source | 204 | 895 | { | 205 | 895 | uint32_t x = stream.getZeros(12); | 206 | 895 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 895 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 895 | } |
unsigned int GFWX::unsignedDecode<62>(GFWX::Bits&) Line | Count | Source | 204 | 893 | { | 205 | 893 | uint32_t x = stream.getZeros(12); | 206 | 893 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 893 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 893 | } |
unsigned int GFWX::unsignedDecode<66>(GFWX::Bits&) Line | Count | Source | 204 | 875 | { | 205 | 875 | uint32_t x = stream.getZeros(12); | 206 | 875 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 875 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 875 | } |
unsigned int GFWX::unsignedDecode<70>(GFWX::Bits&) Line | Count | Source | 204 | 874 | { | 205 | 874 | uint32_t x = stream.getZeros(12); | 206 | 874 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 874 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 874 | } |
unsigned int GFWX::unsignedDecode<74>(GFWX::Bits&) Line | Count | Source | 204 | 871 | { | 205 | 871 | uint32_t x = stream.getZeros(12); | 206 | 871 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 871 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 871 | } |
unsigned int GFWX::unsignedDecode<78>(GFWX::Bits&) Line | Count | Source | 204 | 871 | { | 205 | 871 | uint32_t x = stream.getZeros(12); | 206 | 871 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 871 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 871 | } |
unsigned int GFWX::unsignedDecode<82>(GFWX::Bits&) Line | Count | Source | 204 | 871 | { | 205 | 871 | uint32_t x = stream.getZeros(12); | 206 | 871 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 871 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 871 | } |
unsigned int GFWX::unsignedDecode<86>(GFWX::Bits&) Line | Count | Source | 204 | 869 | { | 205 | 869 | uint32_t x = stream.getZeros(12); | 206 | 869 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 869 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 869 | } |
unsigned int GFWX::unsignedDecode<90>(GFWX::Bits&) Line | Count | Source | 204 | 869 | { | 205 | 869 | uint32_t x = stream.getZeros(12); | 206 | 869 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 869 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 869 | } |
unsigned int GFWX::unsignedDecode<94>(GFWX::Bits&) Line | Count | Source | 204 | 863 | { | 205 | 863 | uint32_t x = stream.getZeros(12); | 206 | 863 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 863 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 863 | } |
unsigned int GFWX::unsignedDecode<98>(GFWX::Bits&) Line | Count | Source | 204 | 863 | { | 205 | 863 | uint32_t x = stream.getZeros(12); | 206 | 863 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 863 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 863 | } |
unsigned int GFWX::unsignedDecode<102>(GFWX::Bits&) Line | Count | Source | 204 | 863 | { | 205 | 863 | uint32_t x = stream.getZeros(12); | 206 | 863 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 863 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 863 | } |
unsigned int GFWX::unsignedDecode<106>(GFWX::Bits&) Line | Count | Source | 204 | 862 | { | 205 | 862 | uint32_t x = stream.getZeros(12); | 206 | 862 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 862 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 862 | } |
unsigned int GFWX::unsignedDecode<110>(GFWX::Bits&) Line | Count | Source | 204 | 862 | { | 205 | 862 | uint32_t x = stream.getZeros(12); | 206 | 862 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 862 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 862 | } |
unsigned int GFWX::unsignedDecode<1>(GFWX::Bits&) Line | Count | Source | 204 | 51.1k | { | 205 | 51.1k | uint32_t x = stream.getZeros(12); | 206 | 51.1k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 51.1k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 51.1k | } |
unsigned int GFWX::unsignedDecode<5>(GFWX::Bits&) Line | Count | Source | 204 | 5.23k | { | 205 | 5.23k | uint32_t x = stream.getZeros(12); | 206 | 5.23k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 5.23k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 5.23k | } |
unsigned int GFWX::unsignedDecode<9>(GFWX::Bits&) Line | Count | Source | 204 | 4.48k | { | 205 | 4.48k | uint32_t x = stream.getZeros(12); | 206 | 4.48k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 4.48k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 4.48k | } |
unsigned int GFWX::unsignedDecode<13>(GFWX::Bits&) Line | Count | Source | 204 | 3.80k | { | 205 | 3.80k | uint32_t x = stream.getZeros(12); | 206 | 3.80k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 3.80k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 3.80k | } |
unsigned int GFWX::unsignedDecode<17>(GFWX::Bits&) Line | Count | Source | 204 | 3.61k | { | 205 | 3.61k | uint32_t x = stream.getZeros(12); | 206 | 3.61k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 3.61k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 3.61k | } |
unsigned int GFWX::unsignedDecode<21>(GFWX::Bits&) Line | Count | Source | 204 | 3.11k | { | 205 | 3.11k | uint32_t x = stream.getZeros(12); | 206 | 3.11k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 3.11k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 3.11k | } |
unsigned int GFWX::unsignedDecode<25>(GFWX::Bits&) Line | Count | Source | 204 | 2.97k | { | 205 | 2.97k | uint32_t x = stream.getZeros(12); | 206 | 2.97k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.97k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.97k | } |
unsigned int GFWX::unsignedDecode<29>(GFWX::Bits&) Line | Count | Source | 204 | 2.88k | { | 205 | 2.88k | uint32_t x = stream.getZeros(12); | 206 | 2.88k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.88k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.88k | } |
unsigned int GFWX::unsignedDecode<33>(GFWX::Bits&) Line | Count | Source | 204 | 2.80k | { | 205 | 2.80k | uint32_t x = stream.getZeros(12); | 206 | 2.80k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.80k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.80k | } |
unsigned int GFWX::unsignedDecode<37>(GFWX::Bits&) Line | Count | Source | 204 | 2.71k | { | 205 | 2.71k | uint32_t x = stream.getZeros(12); | 206 | 2.71k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.71k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.71k | } |
unsigned int GFWX::unsignedDecode<41>(GFWX::Bits&) Line | Count | Source | 204 | 2.63k | { | 205 | 2.63k | uint32_t x = stream.getZeros(12); | 206 | 2.63k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.63k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.63k | } |
unsigned int GFWX::unsignedDecode<45>(GFWX::Bits&) Line | Count | Source | 204 | 2.59k | { | 205 | 2.59k | uint32_t x = stream.getZeros(12); | 206 | 2.59k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.59k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.59k | } |
unsigned int GFWX::unsignedDecode<49>(GFWX::Bits&) Line | Count | Source | 204 | 2.52k | { | 205 | 2.52k | uint32_t x = stream.getZeros(12); | 206 | 2.52k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.52k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.52k | } |
unsigned int GFWX::unsignedDecode<53>(GFWX::Bits&) Line | Count | Source | 204 | 2.46k | { | 205 | 2.46k | uint32_t x = stream.getZeros(12); | 206 | 2.46k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.46k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.46k | } |
unsigned int GFWX::unsignedDecode<57>(GFWX::Bits&) Line | Count | Source | 204 | 2.40k | { | 205 | 2.40k | uint32_t x = stream.getZeros(12); | 206 | 2.40k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.40k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.40k | } |
unsigned int GFWX::unsignedDecode<61>(GFWX::Bits&) Line | Count | Source | 204 | 2.35k | { | 205 | 2.35k | uint32_t x = stream.getZeros(12); | 206 | 2.35k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.35k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.35k | } |
unsigned int GFWX::unsignedDecode<65>(GFWX::Bits&) Line | Count | Source | 204 | 2.30k | { | 205 | 2.30k | uint32_t x = stream.getZeros(12); | 206 | 2.30k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.30k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.30k | } |
unsigned int GFWX::unsignedDecode<69>(GFWX::Bits&) Line | Count | Source | 204 | 2.24k | { | 205 | 2.24k | uint32_t x = stream.getZeros(12); | 206 | 2.24k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 2.24k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 2.24k | } |
unsigned int GFWX::unsignedDecode<73>(GFWX::Bits&) Line | Count | Source | 204 | 1.85k | { | 205 | 1.85k | uint32_t x = stream.getZeros(12); | 206 | 1.85k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.85k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.85k | } |
unsigned int GFWX::unsignedDecode<77>(GFWX::Bits&) Line | Count | Source | 204 | 1.81k | { | 205 | 1.81k | uint32_t x = stream.getZeros(12); | 206 | 1.81k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.81k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.81k | } |
unsigned int GFWX::unsignedDecode<81>(GFWX::Bits&) Line | Count | Source | 204 | 1.56k | { | 205 | 1.56k | uint32_t x = stream.getZeros(12); | 206 | 1.56k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.56k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.56k | } |
unsigned int GFWX::unsignedDecode<85>(GFWX::Bits&) Line | Count | Source | 204 | 1.54k | { | 205 | 1.54k | uint32_t x = stream.getZeros(12); | 206 | 1.54k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.54k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.54k | } |
unsigned int GFWX::unsignedDecode<89>(GFWX::Bits&) Line | Count | Source | 204 | 1.48k | { | 205 | 1.48k | uint32_t x = stream.getZeros(12); | 206 | 1.48k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.48k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.48k | } |
unsigned int GFWX::unsignedDecode<93>(GFWX::Bits&) Line | Count | Source | 204 | 1.13k | { | 205 | 1.13k | uint32_t x = stream.getZeros(12); | 206 | 1.13k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.13k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.13k | } |
unsigned int GFWX::unsignedDecode<97>(GFWX::Bits&) Line | Count | Source | 204 | 769 | { | 205 | 769 | uint32_t x = stream.getZeros(12); | 206 | 769 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 769 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 769 | } |
unsigned int GFWX::unsignedDecode<101>(GFWX::Bits&) Line | Count | Source | 204 | 620 | { | 205 | 620 | uint32_t x = stream.getZeros(12); | 206 | 620 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 620 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 620 | } |
unsigned int GFWX::unsignedDecode<105>(GFWX::Bits&) Line | Count | Source | 204 | 456 | { | 205 | 456 | uint32_t x = stream.getZeros(12); | 206 | 456 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 456 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 456 | } |
unsigned int GFWX::unsignedDecode<109>(GFWX::Bits&) Line | Count | Source | 204 | 421 | { | 205 | 421 | uint32_t x = stream.getZeros(12); | 206 | 421 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 421 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 421 | } |
unsigned int GFWX::unsignedDecode<3>(GFWX::Bits&) Line | Count | Source | 204 | 21.0k | { | 205 | 21.0k | uint32_t x = stream.getZeros(12); | 206 | 21.0k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 21.0k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 21.0k | } |
unsigned int GFWX::unsignedDecode<7>(GFWX::Bits&) Line | Count | Source | 204 | 160 | { | 205 | 160 | uint32_t x = stream.getZeros(12); | 206 | 160 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 160 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 160 | } |
unsigned int GFWX::unsignedDecode<11>(GFWX::Bits&) Line | Count | Source | 204 | 121 | { | 205 | 121 | uint32_t x = stream.getZeros(12); | 206 | 121 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 121 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 121 | } |
unsigned int GFWX::unsignedDecode<15>(GFWX::Bits&) Line | Count | Source | 204 | 99 | { | 205 | 99 | uint32_t x = stream.getZeros(12); | 206 | 99 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 99 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 99 | } |
unsigned int GFWX::unsignedDecode<19>(GFWX::Bits&) Line | Count | Source | 204 | 91 | { | 205 | 91 | uint32_t x = stream.getZeros(12); | 206 | 91 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 91 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 91 | } |
unsigned int GFWX::unsignedDecode<23>(GFWX::Bits&) Line | Count | Source | 204 | 87 | { | 205 | 87 | uint32_t x = stream.getZeros(12); | 206 | 87 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 87 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 87 | } |
unsigned int GFWX::unsignedDecode<27>(GFWX::Bits&) Line | Count | Source | 204 | 84 | { | 205 | 84 | uint32_t x = stream.getZeros(12); | 206 | 84 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 84 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 84 | } |
unsigned int GFWX::unsignedDecode<31>(GFWX::Bits&) Line | Count | Source | 204 | 83 | { | 205 | 83 | uint32_t x = stream.getZeros(12); | 206 | 83 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 83 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 83 | } |
unsigned int GFWX::unsignedDecode<35>(GFWX::Bits&) Line | Count | Source | 204 | 83 | { | 205 | 83 | uint32_t x = stream.getZeros(12); | 206 | 83 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 83 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 83 | } |
unsigned int GFWX::unsignedDecode<39>(GFWX::Bits&) Line | Count | Source | 204 | 75 | { | 205 | 75 | uint32_t x = stream.getZeros(12); | 206 | 75 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 75 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 75 | } |
unsigned int GFWX::unsignedDecode<43>(GFWX::Bits&) Line | Count | Source | 204 | 75 | { | 205 | 75 | uint32_t x = stream.getZeros(12); | 206 | 75 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 75 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 75 | } |
unsigned int GFWX::unsignedDecode<47>(GFWX::Bits&) Line | Count | Source | 204 | 71 | { | 205 | 71 | uint32_t x = stream.getZeros(12); | 206 | 71 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 71 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 71 | } |
unsigned int GFWX::unsignedDecode<51>(GFWX::Bits&) Line | Count | Source | 204 | 70 | { | 205 | 70 | uint32_t x = stream.getZeros(12); | 206 | 70 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 70 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 70 | } |
unsigned int GFWX::unsignedDecode<55>(GFWX::Bits&) Line | Count | Source | 204 | 69 | { | 205 | 69 | uint32_t x = stream.getZeros(12); | 206 | 69 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 69 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 69 | } |
unsigned int GFWX::unsignedDecode<59>(GFWX::Bits&) Line | Count | Source | 204 | 68 | { | 205 | 68 | uint32_t x = stream.getZeros(12); | 206 | 68 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 68 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 68 | } |
unsigned int GFWX::unsignedDecode<63>(GFWX::Bits&) Line | Count | Source | 204 | 68 | { | 205 | 68 | uint32_t x = stream.getZeros(12); | 206 | 68 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 68 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 68 | } |
unsigned int GFWX::unsignedDecode<67>(GFWX::Bits&) Line | Count | Source | 204 | 62 | { | 205 | 62 | uint32_t x = stream.getZeros(12); | 206 | 62 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 62 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 62 | } |
unsigned int GFWX::unsignedDecode<71>(GFWX::Bits&) Line | Count | Source | 204 | 62 | { | 205 | 62 | uint32_t x = stream.getZeros(12); | 206 | 62 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 62 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 62 | } |
unsigned int GFWX::unsignedDecode<75>(GFWX::Bits&) Line | Count | Source | 204 | 57 | { | 205 | 57 | uint32_t x = stream.getZeros(12); | 206 | 57 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 57 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 57 | } |
unsigned int GFWX::unsignedDecode<79>(GFWX::Bits&) Line | Count | Source | 204 | 57 | { | 205 | 57 | uint32_t x = stream.getZeros(12); | 206 | 57 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 57 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 57 | } |
unsigned int GFWX::unsignedDecode<83>(GFWX::Bits&) Line | Count | Source | 204 | 55 | { | 205 | 55 | uint32_t x = stream.getZeros(12); | 206 | 55 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 55 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 55 | } |
unsigned int GFWX::unsignedDecode<87>(GFWX::Bits&) Line | Count | Source | 204 | 55 | { | 205 | 55 | uint32_t x = stream.getZeros(12); | 206 | 55 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 55 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 55 | } |
unsigned int GFWX::unsignedDecode<91>(GFWX::Bits&) Line | Count | Source | 204 | 55 | { | 205 | 55 | uint32_t x = stream.getZeros(12); | 206 | 55 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 55 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 55 | } |
unsigned int GFWX::unsignedDecode<95>(GFWX::Bits&) Line | Count | Source | 204 | 53 | { | 205 | 53 | uint32_t x = stream.getZeros(12); | 206 | 53 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 53 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 53 | } |
unsigned int GFWX::unsignedDecode<99>(GFWX::Bits&) Line | Count | Source | 204 | 53 | { | 205 | 53 | uint32_t x = stream.getZeros(12); | 206 | 53 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 53 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 53 | } |
unsigned int GFWX::unsignedDecode<103>(GFWX::Bits&) Line | Count | Source | 204 | 53 | { | 205 | 53 | uint32_t x = stream.getZeros(12); | 206 | 53 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 53 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 53 | } |
unsigned int GFWX::unsignedDecode<107>(GFWX::Bits&) Line | Count | Source | 204 | 53 | { | 205 | 53 | uint32_t x = stream.getZeros(12); | 206 | 53 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 53 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 53 | } |
unsigned int GFWX::unsignedDecode<111>(GFWX::Bits&) Line | Count | Source | 204 | 53 | { | 205 | 53 | uint32_t x = stream.getZeros(12); | 206 | 53 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 53 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 53 | } |
unsigned int GFWX::unsignedDecode<4>(GFWX::Bits&) Line | Count | Source | 204 | 61.0k | { | 205 | 61.0k | uint32_t x = stream.getZeros(12); | 206 | 61.0k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 61.0k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 61.0k | } |
unsigned int GFWX::unsignedDecode<8>(GFWX::Bits&) Line | Count | Source | 204 | 1.72k | { | 205 | 1.72k | uint32_t x = stream.getZeros(12); | 206 | 1.72k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.72k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.72k | } |
unsigned int GFWX::unsignedDecode<12>(GFWX::Bits&) Line | Count | Source | 204 | 1.32k | { | 205 | 1.32k | uint32_t x = stream.getZeros(12); | 206 | 1.32k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.32k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.32k | } |
unsigned int GFWX::unsignedDecode<16>(GFWX::Bits&) Line | Count | Source | 204 | 1.17k | { | 205 | 1.17k | uint32_t x = stream.getZeros(12); | 206 | 1.17k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.17k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.17k | } |
unsigned int GFWX::unsignedDecode<20>(GFWX::Bits&) Line | Count | Source | 204 | 1.12k | { | 205 | 1.12k | uint32_t x = stream.getZeros(12); | 206 | 1.12k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.12k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.12k | } |
unsigned int GFWX::unsignedDecode<24>(GFWX::Bits&) Line | Count | Source | 204 | 1.08k | { | 205 | 1.08k | uint32_t x = stream.getZeros(12); | 206 | 1.08k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.08k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.08k | } |
unsigned int GFWX::unsignedDecode<28>(GFWX::Bits&) Line | Count | Source | 204 | 1.06k | { | 205 | 1.06k | uint32_t x = stream.getZeros(12); | 206 | 1.06k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.06k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.06k | } |
unsigned int GFWX::unsignedDecode<32>(GFWX::Bits&) Line | Count | Source | 204 | 1.04k | { | 205 | 1.04k | uint32_t x = stream.getZeros(12); | 206 | 1.04k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.04k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.04k | } |
unsigned int GFWX::unsignedDecode<36>(GFWX::Bits&) Line | Count | Source | 204 | 1.04k | { | 205 | 1.04k | uint32_t x = stream.getZeros(12); | 206 | 1.04k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.04k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.04k | } |
unsigned int GFWX::unsignedDecode<40>(GFWX::Bits&) Line | Count | Source | 204 | 1.01k | { | 205 | 1.01k | uint32_t x = stream.getZeros(12); | 206 | 1.01k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 1.01k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 1.01k | } |
unsigned int GFWX::unsignedDecode<44>(GFWX::Bits&) Line | Count | Source | 204 | 986 | { | 205 | 986 | uint32_t x = stream.getZeros(12); | 206 | 986 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 986 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 986 | } |
unsigned int GFWX::unsignedDecode<48>(GFWX::Bits&) Line | Count | Source | 204 | 968 | { | 205 | 968 | uint32_t x = stream.getZeros(12); | 206 | 968 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 968 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 968 | } |
unsigned int GFWX::unsignedDecode<52>(GFWX::Bits&) Line | Count | Source | 204 | 946 | { | 205 | 946 | uint32_t x = stream.getZeros(12); | 206 | 946 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 946 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 946 | } |
unsigned int GFWX::unsignedDecode<56>(GFWX::Bits&) Line | Count | Source | 204 | 938 | { | 205 | 938 | uint32_t x = stream.getZeros(12); | 206 | 938 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 938 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 938 | } |
unsigned int GFWX::unsignedDecode<60>(GFWX::Bits&) Line | Count | Source | 204 | 926 | { | 205 | 926 | uint32_t x = stream.getZeros(12); | 206 | 926 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 926 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 926 | } |
unsigned int GFWX::unsignedDecode<64>(GFWX::Bits&) Line | Count | Source | 204 | 924 | { | 205 | 924 | uint32_t x = stream.getZeros(12); | 206 | 924 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 924 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 924 | } |
unsigned int GFWX::unsignedDecode<68>(GFWX::Bits&) Line | Count | Source | 204 | 909 | { | 205 | 909 | uint32_t x = stream.getZeros(12); | 206 | 909 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 909 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 909 | } |
unsigned int GFWX::unsignedDecode<72>(GFWX::Bits&) Line | Count | Source | 204 | 831 | { | 205 | 831 | uint32_t x = stream.getZeros(12); | 206 | 831 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 831 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 831 | } |
unsigned int GFWX::unsignedDecode<76>(GFWX::Bits&) Line | Count | Source | 204 | 826 | { | 205 | 826 | uint32_t x = stream.getZeros(12); | 206 | 826 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 826 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 826 | } |
unsigned int GFWX::unsignedDecode<80>(GFWX::Bits&) Line | Count | Source | 204 | 821 | { | 205 | 821 | uint32_t x = stream.getZeros(12); | 206 | 821 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 821 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 821 | } |
unsigned int GFWX::unsignedDecode<84>(GFWX::Bits&) Line | Count | Source | 204 | 806 | { | 205 | 806 | uint32_t x = stream.getZeros(12); | 206 | 806 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 806 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 806 | } |
unsigned int GFWX::unsignedDecode<88>(GFWX::Bits&) Line | Count | Source | 204 | 793 | { | 205 | 793 | uint32_t x = stream.getZeros(12); | 206 | 793 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 793 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 793 | } |
unsigned int GFWX::unsignedDecode<92>(GFWX::Bits&) Line | Count | Source | 204 | 788 | { | 205 | 788 | uint32_t x = stream.getZeros(12); | 206 | 788 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 788 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 788 | } |
unsigned int GFWX::unsignedDecode<96>(GFWX::Bits&) Line | Count | Source | 204 | 770 | { | 205 | 770 | uint32_t x = stream.getZeros(12); | 206 | 770 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 770 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 770 | } |
unsigned int GFWX::unsignedDecode<100>(GFWX::Bits&) Line | Count | Source | 204 | 768 | { | 205 | 768 | uint32_t x = stream.getZeros(12); | 206 | 768 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 768 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 768 | } |
unsigned int GFWX::unsignedDecode<104>(GFWX::Bits&) Line | Count | Source | 204 | 750 | { | 205 | 750 | uint32_t x = stream.getZeros(12); | 206 | 750 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 750 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 750 | } |
unsigned int GFWX::unsignedDecode<108>(GFWX::Bits&) Line | Count | Source | 204 | 711 | { | 205 | 711 | uint32_t x = stream.getZeros(12); | 206 | 711 | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 711 | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 711 | } |
unsigned int GFWX::unsignedDecode<0>(GFWX::Bits&) Line | Count | Source | 204 | 54.5k | { | 205 | 54.5k | uint32_t x = stream.getZeros(12); | 206 | 54.5k | int const p = pot < 24 ? pot : 24; // actual pot. The max 108 below is to prevent unlimited recursion in malformed files, yet admit 2^32 - 1. | 207 | 54.5k | return (pot < 108 && x == 12) ? (12 << p) + unsignedDecode<pot < 108 ? pot + 4 : 108>(stream) : p ? (x << p) + stream.getBits(p) : x; | 208 | 54.5k | } |
|
209 | | |
210 | | template<int pot> void interleavedCode(int x, Bits & stream) |
211 | 12.2M | { |
212 | 12.2M | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values |
213 | 12.2M | } void GFWX::interleavedCode<1>(int, GFWX::Bits&) Line | Count | Source | 211 | 8.07M | { | 212 | 8.07M | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values | 213 | 8.07M | } |
void GFWX::interleavedCode<0>(int, GFWX::Bits&) Line | Count | Source | 211 | 2.73M | { | 212 | 2.73M | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values | 213 | 2.73M | } |
void GFWX::interleavedCode<2>(int, GFWX::Bits&) Line | Count | Source | 211 | 358k | { | 212 | 358k | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values | 213 | 358k | } |
void GFWX::interleavedCode<3>(int, GFWX::Bits&) Line | Count | Source | 211 | 424k | { | 212 | 424k | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values | 213 | 424k | } |
void GFWX::interleavedCode<4>(int, GFWX::Bits&) Line | Count | Source | 211 | 632k | { | 212 | 632k | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values | 213 | 632k | } |
|
214 | | |
215 | | template<int pot> int interleavedDecode(Bits & stream) |
216 | 130k | { |
217 | 130k | int const x = unsignedDecode<pot>(stream); |
218 | 130k | return (x & 1) ? (x + 1) / 2 : -x / 2; |
219 | 130k | } int GFWX::interleavedDecode<1>(GFWX::Bits&) Line | Count | Source | 216 | 45.1k | { | 217 | 45.1k | int const x = unsignedDecode<pot>(stream); | 218 | 45.1k | return (x & 1) ? (x + 1) / 2 : -x / 2; | 219 | 45.1k | } |
int GFWX::interleavedDecode<0>(GFWX::Bits&) Line | Count | Source | 216 | 54.5k | { | 217 | 54.5k | int const x = unsignedDecode<pot>(stream); | 218 | 54.5k | return (x & 1) ? (x + 1) / 2 : -x / 2; | 219 | 54.5k | } |
int GFWX::interleavedDecode<2>(GFWX::Bits&) Line | Count | Source | 216 | 13.8k | { | 217 | 13.8k | int const x = unsignedDecode<pot>(stream); | 218 | 13.8k | return (x & 1) ? (x + 1) / 2 : -x / 2; | 219 | 13.8k | } |
int GFWX::interleavedDecode<3>(GFWX::Bits&) Line | Count | Source | 216 | 11.4k | { | 217 | 11.4k | int const x = unsignedDecode<pot>(stream); | 218 | 11.4k | return (x & 1) ? (x + 1) / 2 : -x / 2; | 219 | 11.4k | } |
int GFWX::interleavedDecode<4>(GFWX::Bits&) Line | Count | Source | 216 | 4.95k | { | 217 | 4.95k | int const x = unsignedDecode<pot>(stream); | 218 | 4.95k | return (x & 1) ? (x + 1) / 2 : -x / 2; | 219 | 4.95k | } |
|
220 | | |
221 | | template<int pot> void signedCode(int x, Bits & stream) |
222 | 12.1M | { |
223 | 12.1M | unsignedCode<pot>(abs(x), stream); |
224 | 12.1M | if (x) |
225 | 10.6M | stream.putBits(x > 0 ? 1 : 0, 1); |
226 | 12.1M | } void GFWX::signedCode<2>(int, GFWX::Bits&) Line | Count | Source | 222 | 312k | { | 223 | 312k | unsignedCode<pot>(abs(x), stream); | 224 | 312k | if (x) | 225 | 227k | stream.putBits(x > 0 ? 1 : 0, 1); | 226 | 312k | } |
void GFWX::signedCode<4>(int, GFWX::Bits&) Line | Count | Source | 222 | 10.8M | { | 223 | 10.8M | unsignedCode<pot>(abs(x), stream); | 224 | 10.8M | if (x) | 225 | 9.77M | stream.putBits(x > 0 ? 1 : 0, 1); | 226 | 10.8M | } |
void GFWX::signedCode<1>(int, GFWX::Bits&) Line | Count | Source | 222 | 304k | { | 223 | 304k | unsignedCode<pot>(abs(x), stream); | 224 | 304k | if (x) | 225 | 165k | stream.putBits(x > 0 ? 1 : 0, 1); | 226 | 304k | } |
void GFWX::signedCode<3>(int, GFWX::Bits&) Line | Count | Source | 222 | 618k | { | 223 | 618k | unsignedCode<pot>(abs(x), stream); | 224 | 618k | if (x) | 225 | 460k | stream.putBits(x > 0 ? 1 : 0, 1); | 226 | 618k | } |
|
227 | | |
228 | | template<int pot> int signedDecode(Bits & stream) |
229 | 5.04M | { |
230 | 5.04M | int x = unsignedDecode<pot>(stream); |
231 | 5.04M | return x ? stream.getBits(1) ? x : -x : 0; |
232 | 5.04M | } int GFWX::signedDecode<2>(GFWX::Bits&) Line | Count | Source | 229 | 5.01M | { | 230 | 5.01M | int x = unsignedDecode<pot>(stream); | 231 | 5.01M | return x ? stream.getBits(1) ? x : -x : 0; | 232 | 5.01M | } |
int GFWX::signedDecode<4>(GFWX::Bits&) Line | Count | Source | 229 | 13.3k | { | 230 | 13.3k | int x = unsignedDecode<pot>(stream); | 231 | 13.3k | return x ? stream.getBits(1) ? x : -x : 0; | 232 | 13.3k | } |
int GFWX::signedDecode<1>(GFWX::Bits&) Line | Count | Source | 229 | 4.30k | { | 230 | 4.30k | int x = unsignedDecode<pot>(stream); | 231 | 4.30k | return x ? stream.getBits(1) ? x : -x : 0; | 232 | 4.30k | } |
int GFWX::signedDecode<3>(GFWX::Bits&) Line | Count | Source | 229 | 8.22k | { | 230 | 8.22k | int x = unsignedDecode<pot>(stream); | 231 | 8.22k | return x ? stream.getBits(1) ? x : -x : 0; | 232 | 8.22k | } |
|
233 | | |
234 | | template<typename T> T median(T a, T b, T c) |
235 | 154M | { |
236 | 154M | return a < b ? c > b ? b : c < a ? a : c : c > a ? a : c < b ? b : c; |
237 | 154M | } |
238 | | |
239 | | template<typename T> T roundFraction(T num, T denom) |
240 | 154M | { |
241 | 154M | return num < 0 ? (num - denom / 2) / denom : (num + denom / 2) / denom; |
242 | 154M | } |
243 | | |
244 | | template<typename T> T cubic(T c0, T c1, T c2, T c3) |
245 | 154M | { |
246 | 154M | return median(T(roundFraction((-c0 + 9 * (c1 + c2) - c3), 16)), c1, c2); |
247 | 154M | } |
248 | | |
249 | | template<typename T> void lift(Image<T> & image, int x0, int y0, int x1, int y1, int step, int filter) |
250 | 21.9k | { |
251 | 21.9k | int const sizex = x1 - x0; |
252 | 21.9k | int const sizey = y1 - y0; |
253 | 127k | while (step < sizex || step < sizey) |
254 | 105k | { |
255 | 105k | if (step < sizex) // horizontal lifting |
256 | 51.2k | { |
257 | 51.2k | OMP_PARALLEL_FOR(ThreadIterations) |
258 | 22.6M | for (int y = 0; y < sizey; y += step) |
259 | 22.5M | { |
260 | 22.5M | int x; |
261 | 22.5M | T * base = &image[y0 + y][x0], * base1 = base - step, * base2 = base + step, * base3 = base + step * 3; |
262 | 22.5M | if (filter == FilterCubic) |
263 | 13.3M | { |
264 | 13.3M | T c0 = *base, c1 = *base, c2 = step * 2 < sizex ? base[step * 2] : *base, c3; |
265 | 28.9M | for (x = step; x < sizex - step * 3; x += step * 2, c0 = c1, c1 = c2, c2 = c3) |
266 | 15.6M | base[x] -= cubic(c0, c1, c2, c3 = base3[x]); |
267 | 30.3M | for (; x < sizex; x += step * 2, c0 = c1, c1 = c2) |
268 | 17.0M | base[x] -= cubic(c0, c1, c2, c2); |
269 | 13.3M | T g0 = base[step], g1 = base[step], g2 = step * 3 < sizex ? base[step * 3] : base[step], g3; |
270 | 28.2M | for (x = step * 2; x < sizex - step * 3; x += step * 2, g0 = g1, g1 = g2, g2 = g3) |
271 | 14.9M | base[x] += cubic(g0, g1, g2, g3 = base3[x]) / 2; |
272 | 19.6M | for (; x < sizex; x += step * 2, g0 = g1, g1 = g2) |
273 | 6.34M | base[x] += cubic(g0, g1, g2, g2) / 2; |
274 | 13.3M | } |
275 | 9.24M | else |
276 | 9.24M | { |
277 | 36.7M | for (x = step; x < sizex - step; x += step * 2) |
278 | 27.5M | base[x] -= (base1[x] + base2[x]) / 2; |
279 | 9.24M | if (x < sizex) |
280 | 7.70M | base[x] -= base1[x]; |
281 | 35.2M | for (x = step * 2; x < sizex - step; x += step * 2) |
282 | 25.9M | base[x] += (base1[x] + base2[x]) / 4; |
283 | 9.24M | if (x < sizex) |
284 | 1.54M | base[x] += base1[x] / 2; |
285 | 9.24M | } |
286 | 22.5M | } |
287 | 51.2k | } |
288 | 105k | if (step < sizey) // vertical lifting |
289 | 74.9k | { |
290 | 74.9k | OMP_PARALLEL_FOR(ThreadIterations) |
291 | 71.0M | for (int y = step; y < sizey; y += step * 2) |
292 | 70.9M | { |
293 | 70.9M | T * const base = &image[y0 + y][x0]; |
294 | 70.9M | T const * const c1base = &image[y0 + y - step][x0], * const c2base = y + step < sizey ? &image[y0 + y + step][x0] : c1base; |
295 | 70.9M | if (filter == FilterCubic) |
296 | 37.9M | { |
297 | 37.9M | T const * const c0base = y - step * 3 >= 0 ? &image[y0 + y - step * 3][x0] : c1base; |
298 | 37.9M | T const * const c3base = y + step * 3 < sizey ? &image[y0 + y + step * 3][x0] : c2base; |
299 | 87.5M | for (int x = 0; x < sizex; x += step) |
300 | 49.6M | base[x] -= cubic(c0base[x], c1base[x], c2base[x], c3base[x]); |
301 | 37.9M | } |
302 | 75.8M | else for (int x = 0; x < sizex; x += step) |
303 | 42.8M | base[x] -= (c1base[x] + c2base[x]) / 2; |
304 | 70.9M | } |
305 | 74.9k | OMP_PARALLEL_FOR(ThreadIterations) |
306 | 70.9M | for (int y = step * 2; y < sizey; y += step * 2) |
307 | 70.9M | { |
308 | 70.9M | T * const base = &image[y0 + y][x0]; |
309 | 70.9M | T const * const g1base = &image[y0 + y - step][x0], * const g2base = y + step < sizey ? &image[y0 + y + step][x0] : g1base; |
310 | 70.9M | if (filter == FilterCubic) |
311 | 37.8M | { |
312 | 37.8M | T const * const g0base = y - step * 3 >= 0 ? &image[y0 + y - step * 3][x0] : g1base; |
313 | 37.8M | T const * const g3base = y + step * 3 < sizey ? &image[y0 + y + step * 3][x0] : g2base; |
314 | 86.9M | for (int x = 0; x < sizex; x += step) |
315 | 49.0M | base[x] += cubic(g0base[x], g1base[x], g2base[x], g3base[x]) / 2; |
316 | 37.8M | } |
317 | 74.7M | else for (int x = 0; x < sizex; x += step) |
318 | 41.7M | base[x] += (g1base[x] + g2base[x]) / 4; |
319 | 70.9M | } |
320 | 74.9k | } |
321 | 105k | step *= 2; |
322 | 105k | } |
323 | 21.9k | } |
324 | | |
325 | | template<typename T> void unlift(Image<T> & image, int x0, int y0, int x1, int y1, int minStep, int filter) |
326 | 542 | { |
327 | 542 | int const sizex = x1 - x0; |
328 | 542 | int const sizey = y1 - y0; |
329 | 542 | int step = minStep; |
330 | 4.38k | while (step * 2 < sizex || step * 2 < sizey) |
331 | 3.84k | step *= 2; |
332 | 4.92k | while (step >= minStep) |
333 | 4.38k | { |
334 | 4.38k | if (step < sizey) // vertical unlifting |
335 | 1.12k | { |
336 | 1.12k | OMP_PARALLEL_FOR(ThreadIterations) |
337 | 15.1k | for (int y = step * 2; y < sizey; y += step * 2) |
338 | 14.0k | { |
339 | 14.0k | T * const base = &image[y0 + y][x0]; |
340 | 14.0k | T const * const g1base = &image[y0 + y - step][x0], * const g2base = y + step < sizey ? &image[y0 + y + step][x0] : g1base; |
341 | 14.0k | if (filter == FilterCubic) |
342 | 5.62k | { |
343 | 5.62k | T const * const g0base = y - step * 3 >= 0 ? &image[y0 + y - step * 3][x0] : g1base; |
344 | 5.62k | T const * const g3base = y + step * 3 < sizey ? &image[y0 + y + step * 3][x0] : g2base; |
345 | 425k | for (int x = 0; x < sizex; x += step) |
346 | 419k | base[x] -= cubic(g0base[x], g1base[x], g2base[x], g3base[x]) / 2; |
347 | 5.62k | } |
348 | 1.39M | else for (int x = 0; x < sizex; x += step) |
349 | 1.39M | base[x] -= (g1base[x] + g2base[x]) / 4; |
350 | 14.0k | } |
351 | 1.12k | OMP_PARALLEL_FOR(ThreadIterations) |
352 | 15.7k | for (int y = step; y < sizey; y += step * 2) |
353 | 14.6k | { |
354 | 14.6k | T * const base = &image[y0 + y][x0]; |
355 | 14.6k | T const * const c1base = &image[y0 + y - step][x0], * const c2base = y + step < sizey ? &image[y0 + y + step][x0] : c1base; |
356 | 14.6k | if (filter == FilterCubic) |
357 | 5.73k | { |
358 | 5.73k | T const * const c0base = y - step * 3 >= 0 ? &image[y0 + y - step * 3][x0] : c1base; |
359 | 5.73k | T const * const c3base = y + step * 3 < sizey ? &image[y0 + y + step * 3][x0] : c2base; |
360 | 427k | for (int x = 0; x < sizex; x += step) |
361 | 421k | base[x] += cubic(c0base[x], c1base[x], c2base[x], c3base[x]); |
362 | 5.73k | } |
363 | 1.45M | else for (int x = 0; x < sizex; x += step) |
364 | 1.45M | base[x] += (c1base[x] + c2base[x]) / 2; |
365 | 14.6k | } |
366 | 1.12k | } |
367 | 4.38k | if (step < sizex) // horizontal unlifting |
368 | 4.35k | { |
369 | 4.35k | OMP_PARALLEL_FOR(ThreadIterations) |
370 | 36.6k | for (int y = 0; y < sizey; y += step) |
371 | 32.3k | { |
372 | 32.3k | int x; |
373 | 32.3k | T * base = &image[y0 + y][x0], * base1 = base - step, * base2 = base + step, * base3 = base + step * 3; |
374 | 32.3k | if (filter == FilterCubic) |
375 | 11.4k | { |
376 | 11.4k | T g0 = base[step], g1 = base[step], g2 = step * 3 < sizex ? base[step * 3] : base[step], g3; |
377 | 409k | for (x = step * 2; x < sizex - step * 3; x += step * 2, g0 = g1, g1 = g2, g2 = g3) |
378 | 397k | base[x] -= cubic(g0, g1, g2, g3 = base3[x]) / 2; |
379 | 25.9k | for (; x < sizex; x += step * 2, g0 = g1, g1 = g2) |
380 | 14.5k | base[x] -= cubic(g0, g1, g2, g2) / 2; |
381 | 11.4k | T c0 = *base, c1 = *base, c2 = step * 2 < sizex ? base[step * 2] : *base, c3; |
382 | 412k | for (x = step; x < sizex - step * 3; x += step * 2, c0 = c1, c1 = c2, c2 = c3) |
383 | 400k | base[x] += cubic(c0, c1, c2, c3 = base3[x]); |
384 | 30.9k | for (; x < sizex; x += step * 2, c0 = c1, c1 = c2) |
385 | 19.5k | base[x] += cubic(c0, c1, c2, c2); |
386 | 11.4k | } |
387 | 20.9k | else |
388 | 20.9k | { |
389 | 1.56M | for (x = step * 2; x < sizex - step; x += step * 2) |
390 | 1.54M | base[x] -= (base1[x] + base2[x]) / 4; |
391 | 20.9k | if (x < sizex) |
392 | 15.2k | base[x] -= base1[x] / 2; |
393 | 1.58M | for (x = step; x < sizex - step; x += step * 2) |
394 | 1.55M | base[x] += (base1[x] + base2[x]) / 2; |
395 | 20.9k | if (x < sizex) |
396 | 5.63k | base[x] += base1[x]; |
397 | 20.9k | } |
398 | 32.3k | } |
399 | 4.35k | } |
400 | 4.38k | step /= 2; |
401 | 4.38k | } |
402 | 542 | } |
403 | | |
404 | | template<typename T, bool dequantize> void quantize(Image<T> & image, int x0, int y0, int x1, int y1, int step, int quality, int minQ, int maxQ) |
405 | 22.5k | { |
406 | 22.5k | typedef typename std::conditional<sizeof(T) < 4, int32_t, int64_t>::type aux; |
407 | 22.5k | int const sizex = x1 - x0; |
408 | 22.5k | int const sizey = y1 - y0; |
409 | 22.5k | int skip = step; |
410 | 40.0k | while (skip < sizex && skip < sizey) |
411 | 18.7k | { |
412 | 18.7k | int const q = std::max(std::max(1, minQ), quality); |
413 | 18.7k | if (q >= maxQ) break; |
414 | 17.5k | OMP_PARALLEL_FOR(ThreadIterations) |
415 | 21.5M | for (int y = 0; y < sizey; y += skip) |
416 | 21.5M | { |
417 | 21.5M | T * base = &image[y0 + y][x0]; |
418 | 21.5M | int const xStep = (y & skip) ? skip : skip * 2; |
419 | 92.0M | for (int x = xStep - skip; x < sizex; x += xStep) // [NOTE] arranged so that (x | y) & skip == 1 |
420 | 70.5M | base[x] = dequantize ? (aux(base[x]) * maxQ + (base[x] < 0 ? -maxQ / 2 : base[x] > 0 ? maxQ / 2 : 0)) / q : aux(base[x]) * q / maxQ; |
421 | 21.5M | } |
422 | 17.5k | skip *= 2; |
423 | 17.5k | quality = std::min(maxQ, quality * 2); // [MAGIC] This approximates the JPEG 2000 baseline quantizer |
424 | 17.5k | } |
425 | 22.5k | } void GFWX::quantize<short, false>(GFWX::Image<short>&, int, int, int, int, int, int, int, int) Line | Count | Source | 405 | 21.9k | { | 406 | 21.9k | typedef typename std::conditional<sizeof(T) < 4, int32_t, int64_t>::type aux; | 407 | 21.9k | int const sizex = x1 - x0; | 408 | 21.9k | int const sizey = y1 - y0; | 409 | 21.9k | int skip = step; | 410 | 38.7k | while (skip < sizex && skip < sizey) | 411 | 17.8k | { | 412 | 17.8k | int const q = std::max(std::max(1, minQ), quality); | 413 | 17.8k | if (q >= maxQ) break; | 414 | 16.7k | OMP_PARALLEL_FOR(ThreadIterations) | 415 | 21.4M | for (int y = 0; y < sizey; y += skip) | 416 | 21.4M | { | 417 | 21.4M | T * base = &image[y0 + y][x0]; | 418 | 21.4M | int const xStep = (y & skip) ? skip : skip * 2; | 419 | 89.2M | for (int x = xStep - skip; x < sizex; x += xStep) // [NOTE] arranged so that (x | y) & skip == 1 | 420 | 67.7M | base[x] = dequantize ? (aux(base[x]) * maxQ + (base[x] < 0 ? -maxQ / 2 : base[x] > 0 ? maxQ / 2 : 0)) / q : aux(base[x]) * q / maxQ; | 421 | 21.4M | } | 422 | 16.7k | skip *= 2; | 423 | 16.7k | quality = std::min(maxQ, quality * 2); // [MAGIC] This approximates the JPEG 2000 baseline quantizer | 424 | 16.7k | } | 425 | 21.9k | } |
void GFWX::quantize<short, true>(GFWX::Image<short>&, int, int, int, int, int, int, int, int) Line | Count | Source | 405 | 542 | { | 406 | 542 | typedef typename std::conditional<sizeof(T) < 4, int32_t, int64_t>::type aux; | 407 | 542 | int const sizex = x1 - x0; | 408 | 542 | int const sizey = y1 - y0; | 409 | 542 | int skip = step; | 410 | 1.30k | while (skip < sizex && skip < sizey) | 411 | 917 | { | 412 | 917 | int const q = std::max(std::max(1, minQ), quality); | 413 | 917 | if (q >= maxQ) break; | 414 | 761 | OMP_PARALLEL_FOR(ThreadIterations) | 415 | 28.9k | for (int y = 0; y < sizey; y += skip) | 416 | 28.2k | { | 417 | 28.2k | T * base = &image[y0 + y][x0]; | 418 | 28.2k | int const xStep = (y & skip) ? skip : skip * 2; | 419 | 2.83M | for (int x = xStep - skip; x < sizex; x += xStep) // [NOTE] arranged so that (x | y) & skip == 1 | 420 | 2.80M | base[x] = dequantize ? (aux(base[x]) * maxQ + (base[x] < 0 ? -maxQ / 2 : base[x] > 0 ? maxQ / 2 : 0)) / q : aux(base[x]) * q / maxQ; | 421 | 28.2k | } | 422 | 761 | skip *= 2; | 423 | 761 | quality = std::min(maxQ, quality * 2); // [MAGIC] This approximates the JPEG 2000 baseline quantizer | 424 | 761 | } | 425 | 542 | } |
|
426 | | |
427 | | template<typename T> T square(T t) |
428 | 49.8M | { |
429 | 49.8M | return t * t; |
430 | 49.8M | } |
431 | | |
432 | | inline void addContext(int x, int w, uint32_t & sum, uint32_t & sum2, uint32_t & count) |
433 | 28.2M | { |
434 | 28.2M | sum += uint32_t(x = abs(x)) * w; |
435 | 28.2M | sum2 += square(std::min(uint32_t(x), 4096u)) * w; // [MAGIC] avoid overflow in last line of getContext |
436 | 28.2M | count += w; |
437 | 28.2M | } |
438 | | |
439 | | template<typename T> std::pair<uint32_t, uint32_t> getContext(Image<T> & image, int x0, int y0, int x1, int y1, int x, int y, int skip) |
440 | 12.3M | { |
441 | 12.3M | int px = x0 + (x & ~(skip * 2)) + (x & skip); |
442 | 12.3M | if (px >= x1) |
443 | 927k | px -= skip * 2; |
444 | 12.3M | int py = y0 + (y & ~(skip * 2)) + (y & skip); |
445 | 12.3M | if (py >= y1) |
446 | 681k | py -= skip * 2; |
447 | 12.3M | uint32_t count = 0, sum = 0, sum2 = 0; |
448 | 12.3M | addContext(abs(image[py][px]), 2, sum, sum2, count); // ancestor |
449 | 12.3M | if ((y & skip) && (x | skip) < x1 - x0) |
450 | 3.05M | { |
451 | 3.05M | addContext(image[y0 + y - skip][x0 + (x | skip)], 2, sum, sum2, count); // upper sibling |
452 | 3.05M | if (x & skip) |
453 | 1.52M | addContext(image[y0 + y][x0 + x - skip], 2, sum, sum2, count); // left sibling |
454 | 3.05M | } |
455 | 12.3M | if (y >= skip * 2 && x >= skip * 2) // neighbors |
456 | 1.83M | { |
457 | 1.83M | addContext(image[y0 + y - skip * 2][x0 + x], 4, sum, sum2, count); |
458 | 1.83M | addContext(image[y0 + y][x0 + x - skip * 2], 4, sum, sum2, count); |
459 | 1.83M | addContext(image[y0 + y - skip * 2][x0 + x - skip * 2], 2, sum, sum2, count); |
460 | 1.83M | if (x + skip * 2 < x1 - x0) |
461 | 1.61M | addContext(image[y0 + y - skip * 2][x0 + x + skip * 2], 2, sum, sum2, count); |
462 | 1.83M | if (y >= skip * 4 && x >= skip * 4) |
463 | 1.10M | { |
464 | 1.10M | addContext(image[y0 + y - skip * 4][x0 + x], 2, sum, sum2, count); |
465 | 1.10M | addContext(image[y0 + y][x0 + x - skip * 4], 2, sum, sum2, count); |
466 | 1.10M | addContext(image[y0 + y - skip * 4][x0 + x - skip * 4], 1, sum, sum2, count); |
467 | 1.10M | if (x + skip * 4 < x1 - x0) |
468 | 914k | addContext(image[y0 + y - skip * 4][x0 + x + skip * 4], 1, sum, sum2, count); |
469 | 1.10M | } |
470 | 1.83M | } |
471 | 12.3M | return std::make_pair((sum * 16u + count / 2u) / count, (sum2 * 16u + count / 2u) / count); // set sums relative to 16 count |
472 | 12.3M | } |
473 | | |
474 | | template<typename T> void encode(Image<T> & image, Bits & stream, int x0, int y0, int x1, int y1, int step, int scheme, int q, bool hasDC, bool isChroma) |
475 | 8.32M | { |
476 | 8.32M | int const sizex = x1 - x0; |
477 | 8.32M | int const sizey = y1 - y0; |
478 | 8.32M | if (hasDC && sizex > 0 && sizey > 0) |
479 | 15.1k | signedCode<4>(image[y0][x0], stream); |
480 | 8.32M | std::pair<uint32_t, uint32_t> context(0, 0); |
481 | 8.32M | int run = 0, runCoder = (scheme == EncoderTurbo ? (!q || (step < 2048 && q * step < 2048)) ? 1 : 0 : 0); // avoid overflow checking q * step < 2048 |
482 | 99.7M | for (int y = 0; y < sizey; y += step) |
483 | 91.4M | { |
484 | 91.4M | T * base = &image[y0 + y][x0]; |
485 | 91.4M | int const xStep = (y & step) ? step : step * 2; |
486 | 185M | for (int x = xStep - step; x < sizex; x += xStep) // [NOTE] arranged so that (x | y) & step == 1 |
487 | 94.3M | { |
488 | 94.3M | T s = base[x]; |
489 | 94.3M | if (runCoder && !s) // run |
490 | 70.0M | ++ run; |
491 | 24.3M | else |
492 | 24.3M | { |
493 | 24.3M | if (scheme == EncoderTurbo) |
494 | 7.48M | { |
495 | 7.48M | if (runCoder) // break the run |
496 | 4.39M | { |
497 | 4.39M | unsignedCode<1>(run, stream); |
498 | 4.39M | run = 0; |
499 | 4.39M | interleavedCode<1>(s < 0 ? s + 1 : s, stream); // s can't be zero, so shift negatives by 1 |
500 | 4.39M | } |
501 | 3.08M | else |
502 | 3.08M | interleavedCode<1>(s, stream); |
503 | 7.48M | continue; |
504 | 7.48M | } |
505 | 16.8M | if (runCoder) // break the run |
506 | 380k | { |
507 | 380k | runCoder == 1 ? unsignedCode<1>(run, stream) : runCoder == 2 ? unsignedCode<2>(run, stream) |
508 | 282k | : runCoder == 3 ? unsignedCode<3>(run, stream) : unsignedCode<4>(run, stream); |
509 | 380k | run = 0; |
510 | 380k | if (s < 0) |
511 | 191k | ++ s; // s can't be zero, so shift negatives by 1 |
512 | 380k | } |
513 | 16.8M | if (scheme == EncoderContextual) |
514 | 12.2M | context = getContext(image, x0, y0, x1, y1, x, y, step); |
515 | 16.8M | uint32_t const sumSq = square(context.first); |
516 | 16.8M | if (sumSq < 2u * context.second + (isChroma ? 250u : 100u)) |
517 | 2.73M | interleavedCode<0>(s, stream); |
518 | 14.1M | else if (sumSq < 2u * context.second + 950u) |
519 | 590k | interleavedCode<1>(s, stream); |
520 | 13.5M | else if (sumSq < 3u * context.second + 3000u) |
521 | 663k | { |
522 | 663k | if (sumSq < 5u * context.second + 400u) |
523 | 304k | signedCode<1>(s, stream); |
524 | 358k | else |
525 | 358k | interleavedCode<2>(s, stream); |
526 | 663k | } |
527 | 12.8M | else if (sumSq < 3u * context.second + 12000u) |
528 | 716k | { |
529 | 716k | if (sumSq < 5u * context.second + 3000u) |
530 | 292k | signedCode<2>(s, stream); |
531 | 424k | else |
532 | 424k | interleavedCode<3>(s, stream); |
533 | 716k | } |
534 | 12.1M | else if (sumSq < 4u * context.second + 44000u) |
535 | 1.25M | { |
536 | 1.25M | if (sumSq < 6u * context.second + 12000u) |
537 | 618k | signedCode<3>(s, stream); |
538 | 632k | else |
539 | 632k | interleavedCode<4>(s, stream); |
540 | 1.25M | } |
541 | 10.8M | else |
542 | 10.8M | signedCode<4>(s, stream); |
543 | 16.8M | if (scheme == EncoderFast) // use decaying first and second moment |
544 | 4.61M | { |
545 | 4.61M | uint32_t const t = abs(s); |
546 | 4.61M | context = std::make_pair(((context.first * 15u + 7u) >> 4) + t, ((context.second * 15u + 7u) >> 4) + square(std::min(t, 4096u))); |
547 | 4.61M | if (!s == !runCoder) |
548 | 1.99M | runCoder = context.first < 1 ? 4 : context.first < 2 ? 3 : context.first < 4 ? 2 : context.first < 8 ? 1 : 0; |
549 | 4.61M | } |
550 | 12.2M | else if (!s == !runCoder) |
551 | 2.17M | runCoder = q == 1024 ? context.first < 2u ? 1 : 0 : (context.first < 4u && context.second < 2u) ? 4 : (context.first < 8u |
552 | 1.64M | && context.second < 4u) ? 3 : (2u * sumSq < 3u * context.second + 48u) ? 2 : (2u * sumSq < 5u * context.second + 32u) ? 1 : 0; |
553 | 16.8M | } |
554 | 94.3M | } |
555 | 91.4M | } |
556 | 8.32M | if (run) // flush run |
557 | 1.53M | runCoder == 1 ? unsignedCode<1>(run, stream) : runCoder == 2 ? unsignedCode<2>(run, stream) |
558 | 300k | : runCoder == 3 ? unsignedCode<3>(run, stream) : unsignedCode<4>(run, stream); |
559 | 8.32M | } |
560 | | |
561 | | template<typename T> void decode(Image<T> & image, Bits & stream, int x0, int y0, int x1, int y1, int step, int scheme, int q, bool hasDC, bool isChroma) |
562 | 41 | { |
563 | 41 | int const sizex = x1 - x0; |
564 | 41 | int const sizey = y1 - y0; |
565 | 41 | if (hasDC && sizex > 0 && sizey > 0) |
566 | 4 | image[y0][x0] = signedDecode<4>(stream); |
567 | 41 | std::pair<uint32_t, uint32_t> context(0, 0); |
568 | 41 | int run = -1, runCoder = (scheme == EncoderTurbo ? (!q || (step < 2048 && q * step < 2048)) ? 1 : 0 : 0); // avoid overflow checking q * step < 2048 |
569 | 750 | for (int y = 0; y < sizey; y += step) |
570 | 709 | { |
571 | 709 | T * base = &image[y0 + y][x0]; |
572 | 709 | int const xStep = (y & step) ? step : step * 2; |
573 | 499k | for (int x = xStep - step; x < sizex; x += xStep) // [NOTE] arranged so that (x | y) & step == 1 |
574 | 499k | { |
575 | 499k | T s = 0; |
576 | 499k | if (runCoder && run == -1) |
577 | 50.1k | run = runCoder == 1 ? unsignedDecode<1>(stream) : runCoder == 2 ? unsignedDecode<2>(stream) |
578 | 48.5k | : runCoder == 3 ? unsignedDecode<3>(stream) : unsignedDecode<4>(stream); |
579 | 499k | if (run > 0) |
580 | 336k | -- run; // consume a zero |
581 | 162k | else |
582 | 162k | { |
583 | 162k | if (scheme == EncoderTurbo) |
584 | 16.3k | s = interleavedDecode<1>(stream); |
585 | 145k | else |
586 | 145k | { |
587 | 145k | if (scheme == EncoderContextual) |
588 | 145k | context = getContext(image, x0, y0, x1, y1, x, y, step); |
589 | 145k | uint32_t const sumSq = square(context.first); |
590 | 145k | if (sumSq < 2u * context.second + (isChroma ? 250u : 100u)) |
591 | 54.5k | s = interleavedDecode<0>(stream); |
592 | 91.2k | else if (sumSq < 2u * context.second + 950u) |
593 | 28.7k | s = interleavedDecode<1>(stream); |
594 | 62.4k | else if (sumSq < 3u * context.second + 3000u) |
595 | 18.2k | { |
596 | 18.2k | if (sumSq < 5u * context.second + 400u) |
597 | 4.30k | s = signedDecode<1>(stream); |
598 | 13.8k | else |
599 | 13.8k | s = interleavedDecode<2>(stream); |
600 | 18.2k | } |
601 | 44.2k | else if (sumSq < 3u * context.second + 12000u) |
602 | 17.7k | { |
603 | 17.7k | if (sumSq < 5u * context.second + 3000u) |
604 | 6.29k | s = signedDecode<2>(stream); |
605 | 11.4k | else |
606 | 11.4k | s = interleavedDecode<3>(stream); |
607 | 17.7k | } |
608 | 26.5k | else if (sumSq < 4u * context.second + 44000u) |
609 | 13.1k | { |
610 | 13.1k | if (sumSq < 6u * context.second + 12000u) |
611 | 8.22k | s = signedDecode<3>(stream); |
612 | 4.95k | else |
613 | 4.95k | s = interleavedDecode<4>(stream); |
614 | 13.1k | } |
615 | 13.3k | else |
616 | 13.3k | s = signedDecode<4>(stream); |
617 | 145k | if (scheme == EncoderFast) // use decaying first and second moment |
618 | 0 | { |
619 | 0 | uint32_t const t = abs(s); |
620 | 0 | context = std::make_pair(((context.first * 15u + 7u) >> 4) + t, ((context.second * 15u + 7u) >> 4) + square(std::min(t, 4096u))); |
621 | 0 | if (!s == !runCoder) |
622 | 0 | runCoder = context.first < 1 ? 4 : context.first < 2 ? 3 : context.first < 4 ? 2 : context.first < 8 ? 1 : 0; |
623 | 0 | } |
624 | 145k | else if (!s == !runCoder) |
625 | 17.2k | runCoder = q == 1024 ? context.first < 2u ? 1 : 0 : (context.first < 4u && context.second < 2u) ? 4 : (context.first < 8u |
626 | 13.8k | && context.second < 4u) ? 3 : (2u * sumSq < 3u * context.second + 48u) ? 2 : (2u * sumSq < 5u * context.second + 32u) ? 1 : 0; |
627 | 145k | } |
628 | 162k | if (run == 0 && s <= 0) |
629 | 7.37k | -- s; // s can't be zero, so shift negatives by 1 |
630 | 162k | run = -1; |
631 | 162k | } |
632 | 499k | base[x] = s; |
633 | 499k | } |
634 | 709 | } |
635 | 41 | } |
636 | | |
637 | | template<typename T> void shiftVector(T * data, int shift, int count) |
638 | 1.22k | { |
639 | 1.22k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
640 | 35.3M | for (int i = 0; i < count; ++ i) |
641 | 35.3M | data[i] >>= shift; |
642 | 1.22k | } |
643 | | |
644 | | template<typename I, typename A> void transformTerm(int const * & pc, A * destination, A const * auxData, int const bufferSize, |
645 | | I const & imageData, Header const & header, std::vector<int> const & isChroma, int boost) |
646 | 709k | { |
647 | 1.80M | while (*pc >= 0) |
648 | 1.09M | { |
649 | 1.09M | int const c = *(pc ++); |
650 | 1.09M | A const factor = *(pc ++); |
651 | 1.09M | if (isChroma[c] == -1) |
652 | 301k | { |
653 | 301k | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); |
654 | 301k | A const boostFactor = boost * factor; |
655 | 301k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
656 | 2.97G | for (int i = 0; i < bufferSize; ++ i) |
657 | 2.97G | destination[i] += layer[i * header.channels] * boostFactor; |
658 | 301k | } |
659 | 792k | else |
660 | 792k | { |
661 | 792k | A const * auxDataC = auxData + c * bufferSize; |
662 | 792k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
663 | 5.76G | for (int i = 0; i < bufferSize; ++ i) |
664 | 5.76G | destination[i] += auxDataC[i] * factor; |
665 | 792k | } |
666 | 1.09M | } |
667 | 709k | A const denom = *((++ pc) ++); |
668 | 709k | if (denom == 2) |
669 | 341 | shiftVector(destination, 1, bufferSize); |
670 | 709k | else if (denom == 4) |
671 | 634 | shiftVector(destination, 2, bufferSize); |
672 | 708k | else if (denom == 8) |
673 | 246 | shiftVector(destination, 3, bufferSize); |
674 | 708k | else if (denom > 1) // [NOTE] disallow non-positive denominators |
675 | 457k | { |
676 | 457k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
677 | 1.86G | for (int i = 0; i < bufferSize; ++ i) |
678 | 1.86G | destination[i] /= denom; |
679 | 457k | } |
680 | 709k | } void GFWX::transformTerm<unsigned char const*, short>(int const*&, short*, short const*, int, unsigned char const* const&, GFWX::Header const&, std::__1::vector<int, std::__1::allocator<int> > const&, int) Line | Count | Source | 646 | 2.41k | { | 647 | 5.88k | while (*pc >= 0) | 648 | 3.47k | { | 649 | 3.47k | int const c = *(pc ++); | 650 | 3.47k | A const factor = *(pc ++); | 651 | 3.47k | if (isChroma[c] == -1) | 652 | 1.61k | { | 653 | 1.61k | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); | 654 | 1.61k | A const boostFactor = boost * factor; | 655 | 1.61k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) | 656 | 41.1M | for (int i = 0; i < bufferSize; ++ i) | 657 | 41.1M | destination[i] += layer[i * header.channels] * boostFactor; | 658 | 1.61k | } | 659 | 1.85k | else | 660 | 1.85k | { | 661 | 1.85k | A const * auxDataC = auxData + c * bufferSize; | 662 | 1.85k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) | 663 | 54.7M | for (int i = 0; i < bufferSize; ++ i) | 664 | 54.7M | destination[i] += auxDataC[i] * factor; | 665 | 1.85k | } | 666 | 3.47k | } | 667 | 2.41k | A const denom = *((++ pc) ++); | 668 | 2.41k | if (denom == 2) | 669 | 246 | shiftVector(destination, 1, bufferSize); | 670 | 2.17k | else if (denom == 4) | 671 | 560 | shiftVector(destination, 2, bufferSize); | 672 | 1.61k | else if (denom == 8) | 673 | 246 | shiftVector(destination, 3, bufferSize); | 674 | 1.36k | else if (denom > 1) // [NOTE] disallow non-positive denominators | 675 | 0 | { | 676 | 0 | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) | 677 | 0 | for (int i = 0; i < bufferSize; ++ i) | 678 | 0 | destination[i] /= denom; | 679 | 0 | } | 680 | 2.41k | } |
void GFWX::transformTerm<unsigned char*, short>(int const*&, short*, short const*, int, unsigned char* const&, GFWX::Header const&, std::__1::vector<int, std::__1::allocator<int> > const&, int) Line | Count | Source | 646 | 707k | { | 647 | 1.79M | while (*pc >= 0) | 648 | 1.09M | { | 649 | 1.09M | int const c = *(pc ++); | 650 | 1.09M | A const factor = *(pc ++); | 651 | 1.09M | if (isChroma[c] == -1) | 652 | 299k | { | 653 | 299k | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); | 654 | 299k | A const boostFactor = boost * factor; | 655 | 299k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) | 656 | 2.93G | for (int i = 0; i < bufferSize; ++ i) | 657 | 2.93G | destination[i] += layer[i * header.channels] * boostFactor; | 658 | 299k | } | 659 | 790k | else | 660 | 790k | { | 661 | 790k | A const * auxDataC = auxData + c * bufferSize; | 662 | 790k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) | 663 | 5.71G | for (int i = 0; i < bufferSize; ++ i) | 664 | 5.71G | destination[i] += auxDataC[i] * factor; | 665 | 790k | } | 666 | 1.09M | } | 667 | 707k | A const denom = *((++ pc) ++); | 668 | 707k | if (denom == 2) | 669 | 95 | shiftVector(destination, 1, bufferSize); | 670 | 707k | else if (denom == 4) | 671 | 74 | shiftVector(destination, 2, bufferSize); | 672 | 707k | else if (denom == 8) | 673 | 0 | shiftVector(destination, 3, bufferSize); | 674 | 707k | else if (denom > 1) // [NOTE] disallow non-positive denominators | 675 | 457k | { | 676 | 457k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) | 677 | 1.86G | for (int i = 0; i < bufferSize; ++ i) | 678 | 1.86G | destination[i] /= denom; | 679 | 457k | } | 680 | 707k | } |
|
681 | | |
682 | | // GFWX_TRANSFORM_UYV implements YUV (actually UYV) as R -= G (chroma); B -= G (chroma); G += (R + B) / 4 (luma) |
683 | 3.25k | #define GFWX_TRANSFORM_UYV { 0, 1, -1, -1, 1, 1, 2, 1, -1, -1, 1, 1, 1, 0, 1, 2, 1, -1, 4, 0, -1 } |
684 | | // GFWX_TRANSFORM_A710 implements A710 as R -= G (chroma); B -= (G * 2 + R) / 2 (chroma); G += (B * 2 + R * 3) / 8 (luma) |
685 | 3.25k | #define GFWX_TRANSFORM_A710_BGR { 2, 1, -1, -1, 1, 1, 0, 1, -2, 2, -1, -1, 2, 1, 1, 0, 2, 2, 3, -1, 8, 0, -1 } |
686 | 3.25k | #define GFWX_TRANSFORM_A710_RGB { 0, 1, -1, -1, 1, 1, 2, 1, -2, 0, -1, -1, 2, 1, 1, 2, 2, 0, 3, -1, 8, 0, -1 } |
687 | | |
688 | | template<typename I> ptrdiff_t compress(I const & imageData, Header & header, uint8_t * buffer, size_t size, |
689 | | int const * channelTransform, uint8_t * metaData, size_t metaDataSize) |
690 | 3.02k | { |
691 | 3.02k | typedef typename std::remove_reference<decltype(imageData[0])>::type base; |
692 | 3.02k | typedef typename std::conditional<sizeof(base) < 2, int16_t, int32_t>::type aux; |
693 | 3.02k | if (header.sizex > (1 << 30) || header.sizey > (1 << 30)) // [NOTE] current implementation can't go over 2^30 |
694 | 0 | return ErrorMalformed; |
695 | 3.02k | Bits stream(reinterpret_cast<uint32_t *>(buffer), reinterpret_cast<uint32_t *>(buffer) + size / 4); |
696 | 3.02k | stream.putBits('G' | ('F' << 8) | ('W' << 16) | ('X' << 24), 32); |
697 | 3.02k | stream.putBits(header.version = 1, 32); |
698 | 3.02k | stream.putBits(header.sizex, 32); |
699 | 3.02k | stream.putBits(header.sizey, 32); |
700 | 3.02k | stream.putBits(header.layers - 1, 16); |
701 | 3.02k | stream.putBits(header.channels - 1, 16); |
702 | 3.02k | stream.putBits((header.bitDepth ? header.bitDepth : (header.bitDepth = std::numeric_limits<base>::digits)) - 1, 8); |
703 | 3.02k | stream.putBits(header.isSigned = std::numeric_limits<base>::is_signed ? 1 : 0, 1); |
704 | 3.02k | stream.putBits(header.quality - 1, 10); |
705 | 3.02k | stream.putBits(header.chromaScale - 1, 8); |
706 | 3.02k | stream.putBits(header.blockSize - 2, 5); |
707 | 3.02k | stream.putBits(header.filter, 8); |
708 | 3.02k | stream.putBits(header.quantization, 8); |
709 | 3.02k | stream.putBits(header.encoder, 8); |
710 | 3.02k | stream.putBits(header.intent, 8); |
711 | 3.02k | stream.putBits(int(metaDataSize / 4), 32); |
712 | 3.02k | stream.buffer = std::copy(reinterpret_cast<uint32_t *>(metaData), reinterpret_cast<uint32_t *>(metaData) + metaDataSize / 4, stream.buffer); |
713 | 3.02k | int const bufferSize = header.sizex * header.sizey; |
714 | 3.02k | std::vector<aux> auxData((size_t)header.layers * header.channels * bufferSize, 0); |
715 | 3.02k | std::vector<int> isChroma(header.layers * header.channels, -1); |
716 | 3.02k | int const chromaQuality = std::max(1, (header.quality + header.chromaScale / 2) / header.chromaScale); |
717 | 3.02k | int const boost = header.quality == QualityMax ? 1 : 8; // [NOTE] due to Cubic lifting max multiplier of 20, boost * 20 must be less than 256 |
718 | 3.02k | if (channelTransform) // run color transform program (and also encode it to the file) |
719 | 806 | { |
720 | 806 | int const * pc = channelTransform; |
721 | 3.22k | while (*pc >= 0) |
722 | 2.41k | { |
723 | 2.41k | int const c = *(pc ++); |
724 | 2.41k | aux * destination = &auxData[c * bufferSize]; |
725 | 2.41k | transformTerm(pc, destination, &auxData[0], bufferSize, imageData, header, isChroma, boost); |
726 | 2.41k | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); |
727 | 2.41k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
728 | 61.7M | for (int i = 0; i < bufferSize; ++ i) |
729 | 61.7M | destination[i] += layer[i * header.channels] * boost; |
730 | 2.41k | isChroma[c] = *(pc ++); |
731 | 2.41k | } |
732 | 18.2k | for (int const * i = channelTransform; i <= pc; ++ i) |
733 | 17.4k | signedCode<2>(*i, stream); |
734 | 806 | } |
735 | 2.21k | else |
736 | 2.21k | signedCode<2>(-1, stream); |
737 | 3.02k | stream.flushWriteWord(); |
738 | 12.1k | for (int c = 0; c < header.layers * header.channels; ++ c) if (isChroma[c] == -1) // copy channels having no transform |
739 | 6.65k | { |
740 | 6.65k | aux * destination = &auxData[c * bufferSize]; |
741 | 6.65k | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); |
742 | 6.65k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
743 | 60.3M | for (int i = 0; i < bufferSize; ++ i) |
744 | 60.3M | destination[i] = layer[i * header.channels] * boost; |
745 | 6.65k | isChroma[c] = 0; |
746 | 6.65k | } |
747 | 12.1k | for (int c = 0; c < header.layers * header.channels; ++ c) // lift and quantize the channels |
748 | 9.07k | { |
749 | 9.07k | Image<aux> auxImage(&auxData[c * bufferSize], header.sizex, header.sizey); |
750 | 9.07k | lift(auxImage, 0, 0, header.sizex, header.sizey, 1, header.filter); |
751 | 9.07k | if (header.intent >= IntentBayerRGGB && header.intent <= IntentBayerGeneric) |
752 | 4.30k | { |
753 | 21.5k | for (int ox = 0; ox <= 1; ++ ox) for (int oy = 1 - ox; oy <= 1; ++ oy) |
754 | 12.9k | lift(auxImage, ox, oy, header.sizex, header.sizey, 2, header.filter); |
755 | 25.8k | for (int ox = 0; ox <= 1; ++ ox) for (int oy = 0; oy <= 1; ++ oy) |
756 | 17.2k | quantize<aux, false>(auxImage, ox, oy, header.sizex, header.sizey, 2, |
757 | 17.2k | (ox | oy) ? chromaQuality : header.quality, header.quality, QualityMax * boost); |
758 | 4.30k | } |
759 | 4.76k | else |
760 | 4.76k | quantize<aux, false>(auxImage, 0, 0, header.sizex, header.sizey, 1, isChroma[c] ? chromaQuality : header.quality, 0, QualityMax * boost); |
761 | 9.07k | } |
762 | 3.02k | int step = 1; |
763 | 16.8k | while (step * 2 < header.sizex || step * 2 < header.sizey) |
764 | 13.7k | step *= 2; |
765 | 13.4k | for (bool hasDC = true; step >= 1; hasDC = false) |
766 | 13.1k | { |
767 | 13.1k | int64_t const bs = int64_t(step) << header.blockSize; |
768 | 13.1k | int const blockCountX = (header.sizex + bs - 1) / bs; |
769 | 13.1k | int const blockCountY = (header.sizey + bs - 1) / bs; |
770 | 13.1k | int const blockCount = blockCountX * blockCountY * header.layers * header.channels; |
771 | 13.1k | std::vector<Bits> streamBlock(blockCount, Bits(0, 0)); |
772 | 13.1k | uint32_t * blockBegin = stream.buffer + blockCount; // leave space for block sizes |
773 | 13.1k | if (blockBegin >= stream.bufferEnd) |
774 | 687 | return ErrorOverflow; |
775 | 3.51M | for (int block = 0; block < blockCount; ++ block) // partition buffer into temporary regions for each block |
776 | 3.50M | streamBlock[block].buffer = blockBegin + (stream.bufferEnd - blockBegin) * block / blockCount; |
777 | 3.51M | for (int block = 0; block < blockCount; ++ block) |
778 | 3.50M | streamBlock[block].bufferEnd = block + 1 < blockCount ? streamBlock[block + 1].buffer : stream.bufferEnd; |
779 | 12.4k | OMP_PARALLEL_FOR(4) // [MAGIC] for some reason, 4 is by far the best option here |
780 | 3.51M | for (int block = 0; block < blockCount; ++ block) |
781 | 3.50M | { |
782 | 3.50M | int const bx = block % blockCountX, by = (block / blockCountX) % blockCountY, c = block / (blockCountX * blockCountY); |
783 | 3.50M | Image<aux> auxImage(&auxData[c * bufferSize], header.sizex, header.sizey); |
784 | 3.50M | if (header.intent < IntentBayerRGGB || header.intent > IntentBayerGeneric) |
785 | 1.90M | encode(auxImage, streamBlock[block], bx * bs, by * bs, |
786 | 1.90M | int(std::min((bx + 1) * bs, int64_t(header.sizex))), int(std::min((by + 1) * bs, int64_t(header.sizey))), |
787 | 1.90M | step, header.encoder, isChroma[c] ? chromaQuality : header.quality, hasDC && !bx && !by, isChroma[c] != 0); |
788 | 9.63M | else for (int ox = 0; ox <= 1; ++ ox) for (int oy = 0; oy <= 1; ++ oy) |
789 | 6.42M | encode(auxImage, streamBlock[block], bx * bs + ox, by * bs + oy, |
790 | 6.42M | int(std::min((bx + 1) * bs, int64_t(header.sizex))), int(std::min((by + 1) * bs, int64_t(header.sizey))), |
791 | 6.42M | 2 * step, header.encoder, (ox || oy) ? chromaQuality : header.quality, hasDC && !bx && !by, ox || oy); |
792 | 3.50M | streamBlock[block].flushWriteWord(); |
793 | 3.50M | } |
794 | 2.17M | for (int block = 0; block < blockCount; ++ block) // check streamBlocks for overflow |
795 | 2.16M | if (streamBlock[block].indexBits < 0) |
796 | 2.05k | return ErrorOverflow; |
797 | 2.15M | for (int block = 0; block < blockCount; ++ block) // encode block lengths [NOTE] this 32-bit encoding limits the file size to < 16 GB |
798 | 2.14M | *(stream.buffer ++) = uint32_t(streamBlock[block].buffer - (block ? streamBlock[block - 1].bufferEnd : blockBegin)); |
799 | 2.15M | for (int block = 0; block < blockCount; ++ block) // pack the streamBlock data tightly, by word [NOTE] first block is already packed |
800 | 2.14M | stream.buffer = block ? std::copy(streamBlock[block - 1].bufferEnd, streamBlock[block].buffer, stream.buffer) : streamBlock[0].buffer; |
801 | 10.4k | step /= 2; |
802 | 10.4k | } |
803 | 284 | return reinterpret_cast<uint8_t *>(stream.buffer) - buffer; // return size in bytes |
804 | 3.02k | } |
805 | | |
806 | | template<typename I> ptrdiff_t decompress(I const & imageData, Header & header, uint8_t const * data, size_t size, int downsampling, bool test) |
807 | 26 | { |
808 | 26 | typedef typename std::remove_reference<decltype(imageData[0])>::type base; |
809 | 26 | typedef typename std::conditional<sizeof(base) < 2, int16_t, int32_t>::type aux; |
810 | 26 | Bits stream(reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(data)), reinterpret_cast<uint32_t *>(const_cast<uint8_t *>(data)) + size / 4); |
811 | 26 | if (size < 28) // at least load the header |
812 | 0 | return 28; |
813 | 26 | if (stream.getBits(32) != uint32_t('G' | ('F' << 8) | ('W' << 16) | ('X' << 24))) |
814 | 3 | return ErrorMalformed; |
815 | 23 | header.version = stream.getBits(32); |
816 | 23 | header.sizex = stream.getBits(32); |
817 | 23 | header.sizey = stream.getBits(32); |
818 | 23 | header.layers = stream.getBits(16) + 1; |
819 | 23 | header.channels = stream.getBits(16) + 1; |
820 | 23 | header.bitDepth = stream.getBits(8) + 1; |
821 | 23 | header.isSigned = stream.getBits(1); |
822 | 23 | header.quality = stream.getBits(10) + 1; |
823 | 23 | header.chromaScale = stream.getBits(8) + 1; |
824 | 23 | header.blockSize = stream.getBits(5) + 2; |
825 | 23 | header.filter = stream.getBits(8); |
826 | 23 | header.quantization = stream.getBits(8); |
827 | 23 | header.encoder = stream.getBits(8); |
828 | 23 | header.intent = stream.getBits(8); |
829 | 23 | if (header.sizex < 0 || header.sizex > (1 << 30) || header.sizey < 0 || header.sizey > (1 << 30) || header.bufferSize() == 0) |
830 | 1 | return ErrorMalformed; // [NOTE] current implementation can't go over 2^30 |
831 | 22 | if (!imageData) // just header |
832 | 11 | return ResultOk; |
833 | 11 | if (header.isSigned != (std::numeric_limits<base>::is_signed ? 1 : 0) || header.bitDepth > std::numeric_limits<base>::digits) |
834 | 0 | return ErrorTypeMismatch; // check for correct buffer type (though doesn't test the buffer size) |
835 | | // [NOTE] clients can read metadata themselves by accessing the size (in words) at word[7] and the metadata at word[8+] |
836 | 11 | if ((stream.buffer += stream.getBits(32)) >= stream.bufferEnd) // skip metadata |
837 | 0 | return reinterpret_cast<uint8_t *>(stream.buffer) - data; // suggest point of interest to skip metadata |
838 | 11 | int const sizexDown = (header.sizex + (1 << downsampling) - 1) >> downsampling, sizeyDown = (header.sizey + (1 << downsampling) - 1) >> downsampling; |
839 | 11 | int const bufferSize = sizexDown * sizeyDown; |
840 | 11 | std::vector<aux> auxData((size_t)header.layers * header.channels * bufferSize, 0); |
841 | 11 | std::vector<int> isChroma(header.layers * header.channels, 0), transformProgram, transformSteps; |
842 | 11 | size_t nextPointOfInterest = size + 1024; // guess next point of interest [NOTE] may be larger than the complete file |
843 | 707k | while (true) // decode color transform program (including isChroma flags) |
844 | 707k | { |
845 | 707k | transformProgram.push_back(signedDecode<2>(stream)); // channel |
846 | 707k | if (transformProgram.back() >= static_cast<int>(isChroma.size())) |
847 | 0 | return ErrorMalformed; |
848 | 707k | if (transformProgram.back() < 0) |
849 | 11 | break; |
850 | 707k | transformSteps.push_back(int(transformProgram.size()) - 1); |
851 | 1.79M | while (true) |
852 | 1.79M | { |
853 | 1.79M | if (stream.indexBits < 0) // test for truncation |
854 | 0 | return nextPointOfInterest; // need more data |
855 | 1.79M | transformProgram.push_back(signedDecode<2>(stream)); // other channel |
856 | 1.79M | if (transformProgram.back() >= static_cast<int>(isChroma.size())) |
857 | 0 | return ErrorMalformed; |
858 | 1.79M | if (transformProgram.back() < 0) |
859 | 707k | break; |
860 | 1.09M | transformProgram.push_back(signedDecode<2>(stream)); // factor |
861 | 1.09M | } |
862 | 707k | transformProgram.push_back(signedDecode<2>(stream)); // denominator |
863 | 707k | transformProgram.push_back(signedDecode<2>(stream)); // chroma flag |
864 | 707k | isChroma[transformProgram[transformSteps.back()]] = transformProgram.back(); |
865 | 707k | } |
866 | 11 | stream.flushReadWord(); |
867 | 11 | int const chromaQuality = std::max(1, (header.quality + header.chromaScale / 2) / header.chromaScale); |
868 | 11 | int const boost = header.quality == QualityMax ? 1 : 8; // [NOTE] due to Cubic lifting max multiplier of 20, boost * 20 must be less than 256 |
869 | 11 | bool isTruncated = false; |
870 | 11 | int step = 1; |
871 | 101 | while (step * 2 < header.sizex || step * 2 < header.sizey) |
872 | 90 | step *= 2; |
873 | 53 | for (bool hasDC = true; (step >> downsampling) >= 1; hasDC = false) // decode just enough coefficients for downsampled image |
874 | 51 | { |
875 | 51 | int64_t const bs = int64_t(step) << header.blockSize; |
876 | 51 | int const blockCountX = int((header.sizex + bs - 1) / bs); |
877 | 51 | int const blockCountY = int((header.sizey + bs - 1) / bs); |
878 | 51 | int const blockCount = blockCountX * blockCountY * header.layers * header.channels; |
879 | 51 | isTruncated = true; |
880 | 51 | if (stream.buffer + 1 + blockCount > stream.bufferEnd) // check for enough buffer to read block sizes |
881 | 7 | break; |
882 | 44 | std::vector<Bits> streamBlock(blockCount, Bits(0, 0)); |
883 | 182 | for (int block = 0; block < blockCount; ++ block) // first, read sizes into bufferEnd pointers |
884 | 138 | streamBlock[block].bufferEnd = static_cast<uint32_t *>(0) + *(stream.buffer ++); |
885 | 182 | for (int block = 0; block < blockCount; ++ block) // then convert sizes to true buffer pointers |
886 | 138 | streamBlock[block].bufferEnd = (streamBlock[block].buffer = block ? streamBlock[block - 1].bufferEnd : stream.buffer) |
887 | 138 | + (streamBlock[block].bufferEnd - static_cast<uint32_t *>(0)); |
888 | 44 | stream.buffer = streamBlock[blockCount - 1].bufferEnd; |
889 | 44 | nextPointOfInterest = reinterpret_cast<uint8_t *>(stream.buffer + ((step >> downsampling) > 1 ? blockCount * 4 : 0)) - data; |
890 | 44 | if (stream.buffer <= stream.bufferEnd) |
891 | 41 | isTruncated = false; |
892 | 44 | int const stepDown = step >> downsampling; |
893 | 44 | int64_t const bsDown = int64_t(stepDown) << header.blockSize; |
894 | 44 | OMP_PARALLEL_FOR(4) // [MAGIC] for some reason, 4 is by far the best option here |
895 | 182 | for (int block = 0; block < blockCount; ++ block) if (!test && streamBlock[block].bufferEnd <= stream.bufferEnd) |
896 | 41 | { |
897 | 41 | int const bx = block % blockCountX, by = (block / blockCountX) % blockCountY, c = block / (blockCountX * blockCountY); |
898 | 41 | Image<aux> auxImage(&auxData[c * bufferSize], sizexDown, sizeyDown); |
899 | 41 | if (header.intent < IntentBayerRGGB || header.intent > IntentBayerGeneric) |
900 | 41 | decode(auxImage, streamBlock[block], int(bx * bsDown), int(by * bsDown), |
901 | 41 | int(std::min((bx + 1) * bsDown, int64_t(sizexDown))), int(std::min((by + 1) * bsDown, int64_t(sizeyDown))), |
902 | 41 | stepDown, header.encoder, isChroma[c] ? chromaQuality : header.quality, hasDC && !bx && !by, isChroma[c] != 0); |
903 | 0 | else for (int ox = 0; ox <= 1; ++ ox) for (int oy = 0; oy <= 1; ++ oy) |
904 | 0 | decode(auxImage, streamBlock[block], int(bx * bsDown + ox), int(by * bsDown + oy), |
905 | 0 | int(std::min((bx + 1) * bsDown, int64_t(sizexDown))), int(std::min((by + 1) * bsDown, int64_t(sizeyDown))), |
906 | 0 | 2 * stepDown, header.encoder, (ox || oy) ? chromaQuality : header.quality, hasDC && !bx && !by, ox || oy); |
907 | 41 | } |
908 | 180 | for (int block = 0; block < blockCount; ++ block) // check if any blocks ran out of buffer, which should not happen on valid files |
909 | 138 | if (streamBlock[block].indexBits < 0) |
910 | 2 | return ErrorMalformed; |
911 | 42 | step /= 2; |
912 | 42 | } |
913 | 9 | if (test) |
914 | 0 | return isTruncated ? nextPointOfInterest : ResultOk; // return next point of interest if the data was truncated prior to completing request |
915 | 461 | for (int c = 0; c < header.layers * header.channels; ++ c) // dequantize and unlift the channels |
916 | 452 | { |
917 | 452 | Image<aux> auxImage(&auxData[c * bufferSize], sizexDown, sizeyDown); |
918 | 452 | if (header.intent >= IntentBayerRGGB && header.intent <= IntentBayerGeneric) |
919 | 30 | { |
920 | 180 | for (int ox = 0; ox <= 1; ++ ox) for (int oy = 0; oy <= 1; ++ oy) |
921 | 120 | quantize<aux, true>(auxImage, ox, oy, sizexDown, sizeyDown, 2, |
922 | 120 | ((ox | oy) ? chromaQuality : header.quality) << downsampling, header.quality, QualityMax * boost); |
923 | 150 | for (int ox = 0; ox <= 1; ++ ox) for (int oy = 1 - ox; oy <= 1; ++ oy) |
924 | 90 | unlift(auxImage, ox, oy, sizexDown, sizeyDown, 2, header.filter); |
925 | 30 | } |
926 | 422 | else |
927 | 422 | quantize<aux, true>(auxImage, 0, 0, sizexDown, sizeyDown, 1, |
928 | 422 | (isChroma[c] ? chromaQuality : header.quality) << downsampling, 0, QualityMax * boost); |
929 | 452 | unlift(auxImage, 0, 0, sizexDown, sizeyDown, 1, header.filter); |
930 | 452 | } |
931 | 707k | for (int s = (int)transformSteps.size() - 1; s >= 0; -- s) // run color transform program in reverse |
932 | 707k | { |
933 | 707k | int const * pc = &transformProgram[transformSteps[s]]; |
934 | 707k | int const c = *(pc ++); |
935 | 707k | std::vector<aux> transformTemp(bufferSize, 0); |
936 | 707k | transformTerm(pc, &transformTemp[0], &auxData[0], bufferSize, imageData, header, isChroma, boost); |
937 | 707k | aux * destination = &auxData[c * bufferSize]; |
938 | 707k | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
939 | 4.68G | for (int i = 0; i < bufferSize; ++ i) |
940 | 4.68G | destination[i] -= transformTemp[i]; |
941 | 707k | } |
942 | 461 | for (int c = 0; c < header.layers * header.channels; ++ c) // copy the channels to the destination buffer |
943 | 452 | { |
944 | 452 | aux * destination = &auxData[c * bufferSize]; |
945 | 452 | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); |
946 | 452 | if (boost == 1) |
947 | 0 | { |
948 | 0 | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
949 | 0 | for (int i = 0; i < bufferSize; ++ i) |
950 | 0 | layer[i * header.channels] = static_cast<base>(std::max(static_cast<aux>(std::numeric_limits<base>::lowest()), |
951 | 0 | std::min(static_cast<aux>(std::numeric_limits<base>::max()), static_cast<aux>(destination[i])))); |
952 | 0 | } |
953 | 452 | else |
954 | 452 | { |
955 | 452 | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
956 | 2.89M | for (int i = 0; i < bufferSize; ++ i) |
957 | 2.89M | layer[i * header.channels] = static_cast<base>(std::max(static_cast<aux>(std::numeric_limits<base>::lowest()), |
958 | 2.89M | std::min(static_cast<aux>(std::numeric_limits<base>::max()), static_cast<aux>(destination[i] / boost)))); |
959 | 452 | } |
960 | 452 | if (header.quality < QualityMax && header.intent >= IntentBayerRGGB && header.intent <= IntentBayerGBRG) // check if Bayer cleanup is required |
961 | 30 | { |
962 | 30 | int const bayerNoiseThresh = ((QualityMax + header.quality / 2) / header.quality + (QualityMax + chromaQuality / 2) / chromaQuality) * 2; |
963 | 30 | Image<aux> auxImage(&auxData[c * bufferSize], sizexDown, sizeyDown); |
964 | 30 | OMP_PARALLEL_FOR(ThreadIterations) |
965 | 30 | for (int y = 1; y < sizeyDown - 1; ++ y) |
966 | 0 | for (int x = 1 + (y + (header.intent == IntentBayerGBRG || header.intent == IntentBayerGRBG ? 1 : 0)) % 2; x < sizexDown - 1; x += 2) |
967 | 0 | { |
968 | 0 | aux s = auxImage[y][x]; |
969 | 0 | aux sum = s * 4; |
970 | 0 | int count = 4; |
971 | 0 | for (int oy = -1; oy <= 1; oy += 2) for (int ox = -1; ox <= 1; ox += 2) |
972 | 0 | { |
973 | 0 | aux t = auxImage[y + oy][x + ox]; |
974 | 0 | if (abs(s - t) > bayerNoiseThresh) |
975 | 0 | continue; |
976 | 0 | sum += t; |
977 | 0 | ++ count; |
978 | 0 | } |
979 | 0 | layer[(y * sizexDown + x) * header.channels] |
980 | 0 | = static_cast<base>(std::max(static_cast<aux>(std::numeric_limits<base>::lowest()), |
981 | 0 | std::min(static_cast<aux>(std::numeric_limits<base>::max()), aux((sum + count / 2) / (count * boost))))); |
982 | 0 | } |
983 | 30 | } |
984 | 452 | } |
985 | 9 | return isTruncated ? nextPointOfInterest : ResultOk; // return next point of interest if the data was truncated prior to completing request |
986 | 9 | } |
987 | | } |