Coverage Report

Created: 2025-12-20 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}