File indexing completed on 2025-01-05 03:56:53

0001 /* -*- C++ -*-
0002  * File: libraw_fuji_compressed.cpp
0003  * Copyright (C) 2016-2019 Alexey Danilchenko
0004  *
0005  * Adopted to LibRaw by Alex Tutubalin, lexa@lexa.ru
0006  * LibRaw Fujifilm/compressed decoder
0007 
0008 LibRaw is free software; you can redistribute it and/or modify
0009 it under the terms of the one of two licenses as you choose:
0010 
0011 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0012    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0013 
0014 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0015    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0016 
0017  */
0018 
0019 #include "../../internal/libraw_cxx_defs.h"
0020 
0021 #ifdef _abs
0022 #undef _abs
0023 #undef _min
0024 #undef _max
0025 #endif
0026 #define _abs(x) (((int)(x) ^ ((int)(x) >> 31)) - ((int)(x) >> 31))
0027 #define _min(a, b) ((a) < (b) ? (a) : (b))
0028 #define _max(a, b) ((a) > (b) ? (a) : (b))
0029 
0030 struct int_pair
0031 {
0032   int value1;
0033   int value2;
0034 };
0035 
0036 enum _xt_lines
0037 {
0038   _R0 = 0,
0039   _R1,
0040   _R2,
0041   _R3,
0042   _R4,
0043   _G0,
0044   _G1,
0045   _G2,
0046   _G3,
0047   _G4,
0048   _G5,
0049   _G6,
0050   _G7,
0051   _B0,
0052   _B1,
0053   _B2,
0054   _B3,
0055   _B4,
0056   _ltotal
0057 };
0058 
0059 // tables of gradients for single sample level
0060 struct fuji_grads
0061 {
0062   int_pair grads[41];
0063   int_pair lossy_grads[3][5];
0064 };
0065 
0066 struct fuji_compressed_block
0067 {
0068   int cur_bit;            // current bit being read (from left to right)
0069   int cur_pos;            // current position in a buffer
0070   INT64 cur_buf_offset;   // offset of this buffer in a file
0071   unsigned max_read_size; // Amount of data to be read
0072   int cur_buf_size;       // buffer size
0073   uchar *cur_buf;         // currently read block
0074   int fillbytes;          // Counter to add extra byte for block size N*16
0075   LibRaw_abstract_datastream *input;
0076   fuji_grads even[3]; // tables of even gradients
0077   fuji_grads odd[3];  // tables of odd gradients
0078   ushort *linealloc;
0079   ushort *linebuf[_ltotal];
0080 };
0081 
0082 static inline int log2ceil(int val)
0083 {
0084   int result = 0;
0085   if (val--)
0086     do
0087       ++result;
0088     while (val >>= 1);
0089 
0090   return result;
0091 }
0092 
0093 void setup_qlut(int8_t *qt, int *q_point)
0094 {
0095   for (int curVal = -q_point[4]; curVal <= q_point[4]; ++qt, ++curVal)
0096   {
0097     if (curVal <= -q_point[3])
0098       *qt = -4;
0099     else if (curVal <= -q_point[2])
0100       *qt = -3;
0101     else if (curVal <= -q_point[1])
0102       *qt = -2;
0103     else if (curVal < -q_point[0])
0104       *qt = -1;
0105     else if (curVal <= q_point[0])
0106       *qt = 0;
0107     else if (curVal < q_point[1])
0108       *qt = 1;
0109     else if (curVal < q_point[2])
0110       *qt = 2;
0111     else if (curVal < q_point[3])
0112       *qt = 3;
0113     else
0114       *qt = 4;
0115   }
0116 }
0117 
0118 void init_main_qtable(fuji_compressed_params *params, uchar q_base)
0119 {
0120   fuji_q_table *qt = params->qt;
0121   int qp[5];
0122   int maxVal = params->max_value + 1;
0123   qp[0] = q_base;
0124   qp[1] = 3 * q_base + 0x12;
0125   qp[2] = 5 * q_base + 0x43;
0126   qp[3] = 7 * q_base + 0x114;
0127   qp[4] = params->max_value;
0128   if (qp[1] >= maxVal || qp[1] < q_base + 1)
0129     qp[1] = q_base + 1;
0130   if (qp[2] < qp[1] || qp[2] >= maxVal)
0131     qp[2] = qp[1];
0132   if (qp[3] < qp[2] || qp[3] >= maxVal)
0133     qp[3] = qp[2];
0134   setup_qlut(qt->q_table, qp);
0135   qt->q_base = q_base;
0136   qt->max_grad = 0;
0137   qt->total_values = (qp[4] + 2 * q_base) / (2 * q_base + 1) + 1;
0138   qt->raw_bits = log2ceil(qt->total_values);
0139   qt->q_grad_mult = 9;
0140   params->max_bits = 4 * log2ceil(qp[4] + 1);
0141 }
0142 
0143 void LibRaw::init_fuji_compr(fuji_compressed_params *params)
0144 {
0145   if ((libraw_internal_data.unpacker_data.fuji_block_width % 3 &&
0146        libraw_internal_data.unpacker_data.fuji_raw_type == 16) ||
0147       (libraw_internal_data.unpacker_data.fuji_block_width & 1 &&
0148        libraw_internal_data.unpacker_data.fuji_raw_type == 0))
0149     derror();
0150 
0151   size_t q_table_size = 2 << libraw_internal_data.unpacker_data.fuji_bits;
0152   if (libraw_internal_data.unpacker_data.fuji_lossless)
0153     params->buf = malloc(q_table_size);
0154   else
0155     params->buf = malloc(3 * q_table_size);
0156 
0157   if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
0158     params->line_width = (libraw_internal_data.unpacker_data.fuji_block_width * 2) / 3;
0159   else
0160     params->line_width = libraw_internal_data.unpacker_data.fuji_block_width >> 1;
0161 
0162   params->min_value = 0x40;
0163   params->max_value = (1 << libraw_internal_data.unpacker_data.fuji_bits) - 1;
0164 
0165   // setup qtables
0166   if (libraw_internal_data.unpacker_data.fuji_lossless)
0167   {
0168     // setup main qtable only, zero the rest
0169     memset(params->qt + 1, 0, 3 * sizeof(fuji_q_table));
0170     params->qt[0].q_table = (int8_t *)params->buf;
0171     params->qt[0].q_base = -1;
0172     init_main_qtable(params, 0);
0173   }
0174   else
0175   {
0176     // setup 3 extra qtables - main one will be set for each block
0177     memset(params->qt, 0, sizeof(fuji_q_table));
0178     int qp[5];
0179 
0180     qp[0] = 0;
0181     qp[4] = params->max_value;
0182 
0183     // table 0
0184     params->qt[1].q_table = (int8_t *)params->buf;
0185     params->qt[1].q_base = 0;
0186     params->qt[1].max_grad = 5;
0187     params->qt[1].q_grad_mult = 3;
0188     params->qt[1].total_values = qp[4] + 1;
0189     params->qt[1].raw_bits = log2ceil(params->qt[1].total_values);
0190 
0191     qp[1] = qp[4] >= 0x12 ? 0x12 : qp[0] + 1;
0192     qp[2] = qp[4] >= 0x43 ? 0x43 : qp[1];
0193     qp[3] = qp[4] >= 0x114 ? 0x114 : qp[2];
0194     setup_qlut(params->qt[1].q_table, qp);
0195 
0196     // table 1
0197     params->qt[2].q_table = params->qt[1].q_table + q_table_size;
0198     params->qt[2].q_base = 1;
0199     params->qt[2].max_grad = 6;
0200     params->qt[2].q_grad_mult = 3;
0201     params->qt[2].total_values = (qp[4] + 2) / 3 + 1;
0202     params->qt[2].raw_bits = log2ceil(params->qt[2].total_values);
0203 
0204     qp[0] = params->qt[2].q_base;
0205     qp[1] = qp[4] >= 0x15 ? 0x15 : qp[0] + 1;
0206     qp[2] = qp[4] >= 0x48 ? 0x48 : qp[1];
0207     qp[3] = qp[4] >= 0x11B ? 0x11B : qp[2];
0208     setup_qlut(params->qt[2].q_table, qp);
0209 
0210     // table 2
0211     params->qt[3].q_table = params->qt[2].q_table + q_table_size;
0212     params->qt[3].q_base = 2;
0213     params->qt[3].max_grad = 7;
0214     params->qt[3].q_grad_mult = 3;
0215     params->qt[3].total_values = (qp[4] + 4) / 5 + 1;
0216     params->qt[3].raw_bits = log2ceil(params->qt[3].total_values);
0217 
0218     qp[0] = params->qt[3].q_base;
0219     qp[1] = qp[4] >= 0x18 ? 0x18 : qp[0] + 1;
0220     qp[2] = qp[4] >= 0x4D ? 0x4D : qp[1];
0221     qp[3] = qp[4] >= 0x122 ? 0x122 : qp[2];
0222     setup_qlut(params->qt[3].q_table, qp);
0223   }
0224 }
0225 
0226 #define XTRANS_BUF_SIZE 0x10000
0227 
0228 static inline void fuji_fill_buffer(fuji_compressed_block *info)
0229 {
0230   if (info->cur_pos >= info->cur_buf_size)
0231   {
0232     info->cur_pos = 0;
0233     info->cur_buf_offset += info->cur_buf_size;
0234 #ifdef LIBRAW_USE_OPENMP
0235 #pragma omp critical
0236 #endif
0237     {
0238 #ifndef LIBRAW_USE_OPENMP
0239       info->input->lock();
0240 #endif
0241       info->input->seek(info->cur_buf_offset, SEEK_SET);
0242       info->cur_buf_size = info->input->read(info->cur_buf, 1, _min(info->max_read_size, XTRANS_BUF_SIZE));
0243 #ifndef LIBRAW_USE_OPENMP
0244       info->input->unlock();
0245 #endif
0246       if (info->cur_buf_size < 1) // nothing read
0247       {
0248         if (info->fillbytes > 0)
0249         {
0250           int ls = _max(1, _min(info->fillbytes, XTRANS_BUF_SIZE));
0251           memset(info->cur_buf, 0, ls);
0252           info->fillbytes -= ls;
0253         }
0254         else
0255           throw LIBRAW_EXCEPTION_IO_EOF;
0256       }
0257       info->max_read_size -= info->cur_buf_size;
0258     }
0259   }
0260 }
0261 
0262 void init_main_grads(const fuji_compressed_params *params, fuji_compressed_block *info)
0263 {
0264   int max_diff = _max(2, (params->qt->total_values + 0x20) >> 6);
0265   for (int j = 0; j < 3; j++)
0266     for (int i = 0; i < 41; i++)
0267     {
0268       info->even[j].grads[i].value1 = max_diff;
0269       info->even[j].grads[i].value2 = 1;
0270       info->odd[j].grads[i].value1 = max_diff;
0271       info->odd[j].grads[i].value2 = 1;
0272     }
0273 }
0274 
0275 void LibRaw::init_fuji_block(fuji_compressed_block *info, const fuji_compressed_params *params, INT64 raw_offset,
0276                              unsigned dsize)
0277 {
0278   info->linealloc = (ushort *)calloc(sizeof(ushort), _ltotal * (params->line_width + 2));
0279 
0280   INT64 fsize = libraw_internal_data.internal_data.input->size();
0281   info->max_read_size = _min(unsigned(fsize - raw_offset), dsize); // Data size may be incorrect?
0282   info->fillbytes = 1;
0283 
0284   info->input = libraw_internal_data.internal_data.input;
0285   info->linebuf[_R0] = info->linealloc;
0286   for (int i = _R1; i <= _B4; i++)
0287     info->linebuf[i] = info->linebuf[i - 1] + params->line_width + 2;
0288 
0289   // init buffer
0290   info->cur_buf = (uchar *)malloc(XTRANS_BUF_SIZE);
0291   info->cur_bit = 0;
0292   info->cur_pos = 0;
0293   info->cur_buf_offset = raw_offset;
0294   info->cur_buf_size = 0;
0295   fuji_fill_buffer(info);
0296 
0297   // init grads for lossy and lossless
0298   if (libraw_internal_data.unpacker_data.fuji_lossless)
0299     init_main_grads(params, info);
0300   else
0301   {
0302     // init static grads for lossy only - main ones are done per line
0303     for (int k = 0; k < 3; ++k)
0304     {
0305       int max_diff = _max(2, ((params->qt[k + 1].total_values + 0x20) >> 6));
0306       for (int j = 0; j < 3; ++j)
0307         for (int i = 0; i < 5; ++i)
0308         {
0309           info->even[j].lossy_grads[k][i].value1 = max_diff;
0310           info->even[j].lossy_grads[k][i].value2 = 1;
0311           info->odd[j].lossy_grads[k][i].value1 = max_diff;
0312           info->odd[j].lossy_grads[k][i].value2 = 1;
0313         }
0314     }
0315   }
0316 }
0317 
0318 void LibRaw::copy_line_to_xtrans(fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width)
0319 {
0320   ushort *lineBufB[3];
0321   ushort *lineBufG[6];
0322   ushort *lineBufR[3];
0323   unsigned pixel_count;
0324   ushort *line_buf;
0325   int index;
0326 
0327   int offset = libraw_internal_data.unpacker_data.fuji_block_width * cur_block + 6 * imgdata.sizes.raw_width * cur_line;
0328   ushort *raw_block_data = imgdata.rawdata.raw_image + offset;
0329   int row_count = 0;
0330 
0331   for (int i = 0; i < 3; i++)
0332   {
0333     lineBufR[i] = info->linebuf[_R2 + i] + 1;
0334     lineBufB[i] = info->linebuf[_B2 + i] + 1;
0335   }
0336   for (int i = 0; i < 6; i++)
0337     lineBufG[i] = info->linebuf[_G2 + i] + 1;
0338 
0339   while (row_count < 6)
0340   {
0341     pixel_count = 0;
0342     while (pixel_count < (unsigned)cur_block_width)
0343     {
0344       switch (imgdata.idata.xtrans_abs[row_count][(pixel_count % 6)])
0345       {
0346       case 0: // red
0347         line_buf = lineBufR[row_count >> 1];
0348         break;
0349       case 1:  // green
0350       default: // to make static analyzer happy
0351         line_buf = lineBufG[row_count];
0352         break;
0353       case 2: // blue
0354         line_buf = lineBufB[row_count >> 1];
0355         break;
0356       }
0357 
0358       index = (((pixel_count * 2 / 3) & 0x7FFFFFFE) | ((pixel_count % 3) & 1)) + ((pixel_count % 3) >> 1);
0359       raw_block_data[pixel_count] = line_buf[index];
0360 
0361       ++pixel_count;
0362     }
0363     ++row_count;
0364     raw_block_data += imgdata.sizes.raw_width;
0365   }
0366 }
0367 
0368 void LibRaw::copy_line_to_bayer(fuji_compressed_block *info, int cur_line, int cur_block, int cur_block_width)
0369 {
0370   ushort *lineBufB[3];
0371   ushort *lineBufG[6];
0372   ushort *lineBufR[3];
0373   unsigned pixel_count;
0374   ushort *line_buf;
0375 
0376   int fuji_bayer[2][2];
0377   for (int r = 0; r < 2; r++)
0378     for (int c = 0; c < 2; c++)
0379       fuji_bayer[r][c] = FC(r, c); // We'll downgrade G2 to G below
0380 
0381   int offset = libraw_internal_data.unpacker_data.fuji_block_width * cur_block + 6 * imgdata.sizes.raw_width * cur_line;
0382   ushort *raw_block_data = imgdata.rawdata.raw_image + offset;
0383   int row_count = 0;
0384 
0385   for (int i = 0; i < 3; i++)
0386   {
0387     lineBufR[i] = info->linebuf[_R2 + i] + 1;
0388     lineBufB[i] = info->linebuf[_B2 + i] + 1;
0389   }
0390   for (int i = 0; i < 6; i++)
0391     lineBufG[i] = info->linebuf[_G2 + i] + 1;
0392 
0393   while (row_count < 6)
0394   {
0395     pixel_count = 0;
0396     while (pixel_count < (unsigned)cur_block_width)
0397     {
0398       switch (fuji_bayer[row_count & 1][pixel_count & 1])
0399       {
0400       case 0: // red
0401         line_buf = lineBufR[row_count >> 1];
0402         break;
0403       case 1:  // green
0404       case 3:  // second green
0405       default: // to make static analyzer happy
0406         line_buf = lineBufG[row_count];
0407         break;
0408       case 2: // blue
0409         line_buf = lineBufB[row_count >> 1];
0410         break;
0411       }
0412 
0413       raw_block_data[pixel_count] = line_buf[pixel_count >> 1];
0414       ++pixel_count;
0415     }
0416     ++row_count;
0417     raw_block_data += imgdata.sizes.raw_width;
0418   }
0419 }
0420 
0421 #define fuji_quant_gradient(max, q, v1, v2) (q->q_grad_mult * q->q_table[(max) + (v1)] + q->q_table[(max) + (v2)])
0422 
0423 static inline void fuji_zerobits(fuji_compressed_block *info, int *count)
0424 {
0425   uchar zero = 0;
0426   *count = 0;
0427   while (zero == 0)
0428   {
0429     zero = (info->cur_buf[info->cur_pos] >> (7 - info->cur_bit)) & 1;
0430     info->cur_bit++;
0431     info->cur_bit &= 7;
0432     if (!info->cur_bit)
0433     {
0434       ++info->cur_pos;
0435       fuji_fill_buffer(info);
0436     }
0437     if (zero)
0438       break;
0439     ++*count;
0440   }
0441 }
0442 
0443 static inline void fuji_read_code(fuji_compressed_block *info, int *data, int bits_to_read)
0444 {
0445   uchar bits_left = bits_to_read;
0446   uchar bits_left_in_byte = 8 - (info->cur_bit & 7);
0447   *data = 0;
0448   if (!bits_to_read)
0449     return;
0450   if (bits_to_read >= bits_left_in_byte)
0451   {
0452     do
0453     {
0454       *data <<= bits_left_in_byte;
0455       bits_left -= bits_left_in_byte;
0456       *data |= info->cur_buf[info->cur_pos] & ((1 << bits_left_in_byte) - 1);
0457       ++info->cur_pos;
0458       fuji_fill_buffer(info);
0459       bits_left_in_byte = 8;
0460     } while (bits_left >= 8);
0461   }
0462   if (!bits_left)
0463   {
0464     info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
0465     return;
0466   }
0467   *data <<= bits_left;
0468   bits_left_in_byte -= bits_left;
0469   *data |= ((1 << bits_left) - 1) & ((unsigned)info->cur_buf[info->cur_pos] >> bits_left_in_byte);
0470   info->cur_bit = (8 - (bits_left_in_byte & 7)) & 7;
0471 }
0472 
0473 static inline int bitDiff(int value1, int value2)
0474 {
0475   int decBits = 0;
0476   if (value2 < value1)
0477     while (decBits <= 14 && (value2 << ++decBits) < value1)
0478       ;
0479   return decBits;
0480 }
0481 
0482 static inline int fuji_decode_sample_even(fuji_compressed_block *info, const fuji_compressed_params *params,
0483                                           ushort *line_buf, int pos, fuji_grads *grad_params)
0484 {
0485   int interp_val = 0;
0486   // ushort decBits;
0487   int errcnt = 0;
0488 
0489   int sample = 0, code = 0;
0490   ushort *line_buf_cur = line_buf + pos;
0491   int Rb = line_buf_cur[-2 - params->line_width];
0492   int Rc = line_buf_cur[-3 - params->line_width];
0493   int Rd = line_buf_cur[-1 - params->line_width];
0494   int Rf = line_buf_cur[-4 - 2 * params->line_width];
0495 
0496   int grad, gradient, diffRcRb, diffRfRb, diffRdRb;
0497 
0498   diffRcRb = _abs(Rc - Rb);
0499   diffRfRb = _abs(Rf - Rb);
0500   diffRdRb = _abs(Rd - Rb);
0501 
0502   const fuji_q_table *qt = params->qt;
0503   int_pair *grads = grad_params->grads;
0504   for (int i = 1; params->qt[0].q_base >= i && i < 4; ++i)
0505     if (diffRfRb + diffRcRb <= params->qt[i].max_grad)
0506     {
0507       qt = params->qt + i;
0508       grads = grad_params->lossy_grads[i - 1];
0509       break;
0510     }
0511 
0512   grad = fuji_quant_gradient(params->max_value, qt, Rb - Rf, Rc - Rb);
0513   gradient = _abs(grad);
0514 
0515   if (diffRcRb > diffRfRb && diffRcRb > diffRdRb)
0516     interp_val = Rf + Rd + 2 * Rb;
0517   else if (diffRdRb > diffRcRb && diffRdRb > diffRfRb)
0518     interp_val = Rf + Rc + 2 * Rb;
0519   else
0520     interp_val = Rd + Rc + 2 * Rb;
0521 
0522   fuji_zerobits(info, &sample);
0523 
0524   if (sample < params->max_bits - qt->raw_bits - 1)
0525   {
0526     int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
0527     fuji_read_code(info, &code, decBits);
0528     code += sample << decBits;
0529   }
0530   else
0531   {
0532     fuji_read_code(info, &code, qt->raw_bits);
0533     ++code;
0534   }
0535 
0536   if (code < 0 || code >= qt->total_values)
0537     ++errcnt;
0538 
0539   if (code & 1)
0540     code = -1 - code / 2;
0541   else
0542     code /= 2;
0543 
0544   grads[gradient].value1 += _abs(code);
0545   if (grads[gradient].value2 == params->min_value)
0546   {
0547     grads[gradient].value1 >>= 1;
0548     grads[gradient].value2 >>= 1;
0549   }
0550   ++grads[gradient].value2;
0551   if (grad < 0)
0552     interp_val = (interp_val >> 2) - code * (2 * qt->q_base + 1);
0553   else
0554     interp_val = (interp_val >> 2) + code * (2 * qt->q_base + 1);
0555   if (interp_val < -qt->q_base)
0556     interp_val += qt->total_values * (2 * qt->q_base + 1);
0557   else if (interp_val > qt->q_base + params->max_value)
0558     interp_val -= qt->total_values * (2 * qt->q_base + 1);
0559 
0560   if (interp_val >= 0)
0561     line_buf_cur[0] = _min(interp_val, params->max_value);
0562   else
0563     line_buf_cur[0] = 0;
0564   return errcnt;
0565 }
0566 
0567 static inline int fuji_decode_sample_odd(fuji_compressed_block *info, const fuji_compressed_params *params,
0568                                          ushort *line_buf, int pos, fuji_grads *grad_params)
0569 {
0570   int interp_val = 0;
0571   int errcnt = 0;
0572 
0573   int sample = 0, code = 0;
0574   ushort *line_buf_cur = line_buf + pos;
0575   int Ra = line_buf_cur[-1];
0576   int Rb = line_buf_cur[-2 - params->line_width];
0577   int Rc = line_buf_cur[-3 - params->line_width];
0578   int Rd = line_buf_cur[-1 - params->line_width];
0579   int Rg = line_buf_cur[1];
0580 
0581   int grad, gradient;
0582 
0583   int diffRcRa = _abs(Rc - Ra);
0584   int diffRbRc = _abs(Rb - Rc);
0585 
0586   const fuji_q_table *qt = params->qt;
0587   int_pair *grads = grad_params->grads;
0588   for (int i = 1; params->qt[0].q_base >= i && i < 4; ++i)
0589     if (diffRbRc + diffRcRa <= params->qt[i].max_grad)
0590     {
0591       qt = params->qt + i;
0592       grads = grad_params->lossy_grads[i - 1];
0593       break;
0594     }
0595 
0596   grad = fuji_quant_gradient(params->max_value, qt, Rb - Rc, Rc - Ra);
0597   gradient = _abs(grad);
0598 
0599   if ((Rb > Rc && Rb > Rd) || (Rb < Rc && Rb < Rd))
0600     interp_val = (Rg + Ra + 2 * Rb) >> 2;
0601   else
0602     interp_val = (Ra + Rg) >> 1;
0603 
0604   fuji_zerobits(info, &sample);
0605 
0606   if (sample < params->max_bits - qt->raw_bits - 1)
0607   {
0608     int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
0609     fuji_read_code(info, &code, decBits);
0610     code += sample << decBits;
0611   }
0612   else
0613   {
0614     fuji_read_code(info, &code, qt->raw_bits);
0615     ++code;
0616   }
0617 
0618   if (code < 0 || code >= qt->total_values)
0619     ++errcnt;
0620 
0621   if (code & 1)
0622     code = -1 - code / 2;
0623   else
0624     code /= 2;
0625 
0626   grads[gradient].value1 += _abs(code);
0627   if (grads[gradient].value2 == params->min_value)
0628   {
0629     grads[gradient].value1 >>= 1;
0630     grads[gradient].value2 >>= 1;
0631   }
0632   ++grads[gradient].value2;
0633   if (grad < 0)
0634     interp_val -= code * (2 * qt->q_base + 1);
0635   else
0636     interp_val += code * (2 * qt->q_base + 1);
0637   if (interp_val < -qt->q_base)
0638     interp_val += qt->total_values * (2 * qt->q_base + 1);
0639   else if (interp_val > qt->q_base + params->max_value)
0640     interp_val -= qt->total_values * (2 * qt->q_base + 1);
0641 
0642   if (interp_val >= 0)
0643     line_buf_cur[0] = _min(interp_val, params->max_value);
0644   else
0645     line_buf_cur[0] = 0;
0646   return errcnt;
0647 }
0648 
0649 static void fuji_decode_interpolation_even(int line_width, ushort *line_buf, int pos)
0650 {
0651   ushort *line_buf_cur = line_buf + pos;
0652   int Rb = line_buf_cur[-2 - line_width];
0653   int Rc = line_buf_cur[-3 - line_width];
0654   int Rd = line_buf_cur[-1 - line_width];
0655   int Rf = line_buf_cur[-4 - 2 * line_width];
0656   int diffRcRb = _abs(Rc - Rb);
0657   int diffRfRb = _abs(Rf - Rb);
0658   int diffRdRb = _abs(Rd - Rb);
0659   if (diffRcRb > diffRfRb && diffRcRb > diffRdRb)
0660     *line_buf_cur = (Rf + Rd + 2 * Rb) >> 2;
0661   else if (diffRdRb > diffRcRb && diffRdRb > diffRfRb)
0662     *line_buf_cur = (Rf + Rc + 2 * Rb) >> 2;
0663   else
0664     *line_buf_cur = (Rd + Rc + 2 * Rb) >> 2;
0665 }
0666 
0667 static void fuji_extend_generic(ushort *linebuf[_ltotal], int line_width, int start, int end)
0668 {
0669   for (int i = start; i <= end; i++)
0670   {
0671     linebuf[i][0] = linebuf[i - 1][1];
0672     linebuf[i][line_width + 1] = linebuf[i - 1][line_width];
0673   }
0674 }
0675 
0676 static void fuji_extend_red(ushort *linebuf[_ltotal], int line_width)
0677 {
0678   fuji_extend_generic(linebuf, line_width, _R2, _R4);
0679 }
0680 
0681 static void fuji_extend_green(ushort *linebuf[_ltotal], int line_width)
0682 {
0683   fuji_extend_generic(linebuf, line_width, _G2, _G7);
0684 }
0685 
0686 static void fuji_extend_blue(ushort *linebuf[_ltotal], int line_width)
0687 {
0688   fuji_extend_generic(linebuf, line_width, _B2, _B4);
0689 }
0690 
0691 void LibRaw::xtrans_decode_block(fuji_compressed_block *info, const fuji_compressed_params *params, int /*cur_line*/)
0692 {
0693   int r_even_pos = 0, r_odd_pos = 1;
0694   int g_even_pos = 0, g_odd_pos = 1;
0695   int b_even_pos = 0, b_odd_pos = 1;
0696 
0697   int errcnt = 0;
0698 
0699   const int line_width = params->line_width;
0700 
0701   while (g_even_pos < line_width || g_odd_pos < line_width)
0702   {
0703     if (g_even_pos < line_width)
0704     {
0705       fuji_decode_interpolation_even(line_width, info->linebuf[_R2] + 1, r_even_pos);
0706       r_even_pos += 2;
0707       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, &info->even[0]);
0708       g_even_pos += 2;
0709     }
0710     if (g_even_pos > 8)
0711     {
0712       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, &info->odd[0]);
0713       r_odd_pos += 2;
0714       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, &info->odd[0]);
0715       g_odd_pos += 2;
0716     }
0717   }
0718 
0719   fuji_extend_red(info->linebuf, line_width);
0720   fuji_extend_green(info->linebuf, line_width);
0721 
0722   g_even_pos = 0, g_odd_pos = 1;
0723 
0724   while (g_even_pos < line_width || g_odd_pos < line_width)
0725   {
0726     if (g_even_pos < line_width)
0727     {
0728       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, &info->even[1]);
0729       g_even_pos += 2;
0730       fuji_decode_interpolation_even(line_width, info->linebuf[_B2] + 1, b_even_pos);
0731       b_even_pos += 2;
0732     }
0733     if (g_even_pos > 8)
0734     {
0735       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G3] + 1, g_odd_pos, &info->odd[1]);
0736       g_odd_pos += 2;
0737       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B2] + 1, b_odd_pos, &info->odd[1]);
0738       b_odd_pos += 2;
0739     }
0740   }
0741 
0742   fuji_extend_green(info->linebuf, line_width);
0743   fuji_extend_blue(info->linebuf, line_width);
0744 
0745   r_even_pos = 0, r_odd_pos = 1;
0746   g_even_pos = 0, g_odd_pos = 1;
0747 
0748   while (g_even_pos < line_width || g_odd_pos < line_width)
0749   {
0750     if (g_even_pos < line_width)
0751     {
0752       if (r_even_pos & 3)
0753         errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, &info->even[2]);
0754       else
0755         fuji_decode_interpolation_even(line_width, info->linebuf[_R3] + 1, r_even_pos);
0756       r_even_pos += 2;
0757       fuji_decode_interpolation_even(line_width, info->linebuf[_G4] + 1, g_even_pos);
0758       g_even_pos += 2;
0759     }
0760     if (g_even_pos > 8)
0761     {
0762       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R3] + 1, r_odd_pos, &info->odd[2]);
0763       r_odd_pos += 2;
0764       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G4] + 1, g_odd_pos, &info->odd[2]);
0765       g_odd_pos += 2;
0766     }
0767   }
0768 
0769   fuji_extend_red(info->linebuf, line_width);
0770   fuji_extend_green(info->linebuf, line_width);
0771 
0772   g_even_pos = 0, g_odd_pos = 1;
0773   b_even_pos = 0, b_odd_pos = 1;
0774 
0775   while (g_even_pos < line_width || g_odd_pos < line_width)
0776   {
0777     if (g_even_pos < line_width)
0778     {
0779       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G5] + 1, g_even_pos, &info->even[0]);
0780       g_even_pos += 2;
0781       if ((b_even_pos & 3) == 2)
0782         fuji_decode_interpolation_even(line_width, info->linebuf[_B3] + 1, b_even_pos);
0783       else
0784         errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B3] + 1, b_even_pos, &info->even[0]);
0785       b_even_pos += 2;
0786     }
0787     if (g_even_pos > 8)
0788     {
0789       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G5] + 1, g_odd_pos, &info->odd[0]);
0790       g_odd_pos += 2;
0791       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B3] + 1, b_odd_pos, &info->odd[0]);
0792       b_odd_pos += 2;
0793     }
0794   }
0795 
0796   fuji_extend_green(info->linebuf, line_width);
0797   fuji_extend_blue(info->linebuf, line_width);
0798 
0799   r_even_pos = 0, r_odd_pos = 1;
0800   g_even_pos = 0, g_odd_pos = 1;
0801 
0802   while (g_even_pos < line_width || g_odd_pos < line_width)
0803   {
0804     if (g_even_pos < line_width)
0805     {
0806       if ((r_even_pos & 3) == 2)
0807         fuji_decode_interpolation_even(line_width, info->linebuf[_R4] + 1, r_even_pos);
0808       else
0809         errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R4] + 1, r_even_pos, &info->even[1]);
0810       r_even_pos += 2;
0811       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G6] + 1, g_even_pos, &info->even[1]);
0812       g_even_pos += 2;
0813     }
0814     if (g_even_pos > 8)
0815     {
0816       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R4] + 1, r_odd_pos, &info->odd[1]);
0817       r_odd_pos += 2;
0818       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G6] + 1, g_odd_pos, &info->odd[1]);
0819       g_odd_pos += 2;
0820     }
0821   }
0822 
0823   fuji_extend_red(info->linebuf, line_width);
0824   fuji_extend_green(info->linebuf, line_width);
0825 
0826   g_even_pos = 0, g_odd_pos = 1;
0827   b_even_pos = 0, b_odd_pos = 1;
0828 
0829   while (g_even_pos < line_width || g_odd_pos < line_width)
0830   {
0831     if (g_even_pos < line_width)
0832     {
0833       fuji_decode_interpolation_even(line_width, info->linebuf[_G7] + 1, g_even_pos);
0834       g_even_pos += 2;
0835       if (b_even_pos & 3)
0836         errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B4] + 1, b_even_pos, &info->even[2]);
0837       else
0838         fuji_decode_interpolation_even(line_width, info->linebuf[_B4] + 1, b_even_pos);
0839       b_even_pos += 2;
0840     }
0841     if (g_even_pos > 8)
0842     {
0843       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G7] + 1, g_odd_pos, &info->odd[2]);
0844       g_odd_pos += 2;
0845       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B4] + 1, b_odd_pos, &info->odd[2]);
0846       b_odd_pos += 2;
0847     }
0848   }
0849 
0850   fuji_extend_green(info->linebuf, line_width);
0851   fuji_extend_blue(info->linebuf, line_width);
0852 
0853   if (errcnt)
0854     derror();
0855 }
0856 
0857 void LibRaw::fuji_bayer_decode_block(fuji_compressed_block *info, const fuji_compressed_params *params, int /*cur_line*/)
0858 {
0859   int r_even_pos = 0, r_odd_pos = 1;
0860   int g_even_pos = 0, g_odd_pos = 1;
0861   int b_even_pos = 0, b_odd_pos = 1;
0862 
0863   int errcnt = 0;
0864 
0865   const int line_width = params->line_width;
0866 
0867   while (g_even_pos < line_width || g_odd_pos < line_width)
0868   {
0869     if (g_even_pos < line_width)
0870     {
0871       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R2] + 1, r_even_pos, &info->even[0]);
0872       r_even_pos += 2;
0873       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G2] + 1, g_even_pos, &info->even[0]);
0874       g_even_pos += 2;
0875     }
0876     if (g_even_pos > 8)
0877     {
0878       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R2] + 1, r_odd_pos, &info->odd[0]);
0879       r_odd_pos += 2;
0880       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G2] + 1, g_odd_pos, &info->odd[0]);
0881       g_odd_pos += 2;
0882     }
0883   }
0884 
0885   fuji_extend_red(info->linebuf, line_width);
0886   fuji_extend_green(info->linebuf, line_width);
0887 
0888   g_even_pos = 0, g_odd_pos = 1;
0889 
0890   while (g_even_pos < line_width || g_odd_pos < line_width)
0891   {
0892     if (g_even_pos < line_width)
0893     {
0894       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G3] + 1, g_even_pos, &info->even[1]);
0895       g_even_pos += 2;
0896       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B2] + 1, b_even_pos, &info->even[1]);
0897       b_even_pos += 2;
0898     }
0899     if (g_even_pos > 8)
0900     {
0901       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G3] + 1, g_odd_pos, &info->odd[1]);
0902       g_odd_pos += 2;
0903       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B2] + 1, b_odd_pos, &info->odd[1]);
0904       b_odd_pos += 2;
0905     }
0906   }
0907 
0908   fuji_extend_green(info->linebuf, line_width);
0909   fuji_extend_blue(info->linebuf, line_width);
0910 
0911   r_even_pos = 0, r_odd_pos = 1;
0912   g_even_pos = 0, g_odd_pos = 1;
0913 
0914   while (g_even_pos < line_width || g_odd_pos < line_width)
0915   {
0916     if (g_even_pos < line_width)
0917     {
0918       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R3] + 1, r_even_pos, &info->even[2]);
0919       r_even_pos += 2;
0920       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G4] + 1, g_even_pos, &info->even[2]);
0921       g_even_pos += 2;
0922     }
0923     if (g_even_pos > 8)
0924     {
0925       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R3] + 1, r_odd_pos, &info->odd[2]);
0926       r_odd_pos += 2;
0927       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G4] + 1, g_odd_pos, &info->odd[2]);
0928       g_odd_pos += 2;
0929     }
0930   }
0931 
0932   fuji_extend_red(info->linebuf, line_width);
0933   fuji_extend_green(info->linebuf, line_width);
0934 
0935   g_even_pos = 0, g_odd_pos = 1;
0936   b_even_pos = 0, b_odd_pos = 1;
0937 
0938   while (g_even_pos < line_width || g_odd_pos < line_width)
0939   {
0940     if (g_even_pos < line_width)
0941     {
0942       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G5] + 1, g_even_pos, &info->even[0]);
0943       g_even_pos += 2;
0944       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B3] + 1, b_even_pos, &info->even[0]);
0945       b_even_pos += 2;
0946     }
0947     if (g_even_pos > 8)
0948     {
0949       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G5] + 1, g_odd_pos, &info->odd[0]);
0950       g_odd_pos += 2;
0951       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B3] + 1, b_odd_pos, &info->odd[0]);
0952       b_odd_pos += 2;
0953     }
0954   }
0955 
0956   fuji_extend_green(info->linebuf, line_width);
0957   fuji_extend_blue(info->linebuf, line_width);
0958 
0959   r_even_pos = 0, r_odd_pos = 1;
0960   g_even_pos = 0, g_odd_pos = 1;
0961 
0962   while (g_even_pos < line_width || g_odd_pos < line_width)
0963   {
0964     if (g_even_pos < line_width)
0965     {
0966       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_R4] + 1, r_even_pos, &info->even[1]);
0967       r_even_pos += 2;
0968       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G6] + 1, g_even_pos, &info->even[1]);
0969       g_even_pos += 2;
0970     }
0971     if (g_even_pos > 8)
0972     {
0973       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_R4] + 1, r_odd_pos, &info->odd[1]);
0974       r_odd_pos += 2;
0975       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G6] + 1, g_odd_pos, &info->odd[1]);
0976       g_odd_pos += 2;
0977     }
0978   }
0979 
0980   fuji_extend_red(info->linebuf, line_width);
0981   fuji_extend_green(info->linebuf, line_width);
0982 
0983   g_even_pos = 0, g_odd_pos = 1;
0984   b_even_pos = 0, b_odd_pos = 1;
0985 
0986   while (g_even_pos < line_width || g_odd_pos < line_width)
0987   {
0988     if (g_even_pos < line_width)
0989     {
0990       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_G7] + 1, g_even_pos, &info->even[2]);
0991       g_even_pos += 2;
0992       errcnt += fuji_decode_sample_even(info, params, info->linebuf[_B4] + 1, b_even_pos, &info->even[2]);
0993       b_even_pos += 2;
0994     }
0995     if (g_even_pos > 8)
0996     {
0997       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_G7] + 1, g_odd_pos, &info->odd[2]);
0998       g_odd_pos += 2;
0999       errcnt += fuji_decode_sample_odd(info, params, info->linebuf[_B4] + 1, b_odd_pos, &info->odd[2]);
1000       b_odd_pos += 2;
1001     }
1002   }
1003 
1004   fuji_extend_green(info->linebuf, line_width);
1005   fuji_extend_blue(info->linebuf, line_width);
1006 
1007   if (errcnt)
1008     derror();
1009 }
1010 
1011 void LibRaw::fuji_decode_strip(fuji_compressed_params *params, int cur_block, INT64 raw_offset, unsigned dsize,
1012                                uchar *q_bases)
1013 {
1014   int cur_block_width, cur_line;
1015   unsigned line_size;
1016   fuji_compressed_block info;
1017   fuji_compressed_params *info_common = params;
1018 
1019   if (!libraw_internal_data.unpacker_data.fuji_lossless)
1020   {
1021     int buf_size = sizeof(fuji_compressed_params) + (2 << libraw_internal_data.unpacker_data.fuji_bits);
1022 
1023     info_common = (fuji_compressed_params *)malloc(buf_size);
1024     memcpy(info_common, params, sizeof(fuji_compressed_params));
1025     info_common->qt[0].q_table = (int8_t *)(info_common + 1);
1026     info_common->qt[0].q_base = -1;
1027   }
1028   init_fuji_block(&info, info_common, raw_offset, dsize);
1029   line_size = sizeof(ushort) * (info_common->line_width + 2);
1030 
1031   cur_block_width = libraw_internal_data.unpacker_data.fuji_block_width;
1032   if (cur_block + 1 == libraw_internal_data.unpacker_data.fuji_total_blocks)
1033   {
1034     cur_block_width = imgdata.sizes.raw_width - (libraw_internal_data.unpacker_data.fuji_block_width * cur_block);
1035     /* Old code, may get incorrect results on GFX50, but luckily large optical
1036     black cur_block_width = imgdata.sizes.raw_width %
1037     libraw_internal_data.unpacker_data.fuji_block_width;
1038     */
1039   }
1040 
1041   struct i_pair
1042   {
1043     int a, b;
1044   };
1045   const i_pair mtable[6] = {{_R0, _R3}, {_R1, _R4}, {_G0, _G6}, {_G1, _G7}, {_B0, _B3}, {_B1, _B4}},
1046                ztable[3] = {{_R2, 3}, {_G2, 6}, {_B2, 3}};
1047   for (cur_line = 0; cur_line < libraw_internal_data.unpacker_data.fuji_total_lines; cur_line++)
1048   {
1049     // init grads and main qtable
1050     if (!libraw_internal_data.unpacker_data.fuji_lossless)
1051     {
1052       int q_base = q_bases ? q_bases[cur_line] : 0;
1053       if (!cur_line || q_base != info_common->qt[0].q_base)
1054       {
1055         init_main_qtable(info_common, q_bases[cur_line]);
1056         init_main_grads(info_common, &info);
1057       }
1058     }
1059 
1060     if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
1061       xtrans_decode_block(&info, info_common, cur_line);
1062     else
1063       fuji_bayer_decode_block(&info, info_common, cur_line);
1064 
1065     // copy data from line buffers and advance
1066     for (int i = 0; i < 6; i++)
1067       memcpy(info.linebuf[mtable[i].a], info.linebuf[mtable[i].b], line_size);
1068 
1069     if (libraw_internal_data.unpacker_data.fuji_raw_type == 16)
1070       copy_line_to_xtrans(&info, cur_line, cur_block, cur_block_width);
1071     else
1072       copy_line_to_bayer(&info, cur_line, cur_block, cur_block_width);
1073 
1074     for (int i = 0; i < 3; i++)
1075     {
1076       memset(info.linebuf[ztable[i].a], 0, ztable[i].b * line_size);
1077       info.linebuf[ztable[i].a][0] = info.linebuf[ztable[i].a - 1][1];
1078       info.linebuf[ztable[i].a][info_common->line_width + 1] = info.linebuf[ztable[i].a - 1][info_common->line_width];
1079     }
1080   }
1081 
1082   // release data
1083   if (!libraw_internal_data.unpacker_data.fuji_lossless)
1084     free(info_common);
1085   free(info.linealloc);
1086   free(info.cur_buf);
1087 }
1088 
1089 void LibRaw::fuji_compressed_load_raw()
1090 {
1091   fuji_compressed_params common_info;
1092   int cur_block;
1093   unsigned *block_sizes;
1094   uchar *q_bases = 0;
1095   INT64 raw_offset, *raw_block_offsets;
1096 
1097   init_fuji_compr(&common_info);
1098 
1099   // read block sizes
1100   block_sizes = (unsigned *)malloc(sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks);
1101   raw_block_offsets = (INT64 *)malloc(sizeof(INT64) * libraw_internal_data.unpacker_data.fuji_total_blocks);
1102 
1103   libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
1104   int sizesToRead = sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks;
1105   if (libraw_internal_data.internal_data.input->read(block_sizes, 1, sizesToRead) != sizesToRead)
1106   {
1107     free(block_sizes);
1108     free(raw_block_offsets);
1109     throw LIBRAW_EXCEPTION_IO_EOF;
1110   }
1111 
1112   raw_offset = ((sizeof(unsigned) * libraw_internal_data.unpacker_data.fuji_total_blocks) + 0xF) & ~0xF;
1113 
1114   // read q bases for lossy
1115   if (!libraw_internal_data.unpacker_data.fuji_lossless)
1116   {
1117     int total_q_bases = libraw_internal_data.unpacker_data.fuji_total_blocks *
1118                         ((libraw_internal_data.unpacker_data.fuji_total_lines + 0xF) & ~0xF);
1119     q_bases = (uchar *)malloc(total_q_bases);
1120     libraw_internal_data.internal_data.input->seek(raw_offset + libraw_internal_data.unpacker_data.data_offset,
1121                                                    SEEK_SET);
1122     libraw_internal_data.internal_data.input->read(q_bases, 1, total_q_bases);
1123     raw_offset += total_q_bases;
1124   }
1125 
1126   raw_offset += libraw_internal_data.unpacker_data.data_offset;
1127 
1128   // calculating raw block offsets
1129   raw_block_offsets[0] = raw_offset;
1130   for (cur_block = 0; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++)
1131   {
1132     unsigned bsize = sgetn(4, (uchar *)(block_sizes + cur_block));
1133     block_sizes[cur_block] = bsize;
1134   }
1135 
1136   for (cur_block = 1; cur_block < libraw_internal_data.unpacker_data.fuji_total_blocks; cur_block++)
1137     raw_block_offsets[cur_block] = raw_block_offsets[cur_block - 1] + block_sizes[cur_block - 1];
1138 
1139   fuji_decode_loop(&common_info, libraw_internal_data.unpacker_data.fuji_total_blocks, raw_block_offsets, block_sizes,
1140                    q_bases);
1141 
1142   free(q_bases);
1143   free(block_sizes);
1144   free(raw_block_offsets);
1145   free(common_info.buf);
1146 }
1147 
1148 void LibRaw::fuji_decode_loop(fuji_compressed_params *common_info, int count, INT64 *raw_block_offsets,
1149                               unsigned *block_sizes, uchar *q_bases)
1150 {
1151   int cur_block;
1152   const int lineStep = (libraw_internal_data.unpacker_data.fuji_total_lines + 0xF) & ~0xF;
1153 #ifdef LIBRAW_USE_OPENMP
1154 #pragma omp parallel for private(cur_block)
1155 #endif
1156   for (cur_block = 0; cur_block < count; cur_block++)
1157   {
1158     fuji_decode_strip(common_info, cur_block, raw_block_offsets[cur_block], block_sizes[cur_block],
1159                       q_bases ? q_bases + cur_block * lineStep : 0);
1160   }
1161 }
1162 
1163 void LibRaw::parse_fuji_compressed_header()
1164 {
1165   unsigned signature, lossless, h_raw_type, h_raw_bits, h_raw_height, h_raw_rounded_width, h_raw_width, h_block_size,
1166       h_blocks_in_row, h_total_lines;
1167 
1168   uchar header[16];
1169 
1170   libraw_internal_data.internal_data.input->seek(libraw_internal_data.unpacker_data.data_offset, SEEK_SET);
1171   if (libraw_internal_data.internal_data.input->read(header, 1, sizeof(header)) != sizeof(header))
1172     return;
1173 
1174   // read all header
1175   signature = sgetn(2, header);
1176   lossless = header[2];
1177   h_raw_type = header[3];
1178   h_raw_bits = header[4];
1179   h_raw_height = sgetn(2, header + 5);
1180   h_raw_rounded_width = sgetn(2, header + 7);
1181   h_raw_width = sgetn(2, header + 9);
1182   h_block_size = sgetn(2, header + 11);
1183   h_blocks_in_row = header[13];
1184   h_total_lines = sgetn(2, header + 14);
1185 
1186   // general validation
1187   if (signature != 0x4953 || lossless > 1 || h_raw_height > 0x4002 || h_raw_height < 6 || h_raw_height % 6 ||
1188       h_block_size < 1 || h_raw_width > 0x4200 || h_raw_width < 0x300 || h_raw_width % 24 ||
1189       h_raw_rounded_width > 0x4200 || h_raw_rounded_width < h_block_size || h_raw_rounded_width % h_block_size ||
1190       h_raw_rounded_width - h_raw_width >= h_block_size || h_block_size != 0x300 || h_blocks_in_row > 0x10 ||
1191       h_blocks_in_row == 0 || h_blocks_in_row != h_raw_rounded_width / h_block_size || h_total_lines > 0xAAB ||
1192       h_total_lines == 0 || h_total_lines != h_raw_height / 6 ||
1193       (h_raw_bits != 12 && h_raw_bits != 14 && h_raw_bits != 16) || (h_raw_type != 16 && h_raw_type != 0))
1194     return;
1195 
1196   // modify data
1197   libraw_internal_data.unpacker_data.fuji_total_lines = h_total_lines;
1198   libraw_internal_data.unpacker_data.fuji_total_blocks = h_blocks_in_row;
1199   libraw_internal_data.unpacker_data.fuji_block_width = h_block_size;
1200   libraw_internal_data.unpacker_data.fuji_bits = h_raw_bits;
1201   libraw_internal_data.unpacker_data.fuji_raw_type = h_raw_type;
1202   libraw_internal_data.unpacker_data.fuji_lossless = lossless;
1203   imgdata.sizes.raw_width = h_raw_width;
1204   imgdata.sizes.raw_height = h_raw_height;
1205   libraw_internal_data.unpacker_data.data_offset += 16;
1206   load_raw = &LibRaw::fuji_compressed_load_raw;
1207 }
1208 
1209 #undef _abs
1210 #undef _min