Coverage Report

Created: 2026-05-31 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/decoders/fuji_compressed.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * File: libraw_fuji_compressed.cpp
3
 * Copyright (C) 2016-2019 Alexey Danilchenko
4
 *
5
 * Adopted to LibRaw by Alex Tutubalin, lexa@lexa.ru
6
 * LibRaw Fujifilm/compressed decoder
7
8
LibRaw is free software; you can redistribute it and/or modify
9
it under the terms of the one of two licenses as you choose:
10
11
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
12
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
13
14
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
15
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
16
17
 */
18
19
#include "../../internal/libraw_cxx_defs.h"
20
21
#ifdef _abs
22
#undef _abs
23
#undef _min
24
#undef _max
25
#endif
26
0
#define _abs(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
27
0
#define _min(a, b) ((a) < (b) ? (a) : (b))
28
0
#define _max(a, b) ((a) > (b) ? (a) : (b))
29
30
struct int_pair
31
{
32
  int value1;
33
  int value2;
34
};
35
36
enum _xt_lines
37
{
38
  _R0 = 0,
39
  _R1,
40
  _R2,
41
  _R3,
42
  _R4,
43
  _G0,
44
  _G1,
45
  _G2,
46
  _G3,
47
  _G4,
48
  _G5,
49
  _G6,
50
  _G7,
51
  _B0,
52
  _B1,
53
  _B2,
54
  _B3,
55
  _B4,
56
  _ltotal
57
};
58
59
// tables of gradients for single sample level
60
struct fuji_grads
61
{
62
  int_pair grads[41];
63
  int_pair lossy_grads[3][5];
64
};
65
66
struct fuji_compressed_block
67
{
68
  int cur_bit;            // current bit being read (from left to right)
69
  int cur_pos;            // current position in a buffer
70
  INT64 cur_buf_offset;   // offset of this buffer in a file
71
  unsigned max_read_size; // Amount of data to be read
72
  int cur_buf_size;       // buffer size
73
  uchar *cur_buf;         // currently read block
74
  int fillbytes;          // Counter to add extra byte for block size N*16
75
  LibRaw_abstract_datastream *input;
76
  fuji_grads even[3]; // tables of even gradients
77
  fuji_grads odd[3];  // tables of odd gradients
78
  ushort *linealloc;
79
  ushort *linebuf[_ltotal];
80
};
81
82
static inline int log2ceil(int val)
83
0
{
84
0
  int result = 0;
85
0
  if (val--)
86
0
    do
87
0
      ++result;
88
0
    while (val >>= 1);
89
90
0
  return result;
91
0
}
92
93
void setup_qlut(int8_t *qt, int *q_point)
94
0
{
95
0
  for (int curVal = -q_point[4]; curVal <= q_point[4]; ++qt, ++curVal)
96
0
  {
97
0
    if (curVal <= -q_point[3])
98
0
      *qt = -4;
99
0
    else if (curVal <= -q_point[2])
100
0
      *qt = -3;
101
0
    else if (curVal <= -q_point[1])
102
0
      *qt = -2;
103
0
    else if (curVal < -q_point[0])
104
0
      *qt = -1;
105
0
    else if (curVal <= q_point[0])
106
0
      *qt = 0;
107
0
    else if (curVal < q_point[1])
108
0
      *qt = 1;
109
0
    else if (curVal < q_point[2])
110
0
      *qt = 2;
111
0
    else if (curVal < q_point[3])
112
0
      *qt = 3;
113
0
    else
114
0
      *qt = 4;
115
0
  }
116
0
}
117
118
void init_main_qtable(fuji_compressed_params *params, uchar q_base)
119
0
{
120
0
  fuji_q_table *qt = params->qt;
121
0
  int qp[5];
122
0
  int maxVal = params->max_value + 1;
123
0
  qp[0] = q_base;
124
0
  qp[1] = 3 * q_base + 0x12;
125
0
  qp[2] = 5 * q_base + 0x43;
126
0
  qp[3] = 7 * q_base + 0x114;
127
0
  qp[4] = params->max_value;
128
0
  if (qp[1] >= maxVal || qp[1] < q_base + 1)
129
0
    qp[1] = q_base + 1;
130
0
  if (qp[2] < qp[1] || qp[2] >= maxVal)
131
0
    qp[2] = qp[1];
132
0
  if (qp[3] < qp[2] || qp[3] >= maxVal)
133
0
    qp[3] = qp[2];
134
0
  setup_qlut(qt->q_table, qp);
135
0
  qt->q_base = q_base;
136
0
  qt->max_grad = 0;
137
0
  qt->total_values = (qp[4] + 2 * q_base) / (2 * q_base + 1) + 1;
138
0
  qt->raw_bits = log2ceil(qt->total_values);
139
0
  qt->q_grad_mult = 9;
140
0
  params->max_bits = 4 * log2ceil(qp[4] + 1);
141
0
}
142
143
void LibRaw::init_fuji_compr(fuji_compressed_params *params)
144
0
{
145
0
  if ((libraw_internal_data.unpacker_data.fuji_block_width % 3 &&
146
0
       libraw_internal_data.unpacker_data.fuji_raw_type == 16) ||
147
0
      (libraw_internal_data.unpacker_data.fuji_block_width & 1 &&
148
0
       libraw_internal_data.unpacker_data.fuji_raw_type == 0))
149
0
    derror();
150
151
0
  size_t q_table_size = 2 << libraw_internal_data.unpacker_data.fuji_bits;
152
0
  if (libraw_internal_data.unpacker_data.fuji_lossless)
153
0
    params->buf = calloc(q_table_size, 1);
154
0
  else
155
0
    params->buf = calloc(3 * q_table_size, 1);
156
157
0
  if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
158
0
    params->line_width = (libraw_internal_data.unpacker_data.fuji_block_width * 2) / 3;
159
0
  else
160
0
    params->line_width = libraw_internal_data.unpacker_data.fuji_block_width >> 1;
161
162
0
  params->min_value = 0x40;
163
0
  params->max_value = (1 << libraw_internal_data.unpacker_data.fuji_bits) - 1;
164
165
  // setup qtables
166
0
  if (libraw_internal_data.unpacker_data.fuji_lossless)
167
0
  {
168
    // setup main qtable only, zero the rest
169
0
    memset(params->qt + 1, 0, 3 * sizeof(fuji_q_table));
170
0
    params->qt[0].q_table = (int8_t *)params->buf;
171
0
    params->qt[0].q_base = -1;
172
0
    init_main_qtable(params, 0);
173
0
  }
174
0
  else
175
0
  {
176
    // setup 3 extra qtables - main one will be set for each block
177
0
    memset(params->qt, 0, sizeof(fuji_q_table));
178
0
    int qp[5];
179
180
0
    qp[0] = 0;
181
0
    qp[4] = params->max_value;
182
183
    // table 0
184
0
    params->qt[1].q_table = (int8_t *)params->buf;
185
0
    params->qt[1].q_base = 0;
186
0
    params->qt[1].max_grad = 5;
187
0
    params->qt[1].q_grad_mult = 3;
188
0
    params->qt[1].total_values = qp[4] + 1;
189
0
    params->qt[1].raw_bits = log2ceil(params->qt[1].total_values);
190
191
0
    qp[1] = qp[4] >= 0x12 ? 0x12 : qp[0] + 1;
192
0
    qp[2] = qp[4] >= 0x43 ? 0x43 : qp[1];
193
0
    qp[3] = qp[4] >= 0x114 ? 0x114 : qp[2];
194
0
    setup_qlut(params->qt[1].q_table, qp);
195
196
    // table 1
197
0
    params->qt[2].q_table = params->qt[1].q_table + q_table_size;
198
0
    params->qt[2].q_base = 1;
199
0
    params->qt[2].max_grad = 6;
200
0
    params->qt[2].q_grad_mult = 3;
201
0
    params->qt[2].total_values = (qp[4] + 2) / 3 + 1;
202
0
    params->qt[2].raw_bits = log2ceil(params->qt[2].total_values);
203
204
0
    qp[0] = params->qt[2].q_base;
205
0
    qp[1] = qp[4] >= 0x15 ? 0x15 : qp[0] + 1;
206
0
    qp[2] = qp[4] >= 0x48 ? 0x48 : qp[1];
207
0
    qp[3] = qp[4] >= 0x11B ? 0x11B : qp[2];
208
0
    setup_qlut(params->qt[2].q_table, qp);
209
210
    // table 2
211
0
    params->qt[3].q_table = params->qt[2].q_table + q_table_size;
212
0
    params->qt[3].q_base = 2;
213
0
    params->qt[3].max_grad = 7;
214
0
    params->qt[3].q_grad_mult = 3;
215
0
    params->qt[3].total_values = (qp[4] + 4) / 5 + 1;
216
0
    params->qt[3].raw_bits = log2ceil(params->qt[3].total_values);
217
218
0
    qp[0] = params->qt[3].q_base;
219
0
    qp[1] = qp[4] >= 0x18 ? 0x18 : qp[0] + 1;
220
0
    qp[2] = qp[4] >= 0x4D ? 0x4D : qp[1];
221
0
    qp[3] = qp[4] >= 0x122 ? 0x122 : qp[2];
222
0
    setup_qlut(params->qt[3].q_table, qp);
223
0
  }
224
0
}
225
226
0
#define XTRANS_BUF_SIZE 0x10000
227
228
static inline void fuji_fill_buffer(fuji_compressed_block *info)
229
0
{
230
0
  if (info->cur_pos >= info->cur_buf_size)
231
0
  {
232
0
    bool needthrow = false;
233
0
    info->cur_pos = 0;
234
0
    info->cur_buf_offset += info->cur_buf_size;
235
#ifdef LIBRAW_USE_OPENMP
236
#pragma omp critical
237
#endif
238
0
    {
239
0
#ifndef LIBRAW_USE_OPENMP
240
0
      info->input->lock();
241
0
#endif
242
0
      info->input->seek(info->cur_buf_offset, SEEK_SET);
243
0
      info->cur_buf_size = info->input->read(info->cur_buf, 1, _min(info->max_read_size, XTRANS_BUF_SIZE));
244
0
#ifndef LIBRAW_USE_OPENMP
245
0
      info->input->unlock();
246
0
#endif
247
0
      if (info->cur_buf_size < 1) // nothing read
248
0
      {
249
0
        if (info->fillbytes > 0)
250
0
        {
251
0
          int ls = _max(1, _min(info->fillbytes, XTRANS_BUF_SIZE));
252
0
          memset(info->cur_buf, 0, ls);
253
0
          info->fillbytes -= ls;
254
0
        }
255
0
        else
256
0
          needthrow = true;
257
0
      }
258
0
      info->max_read_size -= info->cur_buf_size;
259
0
    }
260
0
    if (needthrow)
261
0
      throw LIBRAW_EXCEPTION_IO_EOF;
262
0
  }
263
0
}
264
265
void init_main_grads(const fuji_compressed_params *params, fuji_compressed_block *info)
266
0
{
267
0
  int max_diff = _max(2, (params->qt->total_values + 0x20) >> 6);
268
0
  for (int j = 0; j < 3; j++)
269
0
    for (int i = 0; i < 41; i++)
270
0
    {
271
0
      info->even[j].grads[i].value1 = max_diff;
272
0
      info->even[j].grads[i].value2 = 1;
273
0
      info->odd[j].grads[i].value1 = max_diff;
274
0
      info->odd[j].grads[i].value2 = 1;
275
0
    }
276
0
}
277
278
void LibRaw::init_fuji_block(fuji_compressed_block *info, const fuji_compressed_params *params, INT64 raw_offset,
279
                             unsigned dsize)
280
0
{
281
0
  info->linealloc = (ushort *)calloc(sizeof(ushort), _ltotal * (params->line_width + 2));
282
283
0
  INT64 fsize = libraw_internal_data.internal_data.input->size();
284
0
  info->max_read_size = _min(unsigned(fsize - raw_offset), dsize); // Data size may be incorrect?
285
0
  info->fillbytes = 1;
286
287
0
  info->input = libraw_internal_data.internal_data.input;
288
0
  info->linebuf[_R0] = info->linealloc;
289
0
  for (int i = _R1; i <= _B4; i++)
290
0
    info->linebuf[i] = info->linebuf[i - 1] + params->line_width + 2;
291
292
  // init buffer
293
0
  info->cur_buf = (uchar *)calloc(XTRANS_BUF_SIZE, 1);
294
0
  info->cur_bit = 0;
295
0
  info->cur_pos = 0;
296
0
  info->cur_buf_offset = raw_offset;
297
0
  info->cur_buf_size = 0;
298
0
  fuji_fill_buffer(info);
299
300
  // init grads for lossy and lossless
301
0
  if (libraw_internal_data.unpacker_data.fuji_lossless)
302
0
    init_main_grads(params, info);
303
0
  else
304
0
  {
305
    // init static grads for lossy only - main ones are done per line
306
0
    for (int k = 0; k < 3; ++k)
307
0
    {
308
0
      int max_diff = _max(2, ((params->qt[k + 1].total_values + 0x20) >> 6));
309
0
      for (int j = 0; j < 3; ++j)
310
0
        for (int i = 0; i < 5; ++i)
311
0
        {
312
0
          info->even[j].lossy_grads[k][i].value1 = max_diff;
313
0
          info->even[j].lossy_grads[k][i].value2 = 1;
314
0
          info->odd[j].lossy_grads[k][i].value1 = max_diff;
315
0
          info->odd[j].lossy_grads[k][i].value2 = 1;
316
0
        }
317
0
    }
318
0
  }
319
0
}
320
321
void LibRaw::copy_line_to_xtrans(fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width)
322
0
{
323
0
  ushort *lineBufB[3];
324
0
  ushort *lineBufG[6];
325
0
  ushort *lineBufR[3];
326
0
  unsigned pixel_count;
327
0
  ushort *line_buf;
328
0
  int index;
329
330
0
  int offset = libraw_internal_data.unpacker_data.fuji_block_width * cur_block + 6 * imgdata.sizes.raw_width * cur_line;
331
0
  ushort *raw_block_data = imgdata.rawdata.raw_image + offset;
332
0
  int row_count = 0;
333
334
0
  for (int i = 0; i < 3; i++)
335
0
  {
336
0
    lineBufR[i] = info->linebuf[_R2 + i] + 1;
337
0
    lineBufB[i] = info->linebuf[_B2 + i] + 1;
338
0
  }
339
0
  for (int i = 0; i < 6; i++)
340
0
    lineBufG[i] = info->linebuf[_G2 + i] + 1;
341
342
0
  while (row_count < 6)
343
0
  {
344
0
    pixel_count = 0;
345
0
    while (pixel_count < (unsigned)cur_block_width)
346
0
    {
347
0
      switch (imgdata.idata.xtrans_abs[row_count][(pixel_count % 6)])
348
0
      {
349
0
      case 0: // red
350
0
        line_buf = lineBufR[row_count >> 1];
351
0
        break;
352
0
      case 1:  // green
353
0
      default: // to make static analyzer happy
354
0
        line_buf = lineBufG[row_count];
355
0
        break;
356
0
      case 2: // blue
357
0
        line_buf = lineBufB[row_count >> 1];
358
0
        break;
359
0
      }
360
361
0
      index = (((pixel_count * 2 / 3) & 0x7FFFFFFE) | ((pixel_count % 3) & 1)) + ((pixel_count % 3) >> 1);
362
0
      raw_block_data[pixel_count] = line_buf[index];
363
364
0
      ++pixel_count;
365
0
    }
366
0
    ++row_count;
367
0
    raw_block_data += imgdata.sizes.raw_width;
368
0
  }
369
0
}
370
371
void LibRaw::copy_line_to_bayer(fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width)
372
0
{
373
0
  ushort *lineBufB[3];
374
0
  ushort *lineBufG[6];
375
0
  ushort *lineBufR[3];
376
0
  unsigned pixel_count;
377
0
  ushort *line_buf;
378
379
0
  int fuji_bayer[2][2];
380
0
  for (int r = 0; r < 2; r++)
381
0
    for (int c = 0; c < 2; c++)
382
0
      fuji_bayer[r][c] = FC(r, c); // We'll downgrade G2 to G below
383
384
0
  int offset = libraw_internal_data.unpacker_data.fuji_block_width * cur_block + 6 * imgdata.sizes.raw_width * cur_line;
385
0
  ushort *raw_block_data = imgdata.rawdata.raw_image + offset;
386
0
  int row_count = 0;
387
388
0
  for (int i = 0; i < 3; i++)
389
0
  {
390
0
    lineBufR[i] = info->linebuf[_R2 + i] + 1;
391
0
    lineBufB[i] = info->linebuf[_B2 + i] + 1;
392
0
  }
393
0
  for (int i = 0; i < 6; i++)
394
0
    lineBufG[i] = info->linebuf[_G2 + i] + 1;
395
396
0
  while (row_count < 6)
397
0
  {
398
0
    pixel_count = 0;
399
0
    while (pixel_count < (unsigned)cur_block_width)
400
0
    {
401
0
      switch (fuji_bayer[row_count & 1][pixel_count & 1])
402
0
      {
403
0
      case 0: // red
404
0
        line_buf = lineBufR[row_count >> 1];
405
0
        break;
406
0
      case 1:  // green
407
0
      case 3:  // second green
408
0
      default: // to make static analyzer happy
409
0
        line_buf = lineBufG[row_count];
410
0
        break;
411
0
      case 2: // blue
412
0
        line_buf = lineBufB[row_count >> 1];
413
0
        break;
414
0
      }
415
416
0
      raw_block_data[pixel_count] = line_buf[pixel_count >> 1];
417
0
      ++pixel_count;
418
0
    }
419
0
    ++row_count;
420
0
    raw_block_data += imgdata.sizes.raw_width;
421
0
  }
422
0
}
423
424
0
#define fuji_quant_gradient(max, q, v1, v2) (q->q_grad_mult * q->q_table[(max) + (v1)] + q->q_table[(max) + (v2)])
425
426
static inline void fuji_zerobits(fuji_compressed_block *info, int *count)
427
0
{
428
0
  uchar zero = 0;
429
0
  *count = 0;
430
0
  while (zero == 0)
431
0
  {
432
0
    zero = (info->cur_buf[info->cur_pos] >> (7 - info->cur_bit)) & 1;
433
0
    info->cur_bit++;
434
0
    info->cur_bit &= 7;
435
0
    if (!info->cur_bit)
436
0
    {
437
0
      ++info->cur_pos;
438
0
      fuji_fill_buffer(info);
439
0
    }
440
0
    if (zero)
441
0
      break;
442
0
    ++*count;
443
0
  }
444
0
}
445
446
static inline void fuji_read_code(fuji_compressed_block *info, int *data, int bits_to_read)
447
0
{
448
0
  uchar bits_left = bits_to_read;
449
0
  uchar bits_left_in_byte = 8 - (info->cur_bit & 7);
450
0
  *data = 0;
451
0
  if (!bits_to_read)
452
0
    return;
453
0
  if (bits_to_read >= bits_left_in_byte)
454
0
  {
455
0
    do
456
0
    {
457
0
      *data <<= bits_left_in_byte;
458
0
      bits_left -= bits_left_in_byte;
459
0
      *data |= info->cur_buf[info->cur_pos] & ((1 << bits_left_in_byte) - 1);
460
0
      ++info->cur_pos;
461
0
      fuji_fill_buffer(info);
462
0
      bits_left_in_byte = 8;
463
0
    } while (bits_left >= 8);
464
0
  }
465
0
  if (!bits_left)
466
0
  {
467
0
    info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
468
0
    return;
469
0
  }
470
0
  *data <<= bits_left;
471
0
  bits_left_in_byte -= bits_left;
472
0
  *data |= ((1 << bits_left) - 1) & ((unsigned)info->cur_buf[info->cur_pos] >> bits_left_in_byte);
473
0
  info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
474
0
}
475
476
static inline int bitDiff(int value1, int value2)
477
0
{
478
0
  int decBits = 0;
479
0
  if (value2 < value1)
480
0
    while (decBits <= 14 && (value2 << ++decBits) < value1)
481
0
      ;
482
0
  return decBits;
483
0
}
484
485
static inline int fuji_decode_sample_even(fuji_compressed_block *info, const fuji_compressed_params *params,
486
                                          ushort *line_buf, int pos, fuji_grads *grad_params)
487
0
{
488
0
  int interp_val = 0;
489
  // ushort decBits;
490
0
  int errcnt = 0;
491
492
0
  int sample = 0, code = 0;
493
0
  ushort *line_buf_cur = line_buf + pos;
494
0
  int Rb = line_buf_cur[-2 - params->line_width];
495
0
  int Rc = line_buf_cur[-3 - params->line_width];
496
0
  int Rd = line_buf_cur[-1 - params->line_width];
497
0
  int Rf = line_buf_cur[-4 - 2 * params->line_width];
498
499
0
  int grad, gradient, diffRcRb, diffRfRb, diffRdRb;
500
501
0
  diffRcRb = _abs(Rc - Rb);
502
0
  diffRfRb = _abs(Rf - Rb);
503
0
  diffRdRb = _abs(Rd - Rb);
504
505
0
  const fuji_q_table *qt = params->qt;
506
0
  int_pair *grads = grad_params->grads;
507
0
  for (int i = 1; params->qt[0].q_base >= i && i < 4; ++i)
508
0
    if (diffRfRb + diffRcRb <= params->qt[i].max_grad)
509
0
    {
510
0
      qt = params->qt + i;
511
0
      grads = grad_params->lossy_grads[i - 1];
512
0
      break;
513
0
    }
514
515
0
  grad = fuji_quant_gradient(params->max_value, qt, Rb - Rf, Rc - Rb);
516
0
  gradient = _abs(grad);
517
518
0
  if (diffRcRb > diffRfRb && diffRcRb > diffRdRb)
519
0
    interp_val = Rf + Rd + 2 * Rb;
520
0
  else if (diffRdRb > diffRcRb && diffRdRb > diffRfRb)
521
0
    interp_val = Rf + Rc + 2 * Rb;
522
0
  else
523
0
    interp_val = Rd + Rc + 2 * Rb;
524
525
0
  fuji_zerobits(info, &sample);
526
527
0
  if (sample < params->max_bits - qt->raw_bits - 1)
528
0
  {
529
0
    int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
530
0
    fuji_read_code(info, &code, decBits);
531
0
    code += sample << decBits;
532
0
  }
533
0
  else
534
0
  {
535
0
    fuji_read_code(info, &code, qt->raw_bits);
536
0
    ++code;
537
0
  }
538
539
0
  if (code < 0 || code >= qt->total_values)
540
0
    ++errcnt;
541
542
0
  if (code & 1)
543
0
    code = -1 - code / 2;
544
0
  else
545
0
    code /= 2;
546
547
0
  grads[gradient].value1 += _abs(code);
548
0
  if (grads[gradient].value2 == params->min_value)
549
0
  {
550
0
    grads[gradient].value1 >>= 1;
551
0
    grads[gradient].value2 >>= 1;
552
0
  }
553
0
  ++grads[gradient].value2;
554
0
  if (grad < 0)
555
0
    interp_val = (interp_val >> 2) - code * (2 * qt->q_base + 1);
556
0
  else
557
0
    interp_val = (interp_val >> 2) + code * (2 * qt->q_base + 1);
558
0
  if (interp_val < -qt->q_base)
559
0
    interp_val += qt->total_values * (2 * qt->q_base + 1);
560
0
  else if (interp_val > qt->q_base + params->max_value)
561
0
    interp_val -= qt->total_values * (2 * qt->q_base + 1);
562
563
0
  if (interp_val >= 0)
564
0
    line_buf_cur[0] = _min(interp_val, params->max_value);
565
0
  else
566
0
    line_buf_cur[0] = 0;
567
0
  return errcnt;
568
0
}
569
570
static inline int fuji_decode_sample_odd(fuji_compressed_block *info, const fuji_compressed_params *params,
571
                                         ushort *line_buf, int pos, fuji_grads *grad_params)
572
0
{
573
0
  int interp_val = 0;
574
0
  int errcnt = 0;
575
576
0
  int sample = 0, code = 0;
577
0
  ushort *line_buf_cur = line_buf + pos;
578
0
  int Ra = line_buf_cur[-1];
579
0
  int Rb = line_buf_cur[-2 - params->line_width];
580
0
  int Rc = line_buf_cur[-3 - params->line_width];
581
0
  int Rd = line_buf_cur[-1 - params->line_width];
582
0
  int Rg = line_buf_cur[1];
583
584
0
  int grad, gradient;
585
586
0
  int diffRcRa = _abs(Rc - Ra);
587
0
  int diffRbRc = _abs(Rb - Rc);
588
589
0
  const fuji_q_table *qt = params->qt;
590
0
  int_pair *grads = grad_params->grads;
591
0
  for (int i = 1; params->qt[0].q_base >= i && i < 4; ++i)
592
0
    if (diffRbRc + diffRcRa <= params->qt[i].max_grad)
593
0
    {
594
0
      qt = params->qt + i;
595
0
      grads = grad_params->lossy_grads[i - 1];
596
0
      break;
597
0
    }
598
599
0
  grad = fuji_quant_gradient(params->max_value, qt, Rb - Rc, Rc - Ra);
600
0
  gradient = _abs(grad);
601
602
0
  if ((Rb > Rc && Rb > Rd) || (Rb < Rc && Rb < Rd))
603
0
    interp_val = (Rg + Ra + 2 * Rb) >> 2;
604
0
  else
605
0
    interp_val = (Ra + Rg) >> 1;
606
607
0
  fuji_zerobits(info, &sample);
608
609
0
  if (sample < params->max_bits - qt->raw_bits - 1)
610
0
  {
611
0
    int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
612
0
    fuji_read_code(info, &code, decBits);
613
0
    code += sample << decBits;
614
0
  }
615
0
  else
616
0
  {
617
0
    fuji_read_code(info, &code, qt->raw_bits);
618
0
    ++code;
619
0
  }
620
621
0
  if (code < 0 || code >= qt->total_values)
622
0
    ++errcnt;
623
624
0
  if (code & 1)
625
0
    code = -1 - code / 2;
626
0
  else
627
0
    code /= 2;
628
629
0
  grads[gradient].value1 += _abs(code);
630
0
  if (grads[gradient].value2 == params->min_value)
631
0
  {
632
0
    grads[gradient].value1 >>= 1;
633
0
    grads[gradient].value2 >>= 1;
634
0
  }
635
0
  ++grads[gradient].value2;
636
0
  if (grad < 0)
637
0
    interp_val -= code * (2 * qt->q_base + 1);
638
0
  else
639
0
    interp_val += code * (2 * qt->q_base + 1);
640
0
  if (interp_val < -qt->q_base)
641
0
    interp_val += qt->total_values * (2 * qt->q_base + 1);
642
0
  else if (interp_val > qt->q_base + params->max_value)
643
0
    interp_val -= qt->total_values * (2 * qt->q_base + 1);
644
645
0
  if (interp_val >= 0)
646
0
    line_buf_cur[0] = _min(interp_val, params->max_value);
647
0
  else
648
0
    line_buf_cur[0] = 0;
649
0
  return errcnt;
650
0
}
651
652
static void fuji_decode_interpolation_even(int line_width, ushort *line_buf, int pos)
653
0
{
654
0
  ushort *line_buf_cur = line_buf + pos;
655
0
  int Rb = line_buf_cur[-2 - line_width];
656
0
  int Rc = line_buf_cur[-3 - line_width];
657
0
  int Rd = line_buf_cur[-1 - line_width];
658
0
  int Rf = line_buf_cur[-4 - 2 * line_width];
659
0
  int diffRcRb = _abs(Rc - Rb);
660
0
  int diffRfRb = _abs(Rf - Rb);
661
0
  int diffRdRb = _abs(Rd - Rb);
662
0
  if (diffRcRb > diffRfRb && diffRcRb > diffRdRb)
663
0
    *line_buf_cur = (Rf + Rd + 2 * Rb) >> 2;
664
0
  else if (diffRdRb > diffRcRb && diffRdRb > diffRfRb)
665
0
    *line_buf_cur = (Rf + Rc + 2 * Rb) >> 2;
666
0
  else
667
0
    *line_buf_cur = (Rd + Rc + 2 * Rb) >> 2;
668
0
}
669
670
static void fuji_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end)
671
0
{
672
0
  for (int i = start; i <= end; i++)
673
0
  {
674
0
    linebuf[i][0] = linebuf[i - 1][1];
675
0
    linebuf[i][line_width + 1] = linebuf[i - 1][line_width];
676
0
  }
677
0
}
678
679
static void fuji_extend_red(ushort *linebuf[_ltotal], int line_width)
680
0
{
681
0
  fuji_extend_generic(linebuf, line_width, _R2, _R4);
682
0
}
683
684
static void fuji_extend_green(ushort *linebuf[_ltotal], int line_width)
685
0
{
686
0
  fuji_extend_generic(linebuf, line_width, _G2, _G7);
687
0
}
688
689
static void fuji_extend_blue(ushort *linebuf[_ltotal], int line_width)
690
0
{
691
0
  fuji_extend_generic(linebuf, line_width, _B2, _B4);
692
0
}
693
694
void LibRaw::xtrans_decode_block(fuji_compressed_block *info, const fuji_compressed_params *params, int /*cur_line*/)
695
0
{
696
0
  int r_even_pos = 0, r_odd_pos = 1;
697
0
  int g_even_pos = 0, g_odd_pos = 1;
698
0
  int b_even_pos = 0, b_odd_pos = 1;
699
700
0
  int errcnt = 0;
701
702
0
  const int line_width = params->line_width;
703
704
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
705
0
  {
706
0
    if (g_even_pos < line_width)
707
0
    {
708
0
      fuji_decode_interpolation_even(line_width, info->linebuf[_R2] + 1, r_even_pos);
709
0
      r_even_pos += 2;
710
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, &info->even[0]);
711
0
      g_even_pos += 2;
712
0
    }
713
0
    if (g_even_pos > 8)
714
0
    {
715
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, &info->odd[0]);
716
0
      r_odd_pos += 2;
717
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, &info->odd[0]);
718
0
      g_odd_pos += 2;
719
0
    }
720
0
  }
721
722
0
  fuji_extend_red(info->linebuf, line_width);
723
0
  fuji_extend_green(info->linebuf, line_width);
724
725
0
  g_even_pos = 0, g_odd_pos = 1;
726
727
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
728
0
  {
729
0
    if (g_even_pos < line_width)
730
0
    {
731
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, &info->even[1]);
732
0
      g_even_pos += 2;
733
0
      fuji_decode_interpolation_even(line_width, info->linebuf[_B2] + 1, b_even_pos);
734
0
      b_even_pos += 2;
735
0
    }
736
0
    if (g_even_pos > 8)
737
0
    {
738
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G3] + 1, g_odd_pos, &info->odd[1]);
739
0
      g_odd_pos += 2;
740
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B2] + 1, b_odd_pos, &info->odd[1]);
741
0
      b_odd_pos += 2;
742
0
    }
743
0
  }
744
745
0
  fuji_extend_green(info->linebuf, line_width);
746
0
  fuji_extend_blue(info->linebuf, line_width);
747
748
0
  r_even_pos = 0, r_odd_pos = 1;
749
0
  g_even_pos = 0, g_odd_pos = 1;
750
751
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
752
0
  {
753
0
    if (g_even_pos < line_width)
754
0
    {
755
0
      if (r_even_pos & 3)
756
0
        errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, &info->even[2]);
757
0
      else
758
0
        fuji_decode_interpolation_even(line_width, info->linebuf[_R3] + 1, r_even_pos);
759
0
      r_even_pos += 2;
760
0
      fuji_decode_interpolation_even(line_width, info->linebuf[_G4] + 1, g_even_pos);
761
0
      g_even_pos += 2;
762
0
    }
763
0
    if (g_even_pos > 8)
764
0
    {
765
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R3] + 1, r_odd_pos, &info->odd[2]);
766
0
      r_odd_pos += 2;
767
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G4] + 1, g_odd_pos, &info->odd[2]);
768
0
      g_odd_pos += 2;
769
0
    }
770
0
  }
771
772
0
  fuji_extend_red(info->linebuf, line_width);
773
0
  fuji_extend_green(info->linebuf, line_width);
774
775
0
  g_even_pos = 0, g_odd_pos = 1;
776
0
  b_even_pos = 0, b_odd_pos = 1;
777
778
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
779
0
  {
780
0
    if (g_even_pos < line_width)
781
0
    {
782
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G5] + 1, g_even_pos, &info->even[0]);
783
0
      g_even_pos += 2;
784
0
      if ((b_even_pos & 3) == 2)
785
0
        fuji_decode_interpolation_even(line_width, info->linebuf[_B3] + 1, b_even_pos);
786
0
      else
787
0
        errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B3] + 1, b_even_pos, &info->even[0]);
788
0
      b_even_pos += 2;
789
0
    }
790
0
    if (g_even_pos > 8)
791
0
    {
792
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G5] + 1, g_odd_pos, &info->odd[0]);
793
0
      g_odd_pos += 2;
794
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B3] + 1, b_odd_pos, &info->odd[0]);
795
0
      b_odd_pos += 2;
796
0
    }
797
0
  }
798
799
0
  fuji_extend_green(info->linebuf, line_width);
800
0
  fuji_extend_blue(info->linebuf, line_width);
801
802
0
  r_even_pos = 0, r_odd_pos = 1;
803
0
  g_even_pos = 0, g_odd_pos = 1;
804
805
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
806
0
  {
807
0
    if (g_even_pos < line_width)
808
0
    {
809
0
      if ((r_even_pos & 3) == 2)
810
0
        fuji_decode_interpolation_even(line_width, info->linebuf[_R4] + 1, r_even_pos);
811
0
      else
812
0
        errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R4] + 1, r_even_pos, &info->even[1]);
813
0
      r_even_pos += 2;
814
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G6] + 1, g_even_pos, &info->even[1]);
815
0
      g_even_pos += 2;
816
0
    }
817
0
    if (g_even_pos > 8)
818
0
    {
819
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R4] + 1, r_odd_pos, &info->odd[1]);
820
0
      r_odd_pos += 2;
821
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G6] + 1, g_odd_pos, &info->odd[1]);
822
0
      g_odd_pos += 2;
823
0
    }
824
0
  }
825
826
0
  fuji_extend_red(info->linebuf, line_width);
827
0
  fuji_extend_green(info->linebuf, line_width);
828
829
0
  g_even_pos = 0, g_odd_pos = 1;
830
0
  b_even_pos = 0, b_odd_pos = 1;
831
832
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
833
0
  {
834
0
    if (g_even_pos < line_width)
835
0
    {
836
0
      fuji_decode_interpolation_even(line_width, info->linebuf[_G7] + 1, g_even_pos);
837
0
      g_even_pos += 2;
838
0
      if (b_even_pos & 3)
839
0
        errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B4] + 1, b_even_pos, &info->even[2]);
840
0
      else
841
0
        fuji_decode_interpolation_even(line_width, info->linebuf[_B4] + 1, b_even_pos);
842
0
      b_even_pos += 2;
843
0
    }
844
0
    if (g_even_pos > 8)
845
0
    {
846
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G7] + 1, g_odd_pos, &info->odd[2]);
847
0
      g_odd_pos += 2;
848
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B4] + 1, b_odd_pos, &info->odd[2]);
849
0
      b_odd_pos += 2;
850
0
    }
851
0
  }
852
853
0
  fuji_extend_green(info->linebuf, line_width);
854
0
  fuji_extend_blue(info->linebuf, line_width);
855
856
0
  if (errcnt)
857
0
    derror();
858
0
}
859
860
void LibRaw::fuji_bayer_decode_block(fuji_compressed_block *info, const fuji_compressed_params *params, int /*cur_line*/)
861
0
{
862
0
  int r_even_pos = 0, r_odd_pos = 1;
863
0
  int g_even_pos = 0, g_odd_pos = 1;
864
0
  int b_even_pos = 0, b_odd_pos = 1;
865
866
0
  int errcnt = 0;
867
868
0
  const int line_width = params->line_width;
869
870
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
871
0
  {
872
0
    if (g_even_pos < line_width)
873
0
    {
874
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R2] + 1, r_even_pos, &info->even[0]);
875
0
      r_even_pos += 2;
876
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, &info->even[0]);
877
0
      g_even_pos += 2;
878
0
    }
879
0
    if (g_even_pos > 8)
880
0
    {
881
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, &info->odd[0]);
882
0
      r_odd_pos += 2;
883
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, &info->odd[0]);
884
0
      g_odd_pos += 2;
885
0
    }
886
0
  }
887
888
0
  fuji_extend_red(info->linebuf, line_width);
889
0
  fuji_extend_green(info->linebuf, line_width);
890
891
0
  g_even_pos = 0, g_odd_pos = 1;
892
893
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
894
0
  {
895
0
    if (g_even_pos < line_width)
896
0
    {
897
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, &info->even[1]);
898
0
      g_even_pos += 2;
899
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B2] + 1, b_even_pos, &info->even[1]);
900
0
      b_even_pos += 2;
901
0
    }
902
0
    if (g_even_pos > 8)
903
0
    {
904
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G3] + 1, g_odd_pos, &info->odd[1]);
905
0
      g_odd_pos += 2;
906
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B2] + 1, b_odd_pos, &info->odd[1]);
907
0
      b_odd_pos += 2;
908
0
    }
909
0
  }
910
911
0
  fuji_extend_green(info->linebuf, line_width);
912
0
  fuji_extend_blue(info->linebuf, line_width);
913
914
0
  r_even_pos = 0, r_odd_pos = 1;
915
0
  g_even_pos = 0, g_odd_pos = 1;
916
917
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
918
0
  {
919
0
    if (g_even_pos < line_width)
920
0
    {
921
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, &info->even[2]);
922
0
      r_even_pos += 2;
923
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G4] + 1, g_even_pos, &info->even[2]);
924
0
      g_even_pos += 2;
925
0
    }
926
0
    if (g_even_pos > 8)
927
0
    {
928
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R3] + 1, r_odd_pos, &info->odd[2]);
929
0
      r_odd_pos += 2;
930
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G4] + 1, g_odd_pos, &info->odd[2]);
931
0
      g_odd_pos += 2;
932
0
    }
933
0
  }
934
935
0
  fuji_extend_red(info->linebuf, line_width);
936
0
  fuji_extend_green(info->linebuf, line_width);
937
938
0
  g_even_pos = 0, g_odd_pos = 1;
939
0
  b_even_pos = 0, b_odd_pos = 1;
940
941
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
942
0
  {
943
0
    if (g_even_pos < line_width)
944
0
    {
945
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G5] + 1, g_even_pos, &info->even[0]);
946
0
      g_even_pos += 2;
947
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B3] + 1, b_even_pos, &info->even[0]);
948
0
      b_even_pos += 2;
949
0
    }
950
0
    if (g_even_pos > 8)
951
0
    {
952
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G5] + 1, g_odd_pos, &info->odd[0]);
953
0
      g_odd_pos += 2;
954
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B3] + 1, b_odd_pos, &info->odd[0]);
955
0
      b_odd_pos += 2;
956
0
    }
957
0
  }
958
959
0
  fuji_extend_green(info->linebuf, line_width);
960
0
  fuji_extend_blue(info->linebuf, line_width);
961
962
0
  r_even_pos = 0, r_odd_pos = 1;
963
0
  g_even_pos = 0, g_odd_pos = 1;
964
965
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
966
0
  {
967
0
    if (g_even_pos < line_width)
968
0
    {
969
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R4] + 1, r_even_pos, &info->even[1]);
970
0
      r_even_pos += 2;
971
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G6] + 1, g_even_pos, &info->even[1]);
972
0
      g_even_pos += 2;
973
0
    }
974
0
    if (g_even_pos > 8)
975
0
    {
976
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R4] + 1, r_odd_pos, &info->odd[1]);
977
0
      r_odd_pos += 2;
978
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G6] + 1, g_odd_pos, &info->odd[1]);
979
0
      g_odd_pos += 2;
980
0
    }
981
0
  }
982
983
0
  fuji_extend_red(info->linebuf, line_width);
984
0
  fuji_extend_green(info->linebuf, line_width);
985
986
0
  g_even_pos = 0, g_odd_pos = 1;
987
0
  b_even_pos = 0, b_odd_pos = 1;
988
989
0
  while (g_even_pos < line_width || g_odd_pos < line_width)
990
0
  {
991
0
    if (g_even_pos < line_width)
992
0
    {
993
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G7] + 1, g_even_pos, &info->even[2]);
994
0
      g_even_pos += 2;
995
0
      errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B4] + 1, b_even_pos, &info->even[2]);
996
0
      b_even_pos += 2;
997
0
    }
998
0
    if (g_even_pos > 8)
999
0
    {
1000
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G7] + 1, g_odd_pos, &info->odd[2]);
1001
0
      g_odd_pos += 2;
1002
0
      errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B4] + 1, b_odd_pos, &info->odd[2]);
1003
0
      b_odd_pos += 2;
1004
0
    }
1005
0
  }
1006
1007
0
  fuji_extend_green(info->linebuf, line_width);
1008
0
  fuji_extend_blue(info->linebuf, line_width);
1009
1010
0
  if (errcnt)
1011
0
    derror();
1012
0
}
1013
1014
void LibRaw::fuji_decode_strip(fuji_compressed_params *params, int cur_block, INT64 raw_offset, unsigned dsize,
1015
                               uchar *q_bases)
1016
0
{
1017
0
  int cur_block_width, cur_line;
1018
0
  unsigned line_size;
1019
0
  fuji_compressed_block info;
1020
0
  fuji_compressed_params *info_common = params;
1021
1022
0
  if (!libraw_internal_data.unpacker_data.fuji_lossless)
1023
0
  {
1024
0
    int buf_size = sizeof(fuji_compressed_params) + (2 << libraw_internal_data.unpacker_data.fuji_bits);
1025
1026
0
    info_common = (fuji_compressed_params *)calloc(buf_size, 1);
1027
0
    memcpy(info_common, params, sizeof(fuji_compressed_params));
1028
0
    info_common->qt[0].q_table = (int8_t *)(info_common + 1);
1029
0
    info_common->qt[0].q_base = -1;
1030
0
  }
1031
0
  init_fuji_block(&info, info_common, raw_offset, dsize);
1032
0
  line_size = sizeof(ushort) * (info_common->line_width + 2);
1033
1034
0
  cur_block_width = libraw_internal_data.unpacker_data.fuji_block_width;
1035
0
  if (cur_block + 1 == libraw_internal_data.unpacker_data.fuji_total_blocks)
1036
0
  {
1037
0
    cur_block_width = imgdata.sizes.raw_width - (libraw_internal_data.unpacker_data.fuji_block_width * cur_block);
1038
    /* Old code, may get incorrect results on GFX50, but luckily large optical
1039
    black cur_block_width = imgdata.sizes.raw_width %
1040
    libraw_internal_data.unpacker_data.fuji_block_width;
1041
    */
1042
0
  }
1043
1044
0
  struct i_pair
1045
0
  {
1046
0
    int a, b;
1047
0
  };
1048
0
  const i_pair mtable[6] = {{_R0, _R3}, {_R1, _R4}, {_G0, _G6}, {_G1, _G7}, {_B0, _B3}, {_B1, _B4}},
1049
0
               ztable[3] = {{_R2, 3}, {_G2, 6}, {_B2, 3}};
1050
0
  for (cur_line = 0; cur_line < libraw_internal_data.unpacker_data.fuji_total_lines; cur_line++)
1051
0
  {
1052
    // init grads and main qtable
1053
0
    if (!libraw_internal_data.unpacker_data.fuji_lossless)
1054
0
    {
1055
0
      int q_base = q_bases ? q_bases[cur_line] : 0;
1056
0
      if (!cur_line || q_base != info_common->qt[0].q_base)
1057
0
      {
1058
0
        init_main_qtable(info_common, q_bases[cur_line]);
1059
0
        init_main_grads(info_common, &info);
1060
0
      }
1061
0
    }
1062
1063
0
    if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
1064
0
      xtrans_decode_block(&info, info_common, cur_line);
1065
0
    else
1066
0
      fuji_bayer_decode_block(&info, info_common, cur_line);
1067
1068
    // copy data from line buffers and advance
1069
0
    for (int i = 0; i < 6; i++)
1070
0
      memcpy(info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size);
1071
1072
0
    if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
1073
0
      copy_line_to_xtrans(&info, cur_line, cur_block, cur_block_width);
1074
0
    else
1075
0
      copy_line_to_bayer(&info, cur_line, cur_block, cur_block_width);
1076
1077
0
    for (int i = 0; i < 3; i++)
1078
0
    {
1079
0
      memset(info.linebuf[ztable[i].a], 0, ztable[i].b * line_size);
1080
0
      info.linebuf[ztable[i].a][0] = info.linebuf[ztable[i].a - 1][1];
1081
0
      info.linebuf[ztable[i].a][info_common->line_width + 1] = info.linebuf[ztable[i].a - 1][info_common->line_width];
1082
0
    }
1083
0
  }
1084
1085
  // release data
1086
0
  if (!libraw_internal_data.unpacker_data.fuji_lossless)
1087
0
    free(info_common);
1088
0
  free(info.linealloc);
1089
0
  free(info.cur_buf);
1090
0
}
1091
1092
void LibRaw::fuji_compressed_load_raw()
1093
0
{
1094
0
  fuji_compressed_params common_info;
1095
0
  int cur_block;
1096
0
  unsigned *block_sizes;
1097
0
  uchar *q_bases = 0;
1098
0
  INT64 raw_offset, *raw_block_offsets;
1099
1100
0
  init_fuji_compr(&common_info);
1101
1102
  // read block sizes
1103
0
  block_sizes = (unsigned *)calloc(sizeof(unsigned), libraw_internal_data.unpacker_data.fuji_total_blocks);
1104
0
  raw_block_offsets = (INT64 *)calloc(sizeof(INT64), libraw_internal_data.unpacker_data.fuji_total_blocks);
1105
1106
0
  libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
1107
0
  int sizesToRead = sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks;
1108
0
  if (libraw_internal_data.internal_data.input->read(block_sizes, 1, sizesToRead) != sizesToRead)
1109
0
  {
1110
0
    free(block_sizes);
1111
0
    free(raw_block_offsets);
1112
0
    throw LIBRAW_EXCEPTION_IO_EOF;
1113
0
  }
1114
1115
0
  raw_offset = ((sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks) + 0xF) & ~0xF;
1116
1117
  // read q bases for lossy
1118
0
  if (!libraw_internal_data.unpacker_data.fuji_lossless)
1119
0
  {
1120
0
    int total_q_bases = libraw_internal_data.unpacker_data.fuji_total_blocks *
1121
0
                        ((libraw_internal_data.unpacker_data.fuji_total_lines + 0xF) & ~0xF);
1122
0
    q_bases = (uchar *)calloc(total_q_bases, 1);
1123
0
    libraw_internal_data.internal_data.input->seek(raw_offset + libraw_internal_data.unpacker_data.data_offset,
1124
0
                                                   SEEK_SET);
1125
0
    libraw_internal_data.internal_data.input->read(q_bases, 1, total_q_bases);
1126
0
    raw_offset += total_q_bases;
1127
0
  }
1128
1129
0
  raw_offset += libraw_internal_data.unpacker_data.data_offset;
1130
1131
  // calculating raw block offsets
1132
0
  raw_block_offsets[0] = raw_offset;
1133
0
  for (cur_block = 0; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++)
1134
0
  {
1135
0
    unsigned bsize = sgetn(4, (uchar *)(block_sizes + cur_block));
1136
0
    block_sizes[cur_block] = bsize;
1137
0
  }
1138
1139
0
  for (cur_block = 1; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++)
1140
0
    raw_block_offsets[cur_block] = raw_block_offsets[cur_block - 1] + block_sizes[cur_block - 1];
1141
1142
0
  fuji_decode_loop(&common_info, libraw_internal_data.unpacker_data.fuji_total_blocks, raw_block_offsets, block_sizes,
1143
0
                   q_bases);
1144
1145
0
  free(q_bases);
1146
0
  free(block_sizes);
1147
0
  free(raw_block_offsets);
1148
0
  free(common_info.buf);
1149
0
}
1150
1151
void LibRaw::fuji_decode_loop(fuji_compressed_params *common_info, int count, INT64 *raw_block_offsets,
1152
                              unsigned *block_sizes, uchar *q_bases)
1153
0
{
1154
0
  int cur_block;
1155
0
  const int lineStep = (libraw_internal_data.unpacker_data.fuji_total_lines + 0xF) & ~0xF;
1156
#ifdef LIBRAW_USE_OPENMP
1157
  unsigned errcnt = 0;
1158
#pragma omp parallel for private(cur_block) shared(errcnt)
1159
#endif
1160
0
  for (cur_block = 0; cur_block < count; cur_block++)
1161
0
  {
1162
0
    try
1163
0
    {
1164
0
      fuji_decode_strip(common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block],
1165
0
                        q_bases ? q_bases + cur_block * lineStep : 0);
1166
0
    }
1167
0
    catch (...)
1168
0
    {
1169
#ifdef LIBRAW_USE_OPENMP
1170
#pragma omp atomic
1171
      errcnt++;
1172
#else
1173
0
      throw;
1174
0
#endif
1175
0
    }
1176
0
  }
1177
#ifdef LIBRAW_USE_OPENMP
1178
  if (errcnt)
1179
      throw LIBRAW_EXCEPTION_IO_EOF;
1180
#endif
1181
0
}
1182
1183
void LibRaw::parse_fuji_compressed_header()
1184
0
{
1185
0
  unsigned signature, lossless, h_raw_type, h_raw_bits, h_raw_height, h_raw_rounded_width, h_raw_width, h_block_size,
1186
0
      h_blocks_in_row, h_total_lines;
1187
1188
0
  uchar header[16];
1189
1190
0
  libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
1191
0
  if (libraw_internal_data.internal_data.input->read(header, 1, sizeof(header)) != sizeof(header))
1192
0
    return;
1193
1194
  // read all header
1195
0
  signature = sgetn(2, header);
1196
0
  lossless = header[2];
1197
0
  h_raw_type = header[3];
1198
0
  h_raw_bits = header[4];
1199
0
  h_raw_height = sgetn(2, header + 5);
1200
0
  h_raw_rounded_width = sgetn(2, header + 7);
1201
0
  h_raw_width = sgetn(2, header + 9);
1202
0
  h_block_size = sgetn(2, header + 11);
1203
0
  h_blocks_in_row = header[13];
1204
0
  h_total_lines = sgetn(2, header + 14);
1205
1206
  // general validation
1207
0
  if (signature != 0x4953 || lossless > 1 || h_raw_height > 0x4002 || h_raw_height < 6 || h_raw_height % 6 ||
1208
0
      h_block_size < 1 || h_raw_width > 0x4200 || h_raw_width < 0x300 || h_raw_width % 24 ||
1209
0
      h_raw_rounded_width > 0x4200 || h_raw_rounded_width < h_block_size || h_raw_rounded_width % h_block_size ||
1210
0
      h_raw_rounded_width - h_raw_width >= h_block_size || h_block_size != 0x300 || h_blocks_in_row > 0x10 ||
1211
0
      h_blocks_in_row == 0 || h_blocks_in_row != h_raw_rounded_width / h_block_size || h_total_lines > 0xAAB ||
1212
0
      h_total_lines == 0 || h_total_lines != h_raw_height / 6 ||
1213
0
      (h_raw_bits != 12 && h_raw_bits != 14 && h_raw_bits != 16) || (h_raw_type != 16 && h_raw_type != 0))
1214
0
    return;
1215
1216
  // modify data
1217
0
  libraw_internal_data.unpacker_data.fuji_total_lines = h_total_lines;
1218
0
  libraw_internal_data.unpacker_data.fuji_total_blocks = h_blocks_in_row;
1219
0
  libraw_internal_data.unpacker_data.fuji_block_width = h_block_size;
1220
0
  libraw_internal_data.unpacker_data.fuji_bits = h_raw_bits;
1221
0
  libraw_internal_data.unpacker_data.fuji_raw_type = h_raw_type;
1222
0
  libraw_internal_data.unpacker_data.fuji_lossless = lossless;
1223
0
  imgdata.sizes.raw_width = h_raw_width;
1224
0
  imgdata.sizes.raw_height = h_raw_height;
1225
0
  libraw_internal_data.unpacker_data.data_offset += 16;
1226
0
  load_raw = &LibRaw::fuji_compressed_load_raw;
1227
0
}
1228
1229
#undef _abs
1230
#undef _min