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