/src/libraw/src/decoders/pana8.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * File: pana8.cpp |
3 | | * Copyright (C) 2022 Alex Tutubalin, LibRaw LLC |
4 | | * |
5 | | Panasonic RawFormat=8 file decoder |
6 | | |
7 | | LibRaw is free software; you can redistribute it and/or modify |
8 | | it under the terms of the one of two licenses as you choose: |
9 | | |
10 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
11 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
12 | | |
13 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
14 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
15 | | |
16 | | */ |
17 | | |
18 | | #include "../../internal/libraw_cxx_defs.h" |
19 | | #include <vector> |
20 | | |
21 | | // in 8-byte words, 800kb |
22 | 0 | #define PANA8_BUFSIZE 102400 |
23 | | |
24 | | class pana8_bufio_t |
25 | | { |
26 | | public: |
27 | | pana8_bufio_t(LibRaw_abstract_datastream *stream, INT64 start, uint32_t len) |
28 | 0 | : data(PANA8_BUFSIZE), input(stream), baseoffset(start), begin(0), end(0), _size(len) |
29 | 0 | { |
30 | 0 | } |
31 | 0 | uint32_t size() { return ((_size+7)/8)*8; } |
32 | | uint64_t getQWord(uint32_t offset) |
33 | 0 | { |
34 | 0 | if (offset >= begin && offset < end) |
35 | 0 | return data[offset - begin]; |
36 | 0 | if (!input) return 0; |
37 | 0 | refill(offset); |
38 | 0 | if (offset >= begin && offset < end) |
39 | 0 | return data[offset - begin]; |
40 | 0 | return 0; |
41 | 0 | } |
42 | | void refill(uint32_t newoffset); |
43 | | |
44 | | std::vector<uint64_t> data; |
45 | | LibRaw_abstract_datastream *input; |
46 | | INT64 baseoffset; |
47 | | INT64 begin, end; |
48 | | uint32_t _size; |
49 | | }; |
50 | | |
51 | | struct pana8_param_t |
52 | | { |
53 | | uint32_t range_shift, gamma_base; |
54 | | uint32_t tag3A[6]; |
55 | | uint32_t tag39[6]; |
56 | | uint32_t tag3B; |
57 | | uint32_t initial[4]; |
58 | | uint32_t huff_coeff[17]; |
59 | | uint32_t tag3B_2; |
60 | | uint32_t noGammaFlag; |
61 | | uint64_t hufftable1[17]; |
62 | | uint64_t hufftable2[17]; |
63 | | std::vector<uint16_t> gammaTable; |
64 | | std::vector<uint8_t> extrahuff; |
65 | | pana8_param_t(const pana8_tags_t& init); |
66 | | int32_t gammaCurve(uint32_t i); |
67 | | bool DecodeC8( |
68 | | pana8_bufio_t& bufio, |
69 | | unsigned int width, unsigned int height, |
70 | | LibRaw *libraw, uint16_t left_margin); |
71 | | uint32_t GetDBit(uint64_t a2); |
72 | | }; |
73 | | |
74 | | void invertBits(void *buf, size_t size); |
75 | | |
76 | | void pana8_bufio_t::refill(uint32_t newoffset) |
77 | 0 | { |
78 | 0 | if (newoffset >= begin && newoffset < end) |
79 | 0 | return; |
80 | 0 | uint32_t readwords, remainwords,toread; |
81 | | #ifdef LIBRAW_USE_OPENMP |
82 | | #pragma omp critical |
83 | | { |
84 | | #endif |
85 | 0 | input->lock(); |
86 | 0 | input->seek(baseoffset + newoffset*sizeof(int64_t), SEEK_SET); |
87 | 0 | remainwords = (_size - newoffset*sizeof(int64_t) + 7) >> 3; |
88 | 0 | toread = MIN(PANA8_BUFSIZE, remainwords); |
89 | 0 | uint32_t readbytes = input->read(data.data(), 1, toread*sizeof(uint64_t)); |
90 | 0 | readwords = (readbytes + 7) >> 3; |
91 | 0 | input->unlock(); |
92 | | #ifdef LIBRAW_USE_OPENMP |
93 | | } |
94 | | #endif |
95 | |
|
96 | 0 | if (INT64(readwords) < INT64(toread) - 1LL) |
97 | 0 | throw LIBRAW_EXCEPTION_IO_EOF; |
98 | | |
99 | 0 | if(readwords>0) |
100 | 0 | invertBits(data.data(), readwords * sizeof(uint64_t)); |
101 | 0 | begin = newoffset; |
102 | 0 | end = newoffset + readwords; |
103 | 0 | } |
104 | | |
105 | | void LibRaw::panasonicC8_load_raw() |
106 | 0 | { |
107 | 0 | int errs = 0; |
108 | 0 | unsigned totalw = 0; |
109 | 0 | INT64 fsz = libraw_internal_data.internal_data.input->size(); |
110 | 0 | if (libraw_internal_data.unpacker_data.pana8.stripe_count > 5) errs++; |
111 | 0 | for (int i = 0; i < libraw_internal_data.unpacker_data.pana8.stripe_count && i < 5; i++) |
112 | 0 | { |
113 | 0 | if (libraw_internal_data.unpacker_data.pana8.stripe_height[i] != imgdata.sizes.raw_height) |
114 | 0 | errs++; |
115 | 0 | if (libraw_internal_data.unpacker_data.pana8.stripe_offsets[i] < 0 |
116 | 0 | || (libraw_internal_data.unpacker_data.pana8.stripe_offsets[i] + INT64((libraw_internal_data.unpacker_data.pana8.stripe_compressed_size[i] + 7u) / 8u)) > fsz) |
117 | 0 | errs++; |
118 | 0 | totalw += libraw_internal_data.unpacker_data.pana8.stripe_width[i]; |
119 | 0 | } |
120 | 0 | if (totalw != imgdata.sizes.raw_width) errs++; |
121 | 0 | if (errs) |
122 | 0 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
123 | | |
124 | 0 | pana8_param_t pana8_param(libraw_internal_data.unpacker_data.pana8); |
125 | 0 | pana8_decode_loop(&pana8_param); |
126 | 0 | } |
127 | | |
128 | | void LibRaw::pana8_decode_loop(void *data) |
129 | 0 | { |
130 | | #ifdef LIBRAW_USE_OPENMP |
131 | | int errs = 0, scount = MIN(5,libraw_internal_data.unpacker_data.pana8.stripe_count); |
132 | | #pragma omp parallel for |
133 | | for (int stream = 0; stream < scount; stream++) |
134 | | { |
135 | | if (pana8_decode_strip(data, stream)) |
136 | | errs++; |
137 | | } |
138 | | if(errs) |
139 | | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
140 | | #else |
141 | 0 | for (int stream = 0; stream < libraw_internal_data.unpacker_data.pana8.stripe_count && stream < 5; stream++) |
142 | 0 | if (pana8_decode_strip(data, stream)) |
143 | 0 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
144 | 0 | #endif |
145 | 0 | } |
146 | | |
147 | | int LibRaw::pana8_decode_strip(void* data, int stream) |
148 | 0 | { |
149 | 0 | pana8_param_t *pana8_param = (pana8_param_t*)data; |
150 | 0 | if (!data || stream < 0 || stream > 4 || stream > libraw_internal_data.unpacker_data.pana8.stripe_count) return 1; // error |
151 | | |
152 | 0 | unsigned exactbytes = (libraw_internal_data.unpacker_data.pana8.stripe_compressed_size[stream] + 7u) / 8u; |
153 | 0 | pana8_bufio_t bufio(libraw_internal_data.internal_data.input, |
154 | 0 | libraw_internal_data.unpacker_data.pana8.stripe_offsets[stream], exactbytes); |
155 | 0 | return !pana8_param->DecodeC8(bufio, libraw_internal_data.unpacker_data.pana8.stripe_width[stream], |
156 | 0 | libraw_internal_data.unpacker_data.pana8.stripe_height[stream], this, |
157 | 0 | libraw_internal_data.unpacker_data.pana8.stripe_left[stream]); |
158 | 0 | } |
159 | | |
160 | | struct pana8_base_t |
161 | | { |
162 | 0 | pana8_base_t() { coeff[0] = coeff[1] = coeff[2] = coeff[3] = 0; } |
163 | 0 | pana8_base_t(const pana8_base_t &s) { clone(s.coeff); } |
164 | | void clone(const uint32_t *scoeff) |
165 | 0 | { // TODO: implement SSE load for SSE-enabled code |
166 | 0 | coeff[0] = scoeff[0]; |
167 | 0 | coeff[1] = scoeff[1]; |
168 | 0 | coeff[2] = scoeff[2]; |
169 | 0 | coeff[3] = scoeff[3]; |
170 | 0 | } |
171 | | uint32_t coeff[4]; |
172 | | }; |
173 | | |
174 | | bool pana8_param_t::DecodeC8(pana8_bufio_t &bufio, unsigned int width, unsigned int height, LibRaw *libraw, |
175 | | uint16_t left_margin) |
176 | 0 | { |
177 | 0 | unsigned halfwidth = width >> 1; |
178 | 0 | unsigned halfheight = height >> 1; |
179 | 0 | if (!halfwidth || !halfheight || bufio.size() < 9) |
180 | 0 | return false; // invalid input |
181 | | |
182 | 0 | uint32_t datamax = tag3B_2 >> range_shift; |
183 | |
|
184 | 0 | pana8_base_t start_coeff; |
185 | 0 | for(int i = 0; i < 4; i++) |
186 | 0 | start_coeff.coeff[i] = initial[i] & 0xffffu; |
187 | |
|
188 | 0 | bool _extrahuff = (extrahuff.size() >= 0x10000); |
189 | |
|
190 | 0 | uint8_t *big_huff_table = 0; |
191 | 0 | if (_extrahuff) |
192 | 0 | big_huff_table = extrahuff.data(); |
193 | |
|
194 | 0 | uint16_t *gammatable = (gammaTable.size() >= 0x10000) && !noGammaFlag ? (uint16_t *)gammaTable.data() : 0; |
195 | |
|
196 | | #ifdef PANA8_FULLY_BUFFERED |
197 | | const uint8_t *inputbyteptr = source.data(); |
198 | | uint32_t jobsz_in_qwords = source.size() >> 3; |
199 | | #else |
200 | 0 | uint32_t jobsz_in_qwords = bufio.size() >> 3; |
201 | 0 | #endif |
202 | 0 | int32_t doublewidth = 4 * halfwidth; |
203 | 0 | std::vector<uint8_t> outline(4 * doublewidth); |
204 | 0 | pana8_base_t line_base(start_coeff); |
205 | 0 | int64_t bittail = 0LL; |
206 | 0 | int32_t bitportion = 0; |
207 | 0 | uint32_t inqword = 0u; |
208 | |
|
209 | 0 | try |
210 | 0 | { |
211 | 0 | for (uint32_t current_row = 0; current_row < halfheight; current_row++) |
212 | 0 | { |
213 | 0 | uint8_t *outrowp = outline.data(); |
214 | 0 | pana8_base_t current_base(line_base); |
215 | |
|
216 | 0 | for (int32_t col = 0; col < doublewidth; col++) |
217 | 0 | { |
218 | 0 | uint64_t pixbits; |
219 | 0 | if (bitportion < 0) |
220 | 0 | { |
221 | 0 | uint32_t inqword_next = inqword + 1; |
222 | 0 | if ((int)inqword + 1 >= int(jobsz_in_qwords)) |
223 | 0 | return false; |
224 | 0 | bitportion += 64; |
225 | 0 | uint64_t inputqword = bufio.getQWord(inqword); |
226 | 0 | uint64_t inputqword_next = bufio.getQWord(inqword_next); |
227 | 0 | pixbits = (inputqword_next >> bitportion) | (inputqword << (64 - (uint8_t)(bitportion & 0xffu))); |
228 | 0 | if ((unsigned int)inqword < jobsz_in_qwords) |
229 | 0 | inqword = inqword_next; |
230 | 0 | } |
231 | 0 | else |
232 | 0 | { |
233 | 0 | if ((unsigned int)inqword >= jobsz_in_qwords) |
234 | 0 | return false; |
235 | 0 | uint64_t inputqword = bufio.getQWord(inqword); |
236 | 0 | pixbits = (inputqword >> bitportion) | bittail; |
237 | 0 | uint32_t step = (bitportion == 0); |
238 | 0 | if (!bitportion) |
239 | 0 | bitportion = 64; |
240 | 0 | inqword += step; |
241 | 0 | } |
242 | 0 | int huff_index = 0; |
243 | 0 | if (_extrahuff) |
244 | 0 | huff_index = *(uint8_t *)(big_huff_table + ((pixbits >> 48) & 0xffffu)); |
245 | 0 | else |
246 | 0 | { |
247 | 0 | huff_index = int(GetDBit(pixbits)); |
248 | 0 | datamax = tag3B_2; |
249 | 0 | } |
250 | 0 | int32_t v37 = (huff_coeff[huff_index] >> 24) & 0x1F; |
251 | 0 | uint32_t hc = huff_coeff[huff_index]; |
252 | 0 | int64_t v38 = pixbits << (((hc >> 16) & 0xffffu) & 0x1F); |
253 | 0 | uint64_t v90 = (uint32_t)(huff_index - v37); |
254 | 0 | int32_t v39 = (uint16_t)((uint64_t)v38 >> ((uint8_t)v37 - (uint8_t)huff_index)) << ((huff_coeff[huff_index] >> 24) & 0xffu); |
255 | |
|
256 | 0 | if (huff_index - v37 <= 0) |
257 | 0 | v39 &= 0xffff0000u; |
258 | |
|
259 | 0 | int32_t delta1; |
260 | 0 | if (v38 < 0) |
261 | 0 | delta1 = (uint16_t)v39; |
262 | 0 | else if (huff_index) |
263 | 0 | { |
264 | 0 | int32_t v40 = -1 << huff_index; |
265 | 0 | if ((uint8_t)v37) |
266 | 0 | delta1 = (uint16_t)v39 + v40; |
267 | 0 | else |
268 | 0 | delta1 = (uint16_t)v39 + v40 + 1; |
269 | 0 | } |
270 | 0 | else |
271 | 0 | delta1 = 0; |
272 | |
|
273 | 0 | uint32_t v42 = bitportion - ((huff_coeff[huff_index] >> 16) & 0x1F); |
274 | 0 | int32_t delta2 = uint8_t(v37) ? 1 << (v37 - 1) : 0; |
275 | 0 | uint32_t *destpixel = (uint32_t *)(outrowp + 16LL * (col >> 2)); |
276 | |
|
277 | 0 | int32_t delta = delta1 + delta2; |
278 | 0 | int32_t col_amp_3 = col & 3; |
279 | 0 | #define _LIM(a, _max_) (a < 0) ? 0 : ((a > _max_) ? _max_ : a) |
280 | 0 | if (col_amp_3 == 2) |
281 | 0 | { |
282 | 0 | int32_t val = current_base.coeff[1] + delta; |
283 | 0 | destpixel[1] = uint32_t(_LIM(val, int(datamax))); |
284 | 0 | } |
285 | 0 | else if (col_amp_3 == 1) |
286 | 0 | { |
287 | 0 | int32_t val = current_base.coeff[2] + delta; |
288 | 0 | destpixel[2] = uint32_t(_LIM(val, int(datamax))); |
289 | 0 | } |
290 | 0 | else if ((col & 3) != 0) // == 3 |
291 | 0 | { |
292 | 0 | int32_t val = current_base.coeff[3] + delta; |
293 | 0 | destpixel[3] = uint32_t(_LIM(val, int(datamax))); |
294 | 0 | } |
295 | 0 | else // 0 |
296 | 0 | { |
297 | 0 | int32_t val = current_base.coeff[0] + delta; |
298 | 0 | destpixel[0] = uint32_t(_LIM(val, int(datamax))); |
299 | 0 | } |
300 | 0 | #undef _LIM |
301 | 0 | if (huff_index <= v37) |
302 | 0 | v90 = 0LL; |
303 | 0 | bittail = v38 << v90; |
304 | 0 | bitportion = int32_t(v42 - v90); |
305 | |
|
306 | 0 | if (col_amp_3 == 3) |
307 | 0 | current_base.clone((uint32_t *)(outrowp + 16LL * (col >> 2))); |
308 | 0 | if (col == 3) |
309 | 0 | line_base.clone((uint32_t *)(outrowp)); |
310 | 0 | } |
311 | | |
312 | 0 | int destrow = current_row * 2; |
313 | 0 | uint16_t *destrow0 = libraw->imgdata.rawdata.raw_image + (destrow * libraw->imgdata.sizes.raw_width) + left_margin; |
314 | 0 | uint16_t *destrow1 = |
315 | 0 | libraw->imgdata.rawdata.raw_image + (destrow + 1) * libraw->imgdata.sizes.raw_width + left_margin; |
316 | 0 | uint16_t *srcrow = (uint16_t *)(outrowp); |
317 | 0 | if (gammatable) |
318 | 0 | { |
319 | 0 | for (unsigned col = 0; col < width - 1; col += 2) |
320 | 0 | { |
321 | 0 | const int c6 = col * 4; |
322 | 0 | destrow0[col] = gammatable[srcrow[c6]]; |
323 | 0 | destrow0[col + 1] = gammatable[srcrow[c6 + 2]]; |
324 | 0 | destrow1[col] = gammatable[srcrow[c6 + 4]]; |
325 | 0 | destrow1[col + 1] = gammatable[srcrow[c6 + 6]]; |
326 | 0 | } |
327 | 0 | } |
328 | 0 | else |
329 | 0 | { |
330 | 0 | for (unsigned col = 0; col < width - 1; col += 2) |
331 | 0 | { |
332 | 0 | const int c6 = col * 4; |
333 | 0 | destrow0[col] = srcrow[c6]; |
334 | 0 | destrow0[col + 1] = srcrow[c6 + 2]; |
335 | 0 | destrow1[col] = srcrow[c6 + 4]; |
336 | 0 | destrow1[col + 1] = srcrow[c6 + 6]; |
337 | 0 | } |
338 | 0 | } |
339 | 0 | } |
340 | 0 | } |
341 | 0 | catch (...) // buffer read may throw an exception |
342 | 0 | { |
343 | 0 | return false; |
344 | 0 | } |
345 | 0 | return true; |
346 | 0 | } |
347 | | |
348 | | |
349 | | uint32_t pana8_param_t::GetDBit(uint64_t a2) |
350 | 0 | { |
351 | 0 | for (int i = 0; i < 16; i++) |
352 | 0 | { |
353 | 0 | if ((a2 & hufftable2[i]) == hufftable1[i]) |
354 | 0 | return i; |
355 | 0 | } |
356 | 0 | return uint32_t((hufftable2[16] & a2) == hufftable1[16]) ^ 0x11u; |
357 | 0 | } |
358 | | |
359 | 0 | pana8_param_t::pana8_param_t(const pana8_tags_t &meta) : gammaTable(0) |
360 | 0 | { |
361 | 0 | range_shift = gamma_base = tag3B = 0; |
362 | | #ifndef ZERO |
363 | | #define ZERO(a) memset(a, 0, sizeof(a)) |
364 | | #endif |
365 | 0 | ZERO(tag3A); |
366 | 0 | ZERO(tag39); |
367 | 0 | ZERO(tag3A); |
368 | 0 | ZERO(initial); |
369 | 0 | ZERO(huff_coeff); |
370 | 0 | ZERO(hufftable1); |
371 | 0 | ZERO(hufftable2); |
372 | 0 | #undef ZERO |
373 | 0 | noGammaFlag = 1; |
374 | |
|
375 | 0 | for (int i = 0; i < 6; i++) |
376 | 0 | { |
377 | 0 | tag3A[i] = meta.tag3A[i]; |
378 | 0 | tag39[i] = meta.tag39[i]; |
379 | 0 | } |
380 | 0 | tag3B_2 = tag3B = meta.tag3B; |
381 | 0 | for(int i = 0; i < 4; i++) |
382 | 0 | initial[i] = meta.initial[i]; |
383 | |
|
384 | 0 | for (int i = 0; i < 17; i++) |
385 | 0 | huff_coeff[i] = (uint32_t(meta.tag41[i]) << 24) | (uint32_t(meta.tag40a[i]) << 16) | meta.tag40b[i]; |
386 | |
|
387 | 0 | std::vector<uint16_t> tempGamma(0x10000); |
388 | 0 | for (unsigned i = 0; i < 0x10000; i++) |
389 | 0 | { |
390 | 0 | uint64_t val = gammaCurve(i); |
391 | 0 | tempGamma[i] = uint16_t(val & 0xffffu); |
392 | 0 | if (i != val) |
393 | 0 | noGammaFlag = 0; |
394 | 0 | } |
395 | 0 | if (!noGammaFlag) |
396 | 0 | gammaTable = tempGamma; |
397 | |
|
398 | 0 | int v7 = 0; |
399 | |
|
400 | 0 | for (unsigned hindex = 0; hindex < 17; hindex++) |
401 | 0 | { |
402 | 0 | uint32_t hc = huff_coeff[hindex]; |
403 | 0 | uint32_t hlow = (hc >> 16) & 0x1F; |
404 | 0 | int16_t v8 = 0; |
405 | 0 | if ((hc & 0x1F0000) != 0) |
406 | 0 | { |
407 | 0 | int h7 = ((hc >> 16) & 0xffffu) & 7; |
408 | 0 | if (hlow - 1 >= 7) |
409 | 0 | { |
410 | 0 | uint32_t hdiff = h7 - hlow; |
411 | 0 | v8 = 0; |
412 | 0 | do |
413 | 0 | { |
414 | 0 | v8 = (v8 << 8) | 0xFFu; |
415 | 0 | hdiff += 8; |
416 | 0 | } while (hdiff); |
417 | 0 | } |
418 | 0 | else |
419 | 0 | v8 = 0; |
420 | 0 | for (; h7; --h7) |
421 | 0 | v8 = 2 * v8 + 1; |
422 | 0 | } |
423 | |
|
424 | 0 | uint16_t v9 = hc & v8; |
425 | 0 | if (uint32_t(v7) < hlow) |
426 | 0 | v7 = ((huff_coeff[hindex] >> 16) & 0xFFFFu) & 0x1F; |
427 | 0 | hufftable2[hindex] = 0xFFFFULL << (64-hlow); |
428 | 0 | hufftable1[hindex] = (uint64_t)v9 << (64-hlow); |
429 | 0 | } |
430 | |
|
431 | 0 | if (v7 < 17) |
432 | 0 | { |
433 | 0 | if (extrahuff.size() < 0x10000) |
434 | 0 | extrahuff.resize(0x10000); |
435 | 0 | uint64_t v17 = 0LL; |
436 | |
|
437 | 0 | for (int j = 0LL; j != 0x10000; ++j) |
438 | 0 | { |
439 | 0 | extrahuff[j] = uint8_t(GetDBit(v17) & 0xffu); |
440 | 0 | v17 += 0x1000000000000ULL; |
441 | 0 | } |
442 | 0 | } |
443 | 0 | } |
444 | | |
445 | | int32_t pana8_param_t::gammaCurve(uint32_t idx) |
446 | 0 | { |
447 | 0 | unsigned int v2 = idx | 0xFFFF0000; |
448 | 0 | if ((idx & 0x10000) == 0) |
449 | 0 | v2 = idx & 0x1FFFF; |
450 | |
|
451 | 0 | int v3 = gamma_base + v2; |
452 | 0 | unsigned int v4 = MIN(v3, 0xFFFF); |
453 | |
|
454 | 0 | int v5 = 0; |
455 | 0 | if ((v4 & 0x80000000) != 0) |
456 | 0 | v4 = 0; |
457 | |
|
458 | 0 | if (v4 >= (0xFFFF & tag3A[1])) |
459 | 0 | { |
460 | 0 | v5 = 1; |
461 | 0 | if (v4 >= (0xFFFF & tag3A[2])) |
462 | 0 | { |
463 | 0 | v5 = 2; |
464 | 0 | if (v4 >= (0xFFFF & tag3A[3])) |
465 | 0 | { |
466 | 0 | v5 = 3; |
467 | 0 | if (v4 >= (0xFFFF & tag3A[4])) |
468 | 0 | v5 = ((v4 | 0x500000000LL) - (uint64_t)(0xFFFF & tag3A[5])) >> 32; |
469 | 0 | } |
470 | 0 | } |
471 | 0 | } |
472 | 0 | unsigned int v6 = tag3A[v5]; |
473 | 0 | int v7 = tag39[v5]; |
474 | 0 | unsigned int v8 = v4 - (uint16_t)v6; |
475 | 0 | char v9 = v7 & 0x1F; |
476 | 0 | int64_t result = 0; |
477 | |
|
478 | 0 | if (v9 == 31) |
479 | 0 | { |
480 | 0 | result = v5 == 5 ? 0xFFFFLL : ((tag3A[v5 + 1] >> 16) & 0xFFFF); |
481 | 0 | return MIN( uint32_t(result), tag3B); |
482 | 0 | } |
483 | 0 | if ((v7 & 0x10) == 0) |
484 | 0 | { |
485 | 0 | if (v9 == 15) |
486 | 0 | { |
487 | 0 | result = ((v6 >> 16) & 0xFFFF); |
488 | 0 | return MIN( uint32_t(result), tag3B); |
489 | 0 | } |
490 | 0 | else if(v9!=0) |
491 | 0 | v8 = (v8 + (1 << (v9 - 1))) >> v9; |
492 | 0 | } |
493 | 0 | else |
494 | 0 | v8 <<= v7 & 0xF; |
495 | | |
496 | 0 | result = v8 + ((v6 >> 16) & 0xFFFF); |
497 | 0 | return MIN( uint32_t(result), tag3B); |
498 | 0 | } |
499 | | |
500 | | const static uint8_t _bitRevTable[256] = { |
501 | | 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, |
502 | | 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, |
503 | | 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, |
504 | | 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, |
505 | | 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, |
506 | | 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, |
507 | | 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, |
508 | | 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, |
509 | | 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, |
510 | | 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, |
511 | | 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, |
512 | | 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, |
513 | | 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, |
514 | | 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; |
515 | | |
516 | | void invertBits(void *buf, size_t size) |
517 | 0 | { |
518 | 0 | unsigned sz = unsigned(size / 8); |
519 | 0 | uint64_t *ptr = (uint64_t *)buf; |
520 | 0 | for (unsigned i = 0; i < sz; i++) |
521 | 0 | { |
522 | 0 | uint8_t *b = (uint8_t *)&ptr[i]; |
523 | 0 | uint64_t r = ((uint64_t)_bitRevTable[b[0]] << 56) | ((uint64_t)_bitRevTable[b[1]] << 48) | |
524 | 0 | ((uint64_t)_bitRevTable[b[2]] << 40) | ((uint64_t)_bitRevTable[b[3]] << 32) | |
525 | 0 | ((uint64_t)_bitRevTable[b[4]] << 24) | ((uint64_t)_bitRevTable[b[5]] << 16) | |
526 | 0 | ((uint64_t)_bitRevTable[b[6]] << 8) | _bitRevTable[b[7]]; |
527 | 0 | ptr[i] = r; |
528 | 0 | } |
529 | 0 | } |