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