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 | | : sizex(sizex), sizey(sizey), layers(layers), channels(channels), bitDepth(bitDepth), quality(std::max(1, std::min(int(QualityMax), quality))), |
84 | | chromaScale(std::max(1, std::min(256, chromaScale))), blockSize(std::min(30, std::max(2, blockSize))), filter(std::min(255, filter)), |
85 | 0 | 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 | 523 | Image(T * data, int sizex, int sizey) : data(data), sizex(sizex), sizey(sizey) {} |
99 | 1.46M | 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 | 70 | 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 | 0 | { |
129 | 0 | int newBits = indexBits + bits; |
130 | 0 | if (buffer == bufferEnd) |
131 | 0 | newBits = -1; // signify overflow |
132 | 0 | else if (newBits < 32) |
133 | 0 | (writeCache <<= bits) |= x; |
134 | 0 | else if (bits == 32 && newBits == 32) |
135 | 0 | { |
136 | 0 | newBits = 0; |
137 | 0 | *(buffer ++) = x; |
138 | 0 | } |
139 | 0 | else |
140 | 0 | { |
141 | 0 | newBits -= 32; |
142 | 0 | *(buffer ++) = (writeCache << (bits - newBits)) | (x >> newBits); |
143 | 0 | writeCache = x; |
144 | 0 | } |
145 | 0 | indexBits = newBits; |
146 | 0 | } |
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 | 0 | { |
180 | 0 | putBits(0, (32 - indexBits) % 32); |
181 | 0 | } |
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 | | { |
193 | | uint32_t const y = x >> (pot); |
194 | | if (y >= 12) |
195 | | { |
196 | | stream.putBits(0, 12); // escape to larger code |
197 | | unsignedCode<pot < 20 ? pot + 4 : 24>(x - (12 << (pot)), stream); |
198 | | } |
199 | | else |
200 | | stream.putBits((1 << (pot)) | (x & ~(~0u << (pot))), y + 1 + pot); // encode x / 2^pot in unary followed by x % 2^pot in binary |
201 | | } |
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 | | { |
212 | | unsignedCode<pot>(x <= 0 ? -2 * x : 2 * x - 1, stream); // interleave positive and negative values |
213 | | } |
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 | | { |
223 | | unsignedCode<pot>(abs(x), stream); |
224 | | if (x) |
225 | | stream.putBits(x > 0 ? 1 : 0, 1); |
226 | | } |
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 | 1.67M | { |
236 | 1.67M | return a < b ? c > b ? b : c < a ? a : c : c > a ? a : c < b ? b : c; |
237 | 1.67M | } |
238 | | |
239 | | template<typename T> T roundFraction(T num, T denom) |
240 | 1.67M | { |
241 | 1.67M | return num < 0 ? (num - denom / 2) / denom : (num + denom / 2) / denom; |
242 | 1.67M | } |
243 | | |
244 | | template<typename T> T cubic(T c0, T c1, T c2, T c3) |
245 | 1.67M | { |
246 | 1.67M | return median(T(roundFraction((-c0 + 9 * (c1 + c2) - c3), 16)), c1, c2); |
247 | 1.67M | } |
248 | | |
249 | | template<typename T> void lift(Image<T> & image, int x0, int y0, int x1, int y1, int step, int filter) |
250 | | { |
251 | | int const sizex = x1 - x0; |
252 | | int const sizey = y1 - y0; |
253 | | while (step < sizex || step < sizey) |
254 | | { |
255 | | if (step < sizex) // horizontal lifting |
256 | | { |
257 | | OMP_PARALLEL_FOR(ThreadIterations) |
258 | | for (int y = 0; y < sizey; y += step) |
259 | | { |
260 | | int x; |
261 | | T * base = &image[y0 + y][x0], * base1 = base - step, * base2 = base + step, * base3 = base + step * 3; |
262 | | if (filter == FilterCubic) |
263 | | { |
264 | | T c0 = *base, c1 = *base, c2 = step * 2 < sizex ? base[step * 2] : *base, c3; |
265 | | for (x = step; x < sizex - step * 3; x += step * 2, c0 = c1, c1 = c2, c2 = c3) |
266 | | base[x] -= cubic(c0, c1, c2, c3 = base3[x]); |
267 | | for (; x < sizex; x += step * 2, c0 = c1, c1 = c2) |
268 | | base[x] -= cubic(c0, c1, c2, c2); |
269 | | T g0 = base[step], g1 = base[step], g2 = step * 3 < sizex ? base[step * 3] : base[step], g3; |
270 | | for (x = step * 2; x < sizex - step * 3; x += step * 2, g0 = g1, g1 = g2, g2 = g3) |
271 | | base[x] += cubic(g0, g1, g2, g3 = base3[x]) / 2; |
272 | | for (; x < sizex; x += step * 2, g0 = g1, g1 = g2) |
273 | | base[x] += cubic(g0, g1, g2, g2) / 2; |
274 | | } |
275 | | else |
276 | | { |
277 | | for (x = step; x < sizex - step; x += step * 2) |
278 | | base[x] -= (base1[x] + base2[x]) / 2; |
279 | | if (x < sizex) |
280 | | base[x] -= base1[x]; |
281 | | for (x = step * 2; x < sizex - step; x += step * 2) |
282 | | base[x] += (base1[x] + base2[x]) / 4; |
283 | | if (x < sizex) |
284 | | base[x] += base1[x] / 2; |
285 | | } |
286 | | } |
287 | | } |
288 | | if (step < sizey) // vertical lifting |
289 | | { |
290 | | OMP_PARALLEL_FOR(ThreadIterations) |
291 | | for (int y = step; y < sizey; y += step * 2) |
292 | | { |
293 | | T * const base = &image[y0 + y][x0]; |
294 | | T const * const c1base = &image[y0 + y - step][x0], * const c2base = y + step < sizey ? &image[y0 + y + step][x0] : c1base; |
295 | | if (filter == FilterCubic) |
296 | | { |
297 | | T const * const c0base = y - step * 3 >= 0 ? &image[y0 + y - step * 3][x0] : c1base; |
298 | | T const * const c3base = y + step * 3 < sizey ? &image[y0 + y + step * 3][x0] : c2base; |
299 | | for (int x = 0; x < sizex; x += step) |
300 | | base[x] -= cubic(c0base[x], c1base[x], c2base[x], c3base[x]); |
301 | | } |
302 | | else for (int x = 0; x < sizex; x += step) |
303 | | base[x] -= (c1base[x] + c2base[x]) / 2; |
304 | | } |
305 | | OMP_PARALLEL_FOR(ThreadIterations) |
306 | | for (int y = step * 2; y < sizey; y += step * 2) |
307 | | { |
308 | | T * const base = &image[y0 + y][x0]; |
309 | | T const * const g1base = &image[y0 + y - step][x0], * const g2base = y + step < sizey ? &image[y0 + y + step][x0] : g1base; |
310 | | if (filter == FilterCubic) |
311 | | { |
312 | | T const * const g0base = y - step * 3 >= 0 ? &image[y0 + y - step * 3][x0] : g1base; |
313 | | T const * const g3base = y + step * 3 < sizey ? &image[y0 + y + step * 3][x0] : g2base; |
314 | | for (int x = 0; x < sizex; x += step) |
315 | | base[x] += cubic(g0base[x], g1base[x], g2base[x], g3base[x]) / 2; |
316 | | } |
317 | | else for (int x = 0; x < sizex; x += step) |
318 | | base[x] += (g1base[x] + g2base[x]) / 4; |
319 | | } |
320 | | } |
321 | | step *= 2; |
322 | | } |
323 | | } |
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 | 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 | 1.44M | { |
429 | 1.44M | return t * t; |
430 | 1.44M | } |
431 | | |
432 | | inline void addContext(int x, int w, uint32_t & sum, uint32_t & sum2, uint32_t & count) |
433 | 1.29M | { |
434 | 1.29M | sum += uint32_t(x = abs(x)) * w; |
435 | 1.29M | sum2 += square(std::min(uint32_t(x), 4096u)) * w; // [MAGIC] avoid overflow in last line of getContext |
436 | 1.29M | count += w; |
437 | 1.29M | } |
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 | 145k | { |
441 | 145k | int px = x0 + (x & ~(skip * 2)) + (x & skip); |
442 | 145k | if (px >= x1) |
443 | 44 | px -= skip * 2; |
444 | 145k | int py = y0 + (y & ~(skip * 2)) + (y & skip); |
445 | 145k | if (py >= y1) |
446 | 172 | py -= skip * 2; |
447 | 145k | uint32_t count = 0, sum = 0, sum2 = 0; |
448 | 145k | addContext(abs(image[py][px]), 2, sum, sum2, count); // ancestor |
449 | 145k | if ((y & skip) && (x | skip) < x1 - x0) |
450 | 93.2k | { |
451 | 93.2k | addContext(image[y0 + y - skip][x0 + (x | skip)], 2, sum, sum2, count); // upper sibling |
452 | 93.2k | if (x & skip) |
453 | 46.7k | addContext(image[y0 + y][x0 + x - skip], 2, sum, sum2, count); // left sibling |
454 | 93.2k | } |
455 | 145k | if (y >= skip * 2 && x >= skip * 2) // neighbors |
456 | 133k | { |
457 | 133k | addContext(image[y0 + y - skip * 2][x0 + x], 4, sum, sum2, count); |
458 | 133k | addContext(image[y0 + y][x0 + x - skip * 2], 4, sum, sum2, count); |
459 | 133k | addContext(image[y0 + y - skip * 2][x0 + x - skip * 2], 2, sum, sum2, count); |
460 | 133k | if (x + skip * 2 < x1 - x0) |
461 | 132k | addContext(image[y0 + y - skip * 2][x0 + x + skip * 2], 2, sum, sum2, count); |
462 | 133k | if (y >= skip * 4 && x >= skip * 4) |
463 | 120k | { |
464 | 120k | addContext(image[y0 + y - skip * 4][x0 + x], 2, sum, sum2, count); |
465 | 120k | addContext(image[y0 + y][x0 + x - skip * 4], 2, sum, sum2, count); |
466 | 120k | addContext(image[y0 + y - skip * 4][x0 + x - skip * 4], 1, sum, sum2, count); |
467 | 120k | if (x + skip * 4 < x1 - x0) |
468 | 120k | addContext(image[y0 + y - skip * 4][x0 + x + skip * 4], 1, sum, sum2, count); |
469 | 120k | } |
470 | 133k | } |
471 | 145k | return std::make_pair((sum * 16u + count / 2u) / count, (sum2 * 16u + count / 2u) / count); // set sums relative to 16 count |
472 | 145k | } |
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 | | { |
476 | | int const sizex = x1 - x0; |
477 | | int const sizey = y1 - y0; |
478 | | if (hasDC && sizex > 0 && sizey > 0) |
479 | | signedCode<4>(image[y0][x0], stream); |
480 | | std::pair<uint32_t, uint32_t> context(0, 0); |
481 | | int run = 0, runCoder = (scheme == EncoderTurbo ? (!q || (step < 2048 && q * step < 2048)) ? 1 : 0 : 0); // avoid overflow checking q * step < 2048 |
482 | | for (int y = 0; y < sizey; y += step) |
483 | | { |
484 | | T * base = &image[y0 + y][x0]; |
485 | | int const xStep = (y & step) ? step : step * 2; |
486 | | for (int x = xStep - step; x < sizex; x += xStep) // [NOTE] arranged so that (x | y) & step == 1 |
487 | | { |
488 | | T s = base[x]; |
489 | | if (runCoder && !s) // run |
490 | | ++ run; |
491 | | else |
492 | | { |
493 | | if (scheme == EncoderTurbo) |
494 | | { |
495 | | if (runCoder) // break the run |
496 | | { |
497 | | unsignedCode<1>(run, stream); |
498 | | run = 0; |
499 | | interleavedCode<1>(s < 0 ? s + 1 : s, stream); // s can't be zero, so shift negatives by 1 |
500 | | } |
501 | | else |
502 | | interleavedCode<1>(s, stream); |
503 | | continue; |
504 | | } |
505 | | if (runCoder) // break the run |
506 | | { |
507 | | runCoder == 1 ? unsignedCode<1>(run, stream) : runCoder == 2 ? unsignedCode<2>(run, stream) |
508 | | : runCoder == 3 ? unsignedCode<3>(run, stream) : unsignedCode<4>(run, stream); |
509 | | run = 0; |
510 | | if (s < 0) |
511 | | ++ s; // s can't be zero, so shift negatives by 1 |
512 | | } |
513 | | if (scheme == EncoderContextual) |
514 | | context = getContext(image, x0, y0, x1, y1, x, y, step); |
515 | | uint32_t const sumSq = square(context.first); |
516 | | if (sumSq < 2u * context.second + (isChroma ? 250u : 100u)) |
517 | | interleavedCode<0>(s, stream); |
518 | | else if (sumSq < 2u * context.second + 950u) |
519 | | interleavedCode<1>(s, stream); |
520 | | else if (sumSq < 3u * context.second + 3000u) |
521 | | { |
522 | | if (sumSq < 5u * context.second + 400u) |
523 | | signedCode<1>(s, stream); |
524 | | else |
525 | | interleavedCode<2>(s, stream); |
526 | | } |
527 | | else if (sumSq < 3u * context.second + 12000u) |
528 | | { |
529 | | if (sumSq < 5u * context.second + 3000u) |
530 | | signedCode<2>(s, stream); |
531 | | else |
532 | | interleavedCode<3>(s, stream); |
533 | | } |
534 | | else if (sumSq < 4u * context.second + 44000u) |
535 | | { |
536 | | if (sumSq < 6u * context.second + 12000u) |
537 | | signedCode<3>(s, stream); |
538 | | else |
539 | | interleavedCode<4>(s, stream); |
540 | | } |
541 | | else |
542 | | signedCode<4>(s, stream); |
543 | | if (scheme == EncoderFast) // use decaying first and second moment |
544 | | { |
545 | | uint32_t const t = abs(s); |
546 | | context = std::make_pair(((context.first * 15u + 7u) >> 4) + t, ((context.second * 15u + 7u) >> 4) + square(std::min(t, 4096u))); |
547 | | if (!s == !runCoder) |
548 | | runCoder = context.first < 1 ? 4 : context.first < 2 ? 3 : context.first < 4 ? 2 : context.first < 8 ? 1 : 0; |
549 | | } |
550 | | else if (!s == !runCoder) |
551 | | runCoder = q == 1024 ? context.first < 2u ? 1 : 0 : (context.first < 4u && context.second < 2u) ? 4 : (context.first < 8u |
552 | | && context.second < 4u) ? 3 : (2u * sumSq < 3u * context.second + 48u) ? 2 : (2u * sumSq < 5u * context.second + 32u) ? 1 : 0; |
553 | | } |
554 | | } |
555 | | } |
556 | | if (run) // flush run |
557 | | runCoder == 1 ? unsignedCode<1>(run, stream) : runCoder == 2 ? unsignedCode<2>(run, stream) |
558 | | : runCoder == 3 ? unsignedCode<3>(run, stream) : unsignedCode<4>(run, stream); |
559 | | } |
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 | 169 | { |
639 | 169 | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
640 | 1.27M | for (int i = 0; i < count; ++ i) |
641 | 1.27M | data[i] >>= shift; |
642 | 169 | } |
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 | 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 | | #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 | | #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 | | #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 | | { |
691 | | typedef typename std::remove_reference<decltype(imageData[0])>::type base; |
692 | | typedef typename std::conditional<sizeof(base) < 2, int16_t, int32_t>::type aux; |
693 | | if (header.sizex > (1 << 30) || header.sizey > (1 << 30)) // [NOTE] current implementation can't go over 2^30 |
694 | | return ErrorMalformed; |
695 | | Bits stream(reinterpret_cast<uint32_t *>(buffer), reinterpret_cast<uint32_t *>(buffer) + size / 4); |
696 | | stream.putBits('G' | ('F' << 8) | ('W' << 16) | ('X' << 24), 32); |
697 | | stream.putBits(header.version = 1, 32); |
698 | | stream.putBits(header.sizex, 32); |
699 | | stream.putBits(header.sizey, 32); |
700 | | stream.putBits(header.layers - 1, 16); |
701 | | stream.putBits(header.channels - 1, 16); |
702 | | stream.putBits((header.bitDepth ? header.bitDepth : (header.bitDepth = std::numeric_limits<base>::digits)) - 1, 8); |
703 | | stream.putBits(header.isSigned = std::numeric_limits<base>::is_signed ? 1 : 0, 1); |
704 | | stream.putBits(header.quality - 1, 10); |
705 | | stream.putBits(header.chromaScale - 1, 8); |
706 | | stream.putBits(header.blockSize - 2, 5); |
707 | | stream.putBits(header.filter, 8); |
708 | | stream.putBits(header.quantization, 8); |
709 | | stream.putBits(header.encoder, 8); |
710 | | stream.putBits(header.intent, 8); |
711 | | stream.putBits(int(metaDataSize / 4), 32); |
712 | | stream.buffer = std::copy(reinterpret_cast<uint32_t *>(metaData), reinterpret_cast<uint32_t *>(metaData) + metaDataSize / 4, stream.buffer); |
713 | | int const bufferSize = header.sizex * header.sizey; |
714 | | std::vector<aux> auxData((size_t)header.layers * header.channels * bufferSize, 0); |
715 | | std::vector<int> isChroma(header.layers * header.channels, -1); |
716 | | int const chromaQuality = std::max(1, (header.quality + header.chromaScale / 2) / header.chromaScale); |
717 | | 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 | | if (channelTransform) // run color transform program (and also encode it to the file) |
719 | | { |
720 | | int const * pc = channelTransform; |
721 | | while (*pc >= 0) |
722 | | { |
723 | | int const c = *(pc ++); |
724 | | aux * destination = &auxData[c * bufferSize]; |
725 | | transformTerm(pc, destination, &auxData[0], bufferSize, imageData, header, isChroma, boost); |
726 | | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); |
727 | | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
728 | | for (int i = 0; i < bufferSize; ++ i) |
729 | | destination[i] += layer[i * header.channels] * boost; |
730 | | isChroma[c] = *(pc ++); |
731 | | } |
732 | | for (int const * i = channelTransform; i <= pc; ++ i) |
733 | | signedCode<2>(*i, stream); |
734 | | } |
735 | | else |
736 | | signedCode<2>(-1, stream); |
737 | | stream.flushWriteWord(); |
738 | | for (int c = 0; c < header.layers * header.channels; ++ c) if (isChroma[c] == -1) // copy channels having no transform |
739 | | { |
740 | | aux * destination = &auxData[c * bufferSize]; |
741 | | auto layer = imageData + ((c / header.channels) * bufferSize * header.channels + c % header.channels); |
742 | | OMP_PARALLEL_FOR(ThreadIterations * ThreadIterations) |
743 | | for (int i = 0; i < bufferSize; ++ i) |
744 | | destination[i] = layer[i * header.channels] * boost; |
745 | | isChroma[c] = 0; |
746 | | } |
747 | | for (int c = 0; c < header.layers * header.channels; ++ c) // lift and quantize the channels |
748 | | { |
749 | | Image<aux> auxImage(&auxData[c * bufferSize], header.sizex, header.sizey); |
750 | | lift(auxImage, 0, 0, header.sizex, header.sizey, 1, header.filter); |
751 | | if (header.intent >= IntentBayerRGGB && header.intent <= IntentBayerGeneric) |
752 | | { |
753 | | for (int ox = 0; ox <= 1; ++ ox) for (int oy = 1 - ox; oy <= 1; ++ oy) |
754 | | lift(auxImage, ox, oy, header.sizex, header.sizey, 2, header.filter); |
755 | | for (int ox = 0; ox <= 1; ++ ox) for (int oy = 0; oy <= 1; ++ oy) |
756 | | quantize<aux, false>(auxImage, ox, oy, header.sizex, header.sizey, 2, |
757 | | (ox | oy) ? chromaQuality : header.quality, header.quality, QualityMax * boost); |
758 | | } |
759 | | else |
760 | | quantize<aux, false>(auxImage, 0, 0, header.sizex, header.sizey, 1, isChroma[c] ? chromaQuality : header.quality, 0, QualityMax * boost); |
761 | | } |
762 | | int step = 1; |
763 | | while (step * 2 < header.sizex || step * 2 < header.sizey) |
764 | | step *= 2; |
765 | | for (bool hasDC = true; step >= 1; hasDC = false) |
766 | | { |
767 | | int64_t const bs = int64_t(step) << header.blockSize; |
768 | | int const blockCountX = (header.sizex + bs - 1) / bs; |
769 | | int const blockCountY = (header.sizey + bs - 1) / bs; |
770 | | int const blockCount = blockCountX * blockCountY * header.layers * header.channels; |
771 | | std::vector<Bits> streamBlock(blockCount, Bits(0, 0)); |
772 | | uint32_t * blockBegin = stream.buffer + blockCount; // leave space for block sizes |
773 | | if (blockBegin >= stream.bufferEnd) |
774 | | return ErrorOverflow; |
775 | | for (int block = 0; block < blockCount; ++ block) // partition buffer into temporary regions for each block |
776 | | streamBlock[block].buffer = blockBegin + (stream.bufferEnd - blockBegin) * block / blockCount; |
777 | | for (int block = 0; block < blockCount; ++ block) |
778 | | streamBlock[block].bufferEnd = block + 1 < blockCount ? streamBlock[block + 1].buffer : stream.bufferEnd; |
779 | | OMP_PARALLEL_FOR(4) // [MAGIC] for some reason, 4 is by far the best option here |
780 | | for (int block = 0; block < blockCount; ++ block) |
781 | | { |
782 | | int const bx = block % blockCountX, by = (block / blockCountX) % blockCountY, c = block / (blockCountX * blockCountY); |
783 | | Image<aux> auxImage(&auxData[c * bufferSize], header.sizex, header.sizey); |
784 | | if (header.intent < IntentBayerRGGB || header.intent > IntentBayerGeneric) |
785 | | encode(auxImage, streamBlock[block], bx * bs, by * bs, |
786 | | int(std::min((bx + 1) * bs, int64_t(header.sizex))), int(std::min((by + 1) * bs, int64_t(header.sizey))), |
787 | | step, header.encoder, isChroma[c] ? chromaQuality : header.quality, hasDC && !bx && !by, isChroma[c] != 0); |
788 | | else for (int ox = 0; ox <= 1; ++ ox) for (int oy = 0; oy <= 1; ++ oy) |
789 | | encode(auxImage, streamBlock[block], bx * bs + ox, by * bs + oy, |
790 | | int(std::min((bx + 1) * bs, int64_t(header.sizex))), int(std::min((by + 1) * bs, int64_t(header.sizey))), |
791 | | 2 * step, header.encoder, (ox || oy) ? chromaQuality : header.quality, hasDC && !bx && !by, ox || oy); |
792 | | streamBlock[block].flushWriteWord(); |
793 | | } |
794 | | for (int block = 0; block < blockCount; ++ block) // check streamBlocks for overflow |
795 | | if (streamBlock[block].indexBits < 0) |
796 | | return ErrorOverflow; |
797 | | for (int block = 0; block < blockCount; ++ block) // encode block lengths [NOTE] this 32-bit encoding limits the file size to < 16 GB |
798 | | *(stream.buffer ++) = uint32_t(streamBlock[block].buffer - (block ? streamBlock[block - 1].bufferEnd : blockBegin)); |
799 | | for (int block = 0; block < blockCount; ++ block) // pack the streamBlock data tightly, by word [NOTE] first block is already packed |
800 | | stream.buffer = block ? std::copy(streamBlock[block - 1].bufferEnd, streamBlock[block].buffer, stream.buffer) : streamBlock[0].buffer; |
801 | | step /= 2; |
802 | | } |
803 | | return reinterpret_cast<uint8_t *>(stream.buffer) - buffer; // return size in bytes |
804 | | } |
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 | | } |