/src/libraw/src/demosaic/xtrans_demosaic.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * Copyright 2019-2026 LibRaw LLC (info@libraw.org) |
3 | | * |
4 | | LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder, |
5 | | dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net. |
6 | | LibRaw do not use RESTRICTED code from dcraw.c |
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/dcraw_defs.h" |
20 | | |
21 | 621M | #define fcol(row, col) xtrans[(row + 6) % 6][(col + 6) % 6] |
22 | | /* |
23 | | Frank Markesteijn's algorithm for Fuji X-Trans sensors |
24 | | */ |
25 | | void LibRaw::xtrans_interpolate(int passes) |
26 | 172 | { |
27 | 172 | int cstat[4] = {0, 0, 0, 0}; |
28 | 172 | int ndir; |
29 | 172 | static const short orth[12] = {1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1}, |
30 | 172 | patt[2][16] = {{0, 1, 0, -1, 2, 0, -1, 0, 1, 1, 1, -1, 0, |
31 | 172 | 0, 0, 0}, |
32 | 172 | {0, 1, 0, -2, 1, 0, -2, 0, 1, 1, -2, -2, 1, |
33 | 172 | -1, -1, 1}}, |
34 | 172 | dir[4] = {1, LIBRAW_AHD_TILE, LIBRAW_AHD_TILE + 1, |
35 | 172 | LIBRAW_AHD_TILE - 1}; |
36 | 172 | short allhex[3][3][2][8]; |
37 | 172 | ushort sgrow = 0, sgcol = 0; |
38 | | |
39 | 172 | if (width < LIBRAW_AHD_TILE || height < LIBRAW_AHD_TILE || filters != 9) |
40 | 5 | throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image |
41 | | /* Check against right pattern */ |
42 | 1.16k | for (int row = 0; row < 6; row++) |
43 | 7.01k | for (int col = 0; col < 6; col++) |
44 | 6.01k | cstat[(unsigned)fcol(row, col)]++; |
45 | | |
46 | 167 | if (cstat[0] < 6 || cstat[0] > 10 || cstat[1] < 16 || cstat[1] > 24 || |
47 | 160 | cstat[2] < 6 || cstat[2] > 10 || cstat[3]) |
48 | 9 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
49 | | |
50 | | // Init allhex table to unreasonable values |
51 | 632 | for (int i = 0; i < 3; i++) |
52 | 1.89k | for (int j = 0; j < 3; j++) |
53 | 4.26k | for (int k = 0; k < 2; k++) |
54 | 25.5k | for (int l = 0; l < 8; l++) |
55 | 22.7k | allhex[i][j][k][l] = 32700; |
56 | | |
57 | 158 | cielab(0, 0); |
58 | 158 | ndir = 4 << int(passes > 1); |
59 | | |
60 | 158 | int minv = 0, maxv = 0, minh = 0, maxh = 0; |
61 | | /* Map a green hexagon around each non-green pixel and vice versa: */ |
62 | 632 | for (int row = 0; row < 3; row++) |
63 | 1.89k | for (int col = 0; col < 3; col++) |
64 | 8.53k | for (int ng = 0, d = 0; d < 10; d += 2) |
65 | 7.11k | { |
66 | 7.11k | int g = fcol(row, col) == 1; |
67 | 7.11k | if (fcol(row + orth[d], col + orth[d + 2]) == 1) |
68 | 2.31k | ng = 0; |
69 | 4.79k | else |
70 | 4.79k | ng++; |
71 | 7.11k | if (ng == 4) |
72 | 287 | { |
73 | 287 | sgrow = row; |
74 | 287 | sgcol = col; |
75 | 287 | } |
76 | 7.11k | if (ng == g + 1) |
77 | 1.97k | { |
78 | 1.97k | int c; |
79 | 1.97k | FORC(8) |
80 | 15.7k | { |
81 | 15.7k | int v = orth[d] * patt[g][c * 2] + orth[d + 1] * patt[g][c * 2 + 1]; |
82 | 15.7k | int h = orth[d + 2] * patt[g][c * 2] + orth[d + 3] * patt[g][c * 2 + 1]; |
83 | 15.7k | minv = MIN(v, minv); |
84 | 15.7k | maxv = MAX(v, maxv); |
85 | 15.7k | minh = MIN(h, minh); |
86 | 15.7k | maxh = MAX(h, maxh); |
87 | 15.7k | allhex[row][col][0][c ^ (g * 2 & d)] = h + v * width; |
88 | 15.7k | allhex[row][col][1][c ^ (g * 2 & d)] = h + v * LIBRAW_AHD_TILE; |
89 | 15.7k | } |
90 | 1.97k | } |
91 | 7.11k | } |
92 | | |
93 | | // Check allhex table initialization |
94 | 609 | for (int i = 0; i < 3; i++) |
95 | 1.82k | for (int j = 0; j < 3; j++) |
96 | 4.08k | for (int k = 0; k < 2; k++) |
97 | 24.4k | for (int l = 0; l < 8; l++) |
98 | 21.7k | if (allhex[i][j][k][l] > maxh + maxv * width + 1 || |
99 | 21.7k | allhex[i][j][k][l] < minh + minv * width - 1) |
100 | 9 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
101 | 149 | int retrycount = 0; |
102 | | |
103 | | /* Set green1 and green3 to the minimum and maximum allowed values: */ |
104 | 409k | for (int row = 2; row < height - 2; row++) |
105 | 409k | { |
106 | 409k | int col; |
107 | 409k | ushort min, max; |
108 | 259M | for (col = 2, max = 0u, min = 0xffffu; col < int(width) - 2; col++) |
109 | 259M | { |
110 | 259M | if (fcol(row, col) == 1 && (min = ~(max = 0))) |
111 | 233M | continue; |
112 | 26.0M | ushort(*pix)[4]; |
113 | 26.0M | pix = image + row * width + col; |
114 | 26.0M | short* hex = allhex[row % 3][col % 3][0]; |
115 | 26.0M | if (!max) |
116 | 19.8M | { |
117 | 19.8M | int c; |
118 | 19.8M | FORC(6) |
119 | 118M | { |
120 | 118M | int val = pix[hex[c]][1]; |
121 | 118M | if (min > val) |
122 | 22.1M | min = val; |
123 | 118M | if (max < val) |
124 | 13.9M | max = val; |
125 | 118M | } |
126 | 19.8M | } |
127 | 26.0M | pix[0][1] = min; |
128 | 26.0M | pix[0][3] = max; |
129 | 26.0M | switch ((row - sgrow) % 3) |
130 | 26.0M | { |
131 | 6.57M | case 1: |
132 | 6.57M | if (row < height - 3) |
133 | 6.56M | { |
134 | 6.56M | row++; |
135 | 6.56M | col--; |
136 | 6.56M | } |
137 | 6.57M | break; |
138 | 6.91M | case 2: |
139 | 6.91M | if ((min = ~(max = 0)) && (col += 2) < width - 3 && row > 2) |
140 | 6.88M | { |
141 | 6.88M | row--; |
142 | 6.88M | if (retrycount++ > width * height) |
143 | 6 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
144 | 6.88M | } |
145 | 26.0M | } |
146 | 26.0M | } |
147 | 409k | } |
148 | | |
149 | 939 | for (int row = 3; row < 9 && row < height - 3; row++) |
150 | 5.61k | for (int col = 3; col < 9 && col < width - 3; col++) |
151 | 4.81k | { |
152 | 4.81k | if ((fcol(row, col)) == 1) |
153 | 2.26k | continue; |
154 | 2.55k | short* hex = allhex[row % 3][col % 3][0]; |
155 | 2.55k | int c; |
156 | 2.55k | FORC(2) |
157 | 5.11k | { |
158 | 5.11k | int idx3 = 3 * hex[4 + c] + row * width + col; |
159 | 5.11k | int idx4 = -3 * hex[4 + c] + row * width + col; |
160 | 5.11k | int maxidx = width * height; |
161 | 5.11k | if (idx3 < 0 || idx3 >= maxidx) |
162 | 2 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
163 | 5.11k | if (idx4 < 0 || idx4 >= maxidx) |
164 | 11 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
165 | 5.11k | } |
166 | 2.55k | } |
167 | | |
168 | | #if defined(LIBRAW_USE_OPENMP) |
169 | | int buffer_count = omp_get_max_threads(); |
170 | | #else |
171 | 130 | int buffer_count = 1; |
172 | 130 | #endif |
173 | | |
174 | 130 | size_t buffer_size = LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 11 + 6); |
175 | 130 | char** buffers = malloc_omp_buffers(buffer_count, buffer_size); |
176 | 130 | INT64 allocate_sz = (INT64(iheight) + 6) * (INT64(iwidth) + 6) * sizeof(ushort)*4LL; |
177 | 130 | ushort (*destimage)[4] = (ushort(*)[4])calloc(allocate_sz, 1); |
178 | | // For border interpolate: keep original pixels |
179 | 130 | memmove(destimage,image,allocate_sz); |
180 | | |
181 | | #if defined(LIBRAW_USE_OPENMP) |
182 | | # pragma omp parallel for schedule(dynamic) default(none) firstprivate(buffers, allhex, passes, sgrow, sgcol, ndir) shared(dir, destimage) |
183 | | #endif |
184 | 392 | for (int top = 3; top < height - 19; top += LIBRAW_AHD_TILE - 16) |
185 | 262 | { |
186 | | #if defined(LIBRAW_USE_OPENMP) |
187 | | char* buffer = buffers[omp_get_thread_num()]; |
188 | | #else |
189 | 262 | char* buffer = buffers[0]; |
190 | 262 | #endif |
191 | | |
192 | 262 | ushort(*rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3], (*rix)[3]; |
193 | 262 | short(*lab)[LIBRAW_AHD_TILE][3], (*lix)[3]; |
194 | 262 | float(*drv)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE]; |
195 | 262 | char(*homo)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE]; |
196 | | |
197 | 262 | rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer; |
198 | 262 | lab = (short(*)[LIBRAW_AHD_TILE][3])( |
199 | 262 | buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 6)); |
200 | 262 | drv = (float(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE])( |
201 | 262 | buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 6 + 6)); |
202 | 262 | homo = (char(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE])( |
203 | 262 | buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 10 + 6)); |
204 | | |
205 | 792 | for (int left = 3; left < width - 19; left += LIBRAW_AHD_TILE - 16) |
206 | 530 | { |
207 | 530 | int mrow = MIN(top + LIBRAW_AHD_TILE, height - 3); |
208 | 530 | int mcol = MIN(left + LIBRAW_AHD_TILE, width - 3); |
209 | 164k | for (int row = top; row < mrow; row++) |
210 | 60.3M | for (int col = left; col < mcol; col++) |
211 | 60.2M | memcpy(rgb[0][row - top][col - left], image[row * width + col], 6); |
212 | 530 | int c; |
213 | 1.59k | FORC3 memcpy(rgb[c + 1], rgb[0], sizeof * rgb); |
214 | | |
215 | | /* Interpolate green horizontally, vertically, and along both diagonals: |
216 | | */ |
217 | 530 | int color[3][8]; |
218 | 164k | for (int row = top; row < mrow; row++) |
219 | 60.3M | for (int col = left; col < mcol; col++) |
220 | 60.2M | { |
221 | 60.2M | int f; |
222 | 60.2M | if ((f = fcol(row, col)) == 1) |
223 | 28.0M | continue; |
224 | 32.1M | ushort (*pix)[4] = image + row * width + col; |
225 | 32.1M | short* hex = allhex[row % 3][col % 3][0]; |
226 | 32.1M | color[1][0] = 174 * (pix[hex[1]][1] + pix[hex[0]][1]) - |
227 | 32.1M | 46 * (pix[2 * hex[1]][1] + pix[2 * hex[0]][1]); |
228 | 32.1M | color[1][1] = 223 * pix[hex[3]][1] + pix[hex[2]][1] * 33 + |
229 | 32.1M | 92 * (pix[0][f] - pix[-hex[2]][f]); |
230 | 32.1M | FORC(2) |
231 | 64.3M | color[1][2 + c] = 164 * pix[hex[4 + c]][1] + |
232 | 64.3M | 92 * pix[-2 * hex[4 + c]][1] + |
233 | 64.3M | 33 * (2 * pix[0][f] - pix[3 * hex[4 + c]][f] - |
234 | 64.3M | pix[-3 * hex[4 + c]][f]); |
235 | 128M | FORC4 rgb[c ^ !((row - sgrow) % 3)][row - top][col - left][1] = |
236 | 128M | LIM(color[1][c] >> 8, pix[0][1], pix[0][3]); |
237 | 32.1M | } |
238 | | |
239 | 2.12k | for (int pass = 0; pass < passes; pass++) |
240 | 1.59k | { |
241 | 1.59k | if (pass == 1) |
242 | 530 | memcpy(rgb += 4, buffer, 4 * sizeof * rgb); |
243 | | |
244 | | /* Recalculate green from interpolated values of closer pixels: */ |
245 | 1.59k | if (pass) |
246 | 1.06k | { |
247 | 324k | for (int row = top + 2; row < mrow - 2; row++) |
248 | 117M | for (int col = left + 2; col < mcol - 2; col++) |
249 | 117M | { |
250 | 117M | int f; |
251 | 117M | if ((f = fcol(row, col)) == 1) |
252 | 54.6M | continue; |
253 | 62.9M | ushort(*pix)[4] = image + row * width + col; |
254 | 62.9M | short* hex = allhex[row % 3][col % 3][1]; |
255 | 251M | for (int d = 3; d < 6; d++) |
256 | 188M | { |
257 | 188M | rix = |
258 | 188M | &rgb[(d - 2) ^ !((row - sgrow) % 3)][row - top][col - left]; |
259 | 188M | int val = rix[-2 * hex[d]][1] + 2 * rix[hex[d]][1] - |
260 | 188M | rix[-2 * hex[d]][f] - 2 * rix[hex[d]][f] + 3 * rix[0][f]; |
261 | 188M | rix[0][1] = LIM(val / 3, pix[0][1], pix[0][3]); |
262 | 188M | } |
263 | 62.9M | } |
264 | 1.06k | } |
265 | | |
266 | | /* Interpolate red and blue values for solitary green pixels: */ |
267 | 163k | for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3) |
268 | 10.4M | for (int col = (left - sgcol + 4) / 3 * 3 + sgcol; col < mcol - 2; col += 3) |
269 | 10.4M | { |
270 | 10.4M | rix = &rgb[0][row - top][col - left]; |
271 | 10.4M | int h = fcol(row, col + 1); |
272 | | |
273 | 10.4M | if (h == 1) // Incorrect pattern |
274 | 76.8k | break; |
275 | | |
276 | 10.3M | float diff[6]; |
277 | 10.3M | memset(diff, 0, sizeof diff); |
278 | 72.3M | for (int i = 1, d = 0; d < 6; d++, i ^= LIBRAW_AHD_TILE ^ 1, h ^= 2) |
279 | 62.0M | { |
280 | 186M | for (c = 0; c < 2; c++, h ^= 2) |
281 | 124M | { |
282 | 124M | int g = 2 * rix[0][1] - rix[i << c][1] - rix[-i << c][1]; |
283 | 124M | color[h][d] = g + rix[i << c][h] + rix[-i << c][h]; |
284 | 124M | if (d > 1) |
285 | 82.6M | diff[d] += SQR((float)rix[i << c][1] - (float)rix[-i << c][1] - |
286 | 82.6M | (float)rix[i << c][h] + (float)rix[-i << c][h]) + SQR((float)g); |
287 | 124M | } |
288 | 62.0M | if (d > 1 && (d & 1)) |
289 | 20.6M | if (diff[d - 1] < diff[d]) |
290 | 12.0M | FORC(2) color[c * 2][d] = color[c * 2][d - 1]; |
291 | 62.0M | if (d < 2 || (d & 1)) |
292 | 41.3M | { |
293 | 82.6M | FORC(2) rix[0][c * 2] = CLIP(color[c * 2][d] / 2); |
294 | 41.3M | rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE; |
295 | 41.3M | } |
296 | 62.0M | } |
297 | 10.3M | } |
298 | | |
299 | | /* Interpolate red for blue pixels and vice versa: */ |
300 | 483k | for (int row = top + 3; row < mrow - 3; row++) |
301 | 174M | for (int col = left + 3; col < mcol - 3; col++) |
302 | 174M | { |
303 | 174M | int f; |
304 | 174M | if ((f = 2 - fcol(row, col)) == 1) |
305 | 81.0M | continue; |
306 | 93.2M | rix = &rgb[0][row - top][col - left]; |
307 | 93.2M | c = (row - sgrow) % 3 ? LIBRAW_AHD_TILE : 1; |
308 | 93.2M | int h = 3 * (c ^ LIBRAW_AHD_TILE ^ 1); |
309 | 466M | for (int d = 0; d < 4; d++, rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE) |
310 | 372M | { |
311 | 372M | int i = d > 1 || ((d ^ c) & 1) || |
312 | 93.2M | ((ABS(rix[0][1] - rix[c][1]) + |
313 | 93.2M | ABS(rix[0][1] - rix[-c][1])) < |
314 | 93.2M | 2 * (ABS(rix[0][1] - rix[h][1]) + |
315 | 93.2M | ABS(rix[0][1] - rix[-h][1]))) |
316 | 372M | ? c |
317 | 372M | : h; |
318 | 372M | rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + 2 * rix[0][1] - |
319 | 372M | rix[i][1] - rix[-i][1]) / |
320 | 372M | 2); |
321 | 372M | } |
322 | 93.2M | } |
323 | | |
324 | | /* Fill in red and blue for 2x2 blocks of green: */ |
325 | 486k | for (int row = top + 2; row < mrow - 2; row++) |
326 | 485k | if ((row - sgrow) % 3) |
327 | 117M | for (int col = left + 2; col < mcol - 2; col++) |
328 | 117M | if ((col - sgcol) % 3) |
329 | 78.3M | { |
330 | 78.3M | rix = &rgb[0][row - top][col - left]; |
331 | 78.3M | short* hex = allhex[row % 3][col % 3][1]; |
332 | 391M | for (int d = 0; d < 8; |
333 | 313M | d += 2, rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE) |
334 | 313M | if (hex[d] + hex[d + 1]) |
335 | 187M | { |
336 | 187M | int g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1]; |
337 | 561M | for (c = 0; c < 4; c += 2) |
338 | 374M | rix[0][c] = CLIP( |
339 | 187M | (g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) / 3); |
340 | 187M | } |
341 | 126M | else |
342 | 126M | { |
343 | 126M | int g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1]; |
344 | 378M | for (c = 0; c < 4; c += 2) |
345 | 252M | rix[0][c] = |
346 | 252M | CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) / 2); |
347 | 126M | } |
348 | 78.3M | } |
349 | 1.59k | } |
350 | 530 | rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer; |
351 | 530 | mrow -= top; |
352 | 530 | mcol -= left; |
353 | | |
354 | | /* Convert to CIELab and differentiate in all directions: */ |
355 | | // no effect |
356 | 4.77k | for (int d = 0; d < ndir; d++) |
357 | 4.24k | { |
358 | 1.29M | for (int row = 2; row < mrow - 2; row++) |
359 | 471M | for (int col = 2; col < mcol - 2; col++) |
360 | 470M | cielab(rgb[d][row][col], lab[row][col]); |
361 | 1.28M | for (int f = dir[d & 3], row = 3; row < mrow - 3; row++) |
362 | 465M | for (int col = 3; col < mcol - 3; col++) |
363 | 464M | { |
364 | 464M | lix = &lab[row][col]; |
365 | 464M | int g = 2 * lix[0][0] - lix[f][0] - lix[-f][0]; |
366 | 464M | drv[d][row][col] = |
367 | 464M | float( |
368 | 464M | SQR(g) + |
369 | 464M | SQR((2 * lix[0][1] - lix[f][1] - lix[-f][1] + g * 500 / 232)) + |
370 | 464M | SQR((2 * lix[0][2] - lix[f][2] - lix[-f][2] - g * 500 / 580)) |
371 | 464M | ); |
372 | 464M | } |
373 | 4.24k | } |
374 | | |
375 | | /* Build homogeneity maps from the derivatives: */ |
376 | 530 | memset(homo, 0, ndir * LIBRAW_AHD_TILE * LIBRAW_AHD_TILE); |
377 | 160k | for (int row = 4; row < mrow - 4; row++) |
378 | 57.5M | for (int col = 4; col < mcol - 4; col++) |
379 | 57.3M | { |
380 | 57.3M | int d; |
381 | 57.3M | float tr; |
382 | 516M | for (tr = FLT_MAX, d = 0; d < ndir; d++) |
383 | 459M | if (tr > drv[d][row][col]) |
384 | 93.2M | tr = drv[d][row][col]; |
385 | 57.3M | tr *= 8; |
386 | 516M | for (int dd = 0; dd < ndir; dd++) |
387 | 1.83G | for (int v = -1; v <= 1; v++) |
388 | 5.50G | for (int h = -1; h <= 1; h++) |
389 | 4.13G | if (drv[dd][row + v][col + h] <= tr) |
390 | 3.15G | homo[dd][row][col]++; |
391 | 57.3M | } |
392 | | |
393 | | /* Average the most homogeneous pixels for the final result: */ |
394 | 530 | if (height - top < LIBRAW_AHD_TILE + 4) |
395 | 263 | mrow = height - top + 2; |
396 | 530 | if (width - left < LIBRAW_AHD_TILE + 4) |
397 | 262 | mcol = width - left + 2; |
398 | 158k | for (int row = MIN(top, 8); row < mrow - 8; row++) |
399 | 56.4M | for (int col = MIN(left, 8); col < mcol - 8; col++) |
400 | 56.3M | { |
401 | 56.3M | int v; |
402 | 56.3M | int hm[8]; |
403 | 506M | for (int d = 0; d < ndir; d++) |
404 | 2.70G | for (v = -2, hm[d] = 0; v <= 2; v++) |
405 | 13.5G | for (int h = -2; h <= 2; h++) |
406 | 11.2G | hm[d] += homo[d][row + v][col + h]; |
407 | 281M | for (int d = 0; d < ndir - 4; d++) |
408 | 225M | if (hm[d] < hm[d + 4]) |
409 | 77.5M | hm[d] = 0; |
410 | 147M | else if (hm[d] > hm[d + 4]) |
411 | 19.4M | hm[d + 4] = 0; |
412 | 56.3M | ushort max; |
413 | 56.3M | int d; |
414 | 450M | for (d = 1, max = hm[0]; d < ndir; d++) |
415 | 394M | if (max < hm[d]) |
416 | 43.2M | max = hm[d]; |
417 | 56.3M | max -= max >> 3; |
418 | | |
419 | 56.3M | int avg[4]; |
420 | 56.3M | memset(avg, 0, sizeof avg); |
421 | 506M | for (int dd = 0; dd < ndir; dd++) |
422 | 450M | if (hm[dd] >= max) |
423 | 316M | { |
424 | 949M | FORC3 avg[c] += rgb[dd][row][col][c]; |
425 | 316M | avg[3]++; |
426 | 316M | } |
427 | 168M | FORC3 destimage[(row + top) * width + col + left][c] = avg[c] / avg[3]; |
428 | 56.3M | } |
429 | 530 | } |
430 | 262 | } |
431 | | |
432 | | #ifdef LIBRAW_USE_OPENMP |
433 | | #pragma omp barrier |
434 | | #endif |
435 | | |
436 | 130 | free_omp_buffers(buffers, buffer_count); |
437 | 130 | free(image); |
438 | 130 | image = destimage; |
439 | | |
440 | 130 | border_interpolate(8); |
441 | 130 | } |
442 | | #undef fcol |