/src/LibRaw/src/preprocessing/raw2image.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * Copyright 2019-2025 LibRaw LLC (info@libraw.org) |
3 | | * |
4 | | |
5 | | LibRaw is free software; you can redistribute it and/or modify |
6 | | it under the terms of the one of two licenses as you choose: |
7 | | |
8 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
9 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
10 | | |
11 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
12 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
13 | | |
14 | | */ |
15 | | |
16 | | #include "../../internal/libraw_cxx_defs.h" |
17 | | |
18 | | void LibRaw::raw2image_start() |
19 | 2.38k | { |
20 | | // restore color,sizes and internal data into raw_image fields |
21 | 2.38k | memmove(&imgdata.color, &imgdata.rawdata.color, sizeof(imgdata.color)); |
22 | 2.38k | memmove(&imgdata.sizes, &imgdata.rawdata.sizes, sizeof(imgdata.sizes)); |
23 | 2.38k | memmove(&imgdata.idata, &imgdata.rawdata.iparams, sizeof(imgdata.idata)); |
24 | 2.38k | memmove(&libraw_internal_data.internal_output_params, |
25 | 2.38k | &imgdata.rawdata.ioparams, |
26 | 2.38k | sizeof(libraw_internal_data.internal_output_params)); |
27 | | |
28 | 2.38k | if (O.user_flip >= 0) |
29 | 0 | S.flip = O.user_flip; |
30 | | |
31 | 2.38k | switch ((S.flip + 3600) % 360) |
32 | 2.38k | { |
33 | 0 | case 270: |
34 | 0 | S.flip = 5; |
35 | 0 | break; |
36 | 0 | case 180: |
37 | 0 | S.flip = 3; |
38 | 0 | break; |
39 | 0 | case 90: |
40 | 0 | S.flip = 6; |
41 | 0 | break; |
42 | 2.38k | } |
43 | | |
44 | 11.9k | for (int c = 0; c < 4; c++) |
45 | 9.52k | if (O.aber[c] < 0.001 || O.aber[c] > 1000.f) |
46 | 0 | O.aber[c] = 1.0; |
47 | | |
48 | | // adjust for half mode! |
49 | 2.38k | IO.shrink = |
50 | 2.38k | !imgdata.rawdata.color4_image && !imgdata.rawdata.color3_image && |
51 | 1.95k | !imgdata.rawdata.float4_image && !imgdata.rawdata.float3_image && |
52 | 1.95k | P1.filters && |
53 | 1.92k | (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1))); |
54 | | |
55 | 2.38k | S.iheight = (S.height + IO.shrink) >> IO.shrink; |
56 | 2.38k | S.iwidth = (S.width + IO.shrink) >> IO.shrink; |
57 | 2.38k | } |
58 | | |
59 | | int LibRaw::raw2image(void) |
60 | 0 | { |
61 | |
|
62 | 0 | CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); |
63 | | |
64 | 0 | if (!imgdata.rawdata.raw_image && !imgdata.rawdata.color3_image && !imgdata.rawdata.color4_image) |
65 | 0 | return LIBRAW_OUT_OF_ORDER_CALL; |
66 | | |
67 | 0 | try |
68 | 0 | { |
69 | 0 | raw2image_start(); |
70 | |
|
71 | 0 | bool free_p1_buffer = false; |
72 | 0 | if (is_phaseone_compressed() && (imgdata.rawdata.raw_alloc || (imgdata.process_warnings & LIBRAW_WARN_RAWSPEED3_PROCESSED))) |
73 | 0 | { |
74 | 0 | phase_one_allocate_tempbuffer(); |
75 | 0 | free_p1_buffer = true; |
76 | 0 | int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc, |
77 | 0 | imgdata.rawdata.raw_image); |
78 | 0 | if (rc == 0 && imgdata.params.use_p1_correction) |
79 | 0 | rc = phase_one_correct(); |
80 | 0 | if (rc != 0) |
81 | 0 | { |
82 | 0 | phase_one_free_tempbuffer(); |
83 | 0 | return rc; |
84 | 0 | } |
85 | 0 | } |
86 | | |
87 | | // free and re-allocate image bitmap |
88 | 0 | INT64 extra = P1.filters ? (P1.filters == 9 ? 6LL : 2LL) : 0LL; |
89 | 0 | INT64 allocate_sz = (INT64(S.iheight) + extra) * (INT64(S.iwidth) + extra); |
90 | 0 | if (imgdata.image) |
91 | 0 | { |
92 | 0 | imgdata.image = (ushort(*)[4])realloc(imgdata.image, allocate_sz * sizeof(*imgdata.image)); |
93 | 0 | memset(imgdata.image, 0, allocate_sz * sizeof(*imgdata.image)); |
94 | 0 | } |
95 | 0 | else |
96 | 0 | imgdata.image = |
97 | 0 | (ushort(*)[4])calloc(allocate_sz, sizeof(*imgdata.image)); |
98 | |
|
99 | 0 | libraw_decoder_info_t decoder_info; |
100 | 0 | get_decoder_info(&decoder_info); |
101 | | |
102 | | // Copy area size |
103 | 0 | int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin))); |
104 | 0 | int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin))); |
105 | | |
106 | | // Move saved bitmap to imgdata.image |
107 | 0 | if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image) |
108 | 0 | { |
109 | 0 | if (IO.fuji_width) |
110 | 0 | { |
111 | 0 | unsigned r, c; |
112 | 0 | int row, col; |
113 | 0 | for (row = 0; row < S.raw_height - S.top_margin * 2; row++) |
114 | 0 | { |
115 | 0 | for (col = 0; |
116 | 0 | col < IO.fuji_width |
117 | 0 | << int(!libraw_internal_data.unpacker_data.fuji_layout); |
118 | 0 | col++) |
119 | 0 | { |
120 | 0 | if (libraw_internal_data.unpacker_data.fuji_layout) |
121 | 0 | { |
122 | 0 | r = IO.fuji_width - 1 - col + (row >> 1); |
123 | 0 | c = col + ((row + 1) >> 1); |
124 | 0 | } |
125 | 0 | else |
126 | 0 | { |
127 | 0 | r = IO.fuji_width - 1 + row - (col >> 1); |
128 | 0 | c = row + ((col + 1) >> 1); |
129 | 0 | } |
130 | 0 | if (r < S.height && c < S.width && col + int(S.left_margin) < int(S.raw_width)) |
131 | 0 | imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)] |
132 | 0 | [FC(r, c)] = |
133 | 0 | imgdata.rawdata |
134 | 0 | .raw_image[(row + S.top_margin) * S.raw_pitch / 2 + |
135 | 0 | (col + S.left_margin)]; |
136 | 0 | } |
137 | 0 | } |
138 | 0 | } |
139 | 0 | else |
140 | 0 | { |
141 | 0 | int row, col; |
142 | 0 | for (row = 0; row < copyheight; row++) |
143 | 0 | for (col = 0; col < copywidth; col++) |
144 | 0 | imgdata.image[((row) >> IO.shrink) * S.iwidth + |
145 | 0 | ((col) >> IO.shrink)][fcol(row, col)] = |
146 | 0 | imgdata.rawdata |
147 | 0 | .raw_image[(row + S.top_margin) * S.raw_pitch / 2 + |
148 | 0 | (col + S.left_margin)]; |
149 | 0 | } |
150 | 0 | } |
151 | 0 | else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) |
152 | 0 | { |
153 | 0 | if (imgdata.rawdata.color4_image) |
154 | 0 | { |
155 | 0 | if (S.width * 8u == S.raw_pitch && S.height == S.raw_height) |
156 | 0 | memmove(imgdata.image, imgdata.rawdata.color4_image, |
157 | 0 | S.width * S.height * sizeof(*imgdata.image)); |
158 | 0 | else |
159 | 0 | { |
160 | 0 | for (int row = 0; row < copyheight; row++) |
161 | 0 | memmove(&imgdata.image[row * S.width], |
162 | 0 | &imgdata.rawdata |
163 | 0 | .color4_image[(row + S.top_margin) * S.raw_pitch / 8 + |
164 | 0 | S.left_margin], |
165 | 0 | copywidth * sizeof(*imgdata.image)); |
166 | 0 | } |
167 | 0 | } |
168 | 0 | else if (imgdata.rawdata.color3_image) |
169 | 0 | { |
170 | 0 | unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image; |
171 | 0 | for (int row = 0; row < copyheight; row++) |
172 | 0 | { |
173 | 0 | ushort(*srcrow)[3] = |
174 | 0 | (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch]; |
175 | 0 | ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width]; |
176 | 0 | for (int col = 0; col < copywidth; col++) |
177 | 0 | { |
178 | 0 | for (int c = 0; c < 3; c++) |
179 | 0 | dstrow[col][c] = srcrow[S.left_margin + col][c]; |
180 | 0 | dstrow[col][3] = 0; |
181 | 0 | } |
182 | 0 | } |
183 | 0 | } |
184 | 0 | else |
185 | 0 | { |
186 | | // legacy decoder, but no data? |
187 | 0 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
188 | 0 | } |
189 | 0 | } |
190 | | |
191 | | // Free PhaseOne separate copy allocated at function start |
192 | 0 | if (free_p1_buffer) |
193 | 0 | { |
194 | 0 | phase_one_free_tempbuffer(); |
195 | 0 | } |
196 | | // hack - clear later flags! |
197 | |
|
198 | 0 | if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width) |
199 | 0 | { |
200 | 0 | canon_600_correct(); |
201 | 0 | } |
202 | |
|
203 | 0 | imgdata.progress_flags = |
204 | 0 | LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | |
205 | 0 | LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY | |
206 | 0 | LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; |
207 | 0 | return 0; |
208 | 0 | } |
209 | 0 | catch (const std::bad_alloc&) |
210 | 0 | { |
211 | 0 | EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC); |
212 | 0 | } |
213 | 0 | catch (const LibRaw_exceptions& err) |
214 | 0 | { |
215 | 0 | EXCEPTION_HANDLER(err); |
216 | 0 | } |
217 | 0 | } |
218 | | |
219 | | void LibRaw::copy_fuji_uncropped(unsigned short cblack[4], |
220 | | unsigned short *dmaxp) |
221 | 45 | { |
222 | | #if defined(LIBRAW_USE_OPENMP) |
223 | | #pragma omp parallel for schedule(dynamic) default(none) firstprivate(cblack) shared(dmaxp) |
224 | | #endif |
225 | 1.60k | for (int row = 0; row < int(S.raw_height) - int(S.top_margin) * 2; row++) |
226 | 1.56k | { |
227 | 1.56k | int col; |
228 | 1.56k | unsigned short ldmax = 0; |
229 | 1.56k | for (col = 0; |
230 | 37.6k | col < IO.fuji_width << int(!libraw_internal_data.unpacker_data.fuji_layout) |
231 | 36.2k | && col + int(S.left_margin) < int(S.raw_width); |
232 | 36.0k | col++) |
233 | 36.0k | { |
234 | 36.0k | unsigned r, c; |
235 | 36.0k | if (libraw_internal_data.unpacker_data.fuji_layout) |
236 | 26.6k | { |
237 | 26.6k | r = IO.fuji_width - 1 - col + (row >> 1); |
238 | 26.6k | c = col + ((row + 1) >> 1); |
239 | 26.6k | } |
240 | 9.40k | else |
241 | 9.40k | { |
242 | 9.40k | r = IO.fuji_width - 1 + row - (col >> 1); |
243 | 9.40k | c = row + ((col + 1) >> 1); |
244 | 9.40k | } |
245 | 36.0k | if (r < S.height && c < S.width) |
246 | 35.8k | { |
247 | 35.8k | unsigned short val = |
248 | 35.8k | imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + |
249 | 35.8k | (col + S.left_margin)]; |
250 | 35.8k | int cc = FC(r, c); |
251 | 35.8k | if (val > cblack[cc]) |
252 | 22.9k | { |
253 | 22.9k | val -= cblack[cc]; |
254 | 22.9k | if (val > ldmax) |
255 | 3.47k | ldmax = val; |
256 | 22.9k | } |
257 | 12.8k | else |
258 | 12.8k | val = 0; |
259 | 35.8k | imgdata.image[((r) >> IO.shrink) * S.iwidth + ((c) >> IO.shrink)][cc] = |
260 | 35.8k | val; |
261 | 35.8k | } |
262 | 36.0k | } |
263 | | #if defined(LIBRAW_USE_OPENMP) |
264 | | #pragma omp critical(dataupdate) |
265 | | #endif |
266 | 1.56k | { |
267 | 1.56k | if (*dmaxp < ldmax) |
268 | 89 | *dmaxp = ldmax; |
269 | 1.56k | } |
270 | 1.56k | } |
271 | 45 | } |
272 | | |
273 | | void LibRaw::copy_bayer(unsigned short cblack[4], unsigned short *dmaxp) |
274 | 1.77k | { |
275 | | // Both cropped and uncropped |
276 | 1.77k | int maxHeight = MIN(int(S.height),int(S.raw_height)-int(S.top_margin)); |
277 | | #if defined(LIBRAW_USE_OPENMP) |
278 | | #pragma omp parallel for schedule(dynamic) default(none) shared(dmaxp) firstprivate(cblack, maxHeight) |
279 | | #endif |
280 | 2.18M | for (int row = 0; row < maxHeight ; row++) |
281 | 2.18M | { |
282 | 2.18M | int col; |
283 | 2.18M | unsigned short ldmax = 0; |
284 | 1.08G | for (col = 0; col < S.width && col + S.left_margin < S.raw_width; col++) |
285 | 1.08G | { |
286 | 1.08G | unsigned short val = |
287 | 1.08G | imgdata.rawdata.raw_image[(row + S.top_margin) * S.raw_pitch / 2 + |
288 | 1.08G | (col + S.left_margin)]; |
289 | 1.08G | int cc = fcol(row, col); |
290 | 1.08G | if (val > cblack[cc]) |
291 | 761M | { |
292 | 761M | val -= cblack[cc]; |
293 | 761M | if (val > ldmax) |
294 | 3.65M | ldmax = val; |
295 | 761M | } |
296 | 325M | else |
297 | 325M | val = 0; |
298 | 1.08G | imgdata.image[((row) >> IO.shrink) * S.iwidth + ((col) >> IO.shrink)][cc] = val; |
299 | 1.08G | } |
300 | | #if defined(LIBRAW_USE_OPENMP) |
301 | | #pragma omp critical(dataupdate) |
302 | | #endif |
303 | 2.18M | { |
304 | 2.18M | if (*dmaxp < ldmax) |
305 | 3.69k | *dmaxp = ldmax; |
306 | 2.18M | } |
307 | 2.18M | } |
308 | 1.77k | } |
309 | | |
310 | | int LibRaw::raw2image_ex(int do_subtract_black) |
311 | 2.38k | { |
312 | | |
313 | 2.38k | CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW); |
314 | 2.38k | if (!imgdata.rawdata.raw_image && !imgdata.rawdata.color3_image && !imgdata.rawdata.color4_image) |
315 | 0 | return LIBRAW_OUT_OF_ORDER_CALL; |
316 | | |
317 | 2.38k | try |
318 | 2.38k | { |
319 | 2.38k | raw2image_start(); |
320 | 2.38k | bool free_p1_buffer = false; |
321 | | |
322 | | // Compressed P1 files with bl data! |
323 | 2.38k | if (is_phaseone_compressed() && (imgdata.rawdata.raw_alloc || (imgdata.process_warnings & LIBRAW_WARN_RAWSPEED3_PROCESSED))) |
324 | 449 | { |
325 | 449 | phase_one_allocate_tempbuffer(); |
326 | 449 | free_p1_buffer = true; |
327 | 449 | int rc = phase_one_subtract_black((ushort *)imgdata.rawdata.raw_alloc, |
328 | 449 | imgdata.rawdata.raw_image); |
329 | 449 | if (rc == 0 && imgdata.params.use_p1_correction) |
330 | 449 | rc = phase_one_correct(); |
331 | 449 | if (rc != 0) |
332 | 132 | { |
333 | 132 | phase_one_free_tempbuffer(); |
334 | 132 | return rc; |
335 | 132 | } |
336 | 449 | } |
337 | | |
338 | | // process cropping |
339 | 2.24k | int do_crop = 0; |
340 | 2.24k | if (~O.cropbox[2] && ~O.cropbox[3]) |
341 | 0 | { |
342 | 0 | int crop[4], c, filt; |
343 | 0 | for (int q = 0; q < 4; q++) |
344 | 0 | { |
345 | 0 | crop[q] = O.cropbox[q]; |
346 | 0 | if (crop[q] < 0) |
347 | 0 | crop[q] = 0; |
348 | 0 | } |
349 | |
|
350 | 0 | if (IO.fuji_width && imgdata.idata.filters >= 1000) |
351 | 0 | { |
352 | 0 | crop[0] = (crop[0] / 4) * 4; |
353 | 0 | crop[1] = (crop[1] / 4) * 4; |
354 | 0 | if (!libraw_internal_data.unpacker_data.fuji_layout) |
355 | 0 | { |
356 | 0 | crop[2] = int(crop[2] * sqrtf(2.f)); |
357 | 0 | crop[3] = int(crop[3] / sqrtf(2.f)); |
358 | 0 | } |
359 | 0 | crop[2] = (crop[2] / 4 + 1) * 4; |
360 | 0 | crop[3] = (crop[3] / 4 + 1) * 4; |
361 | 0 | } |
362 | 0 | else if (imgdata.idata.filters == 1) |
363 | 0 | { |
364 | 0 | crop[0] = (crop[0] / 16) * 16; |
365 | 0 | crop[1] = (crop[1] / 16) * 16; |
366 | 0 | } |
367 | 0 | else if (imgdata.idata.filters == LIBRAW_XTRANS) |
368 | 0 | { |
369 | 0 | crop[0] = (crop[0] / 6) * 6; |
370 | 0 | crop[1] = (crop[1] / 6) * 6; |
371 | 0 | } |
372 | 0 | do_crop = 1; |
373 | |
|
374 | 0 | crop[2] = MIN(crop[2], (signed)S.width - crop[0]); |
375 | 0 | crop[3] = MIN(crop[3], (signed)S.height - crop[1]); |
376 | 0 | if (crop[2] <= 0 || crop[3] <= 0) |
377 | 0 | throw LIBRAW_EXCEPTION_BAD_CROP; |
378 | | |
379 | | // adjust sizes! |
380 | 0 | S.left_margin += crop[0]; |
381 | 0 | S.top_margin += crop[1]; |
382 | 0 | S.width = crop[2]; |
383 | 0 | S.height = crop[3]; |
384 | |
|
385 | 0 | S.iheight = (S.height + IO.shrink) >> IO.shrink; |
386 | 0 | S.iwidth = (S.width + IO.shrink) >> IO.shrink; |
387 | 0 | if (!IO.fuji_width && imgdata.idata.filters && |
388 | 0 | imgdata.idata.filters >= 1000) |
389 | 0 | { |
390 | 0 | for (filt = c = 0; c < 16; c++) |
391 | 0 | filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2; |
392 | 0 | imgdata.idata.filters = filt; |
393 | 0 | } |
394 | 0 | } |
395 | | |
396 | 2.24k | int extra = P1.filters ? (P1.filters == 9 ? 6 : 2) : 0; |
397 | 2.24k | int alloc_width = S.iwidth + extra; |
398 | 2.24k | int alloc_height = S.iheight + extra; |
399 | | |
400 | 2.24k | if (IO.fuji_width && do_crop) |
401 | 0 | { |
402 | 0 | int IO_fw = S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout); |
403 | 0 | int t_alloc_width = |
404 | 0 | (S.height >> libraw_internal_data.unpacker_data.fuji_layout) + IO_fw; |
405 | 0 | int t_alloc_height = t_alloc_width - 1; |
406 | 0 | alloc_height = (t_alloc_height + IO.shrink) >> IO.shrink; |
407 | 0 | alloc_width = (t_alloc_width + IO.shrink) >> IO.shrink; |
408 | 0 | } |
409 | 2.24k | INT64 alloc_sz = INT64(alloc_width) * INT64(alloc_height); |
410 | | |
411 | 2.24k | if (imgdata.image) |
412 | 0 | { |
413 | 0 | imgdata.image = (ushort(*)[4])realloc(imgdata.image, |
414 | 0 | alloc_sz * sizeof(*imgdata.image)); |
415 | 0 | memset(imgdata.image, 0, alloc_sz * sizeof(*imgdata.image)); |
416 | 0 | } |
417 | 2.24k | else |
418 | 2.24k | imgdata.image = (ushort(*)[4])calloc(alloc_sz, sizeof(*imgdata.image)); |
419 | | |
420 | 2.24k | libraw_decoder_info_t decoder_info; |
421 | 2.24k | get_decoder_info(&decoder_info); |
422 | | |
423 | | // Adjust black levels |
424 | 2.24k | unsigned short cblack[4] = {0, 0, 0, 0}; |
425 | 2.24k | unsigned short dmax = 0; |
426 | 2.24k | if (do_subtract_black) |
427 | 1.69k | { |
428 | 1.69k | adjust_bl(); |
429 | 8.45k | for (int i = 0; i < 4; i++) |
430 | 6.76k | cblack[i] = (unsigned short)C.cblack[i]; |
431 | 1.69k | } |
432 | | |
433 | | // Max area size to definitely not overrun in/out buffers |
434 | 2.24k | int copyheight = MAX(0, MIN(int(S.height), int(S.raw_height) - int(S.top_margin))); |
435 | 2.24k | int copywidth = MAX(0, MIN(int(S.width), int(S.raw_width) - int(S.left_margin))); |
436 | | |
437 | | // Move saved bitmap to imgdata.image |
438 | 2.24k | if ((imgdata.idata.filters || P1.colors == 1) && imgdata.rawdata.raw_image) |
439 | 1.82k | { |
440 | 1.82k | if (IO.fuji_width) |
441 | 45 | { |
442 | 45 | if (do_crop) |
443 | 0 | { |
444 | 0 | IO.fuji_width = |
445 | 0 | S.width >> int(!libraw_internal_data.unpacker_data.fuji_layout); |
446 | 0 | int IO_fwidth = |
447 | 0 | (S.height >> int(libraw_internal_data.unpacker_data.fuji_layout)) + |
448 | 0 | IO.fuji_width; |
449 | 0 | int IO_fheight = IO_fwidth - 1; |
450 | |
|
451 | 0 | int row, col; |
452 | 0 | for (row = 0; row < S.height; row++) |
453 | 0 | { |
454 | 0 | for (col = 0; col < S.width; col++) |
455 | 0 | { |
456 | 0 | int r, c; |
457 | 0 | if (libraw_internal_data.unpacker_data.fuji_layout) |
458 | 0 | { |
459 | 0 | r = IO.fuji_width - 1 - col + (row >> 1); |
460 | 0 | c = col + ((row + 1) >> 1); |
461 | 0 | } |
462 | 0 | else |
463 | 0 | { |
464 | 0 | r = IO.fuji_width - 1 + row - (col >> 1); |
465 | 0 | c = row + ((col + 1) >> 1); |
466 | 0 | } |
467 | |
|
468 | 0 | unsigned short val = |
469 | 0 | imgdata.rawdata |
470 | 0 | .raw_image[(row + S.top_margin) * S.raw_pitch / 2 + |
471 | 0 | (col + S.left_margin)]; |
472 | 0 | int cc = FCF(row, col); |
473 | 0 | if (val > cblack[cc]) |
474 | 0 | { |
475 | 0 | val -= cblack[cc]; |
476 | 0 | if (dmax < val) |
477 | 0 | dmax = val; |
478 | 0 | } |
479 | 0 | else |
480 | 0 | val = 0; |
481 | 0 | imgdata.image[((r) >> IO.shrink) * alloc_width + |
482 | 0 | ((c) >> IO.shrink)][cc] = val; |
483 | 0 | } |
484 | 0 | } |
485 | 0 | S.height = IO_fheight; |
486 | 0 | S.width = IO_fwidth; |
487 | 0 | S.iheight = (S.height + IO.shrink) >> IO.shrink; |
488 | 0 | S.iwidth = (S.width + IO.shrink) >> IO.shrink; |
489 | 0 | S.raw_height -= 2 * S.top_margin; |
490 | 0 | } |
491 | 45 | else |
492 | 45 | { |
493 | 45 | copy_fuji_uncropped(cblack, &dmax); |
494 | 45 | } |
495 | 45 | } // end Fuji |
496 | 1.77k | else |
497 | 1.77k | { |
498 | 1.77k | copy_bayer(cblack, &dmax); |
499 | 1.77k | } |
500 | 1.82k | } |
501 | 428 | else // if(decoder_info.decoder_flags & LIBRAW_DECODER_LEGACY) |
502 | 428 | { |
503 | 428 | if (imgdata.rawdata.color4_image) |
504 | 403 | { |
505 | 403 | if (S.raw_pitch != S.width * 8u || S.height != S.raw_height) |
506 | 136 | { |
507 | 23.5k | for (int row = 0; row < copyheight; row++) |
508 | 23.4k | memmove(&imgdata.image[row * S.width], |
509 | 23.4k | &imgdata.rawdata |
510 | 23.4k | .color4_image[(row + S.top_margin) * S.raw_pitch / 8 + |
511 | 23.4k | S.left_margin], |
512 | 23.4k | copywidth * sizeof(*imgdata.image)); |
513 | 136 | } |
514 | 267 | else |
515 | 267 | { |
516 | | // legacy is always 4channel and not shrinked! |
517 | 267 | memmove(imgdata.image, imgdata.rawdata.color4_image, |
518 | 267 | S.width*copyheight * sizeof(*imgdata.image)); |
519 | 267 | } |
520 | 403 | } |
521 | 25 | else if (imgdata.rawdata.color3_image) |
522 | 25 | { |
523 | 25 | unsigned char *c3image = (unsigned char *)imgdata.rawdata.color3_image; |
524 | 122k | for (int row = 0; row < copyheight; row++) |
525 | 122k | { |
526 | 122k | ushort(*srcrow)[3] = |
527 | 122k | (ushort(*)[3]) & c3image[(row + S.top_margin) * S.raw_pitch]; |
528 | 122k | ushort(*dstrow)[4] = (ushort(*)[4]) & imgdata.image[row * S.width]; |
529 | 9.43M | for (int col = 0; col < copywidth; col++) |
530 | 9.31M | { |
531 | 37.2M | for (int c = 0; c < 3; c++) |
532 | 27.9M | dstrow[col][c] = srcrow[S.left_margin + col][c]; |
533 | 9.31M | dstrow[col][3] = 0; |
534 | 9.31M | } |
535 | 122k | } |
536 | 25 | } |
537 | 0 | else |
538 | 0 | { |
539 | | // legacy decoder, but no data? |
540 | 0 | throw LIBRAW_EXCEPTION_DECODE_RAW; |
541 | 0 | } |
542 | 428 | } |
543 | | |
544 | | // Free PhaseOne separate copy allocated at function start |
545 | 2.24k | if (free_p1_buffer) |
546 | 317 | { |
547 | 317 | phase_one_free_tempbuffer(); |
548 | 317 | } |
549 | 2.24k | if (load_raw == &LibRaw::canon_600_load_raw && S.width < S.raw_width) |
550 | 55 | { |
551 | 55 | canon_600_correct(); |
552 | 55 | } |
553 | | |
554 | 2.24k | if (do_subtract_black) |
555 | 1.69k | { |
556 | 1.69k | C.data_maximum = (int)dmax; |
557 | 1.69k | C.maximum -= C.black; |
558 | | // ZERO(C.cblack); |
559 | 1.69k | C.cblack[0] = C.cblack[1] = C.cblack[2] = C.cblack[3] = 0; |
560 | 1.69k | C.black = 0; |
561 | 1.69k | } |
562 | | |
563 | | // hack - clear later flags! |
564 | 2.24k | imgdata.progress_flags = |
565 | 2.24k | LIBRAW_PROGRESS_START | LIBRAW_PROGRESS_OPEN | |
566 | 2.24k | LIBRAW_PROGRESS_RAW2_IMAGE | LIBRAW_PROGRESS_IDENTIFY | |
567 | 2.24k | LIBRAW_PROGRESS_SIZE_ADJUST | LIBRAW_PROGRESS_LOAD_RAW; |
568 | 2.24k | return 0; |
569 | 2.24k | } |
570 | 2.38k | catch (const LibRaw_exceptions& err) |
571 | 2.38k | { |
572 | 0 | EXCEPTION_HANDLER(err); |
573 | 0 | } |
574 | 2.38k | } |