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