Coverage Report

Created: 2025-11-14 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}