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