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