Coverage Report

Created: 2026-07-25 07:03

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