/src/libraw/src/demosaic/dht_demosaic.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * File: dht_demosaic.cpp |
3 | | * Copyright 2013 Anton Petrusevich |
4 | | * Created: Tue Apr 9, 2013 |
5 | | * |
6 | | * This code is licensed under 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 |
10 | | * details). |
11 | | * |
12 | | * 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
13 | | * (See file LICENSE.CDDL provided in LibRaw distribution archive for |
14 | | * details). |
15 | | * |
16 | | */ |
17 | | |
18 | | /* |
19 | | * функция вычисляет яркостную дистанцию. |
20 | | * если две яркости отличаются в два раза, например 10 и 20, то они имеют такой |
21 | | * же вес при принятии решения об интерполировании, как и 100 и 200 -- |
22 | | * фотографическая яркость между ними 1 стоп. дистанция всегда >=1 |
23 | | */ |
24 | | |
25 | | #include "../../internal/dmp_include.h" |
26 | | |
27 | | static inline float calc_dist(float c1, float c2) |
28 | 228M | { |
29 | 228M | return c1 > c2 ? c1 / c2 : c2 / c1; |
30 | 228M | } |
31 | | |
32 | | struct DHT |
33 | | { |
34 | | int nr_height, nr_width; |
35 | | static const int nr_topmargin = 4, nr_leftmargin = 4; |
36 | | float (*nraw)[3]; |
37 | | ushort channel_maximum[3]; |
38 | | float channel_minimum[3]; |
39 | | LibRaw &libraw; |
40 | | enum |
41 | | { |
42 | | HVSH = 1, |
43 | | HOR = 2, |
44 | | VER = 4, |
45 | | HORSH = HOR | HVSH, |
46 | | VERSH = VER | HVSH, |
47 | | DIASH = 8, |
48 | | LURD = 16, |
49 | | RULD = 32, |
50 | | LURDSH = LURD | DIASH, |
51 | | RULDSH = RULD | DIASH, |
52 | | HOT = 64 |
53 | | }; |
54 | 134k | static inline float Thot(void) throw() { return 64.0f; } |
55 | 16.2M | static inline float Tg(void) throw() { return 256.0f; } |
56 | 16.2M | static inline float T(void) throw() { return 1.4f; } |
57 | | char *ndir; |
58 | | inline int nr_offset(int row, int col) throw() |
59 | 1.89G | { |
60 | 1.89G | return (row * nr_width + col); |
61 | 1.89G | } |
62 | | int get_hv_grb(int x, int y, int kc) |
63 | 8.14M | { |
64 | 8.14M | float hv1 = 2 * nraw[nr_offset(y - 1, x)][1] / |
65 | 8.14M | (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]); |
66 | 8.14M | float hv2 = 2 * nraw[nr_offset(y + 1, x)][1] / |
67 | 8.14M | (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]); |
68 | 8.14M | float kv = calc_dist(hv1, hv2) * |
69 | 8.14M | calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc], |
70 | 8.14M | (nraw[nr_offset(y - 2, x)][kc] * |
71 | 8.14M | nraw[nr_offset(y + 2, x)][kc])); |
72 | 8.14M | kv *= kv; |
73 | 8.14M | kv *= kv; |
74 | 8.14M | kv *= kv; |
75 | 8.14M | float dv = |
76 | 8.14M | kv * |
77 | 8.14M | calc_dist(nraw[nr_offset(y - 3, x)][1] * nraw[nr_offset(y + 3, x)][1], |
78 | 8.14M | nraw[nr_offset(y - 1, x)][1] * nraw[nr_offset(y + 1, x)][1]); |
79 | 8.14M | float hh1 = 2 * nraw[nr_offset(y, x - 1)][1] / |
80 | 8.14M | (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]); |
81 | 8.14M | float hh2 = 2 * nraw[nr_offset(y, x + 1)][1] / |
82 | 8.14M | (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]); |
83 | 8.14M | float kh = calc_dist(hh1, hh2) * |
84 | 8.14M | calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc], |
85 | 8.14M | (nraw[nr_offset(y, x - 2)][kc] * |
86 | 8.14M | nraw[nr_offset(y, x + 2)][kc])); |
87 | 8.14M | kh *= kh; |
88 | 8.14M | kh *= kh; |
89 | 8.14M | kh *= kh; |
90 | 8.14M | float dh = |
91 | 8.14M | kh * |
92 | 8.14M | calc_dist(nraw[nr_offset(y, x - 3)][1] * nraw[nr_offset(y, x + 3)][1], |
93 | 8.14M | nraw[nr_offset(y, x - 1)][1] * nraw[nr_offset(y, x + 1)][1]); |
94 | 8.14M | float e = calc_dist(dh, dv); |
95 | 8.14M | char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER); |
96 | 8.14M | return d; |
97 | 8.14M | } |
98 | | int get_hv_rbg(int x, int y, int hc) |
99 | 8.14M | { |
100 | 8.14M | float hv1 = 2 * nraw[nr_offset(y - 1, x)][hc ^ 2] / |
101 | 8.14M | (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y, x)][1]); |
102 | 8.14M | float hv2 = 2 * nraw[nr_offset(y + 1, x)][hc ^ 2] / |
103 | 8.14M | (nraw[nr_offset(y + 2, x)][1] + nraw[nr_offset(y, x)][1]); |
104 | 8.14M | float kv = calc_dist(hv1, hv2) * |
105 | 8.14M | calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1], |
106 | 8.14M | (nraw[nr_offset(y - 2, x)][1] * |
107 | 8.14M | nraw[nr_offset(y + 2, x)][1])); |
108 | 8.14M | kv *= kv; |
109 | 8.14M | kv *= kv; |
110 | 8.14M | kv *= kv; |
111 | 8.14M | float dv = kv * calc_dist(nraw[nr_offset(y - 3, x)][hc ^ 2] * |
112 | 8.14M | nraw[nr_offset(y + 3, x)][hc ^ 2], |
113 | 8.14M | nraw[nr_offset(y - 1, x)][hc ^ 2] * |
114 | 8.14M | nraw[nr_offset(y + 1, x)][hc ^ 2]); |
115 | 8.14M | float hh1 = 2 * nraw[nr_offset(y, x - 1)][hc] / |
116 | 8.14M | (nraw[nr_offset(y, x - 2)][1] + nraw[nr_offset(y, x)][1]); |
117 | 8.14M | float hh2 = 2 * nraw[nr_offset(y, x + 1)][hc] / |
118 | 8.14M | (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x)][1]); |
119 | 8.14M | float kh = calc_dist(hh1, hh2) * |
120 | 8.14M | calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1], |
121 | 8.14M | (nraw[nr_offset(y, x - 2)][1] * |
122 | 8.14M | nraw[nr_offset(y, x + 2)][1])); |
123 | 8.14M | kh *= kh; |
124 | 8.14M | kh *= kh; |
125 | 8.14M | kh *= kh; |
126 | 8.14M | float dh = |
127 | 8.14M | kh * calc_dist( |
128 | 8.14M | nraw[nr_offset(y, x - 3)][hc] * nraw[nr_offset(y, x + 3)][hc], |
129 | 8.14M | nraw[nr_offset(y, x - 1)][hc] * nraw[nr_offset(y, x + 1)][hc]); |
130 | 8.14M | float e = calc_dist(dh, dv); |
131 | 8.14M | char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER); |
132 | 8.14M | return d; |
133 | 8.14M | } |
134 | | int get_diag_grb(int x, int y, int kc) |
135 | 8.14M | { |
136 | 8.14M | float hlu = |
137 | 8.14M | nraw[nr_offset(y - 1, x - 1)][1] / nraw[nr_offset(y - 1, x - 1)][kc]; |
138 | 8.14M | float hrd = |
139 | 8.14M | nraw[nr_offset(y + 1, x + 1)][1] / nraw[nr_offset(y + 1, x + 1)][kc]; |
140 | 8.14M | float dlurd = |
141 | 8.14M | calc_dist(hlu, hrd) * |
142 | 8.14M | calc_dist(nraw[nr_offset(y - 1, x - 1)][1] * |
143 | 8.14M | nraw[nr_offset(y + 1, x + 1)][1], |
144 | 8.14M | nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); |
145 | 8.14M | float druld = |
146 | 8.14M | calc_dist(hlu, hrd) * |
147 | 8.14M | calc_dist(nraw[nr_offset(y - 1, x + 1)][1] * |
148 | 8.14M | nraw[nr_offset(y + 1, x - 1)][1], |
149 | 8.14M | nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); |
150 | 8.14M | float e = calc_dist(dlurd, druld); |
151 | 8.14M | char d = |
152 | 8.14M | druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD); |
153 | 8.14M | return d; |
154 | 8.14M | } |
155 | | int get_diag_rbg(int x, int y, int /* hc */) |
156 | 8.14M | { |
157 | 8.14M | float dlurd = calc_dist( |
158 | 8.14M | nraw[nr_offset(y - 1, x - 1)][1] * nraw[nr_offset(y + 1, x + 1)][1], |
159 | 8.14M | nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); |
160 | 8.14M | float druld = calc_dist( |
161 | 8.14M | nraw[nr_offset(y - 1, x + 1)][1] * nraw[nr_offset(y + 1, x - 1)][1], |
162 | 8.14M | nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]); |
163 | 8.14M | float e = calc_dist(dlurd, druld); |
164 | 8.14M | char d = |
165 | 8.14M | druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD); |
166 | 8.14M | return d; |
167 | 8.14M | } |
168 | | static inline float scale_over(float ec, float base) |
169 | 708k | { |
170 | 708k | float s = base * .4f; |
171 | 708k | float o = ec - base; |
172 | 708k | return base + sqrt(s * (o + s)) - s; |
173 | 708k | } |
174 | | static inline float scale_under(float ec, float base) |
175 | 1.79M | { |
176 | 1.79M | float s = base * .6f; |
177 | 1.79M | float o = base - ec; |
178 | 1.79M | return base - sqrt(s * (o + s)) + s; |
179 | 1.79M | } |
180 | | ~DHT(); |
181 | | DHT(LibRaw &_libraw); |
182 | | void copy_to_image(); |
183 | | void make_greens(); |
184 | | void make_diag_dirs(); |
185 | | void make_hv_dirs(); |
186 | | void refine_hv_dirs(int i, int js); |
187 | | void refine_diag_dirs(int i, int js); |
188 | | void refine_ihv_dirs(int i); |
189 | | void refine_idiag_dirs(int i); |
190 | | void illustrate_dirs(); |
191 | | void illustrate_dline(int i); |
192 | | void make_hv_dline(int i); |
193 | | void make_diag_dline(int i); |
194 | | void make_gline(int i); |
195 | | void make_rbdiag(int i); |
196 | | void make_rbhv(int i); |
197 | | void make_rb(); |
198 | | void hide_hots(); |
199 | | void restore_hots(); |
200 | | }; |
201 | | |
202 | | typedef float float3[3]; |
203 | | |
204 | | /* |
205 | | * информация о цветах копируется во float в общем то с одной целью -- чтобы |
206 | | * вместо 0 можно было писать 0.5, что больше подходит для вычисления яркостной |
207 | | * разницы. причина: в целых числах разница в 1 стоп составляет ряд 8,4,2,1,0 -- |
208 | | * последнее число должно быть 0.5, которое непредствамио в целых числах. так же |
209 | | * это изменение позволяет не думать о специальных случаях деления на ноль. |
210 | | * |
211 | | * альтернативное решение: умножить все данные на 2 и в младший бит внести 1. |
212 | | * правда, всё равно придётся следить, чтобы при интерпретации зелёного цвета не |
213 | | * получился 0 при округлении, иначе проблема при интерпретации синих и красных. |
214 | | * |
215 | | */ |
216 | 1.41k | DHT::DHT(LibRaw &_libraw) : libraw(_libraw) |
217 | 1.41k | { |
218 | 1.41k | nr_height = libraw.imgdata.sizes.iheight + nr_topmargin * 2; |
219 | 1.41k | nr_width = libraw.imgdata.sizes.iwidth + nr_leftmargin * 2; |
220 | 1.41k | nraw = (float3 *)malloc(nr_height * nr_width * sizeof(float3)); |
221 | 1.41k | int iwidth = libraw.imgdata.sizes.iwidth; |
222 | 1.41k | ndir = (char *)calloc(nr_height * nr_width, 1); |
223 | 1.41k | channel_maximum[0] = channel_maximum[1] = channel_maximum[2] = 0; |
224 | 1.41k | channel_minimum[0] = libraw.imgdata.image[0][0]; |
225 | 1.41k | channel_minimum[1] = libraw.imgdata.image[0][1]; |
226 | 1.41k | channel_minimum[2] = libraw.imgdata.image[0][2]; |
227 | 19.4M | for (int i = 0; i < nr_height * nr_width; ++i) |
228 | 19.4M | nraw[i][0] = nraw[i][1] = nraw[i][2] = 0.5; |
229 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
230 | 207k | { |
231 | 207k | int col_cache[48]; |
232 | 10.1M | for (int j = 0; j < 48; ++j) |
233 | 9.97M | { |
234 | 9.97M | int l = libraw.COLOR(i, j); |
235 | 9.97M | if (l == 3) |
236 | 0 | l = 1; |
237 | 9.97M | col_cache[j] = l; |
238 | 9.97M | } |
239 | 16.4M | for (int j = 0; j < iwidth; ++j) |
240 | 16.2M | { |
241 | 16.2M | int l = col_cache[j % 48]; |
242 | 16.2M | unsigned short c = libraw.imgdata.image[i * iwidth + j][l]; |
243 | 16.2M | if (c != 0) |
244 | 5.53M | { |
245 | 5.53M | if (channel_maximum[l] < c) |
246 | 26.9k | channel_maximum[l] = c; |
247 | 5.53M | if (channel_minimum[l] > c) |
248 | 16.1k | channel_minimum[l] = c; |
249 | 5.53M | nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] = (float)c; |
250 | 5.53M | } |
251 | 16.2M | } |
252 | 207k | } |
253 | 1.41k | channel_minimum[0] += .5; |
254 | 1.41k | channel_minimum[1] += .5; |
255 | 1.41k | channel_minimum[2] += .5; |
256 | 1.41k | } |
257 | | |
258 | | void DHT::hide_hots() |
259 | 1.41k | { |
260 | 1.41k | int iwidth = libraw.imgdata.sizes.iwidth; |
261 | | #if defined(LIBRAW_USE_OPENMP) |
262 | | #pragma omp parallel for schedule(guided) firstprivate(iwidth) |
263 | | #endif |
264 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
265 | 207k | { |
266 | 207k | int js = libraw.COLOR(i, 0) & 1; |
267 | 207k | int kc = libraw.COLOR(i, js); |
268 | | /* |
269 | | * js -- начальная х-координата, которая попадает мимо известного зелёного |
270 | | * kc -- известный цвет в точке интерполирования |
271 | | */ |
272 | 8.35M | for (int j = js; j < iwidth; j += 2) |
273 | 8.14M | { |
274 | 8.14M | int x = j + nr_leftmargin; |
275 | 8.14M | int y = i + nr_topmargin; |
276 | 8.14M | float c = nraw[nr_offset(y, x)][kc]; |
277 | 8.14M | if ((c > nraw[nr_offset(y, x + 2)][kc] && |
278 | 801k | c > nraw[nr_offset(y, x - 2)][kc] && |
279 | 256k | c > nraw[nr_offset(y - 2, x)][kc] && |
280 | 136k | c > nraw[nr_offset(y + 2, x)][kc] && |
281 | 111k | c > nraw[nr_offset(y, x + 1)][1] && |
282 | 80.6k | c > nraw[nr_offset(y, x - 1)][1] && |
283 | 67.3k | c > nraw[nr_offset(y - 1, x)][1] && |
284 | 58.8k | c > nraw[nr_offset(y + 1, x)][1]) || |
285 | 8.08M | (c < nraw[nr_offset(y, x + 2)][kc] && |
286 | 763k | c < nraw[nr_offset(y, x - 2)][kc] && |
287 | 195k | c < nraw[nr_offset(y - 2, x)][kc] && |
288 | 76.0k | c < nraw[nr_offset(y + 2, x)][kc] && |
289 | 54.2k | c < nraw[nr_offset(y, x + 1)][1] && |
290 | 39.5k | c < nraw[nr_offset(y, x - 1)][1] && |
291 | 36.4k | c < nraw[nr_offset(y - 1, x)][1] && |
292 | 30.8k | c < nraw[nr_offset(y + 1, x)][1])) |
293 | 85.5k | { |
294 | 85.5k | float avg = 0; |
295 | 342k | for (int k = -2; k < 3; k += 2) |
296 | 1.02M | for (int m = -2; m < 3; m += 2) |
297 | 770k | if (m == 0 && k == 0) |
298 | 85.5k | continue; |
299 | 684k | else |
300 | 684k | avg += nraw[nr_offset(y + k, x + m)][kc]; |
301 | 85.5k | avg /= 8; |
302 | | // float dev = 0; |
303 | | // for (int k = -2; k < 3; k += 2) |
304 | | // for (int l = -2; l < 3; l += 2) |
305 | | // if (k == 0 && l == 0) |
306 | | // continue; |
307 | | // else { |
308 | | // float t = nraw[nr_offset(y + k, x + l)][kc] - |
309 | | //avg; dev += t * t; |
310 | | // } |
311 | | // dev /= 8; |
312 | | // dev = sqrt(dev); |
313 | 85.5k | if (calc_dist(c, avg) > Thot()) |
314 | 23.0k | { |
315 | 23.0k | ndir[nr_offset(y, x)] |= HOT; |
316 | 23.0k | float dv = calc_dist( |
317 | 23.0k | nraw[nr_offset(y - 2, x)][kc] * nraw[nr_offset(y - 1, x)][1], |
318 | 23.0k | nraw[nr_offset(y + 2, x)][kc] * nraw[nr_offset(y + 1, x)][1]); |
319 | 23.0k | float dh = calc_dist( |
320 | 23.0k | nraw[nr_offset(y, x - 2)][kc] * nraw[nr_offset(y, x - 1)][1], |
321 | 23.0k | nraw[nr_offset(y, x + 2)][kc] * nraw[nr_offset(y, x + 1)][1]); |
322 | 23.0k | if (dv > dh) |
323 | 4.88k | nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y, x + 2)][kc] + |
324 | 4.88k | nraw[nr_offset(y, x - 2)][kc]) / |
325 | 4.88k | 2; |
326 | 18.1k | else |
327 | 18.1k | nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y - 2, x)][kc] + |
328 | 18.1k | nraw[nr_offset(y + 2, x)][kc]) / |
329 | 18.1k | 2; |
330 | 23.0k | } |
331 | 85.5k | } |
332 | 8.14M | } |
333 | 8.34M | for (int j = js ^ 1; j < iwidth; j += 2) |
334 | 8.14M | { |
335 | 8.14M | int x = j + nr_leftmargin; |
336 | 8.14M | int y = i + nr_topmargin; |
337 | 8.14M | float c = nraw[nr_offset(y, x)][1]; |
338 | 8.14M | if ((c > nraw[nr_offset(y, x + 2)][1] && |
339 | 820k | c > nraw[nr_offset(y, x - 2)][1] && |
340 | 246k | c > nraw[nr_offset(y - 2, x)][1] && |
341 | 128k | c > nraw[nr_offset(y + 2, x)][1] && |
342 | 91.5k | c > nraw[nr_offset(y, x + 1)][kc] && |
343 | 49.5k | c > nraw[nr_offset(y, x - 1)][kc] && |
344 | 40.5k | c > nraw[nr_offset(y - 1, x)][kc ^ 2] && |
345 | 32.6k | c > nraw[nr_offset(y + 1, x)][kc ^ 2]) || |
346 | 8.11M | (c < nraw[nr_offset(y, x + 2)][1] && |
347 | 623k | c < nraw[nr_offset(y, x - 2)][1] && |
348 | 179k | c < nraw[nr_offset(y - 2, x)][1] && |
349 | 81.2k | c < nraw[nr_offset(y + 2, x)][1] && |
350 | 47.8k | c < nraw[nr_offset(y, x + 1)][kc] && |
351 | 28.4k | c < nraw[nr_offset(y, x - 1)][kc] && |
352 | 23.9k | c < nraw[nr_offset(y - 1, x)][kc ^ 2] && |
353 | 21.0k | c < nraw[nr_offset(y + 1, x)][kc ^ 2])) |
354 | 48.6k | { |
355 | 48.6k | float avg = 0; |
356 | 194k | for (int k = -2; k < 3; k += 2) |
357 | 584k | for (int m = -2; m < 3; m += 2) |
358 | 438k | if (k == 0 && m == 0) |
359 | 48.6k | continue; |
360 | 389k | else |
361 | 389k | avg += nraw[nr_offset(y + k, x + m)][1]; |
362 | 48.6k | avg /= 8; |
363 | | // float dev = 0; |
364 | | // for (int k = -2; k < 3; k += 2) |
365 | | // for (int l = -2; l < 3; l += 2) |
366 | | // if (k == 0 && l == 0) |
367 | | // continue; |
368 | | // else { |
369 | | // float t = nraw[nr_offset(y + k, x + l)][1] - |
370 | | //avg; dev += t * t; |
371 | | // } |
372 | | // dev /= 8; |
373 | | // dev = sqrt(dev); |
374 | 48.6k | if (calc_dist(c, avg) > Thot()) |
375 | 7.59k | { |
376 | 7.59k | ndir[nr_offset(y, x)] |= HOT; |
377 | 7.59k | float dv = calc_dist( |
378 | 7.59k | nraw[nr_offset(y - 2, x)][1] * nraw[nr_offset(y - 1, x)][kc ^ 2], |
379 | 7.59k | nraw[nr_offset(y + 2, x)][1] * nraw[nr_offset(y + 1, x)][kc ^ 2]); |
380 | 7.59k | float dh = calc_dist( |
381 | 7.59k | nraw[nr_offset(y, x - 2)][1] * nraw[nr_offset(y, x - 1)][kc], |
382 | 7.59k | nraw[nr_offset(y, x + 2)][1] * nraw[nr_offset(y, x + 1)][kc]); |
383 | 7.59k | if (dv > dh) |
384 | 2.05k | nraw[nr_offset(y, x)][1] = |
385 | 2.05k | (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x - 2)][1]) / |
386 | 2.05k | 2; |
387 | 5.53k | else |
388 | 5.53k | nraw[nr_offset(y, x)][1] = |
389 | 5.53k | (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y + 2, x)][1]) / |
390 | 5.53k | 2; |
391 | 7.59k | } |
392 | 48.6k | } |
393 | 8.14M | } |
394 | 207k | } |
395 | 1.41k | } |
396 | | |
397 | | void DHT::restore_hots() |
398 | 1.41k | { |
399 | 1.41k | int iwidth = libraw.imgdata.sizes.iwidth; |
400 | | #if defined(LIBRAW_USE_OPENMP) |
401 | | #ifdef _MSC_VER |
402 | | #pragma omp parallel for firstprivate(iwidth) |
403 | | #else |
404 | | #pragma omp parallel for schedule(guided) firstprivate(iwidth) collapse(2) |
405 | | #endif |
406 | | #endif |
407 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
408 | 207k | { |
409 | 16.4M | for (int j = 0; j < iwidth; ++j) |
410 | 16.2M | { |
411 | 16.2M | int x = j + nr_leftmargin; |
412 | 16.2M | int y = i + nr_topmargin; |
413 | 16.2M | if (ndir[nr_offset(y, x)] & HOT) |
414 | 30.6k | { |
415 | 30.6k | int l = libraw.COLOR(i, j); |
416 | 30.6k | nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] = |
417 | 30.6k | libraw.imgdata.image[i * iwidth + j][l]; |
418 | 30.6k | } |
419 | 16.2M | } |
420 | 207k | } |
421 | 1.41k | } |
422 | | |
423 | | void DHT::make_diag_dirs() |
424 | 1.41k | { |
425 | | #if defined(LIBRAW_USE_OPENMP) |
426 | | #pragma omp parallel for schedule(guided) |
427 | | #endif |
428 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
429 | 207k | { |
430 | 207k | make_diag_dline(i); |
431 | 207k | } |
432 | | //#if defined(LIBRAW_USE_OPENMP) |
433 | | //#pragma omp parallel for schedule(guided) |
434 | | //#endif |
435 | | // for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { |
436 | | // refine_diag_dirs(i, i & 1); |
437 | | // } |
438 | | //#if defined(LIBRAW_USE_OPENMP) |
439 | | //#pragma omp parallel for schedule(guided) |
440 | | //#endif |
441 | | // for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) { |
442 | | // refine_diag_dirs(i, (i & 1) ^ 1); |
443 | | // } |
444 | | #if defined(LIBRAW_USE_OPENMP) |
445 | | #pragma omp parallel for schedule(guided) |
446 | | #endif |
447 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
448 | 207k | { |
449 | 207k | refine_idiag_dirs(i); |
450 | 207k | } |
451 | 1.41k | } |
452 | | |
453 | | void DHT::make_hv_dirs() |
454 | 1.41k | { |
455 | | #if defined(LIBRAW_USE_OPENMP) |
456 | | #pragma omp parallel for schedule(guided) |
457 | | #endif |
458 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
459 | 207k | { |
460 | 207k | make_hv_dline(i); |
461 | 207k | } |
462 | | #if defined(LIBRAW_USE_OPENMP) |
463 | | #pragma omp parallel for schedule(guided) |
464 | | #endif |
465 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
466 | 207k | { |
467 | 207k | refine_hv_dirs(i, i & 1); |
468 | 207k | } |
469 | | #if defined(LIBRAW_USE_OPENMP) |
470 | | #pragma omp parallel for schedule(guided) |
471 | | #endif |
472 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
473 | 207k | { |
474 | 207k | refine_hv_dirs(i, (i & 1) ^ 1); |
475 | 207k | } |
476 | | #if defined(LIBRAW_USE_OPENMP) |
477 | | #pragma omp parallel for schedule(guided) |
478 | | #endif |
479 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
480 | 207k | { |
481 | 207k | refine_ihv_dirs(i); |
482 | 207k | } |
483 | 1.41k | } |
484 | | |
485 | | void DHT::refine_hv_dirs(int i, int js) |
486 | 415k | { |
487 | 415k | int iwidth = libraw.imgdata.sizes.iwidth; |
488 | 16.7M | for (int j = js; j < iwidth; j += 2) |
489 | 16.2M | { |
490 | 16.2M | int x = j + nr_leftmargin; |
491 | 16.2M | int y = i + nr_topmargin; |
492 | 16.2M | if (ndir[nr_offset(y, x)] & HVSH) |
493 | 4.59M | continue; |
494 | 11.6M | int nv = |
495 | 11.6M | (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) + |
496 | 11.6M | (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER); |
497 | 11.6M | int nh = |
498 | 11.6M | (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) + |
499 | 11.6M | (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR); |
500 | 11.6M | bool codir = (ndir[nr_offset(y, x)] & VER) |
501 | 11.6M | ? ((ndir[nr_offset(y - 1, x)] & VER) || |
502 | 583k | (ndir[nr_offset(y + 1, x)] & VER)) |
503 | 11.6M | : ((ndir[nr_offset(y, x - 1)] & HOR) || |
504 | 379k | (ndir[nr_offset(y, x + 1)] & HOR)); |
505 | 11.6M | nv /= VER; |
506 | 11.6M | nh /= HOR; |
507 | 11.6M | if ((ndir[nr_offset(y, x)] & VER) && (nh > 2 && !codir)) |
508 | 96.6k | { |
509 | 96.6k | ndir[nr_offset(y, x)] &= ~VER; |
510 | 96.6k | ndir[nr_offset(y, x)] |= HOR; |
511 | 96.6k | } |
512 | 11.6M | if ((ndir[nr_offset(y, x)] & HOR) && (nv > 2 && !codir)) |
513 | 185k | { |
514 | 185k | ndir[nr_offset(y, x)] &= ~HOR; |
515 | 185k | ndir[nr_offset(y, x)] |= VER; |
516 | 185k | } |
517 | 11.6M | } |
518 | 415k | } |
519 | | |
520 | | void DHT::refine_ihv_dirs(int i) |
521 | 207k | { |
522 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
523 | 16.4M | for (int j = 0; j < iwidth; j++) |
524 | 16.2M | { |
525 | 16.2M | int x = j + nr_leftmargin; |
526 | 16.2M | int y = i + nr_topmargin; |
527 | 16.2M | if (ndir[nr_offset(y, x)] & HVSH) |
528 | 4.59M | continue; |
529 | 11.6M | int nv = |
530 | 11.6M | (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) + |
531 | 11.6M | (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER); |
532 | 11.6M | int nh = |
533 | 11.6M | (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) + |
534 | 11.6M | (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR); |
535 | 11.6M | nv /= VER; |
536 | 11.6M | nh /= HOR; |
537 | 11.6M | if ((ndir[nr_offset(y, x)] & VER) && nh > 3) |
538 | 822 | { |
539 | 822 | ndir[nr_offset(y, x)] &= ~VER; |
540 | 822 | ndir[nr_offset(y, x)] |= HOR; |
541 | 822 | } |
542 | 11.6M | if ((ndir[nr_offset(y, x)] & HOR) && nv > 3) |
543 | 4.36k | { |
544 | 4.36k | ndir[nr_offset(y, x)] &= ~HOR; |
545 | 4.36k | ndir[nr_offset(y, x)] |= VER; |
546 | 4.36k | } |
547 | 11.6M | } |
548 | 207k | } |
549 | | void DHT::make_hv_dline(int i) |
550 | 207k | { |
551 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
552 | 207k | int js = libraw.COLOR(i, 0) & 1; |
553 | 207k | int kc = libraw.COLOR(i, js); |
554 | | /* |
555 | | * js -- начальная х-координата, которая попадает мимо известного зелёного |
556 | | * kc -- известный цвет в точке интерполирования |
557 | | */ |
558 | 16.4M | for (int j = 0; j < iwidth; j++) |
559 | 16.2M | { |
560 | 16.2M | int x = j + nr_leftmargin; |
561 | 16.2M | int y = i + nr_topmargin; |
562 | 16.2M | char d = 0; |
563 | 16.2M | if ((j & 1) == js) |
564 | 8.14M | { |
565 | 8.14M | d = get_hv_grb(x, y, kc); |
566 | 8.14M | } |
567 | 8.14M | else |
568 | 8.14M | { |
569 | 8.14M | d = get_hv_rbg(x, y, kc); |
570 | 8.14M | } |
571 | 16.2M | ndir[nr_offset(y, x)] |= d; |
572 | 16.2M | } |
573 | 207k | } |
574 | | |
575 | | void DHT::make_diag_dline(int i) |
576 | 207k | { |
577 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
578 | 207k | int js = libraw.COLOR(i, 0) & 1; |
579 | 207k | int kc = libraw.COLOR(i, js); |
580 | | /* |
581 | | * js -- начальная х-координата, которая попадает мимо известного зелёного |
582 | | * kc -- известный цвет в точке интерполирования |
583 | | */ |
584 | 16.4M | for (int j = 0; j < iwidth; j++) |
585 | 16.2M | { |
586 | 16.2M | int x = j + nr_leftmargin; |
587 | 16.2M | int y = i + nr_topmargin; |
588 | 16.2M | char d = 0; |
589 | 16.2M | if ((j & 1) == js) |
590 | 8.14M | { |
591 | 8.14M | d = get_diag_grb(x, y, kc); |
592 | 8.14M | } |
593 | 8.14M | else |
594 | 8.14M | { |
595 | 8.14M | d = get_diag_rbg(x, y, kc); |
596 | 8.14M | } |
597 | 16.2M | ndir[nr_offset(y, x)] |= d; |
598 | 16.2M | } |
599 | 207k | } |
600 | | |
601 | | void DHT::refine_diag_dirs(int i, int js) |
602 | 0 | { |
603 | 0 | int iwidth = libraw.imgdata.sizes.iwidth; |
604 | 0 | for (int j = js; j < iwidth; j += 2) |
605 | 0 | { |
606 | 0 | int x = j + nr_leftmargin; |
607 | 0 | int y = i + nr_topmargin; |
608 | 0 | if (ndir[nr_offset(y, x)] & DIASH) |
609 | 0 | continue; |
610 | 0 | int nv = (ndir[nr_offset(y - 1, x)] & LURD) + |
611 | 0 | (ndir[nr_offset(y + 1, x)] & LURD) + |
612 | 0 | (ndir[nr_offset(y, x - 1)] & LURD) + |
613 | 0 | (ndir[nr_offset(y, x + 1)] & LURD) + |
614 | 0 | (ndir[nr_offset(y - 1, x - 1)] & LURD) + |
615 | 0 | (ndir[nr_offset(y - 1, x + 1)] & LURD) + |
616 | 0 | (ndir[nr_offset(y + 1, x - 1)] & LURD) + |
617 | 0 | (ndir[nr_offset(y + 1, x + 1)] & LURD); |
618 | 0 | int nh = (ndir[nr_offset(y - 1, x)] & RULD) + |
619 | 0 | (ndir[nr_offset(y + 1, x)] & RULD) + |
620 | 0 | (ndir[nr_offset(y, x - 1)] & RULD) + |
621 | 0 | (ndir[nr_offset(y, x + 1)] & RULD) + |
622 | 0 | (ndir[nr_offset(y - 1, x - 1)] & RULD) + |
623 | 0 | (ndir[nr_offset(y - 1, x + 1)] & RULD) + |
624 | 0 | (ndir[nr_offset(y + 1, x - 1)] & RULD) + |
625 | 0 | (ndir[nr_offset(y + 1, x + 1)] & RULD); |
626 | 0 | bool codir = (ndir[nr_offset(y, x)] & LURD) |
627 | 0 | ? ((ndir[nr_offset(y - 1, x - 1)] & LURD) || |
628 | 0 | (ndir[nr_offset(y + 1, x + 1)] & LURD)) |
629 | 0 | : ((ndir[nr_offset(y - 1, x + 1)] & RULD) || |
630 | 0 | (ndir[nr_offset(y + 1, x - 1)] & RULD)); |
631 | 0 | nv /= LURD; |
632 | 0 | nh /= RULD; |
633 | 0 | if ((ndir[nr_offset(y, x)] & LURD) && (nh > 4 && !codir)) |
634 | 0 | { |
635 | 0 | ndir[nr_offset(y, x)] &= ~LURD; |
636 | 0 | ndir[nr_offset(y, x)] |= RULD; |
637 | 0 | } |
638 | 0 | if ((ndir[nr_offset(y, x)] & RULD) && (nv > 4 && !codir)) |
639 | 0 | { |
640 | 0 | ndir[nr_offset(y, x)] &= ~RULD; |
641 | 0 | ndir[nr_offset(y, x)] |= LURD; |
642 | 0 | } |
643 | 0 | } |
644 | 0 | } |
645 | | |
646 | | void DHT::refine_idiag_dirs(int i) |
647 | 207k | { |
648 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
649 | 16.4M | for (int j = 0; j < iwidth; j++) |
650 | 16.2M | { |
651 | 16.2M | int x = j + nr_leftmargin; |
652 | 16.2M | int y = i + nr_topmargin; |
653 | 16.2M | if (ndir[nr_offset(y, x)] & DIASH) |
654 | 970k | continue; |
655 | 15.3M | int nv = (ndir[nr_offset(y - 1, x)] & LURD) + |
656 | 15.3M | (ndir[nr_offset(y + 1, x)] & LURD) + |
657 | 15.3M | (ndir[nr_offset(y, x - 1)] & LURD) + |
658 | 15.3M | (ndir[nr_offset(y, x + 1)] & LURD) + |
659 | 15.3M | (ndir[nr_offset(y - 1, x - 1)] & LURD) + |
660 | 15.3M | (ndir[nr_offset(y - 1, x + 1)] & LURD) + |
661 | 15.3M | (ndir[nr_offset(y + 1, x - 1)] & LURD) + |
662 | 15.3M | (ndir[nr_offset(y + 1, x + 1)] & LURD); |
663 | 15.3M | int nh = (ndir[nr_offset(y - 1, x)] & RULD) + |
664 | 15.3M | (ndir[nr_offset(y + 1, x)] & RULD) + |
665 | 15.3M | (ndir[nr_offset(y, x - 1)] & RULD) + |
666 | 15.3M | (ndir[nr_offset(y, x + 1)] & RULD) + |
667 | 15.3M | (ndir[nr_offset(y - 1, x - 1)] & RULD) + |
668 | 15.3M | (ndir[nr_offset(y - 1, x + 1)] & RULD) + |
669 | 15.3M | (ndir[nr_offset(y + 1, x - 1)] & RULD) + |
670 | 15.3M | (ndir[nr_offset(y + 1, x + 1)] & RULD); |
671 | 15.3M | nv /= LURD; |
672 | 15.3M | nh /= RULD; |
673 | 15.3M | if ((ndir[nr_offset(y, x)] & LURD) && nh > 7) |
674 | 7.25k | { |
675 | 7.25k | ndir[nr_offset(y, x)] &= ~LURD; |
676 | 7.25k | ndir[nr_offset(y, x)] |= RULD; |
677 | 7.25k | } |
678 | 15.3M | if ((ndir[nr_offset(y, x)] & RULD) && nv > 7) |
679 | 75.9k | { |
680 | 75.9k | ndir[nr_offset(y, x)] &= ~RULD; |
681 | 75.9k | ndir[nr_offset(y, x)] |= LURD; |
682 | 75.9k | } |
683 | 15.3M | } |
684 | 207k | } |
685 | | |
686 | | /* |
687 | | * вычисление недостающих зелёных точек. |
688 | | */ |
689 | | void DHT::make_greens() |
690 | 1.41k | { |
691 | | #if defined(LIBRAW_USE_OPENMP) |
692 | | #pragma omp parallel for schedule(guided) |
693 | | #endif |
694 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
695 | 207k | { |
696 | 207k | make_gline(i); |
697 | 207k | } |
698 | 1.41k | } |
699 | | |
700 | | void DHT::make_gline(int i) |
701 | 207k | { |
702 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
703 | 207k | int js = libraw.COLOR(i, 0) & 1; |
704 | 207k | int kc = libraw.COLOR(i, js); |
705 | | /* |
706 | | * js -- начальная х-координата, которая попадает мимо известного зелёного |
707 | | * kc -- известный цвет в точке интерполирования |
708 | | */ |
709 | 8.35M | for (int j = js; j < iwidth; j += 2) |
710 | 8.14M | { |
711 | 8.14M | int x = j + nr_leftmargin; |
712 | 8.14M | int y = i + nr_topmargin; |
713 | 8.14M | int dx, dy, dx2, dy2; |
714 | 8.14M | float h1, h2; |
715 | 8.14M | if (ndir[nr_offset(y, x)] & VER) |
716 | 5.77M | { |
717 | 5.77M | dx = dx2 = 0; |
718 | 5.77M | dy = -1; |
719 | 5.77M | dy2 = 1; |
720 | 5.77M | h1 = 2 * nraw[nr_offset(y - 1, x)][1] / |
721 | 5.77M | (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]); |
722 | 5.77M | h2 = 2 * nraw[nr_offset(y + 1, x)][1] / |
723 | 5.77M | (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]); |
724 | 5.77M | } |
725 | 2.37M | else |
726 | 2.37M | { |
727 | 2.37M | dy = dy2 = 0; |
728 | 2.37M | dx = 1; |
729 | 2.37M | dx2 = -1; |
730 | 2.37M | h1 = 2 * nraw[nr_offset(y, x + 1)][1] / |
731 | 2.37M | (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]); |
732 | 2.37M | h2 = 2 * nraw[nr_offset(y, x - 1)][1] / |
733 | 2.37M | (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]); |
734 | 2.37M | } |
735 | 8.14M | float b1 = 1 / calc_dist(nraw[nr_offset(y, x)][kc], |
736 | 8.14M | nraw[nr_offset(y + dy * 2, x + dx * 2)][kc]); |
737 | 8.14M | float b2 = 1 / calc_dist(nraw[nr_offset(y, x)][kc], |
738 | 8.14M | nraw[nr_offset(y + dy2 * 2, x + dx2 * 2)][kc]); |
739 | 8.14M | b1 *= b1; |
740 | 8.14M | b2 *= b2; |
741 | 8.14M | float eg = nraw[nr_offset(y, x)][kc] * (b1 * h1 + b2 * h2) / (b1 + b2); |
742 | 8.14M | float min, max; |
743 | 8.14M | min = MIN(nraw[nr_offset(y + dy, x + dx)][1], |
744 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]); |
745 | 8.14M | max = MAX(nraw[nr_offset(y + dy, x + dx)][1], |
746 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]); |
747 | 8.14M | min /= 1.2f; |
748 | 8.14M | max *= 1.2f; |
749 | 8.14M | if (eg < min) |
750 | 54.7k | eg = scale_under(eg, min); |
751 | 8.08M | else if (eg > max) |
752 | 63.3k | eg = scale_over(eg, max); |
753 | 8.14M | if (eg > channel_maximum[1]) |
754 | 2.09M | eg = channel_maximum[1]; |
755 | 6.04M | else if (eg < channel_minimum[1]) |
756 | 797k | eg = channel_minimum[1]; |
757 | 8.14M | nraw[nr_offset(y, x)][1] = eg; |
758 | 8.14M | } |
759 | 207k | } |
760 | | |
761 | | /* |
762 | | * отладочная функция |
763 | | */ |
764 | | |
765 | | void DHT::illustrate_dirs() |
766 | 0 | { |
767 | | #if defined(LIBRAW_USE_OPENMP) |
768 | | #pragma omp parallel for schedule(guided) |
769 | | #endif |
770 | 0 | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
771 | 0 | { |
772 | 0 | illustrate_dline(i); |
773 | 0 | } |
774 | 0 | } |
775 | | |
776 | | void DHT::illustrate_dline(int i) |
777 | 0 | { |
778 | 0 | int iwidth = libraw.imgdata.sizes.iwidth; |
779 | 0 | for (int j = 0; j < iwidth; j++) |
780 | 0 | { |
781 | 0 | int x = j + nr_leftmargin; |
782 | 0 | int y = i + nr_topmargin; |
783 | 0 | nraw[nr_offset(y, x)][0] = nraw[nr_offset(y, x)][1] = |
784 | 0 | nraw[nr_offset(y, x)][2] = 0.5; |
785 | 0 | int l = ndir[nr_offset(y, x)] & 8; |
786 | | // l >>= 3; // WTF? |
787 | 0 | l = 1; |
788 | 0 | if (ndir[nr_offset(y, x)] & HOT) |
789 | 0 | nraw[nr_offset(y, x)][0] = |
790 | 0 | l * channel_maximum[0] / 4.f + channel_maximum[0] / 4.f; |
791 | 0 | else |
792 | 0 | nraw[nr_offset(y, x)][2] = |
793 | 0 | l * channel_maximum[2] / 4.f + channel_maximum[2] / 4.f; |
794 | 0 | } |
795 | 0 | } |
796 | | |
797 | | /* |
798 | | * интерполяция красных и синих. |
799 | | * |
800 | | * сначала интерполируются недостающие цвета, по диагональным направлениям от |
801 | | * которых находятся известные, затем ситуация сводится к тому как |
802 | | * интерполировались зелёные. |
803 | | */ |
804 | | |
805 | | void DHT::make_rbdiag(int i) |
806 | 207k | { |
807 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
808 | 207k | int js = libraw.COLOR(i, 0) & 1; |
809 | 207k | int uc = libraw.COLOR(i, js); |
810 | 207k | int cl = uc ^ 2; |
811 | | /* |
812 | | * js -- начальная х-координата, которая попадает на уже интерполированный |
813 | | * зелёный al -- известный цвет (кроме зелёного) в точке интерполирования cl |
814 | | * -- неизвестный цвет |
815 | | */ |
816 | 8.35M | for (int j = js; j < iwidth; j += 2) |
817 | 8.14M | { |
818 | 8.14M | int x = j + nr_leftmargin; |
819 | 8.14M | int y = i + nr_topmargin; |
820 | 8.14M | int dx, dy, dx2, dy2; |
821 | 8.14M | if (ndir[nr_offset(y, x)] & LURD) |
822 | 7.16M | { |
823 | 7.16M | dx = -1; |
824 | 7.16M | dx2 = 1; |
825 | 7.16M | dy = -1; |
826 | 7.16M | dy2 = 1; |
827 | 7.16M | } |
828 | 981k | else |
829 | 981k | { |
830 | 981k | dx = -1; |
831 | 981k | dx2 = 1; |
832 | 981k | dy = 1; |
833 | 981k | dy2 = -1; |
834 | 981k | } |
835 | 8.14M | float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1], |
836 | 8.14M | nraw[nr_offset(y + dy, x + dx)][1]); |
837 | 8.14M | float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1], |
838 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]); |
839 | 8.14M | g1 *= g1 * g1; |
840 | 8.14M | g2 *= g2 * g2; |
841 | | |
842 | 8.14M | float eg; |
843 | 8.14M | eg = nraw[nr_offset(y, x)][1] * |
844 | 8.14M | (g1 * nraw[nr_offset(y + dy, x + dx)][cl] / |
845 | 8.14M | nraw[nr_offset(y + dy, x + dx)][1] + |
846 | 8.14M | g2 * nraw[nr_offset(y + dy2, x + dx2)][cl] / |
847 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]) / |
848 | 8.14M | (g1 + g2); |
849 | 8.14M | float min, max; |
850 | 8.14M | min = MIN(nraw[nr_offset(y + dy, x + dx)][cl], |
851 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][cl]); |
852 | 8.14M | max = MAX(nraw[nr_offset(y + dy, x + dx)][cl], |
853 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][cl]); |
854 | 8.14M | min /= 1.2f; |
855 | 8.14M | max *= 1.2f; |
856 | 8.14M | if (eg < min) |
857 | 248k | eg = scale_under(eg, min); |
858 | 7.89M | else if (eg > max) |
859 | 429k | eg = scale_over(eg, max); |
860 | 8.14M | if (eg > channel_maximum[cl]) |
861 | 1.58M | eg = channel_maximum[cl]; |
862 | 6.56M | else if (eg < channel_minimum[cl]) |
863 | 1.29M | eg = channel_minimum[cl]; |
864 | 8.14M | nraw[nr_offset(y, x)][cl] = eg; |
865 | 8.14M | } |
866 | 207k | } |
867 | | |
868 | | /* |
869 | | * интерполяция красных и синих в точках где был известен только зелёный, |
870 | | * направления горизонтальные или вертикальные |
871 | | */ |
872 | | |
873 | | void DHT::make_rbhv(int i) |
874 | 207k | { |
875 | 207k | int iwidth = libraw.imgdata.sizes.iwidth; |
876 | 207k | int js = (libraw.COLOR(i, 0) & 1) ^ 1; |
877 | 8.34M | for (int j = js; j < iwidth; j += 2) |
878 | 8.14M | { |
879 | 8.14M | int x = j + nr_leftmargin; |
880 | 8.14M | int y = i + nr_topmargin; |
881 | | /* |
882 | | * поскольку сверху-снизу и справа-слева уже есть все необходимые красные и |
883 | | * синие, то можно выбрать наилучшее направление исходя из информации по |
884 | | * обоим цветам. |
885 | | */ |
886 | 8.14M | int dx, dy, dx2, dy2; |
887 | 8.14M | if (ndir[nr_offset(y, x)] & VER) |
888 | 5.72M | { |
889 | 5.72M | dx = dx2 = 0; |
890 | 5.72M | dy = -1; |
891 | 5.72M | dy2 = 1; |
892 | 5.72M | } |
893 | 2.41M | else |
894 | 2.41M | { |
895 | 2.41M | dy = dy2 = 0; |
896 | 2.41M | dx = 1; |
897 | 2.41M | dx2 = -1; |
898 | 2.41M | } |
899 | 8.14M | float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1], |
900 | 8.14M | nraw[nr_offset(y + dy, x + dx)][1]); |
901 | 8.14M | float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1], |
902 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]); |
903 | 8.14M | g1 *= g1; |
904 | 8.14M | g2 *= g2; |
905 | 8.14M | float eg_r, eg_b; |
906 | 8.14M | eg_r = nraw[nr_offset(y, x)][1] * |
907 | 8.14M | (g1 * nraw[nr_offset(y + dy, x + dx)][0] / |
908 | 8.14M | nraw[nr_offset(y + dy, x + dx)][1] + |
909 | 8.14M | g2 * nraw[nr_offset(y + dy2, x + dx2)][0] / |
910 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]) / |
911 | 8.14M | (g1 + g2); |
912 | 8.14M | eg_b = nraw[nr_offset(y, x)][1] * |
913 | 8.14M | (g1 * nraw[nr_offset(y + dy, x + dx)][2] / |
914 | 8.14M | nraw[nr_offset(y + dy, x + dx)][1] + |
915 | 8.14M | g2 * nraw[nr_offset(y + dy2, x + dx2)][2] / |
916 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][1]) / |
917 | 8.14M | (g1 + g2); |
918 | 8.14M | float min_r, max_r; |
919 | 8.14M | min_r = MIN(nraw[nr_offset(y + dy, x + dx)][0], |
920 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][0]); |
921 | 8.14M | max_r = MAX(nraw[nr_offset(y + dy, x + dx)][0], |
922 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][0]); |
923 | 8.14M | float min_b, max_b; |
924 | 8.14M | min_b = MIN(nraw[nr_offset(y + dy, x + dx)][2], |
925 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][2]); |
926 | 8.14M | max_b = MAX(nraw[nr_offset(y + dy, x + dx)][2], |
927 | 8.14M | nraw[nr_offset(y + dy2, x + dx2)][2]); |
928 | 8.14M | min_r /= 1.2f; |
929 | 8.14M | max_r *= 1.2f; |
930 | 8.14M | min_b /= 1.2f; |
931 | 8.14M | max_b *= 1.2f; |
932 | | |
933 | 8.14M | if (eg_r < min_r) |
934 | 786k | eg_r = scale_under(eg_r, min_r); |
935 | 7.35M | else if (eg_r > max_r) |
936 | 113k | eg_r = scale_over(eg_r, max_r); |
937 | 8.14M | if (eg_b < min_b) |
938 | 700k | eg_b = scale_under(eg_b, min_b); |
939 | 7.44M | else if (eg_b > max_b) |
940 | 102k | eg_b = scale_over(eg_b, max_b); |
941 | | |
942 | 8.14M | if (eg_r > channel_maximum[0]) |
943 | 661k | eg_r = channel_maximum[0]; |
944 | 7.47M | else if (eg_r < channel_minimum[0]) |
945 | 1.89M | eg_r = channel_minimum[0]; |
946 | 8.14M | if (eg_b > channel_maximum[2]) |
947 | 1.22M | eg_b = channel_maximum[2]; |
948 | 6.91M | else if (eg_b < channel_minimum[2]) |
949 | 1.63M | eg_b = channel_minimum[2]; |
950 | 8.14M | nraw[nr_offset(y, x)][0] = eg_r; |
951 | 8.14M | nraw[nr_offset(y, x)][2] = eg_b; |
952 | 8.14M | } |
953 | 207k | } |
954 | | |
955 | | void DHT::make_rb() |
956 | 1.41k | { |
957 | | #if defined(LIBRAW_USE_OPENMP) |
958 | | #pragma omp barrier |
959 | | #pragma omp parallel for schedule(guided) |
960 | | #endif |
961 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
962 | 207k | { |
963 | 207k | make_rbdiag(i); |
964 | 207k | } |
965 | | #if defined(LIBRAW_USE_OPENMP) |
966 | | #pragma omp barrier |
967 | | #pragma omp parallel for schedule(guided) |
968 | | #endif |
969 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
970 | 207k | { |
971 | 207k | make_rbhv(i); |
972 | 207k | } |
973 | 1.41k | } |
974 | | |
975 | | /* |
976 | | * перенос изображения в выходной массив |
977 | | */ |
978 | | void DHT::copy_to_image() |
979 | 1.41k | { |
980 | 1.41k | int iwidth = libraw.imgdata.sizes.iwidth; |
981 | | #if defined(LIBRAW_USE_OPENMP) |
982 | | #ifdef _MSC_VER |
983 | | #pragma omp parallel for |
984 | | #else |
985 | | #pragma omp parallel for schedule(guided) collapse(2) |
986 | | #endif |
987 | | #endif |
988 | 209k | for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i) |
989 | 207k | { |
990 | 16.4M | for (int j = 0; j < iwidth; ++j) |
991 | 16.2M | { |
992 | 16.2M | libraw.imgdata.image[i * iwidth + j][0] = |
993 | 16.2M | (unsigned short)(nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)] |
994 | 16.2M | [0]); |
995 | 16.2M | libraw.imgdata.image[i * iwidth + j][2] = |
996 | 16.2M | (unsigned short)(nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)] |
997 | 16.2M | [2]); |
998 | 16.2M | libraw.imgdata.image[i * iwidth + j][1] = |
999 | 16.2M | libraw.imgdata.image[i * iwidth + j][3] = |
1000 | 16.2M | (unsigned short)(nraw[nr_offset(i + nr_topmargin, |
1001 | 16.2M | j + nr_leftmargin)][1]); |
1002 | 16.2M | } |
1003 | 207k | } |
1004 | 1.41k | } |
1005 | | |
1006 | | DHT::~DHT() |
1007 | 1.41k | { |
1008 | 1.41k | free(nraw); |
1009 | 1.41k | free(ndir); |
1010 | 1.41k | } |
1011 | | |
1012 | | void LibRaw::dht_interpolate() |
1013 | 1.46k | { |
1014 | 1.46k | if (imgdata.idata.filters != 0x16161616 |
1015 | 1.45k | && imgdata.idata.filters != 0x61616161 |
1016 | 1.43k | && imgdata.idata.filters != 0x49494949 |
1017 | 1.22k | && imgdata.idata.filters != 0x94949494 |
1018 | 1.46k | ) |
1019 | 47 | { |
1020 | 47 | ahd_interpolate(); |
1021 | 47 | return; |
1022 | 47 | } |
1023 | 1.41k | DHT dht(*this); |
1024 | 1.41k | dht.hide_hots(); |
1025 | 1.41k | dht.make_hv_dirs(); |
1026 | | // dht.illustrate_dirs(); |
1027 | 1.41k | dht.make_greens(); |
1028 | 1.41k | dht.make_diag_dirs(); |
1029 | | // dht.illustrate_dirs(); |
1030 | 1.41k | dht.make_rb(); |
1031 | 1.41k | dht.restore_hots(); |
1032 | 1.41k | dht.copy_to_image(); |
1033 | 1.41k | } |