Coverage Report

Created: 2026-06-14 06:57

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
0
{
29
0
  return c1 > c2 ? c1 / c2 : c2 / c1;
30
0
}
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
0
  static inline float Thot(void) throw() { return 64.0f; }
55
0
  static inline float Tg(void) throw() { return 256.0f; }
56
0
  static inline float T(void) throw() { return 1.4f; }
57
  char *ndir;
58
  inline int nr_offset(int row, int col) throw()
59
0
  {
60
0
    return (row * nr_width + col);
61
0
  }
62
  int get_hv_grb(int x, int y, int kc)
63
0
  {
64
0
    float hv1 = 2 * nraw[nr_offset(y - 1, x)][1] /
65
0
                (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
66
0
    float hv2 = 2 * nraw[nr_offset(y + 1, x)][1] /
67
0
                (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
68
0
    float kv = calc_dist(hv1, hv2) *
69
0
               calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc],
70
0
                         (nraw[nr_offset(y - 2, x)][kc] *
71
0
                          nraw[nr_offset(y + 2, x)][kc]));
72
0
    kv *= kv;
73
0
    kv *= kv;
74
0
    kv *= kv;
75
0
    float dv =
76
0
        kv *
77
0
        calc_dist(nraw[nr_offset(y - 3, x)][1] * nraw[nr_offset(y + 3, x)][1],
78
0
                  nraw[nr_offset(y - 1, x)][1] * nraw[nr_offset(y + 1, x)][1]);
79
0
    float hh1 = 2 * nraw[nr_offset(y, x - 1)][1] /
80
0
                (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]);
81
0
    float hh2 = 2 * nraw[nr_offset(y, x + 1)][1] /
82
0
                (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]);
83
0
    float kh = calc_dist(hh1, hh2) *
84
0
               calc_dist(nraw[nr_offset(y, x)][kc] * nraw[nr_offset(y, x)][kc],
85
0
                         (nraw[nr_offset(y, x - 2)][kc] *
86
0
                          nraw[nr_offset(y, x + 2)][kc]));
87
0
    kh *= kh;
88
0
    kh *= kh;
89
0
    kh *= kh;
90
0
    float dh =
91
0
        kh *
92
0
        calc_dist(nraw[nr_offset(y, x - 3)][1] * nraw[nr_offset(y, x + 3)][1],
93
0
                  nraw[nr_offset(y, x - 1)][1] * nraw[nr_offset(y, x + 1)][1]);
94
0
    float e = calc_dist(dh, dv);
95
0
    char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER);
96
0
    return d;
97
0
  }
98
  int get_hv_rbg(int x, int y, int hc)
99
0
  {
100
0
    float hv1 = 2 * nraw[nr_offset(y - 1, x)][hc ^ 2] /
101
0
                (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y, x)][1]);
102
0
    float hv2 = 2 * nraw[nr_offset(y + 1, x)][hc ^ 2] /
103
0
                (nraw[nr_offset(y + 2, x)][1] + nraw[nr_offset(y, x)][1]);
104
0
    float kv = calc_dist(hv1, hv2) *
105
0
               calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1],
106
0
                         (nraw[nr_offset(y - 2, x)][1] *
107
0
                          nraw[nr_offset(y + 2, x)][1]));
108
0
    kv *= kv;
109
0
    kv *= kv;
110
0
    kv *= kv;
111
0
    float dv = kv * calc_dist(nraw[nr_offset(y - 3, x)][hc ^ 2] *
112
0
                                  nraw[nr_offset(y + 3, x)][hc ^ 2],
113
0
                              nraw[nr_offset(y - 1, x)][hc ^ 2] *
114
0
                                  nraw[nr_offset(y + 1, x)][hc ^ 2]);
115
0
    float hh1 = 2 * nraw[nr_offset(y, x - 1)][hc] /
116
0
                (nraw[nr_offset(y, x - 2)][1] + nraw[nr_offset(y, x)][1]);
117
0
    float hh2 = 2 * nraw[nr_offset(y, x + 1)][hc] /
118
0
                (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x)][1]);
119
0
    float kh = calc_dist(hh1, hh2) *
120
0
               calc_dist(nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1],
121
0
                         (nraw[nr_offset(y, x - 2)][1] *
122
0
                          nraw[nr_offset(y, x + 2)][1]));
123
0
    kh *= kh;
124
0
    kh *= kh;
125
0
    kh *= kh;
126
0
    float dh =
127
0
        kh * calc_dist(
128
0
                 nraw[nr_offset(y, x - 3)][hc] * nraw[nr_offset(y, x + 3)][hc],
129
0
                 nraw[nr_offset(y, x - 1)][hc] * nraw[nr_offset(y, x + 1)][hc]);
130
0
    float e = calc_dist(dh, dv);
131
0
    char d = dh < dv ? (e > Tg() ? HORSH : HOR) : (e > Tg() ? VERSH : VER);
132
0
    return d;
133
0
  }
134
  int get_diag_grb(int x, int y, int kc)
135
0
  {
136
0
    float hlu =
137
0
        nraw[nr_offset(y - 1, x - 1)][1] / nraw[nr_offset(y - 1, x - 1)][kc];
138
0
    float hrd =
139
0
        nraw[nr_offset(y + 1, x + 1)][1] / nraw[nr_offset(y + 1, x + 1)][kc];
140
0
    float dlurd =
141
0
        calc_dist(hlu, hrd) *
142
0
        calc_dist(nraw[nr_offset(y - 1, x - 1)][1] *
143
0
                      nraw[nr_offset(y + 1, x + 1)][1],
144
0
                  nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
145
0
    float druld =
146
0
        calc_dist(hlu, hrd) *
147
0
        calc_dist(nraw[nr_offset(y - 1, x + 1)][1] *
148
0
                      nraw[nr_offset(y + 1, x - 1)][1],
149
0
                  nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
150
0
    float e = calc_dist(dlurd, druld);
151
0
    char d =
152
0
        druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD);
153
0
    return d;
154
0
  }
155
  int get_diag_rbg(int x, int y, int /* hc */)
156
0
  {
157
0
    float dlurd = calc_dist(
158
0
        nraw[nr_offset(y - 1, x - 1)][1] * nraw[nr_offset(y + 1, x + 1)][1],
159
0
        nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
160
0
    float druld = calc_dist(
161
0
        nraw[nr_offset(y - 1, x + 1)][1] * nraw[nr_offset(y + 1, x - 1)][1],
162
0
        nraw[nr_offset(y, x)][1] * nraw[nr_offset(y, x)][1]);
163
0
    float e = calc_dist(dlurd, druld);
164
0
    char d =
165
0
        druld < dlurd ? (e > T() ? RULDSH : RULD) : (e > T() ? LURDSH : LURD);
166
0
    return d;
167
0
  }
168
  static inline float scale_over(float ec, float base)
169
0
  {
170
0
    float s = base * .4f;
171
0
    float o = ec - base;
172
0
    return base + sqrt(s * (o + s)) - s;
173
0
  }
174
  static inline float scale_under(float ec, float base)
175
0
  {
176
0
    float s = base * .6f;
177
0
    float o = base - ec;
178
0
    return base - sqrt(s * (o + s)) + s;
179
0
  }
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
0
DHT::DHT(LibRaw &_libraw) : libraw(_libraw)
217
0
{
218
0
  nr_height = libraw.imgdata.sizes.iheight + nr_topmargin * 2;
219
0
  nr_width = libraw.imgdata.sizes.iwidth + nr_leftmargin * 2;
220
0
  nraw = (float3 *)malloc(nr_height * nr_width * sizeof(float3));
221
0
  int iwidth = libraw.imgdata.sizes.iwidth;
222
0
  ndir = (char *)calloc(nr_height * nr_width, 1);
223
0
  channel_maximum[0] = channel_maximum[1] = channel_maximum[2] = 0;
224
0
  channel_minimum[0] = libraw.imgdata.image[0][0];
225
0
  channel_minimum[1] = libraw.imgdata.image[0][1];
226
0
  channel_minimum[2] = libraw.imgdata.image[0][2];
227
0
  for (int i = 0; i < nr_height * nr_width; ++i)
228
0
    nraw[i][0] = nraw[i][1] = nraw[i][2] = 0.5;
229
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
230
0
  {
231
0
    int col_cache[48];
232
0
    for (int j = 0; j < 48; ++j)
233
0
    {
234
0
      int l = libraw.COLOR(i, j);
235
0
      if (l == 3)
236
0
        l = 1;
237
0
      col_cache[j] = l;
238
0
    }
239
0
    for (int j = 0; j < iwidth; ++j)
240
0
    {
241
0
      int l = col_cache[j % 48];
242
0
      unsigned short c = libraw.imgdata.image[i * iwidth + j][l];
243
0
      if (c != 0)
244
0
      {
245
0
        if (channel_maximum[l] < c)
246
0
          channel_maximum[l] = c;
247
0
        if (channel_minimum[l] > c)
248
0
          channel_minimum[l] = c;
249
0
        nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] = (float)c;
250
0
      }
251
0
    }
252
0
  }
253
0
  channel_minimum[0] += .5;
254
0
  channel_minimum[1] += .5;
255
0
  channel_minimum[2] += .5;
256
0
}
257
258
void DHT::hide_hots()
259
0
{
260
0
  int iwidth = libraw.imgdata.sizes.iwidth;
261
#if defined(LIBRAW_USE_OPENMP)
262
#pragma omp parallel for schedule(guided) firstprivate(iwidth)
263
#endif
264
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
265
0
  {
266
0
    int js = libraw.COLOR(i, 0) & 1;
267
0
    int kc = libraw.COLOR(i, js);
268
    /*
269
     * js -- начальная х-координата, которая попадает мимо известного зелёного
270
     * kc -- известный цвет в точке интерполирования
271
     */
272
0
    for (int j = js; j < iwidth; j += 2)
273
0
    {
274
0
      int x = j + nr_leftmargin;
275
0
      int y = i + nr_topmargin;
276
0
      float c = nraw[nr_offset(y, x)][kc];
277
0
      if ((c > nraw[nr_offset(y, x + 2)][kc] &&
278
0
           c > nraw[nr_offset(y, x - 2)][kc] &&
279
0
           c > nraw[nr_offset(y - 2, x)][kc] &&
280
0
           c > nraw[nr_offset(y + 2, x)][kc] &&
281
0
           c > nraw[nr_offset(y, x + 1)][1] &&
282
0
           c > nraw[nr_offset(y, x - 1)][1] &&
283
0
           c > nraw[nr_offset(y - 1, x)][1] &&
284
0
           c > nraw[nr_offset(y + 1, x)][1]) ||
285
0
          (c < nraw[nr_offset(y, x + 2)][kc] &&
286
0
           c < nraw[nr_offset(y, x - 2)][kc] &&
287
0
           c < nraw[nr_offset(y - 2, x)][kc] &&
288
0
           c < nraw[nr_offset(y + 2, x)][kc] &&
289
0
           c < nraw[nr_offset(y, x + 1)][1] &&
290
0
           c < nraw[nr_offset(y, x - 1)][1] &&
291
0
           c < nraw[nr_offset(y - 1, x)][1] &&
292
0
           c < nraw[nr_offset(y + 1, x)][1]))
293
0
      {
294
0
        float avg = 0;
295
0
        for (int k = -2; k < 3; k += 2)
296
0
          for (int m = -2; m < 3; m += 2)
297
0
            if (m == 0 && k == 0)
298
0
              continue;
299
0
            else
300
0
              avg += nraw[nr_offset(y + k, x + m)][kc];
301
0
        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
0
        if (calc_dist(c, avg) > Thot())
314
0
        {
315
0
          ndir[nr_offset(y, x)] |= HOT;
316
0
          float dv = calc_dist(
317
0
              nraw[nr_offset(y - 2, x)][kc] * nraw[nr_offset(y - 1, x)][1],
318
0
              nraw[nr_offset(y + 2, x)][kc] * nraw[nr_offset(y + 1, x)][1]);
319
0
          float dh = calc_dist(
320
0
              nraw[nr_offset(y, x - 2)][kc] * nraw[nr_offset(y, x - 1)][1],
321
0
              nraw[nr_offset(y, x + 2)][kc] * nraw[nr_offset(y, x + 1)][1]);
322
0
          if (dv > dh)
323
0
            nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y, x + 2)][kc] +
324
0
                                         nraw[nr_offset(y, x - 2)][kc]) /
325
0
                                        2;
326
0
          else
327
0
            nraw[nr_offset(y, x)][kc] = (nraw[nr_offset(y - 2, x)][kc] +
328
0
                                         nraw[nr_offset(y + 2, x)][kc]) /
329
0
                                        2;
330
0
        }
331
0
      }
332
0
    }
333
0
    for (int j = js ^ 1; j < iwidth; j += 2)
334
0
    {
335
0
      int x = j + nr_leftmargin;
336
0
      int y = i + nr_topmargin;
337
0
      float c = nraw[nr_offset(y, x)][1];
338
0
      if ((c > nraw[nr_offset(y, x + 2)][1] &&
339
0
           c > nraw[nr_offset(y, x - 2)][1] &&
340
0
           c > nraw[nr_offset(y - 2, x)][1] &&
341
0
           c > nraw[nr_offset(y + 2, x)][1] &&
342
0
           c > nraw[nr_offset(y, x + 1)][kc] &&
343
0
           c > nraw[nr_offset(y, x - 1)][kc] &&
344
0
           c > nraw[nr_offset(y - 1, x)][kc ^ 2] &&
345
0
           c > nraw[nr_offset(y + 1, x)][kc ^ 2]) ||
346
0
          (c < nraw[nr_offset(y, x + 2)][1] &&
347
0
           c < nraw[nr_offset(y, x - 2)][1] &&
348
0
           c < nraw[nr_offset(y - 2, x)][1] &&
349
0
           c < nraw[nr_offset(y + 2, x)][1] &&
350
0
           c < nraw[nr_offset(y, x + 1)][kc] &&
351
0
           c < nraw[nr_offset(y, x - 1)][kc] &&
352
0
           c < nraw[nr_offset(y - 1, x)][kc ^ 2] &&
353
0
           c < nraw[nr_offset(y + 1, x)][kc ^ 2]))
354
0
      {
355
0
        float avg = 0;
356
0
        for (int k = -2; k < 3; k += 2)
357
0
          for (int m = -2; m < 3; m += 2)
358
0
            if (k == 0 && m == 0)
359
0
              continue;
360
0
            else
361
0
              avg += nraw[nr_offset(y + k, x + m)][1];
362
0
        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
0
        if (calc_dist(c, avg) > Thot())
375
0
        {
376
0
          ndir[nr_offset(y, x)] |= HOT;
377
0
          float dv = calc_dist(
378
0
              nraw[nr_offset(y - 2, x)][1] * nraw[nr_offset(y - 1, x)][kc ^ 2],
379
0
              nraw[nr_offset(y + 2, x)][1] * nraw[nr_offset(y + 1, x)][kc ^ 2]);
380
0
          float dh = calc_dist(
381
0
              nraw[nr_offset(y, x - 2)][1] * nraw[nr_offset(y, x - 1)][kc],
382
0
              nraw[nr_offset(y, x + 2)][1] * nraw[nr_offset(y, x + 1)][kc]);
383
0
          if (dv > dh)
384
0
            nraw[nr_offset(y, x)][1] =
385
0
                (nraw[nr_offset(y, x + 2)][1] + nraw[nr_offset(y, x - 2)][1]) /
386
0
                2;
387
0
          else
388
0
            nraw[nr_offset(y, x)][1] =
389
0
                (nraw[nr_offset(y - 2, x)][1] + nraw[nr_offset(y + 2, x)][1]) /
390
0
                2;
391
0
        }
392
0
      }
393
0
    }
394
0
  }
395
0
}
396
397
void DHT::restore_hots()
398
0
{
399
0
  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
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
408
0
  {
409
0
    for (int j = 0; j < iwidth; ++j)
410
0
    {
411
0
      int x = j + nr_leftmargin;
412
0
      int y = i + nr_topmargin;
413
0
      if (ndir[nr_offset(y, x)] & HOT)
414
0
      {
415
0
        int l = libraw.COLOR(i, j);
416
0
        nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)][l] =
417
0
            libraw.imgdata.image[i * iwidth + j][l];
418
0
      }
419
0
    }
420
0
  }
421
0
}
422
423
void DHT::make_diag_dirs()
424
0
{
425
#if defined(LIBRAW_USE_OPENMP)
426
#pragma omp parallel for schedule(guided)
427
#endif
428
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
429
0
  {
430
0
    make_diag_dline(i);
431
0
  }
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
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
448
0
  {
449
0
    refine_idiag_dirs(i);
450
0
  }
451
0
}
452
453
void DHT::make_hv_dirs()
454
0
{
455
#if defined(LIBRAW_USE_OPENMP)
456
#pragma omp parallel for schedule(guided)
457
#endif
458
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
459
0
  {
460
0
    make_hv_dline(i);
461
0
  }
462
#if defined(LIBRAW_USE_OPENMP)
463
#pragma omp parallel for schedule(guided)
464
#endif
465
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
466
0
  {
467
0
    refine_hv_dirs(i, i & 1);
468
0
  }
469
#if defined(LIBRAW_USE_OPENMP)
470
#pragma omp parallel for schedule(guided)
471
#endif
472
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
473
0
  {
474
0
    refine_hv_dirs(i, (i & 1) ^ 1);
475
0
  }
476
#if defined(LIBRAW_USE_OPENMP)
477
#pragma omp parallel for schedule(guided)
478
#endif
479
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
480
0
  {
481
0
    refine_ihv_dirs(i);
482
0
  }
483
0
}
484
485
void DHT::refine_hv_dirs(int i, int js)
486
0
{
487
0
  int iwidth = libraw.imgdata.sizes.iwidth;
488
0
  for (int j = js; j < iwidth; j += 2)
489
0
  {
490
0
    int x = j + nr_leftmargin;
491
0
    int y = i + nr_topmargin;
492
0
    if (ndir[nr_offset(y, x)] & HVSH)
493
0
      continue;
494
0
    int nv =
495
0
        (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) +
496
0
        (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER);
497
0
    int nh =
498
0
        (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) +
499
0
        (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR);
500
0
    bool codir = (ndir[nr_offset(y, x)] & VER)
501
0
                     ? ((ndir[nr_offset(y - 1, x)] & VER) ||
502
0
                        (ndir[nr_offset(y + 1, x)] & VER))
503
0
                     : ((ndir[nr_offset(y, x - 1)] & HOR) ||
504
0
                        (ndir[nr_offset(y, x + 1)] & HOR));
505
0
    nv /= VER;
506
0
    nh /= HOR;
507
0
    if ((ndir[nr_offset(y, x)] & VER) && (nh > 2 && !codir))
508
0
    {
509
0
      ndir[nr_offset(y, x)] &= ~VER;
510
0
      ndir[nr_offset(y, x)] |= HOR;
511
0
    }
512
0
    if ((ndir[nr_offset(y, x)] & HOR) && (nv > 2 && !codir))
513
0
    {
514
0
      ndir[nr_offset(y, x)] &= ~HOR;
515
0
      ndir[nr_offset(y, x)] |= VER;
516
0
    }
517
0
  }
518
0
}
519
520
void DHT::refine_ihv_dirs(int i)
521
0
{
522
0
  int iwidth = libraw.imgdata.sizes.iwidth;
523
0
  for (int j = 0; j < iwidth; j++)
524
0
  {
525
0
    int x = j + nr_leftmargin;
526
0
    int y = i + nr_topmargin;
527
0
    if (ndir[nr_offset(y, x)] & HVSH)
528
0
      continue;
529
0
    int nv =
530
0
        (ndir[nr_offset(y - 1, x)] & VER) + (ndir[nr_offset(y + 1, x)] & VER) +
531
0
        (ndir[nr_offset(y, x - 1)] & VER) + (ndir[nr_offset(y, x + 1)] & VER);
532
0
    int nh =
533
0
        (ndir[nr_offset(y - 1, x)] & HOR) + (ndir[nr_offset(y + 1, x)] & HOR) +
534
0
        (ndir[nr_offset(y, x - 1)] & HOR) + (ndir[nr_offset(y, x + 1)] & HOR);
535
0
    nv /= VER;
536
0
    nh /= HOR;
537
0
    if ((ndir[nr_offset(y, x)] & VER) && nh > 3)
538
0
    {
539
0
      ndir[nr_offset(y, x)] &= ~VER;
540
0
      ndir[nr_offset(y, x)] |= HOR;
541
0
    }
542
0
    if ((ndir[nr_offset(y, x)] & HOR) && nv > 3)
543
0
    {
544
0
      ndir[nr_offset(y, x)] &= ~HOR;
545
0
      ndir[nr_offset(y, x)] |= VER;
546
0
    }
547
0
  }
548
0
}
549
void DHT::make_hv_dline(int i)
550
0
{
551
0
  int iwidth = libraw.imgdata.sizes.iwidth;
552
0
  int js = libraw.COLOR(i, 0) & 1;
553
0
  int kc = libraw.COLOR(i, js);
554
  /*
555
   * js -- начальная х-координата, которая попадает мимо известного зелёного
556
   * kc -- известный цвет в точке интерполирования
557
   */
558
0
  for (int j = 0; j < iwidth; j++)
559
0
  {
560
0
    int x = j + nr_leftmargin;
561
0
    int y = i + nr_topmargin;
562
0
    char d = 0;
563
0
    if ((j & 1) == js)
564
0
    {
565
0
      d = get_hv_grb(x, y, kc);
566
0
    }
567
0
    else
568
0
    {
569
0
      d = get_hv_rbg(x, y, kc);
570
0
    }
571
0
    ndir[nr_offset(y, x)] |= d;
572
0
  }
573
0
}
574
575
void DHT::make_diag_dline(int i)
576
0
{
577
0
  int iwidth = libraw.imgdata.sizes.iwidth;
578
0
  int js = libraw.COLOR(i, 0) & 1;
579
0
  int kc = libraw.COLOR(i, js);
580
  /*
581
   * js -- начальная х-координата, которая попадает мимо известного зелёного
582
   * kc -- известный цвет в точке интерполирования
583
   */
584
0
  for (int j = 0; j < iwidth; j++)
585
0
  {
586
0
    int x = j + nr_leftmargin;
587
0
    int y = i + nr_topmargin;
588
0
    char d = 0;
589
0
    if ((j & 1) == js)
590
0
    {
591
0
      d = get_diag_grb(x, y, kc);
592
0
    }
593
0
    else
594
0
    {
595
0
      d = get_diag_rbg(x, y, kc);
596
0
    }
597
0
    ndir[nr_offset(y, x)] |= d;
598
0
  }
599
0
}
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
0
{
648
0
  int iwidth = libraw.imgdata.sizes.iwidth;
649
0
  for (int j = 0; j < iwidth; j++)
650
0
  {
651
0
    int x = j + nr_leftmargin;
652
0
    int y = i + nr_topmargin;
653
0
    if (ndir[nr_offset(y, x)] & DIASH)
654
0
      continue;
655
0
    int nv = (ndir[nr_offset(y - 1, x)] & LURD) +
656
0
             (ndir[nr_offset(y + 1, x)] & LURD) +
657
0
             (ndir[nr_offset(y, x - 1)] & LURD) +
658
0
             (ndir[nr_offset(y, x + 1)] & LURD) +
659
0
             (ndir[nr_offset(y - 1, x - 1)] & LURD) +
660
0
             (ndir[nr_offset(y - 1, x + 1)] & LURD) +
661
0
             (ndir[nr_offset(y + 1, x - 1)] & LURD) +
662
0
             (ndir[nr_offset(y + 1, x + 1)] & LURD);
663
0
    int nh = (ndir[nr_offset(y - 1, x)] & RULD) +
664
0
             (ndir[nr_offset(y + 1, x)] & RULD) +
665
0
             (ndir[nr_offset(y, x - 1)] & RULD) +
666
0
             (ndir[nr_offset(y, x + 1)] & RULD) +
667
0
             (ndir[nr_offset(y - 1, x - 1)] & RULD) +
668
0
             (ndir[nr_offset(y - 1, x + 1)] & RULD) +
669
0
             (ndir[nr_offset(y + 1, x - 1)] & RULD) +
670
0
             (ndir[nr_offset(y + 1, x + 1)] & RULD);
671
0
    nv /= LURD;
672
0
    nh /= RULD;
673
0
    if ((ndir[nr_offset(y, x)] & LURD) && nh > 7)
674
0
    {
675
0
      ndir[nr_offset(y, x)] &= ~LURD;
676
0
      ndir[nr_offset(y, x)] |= RULD;
677
0
    }
678
0
    if ((ndir[nr_offset(y, x)] & RULD) && nv > 7)
679
0
    {
680
0
      ndir[nr_offset(y, x)] &= ~RULD;
681
0
      ndir[nr_offset(y, x)] |= LURD;
682
0
    }
683
0
  }
684
0
}
685
686
/*
687
 * вычисление недостающих зелёных точек.
688
 */
689
void DHT::make_greens()
690
0
{
691
#if defined(LIBRAW_USE_OPENMP)
692
#pragma omp parallel for schedule(guided)
693
#endif
694
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
695
0
  {
696
0
    make_gline(i);
697
0
  }
698
0
}
699
700
void DHT::make_gline(int i)
701
0
{
702
0
  int iwidth = libraw.imgdata.sizes.iwidth;
703
0
  int js = libraw.COLOR(i, 0) & 1;
704
0
  int kc = libraw.COLOR(i, js);
705
  /*
706
   * js -- начальная х-координата, которая попадает мимо известного зелёного
707
   * kc -- известный цвет в точке интерполирования
708
   */
709
0
  for (int j = js; j < iwidth; j += 2)
710
0
  {
711
0
    int x = j + nr_leftmargin;
712
0
    int y = i + nr_topmargin;
713
0
    int dx, dy, dx2, dy2;
714
0
    float h1, h2;
715
0
    if (ndir[nr_offset(y, x)] & VER)
716
0
    {
717
0
      dx = dx2 = 0;
718
0
      dy = -1;
719
0
      dy2 = 1;
720
0
      h1 = 2 * nraw[nr_offset(y - 1, x)][1] /
721
0
           (nraw[nr_offset(y - 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
722
0
      h2 = 2 * nraw[nr_offset(y + 1, x)][1] /
723
0
           (nraw[nr_offset(y + 2, x)][kc] + nraw[nr_offset(y, x)][kc]);
724
0
    }
725
0
    else
726
0
    {
727
0
      dy = dy2 = 0;
728
0
      dx = 1;
729
0
      dx2 = -1;
730
0
      h1 = 2 * nraw[nr_offset(y, x + 1)][1] /
731
0
           (nraw[nr_offset(y, x + 2)][kc] + nraw[nr_offset(y, x)][kc]);
732
0
      h2 = 2 * nraw[nr_offset(y, x - 1)][1] /
733
0
           (nraw[nr_offset(y, x - 2)][kc] + nraw[nr_offset(y, x)][kc]);
734
0
    }
735
0
    float b1 = 1 / calc_dist(nraw[nr_offset(y, x)][kc],
736
0
                             nraw[nr_offset(y + dy * 2, x + dx * 2)][kc]);
737
0
    float b2 = 1 / calc_dist(nraw[nr_offset(y, x)][kc],
738
0
                             nraw[nr_offset(y + dy2 * 2, x + dx2 * 2)][kc]);
739
0
    b1 *= b1;
740
0
    b2 *= b2;
741
0
    float eg = nraw[nr_offset(y, x)][kc] * (b1 * h1 + b2 * h2) / (b1 + b2);
742
0
    float min, max;
743
0
    min = MIN(nraw[nr_offset(y + dy, x + dx)][1],
744
0
              nraw[nr_offset(y + dy2, x + dx2)][1]);
745
0
    max = MAX(nraw[nr_offset(y + dy, x + dx)][1],
746
0
              nraw[nr_offset(y + dy2, x + dx2)][1]);
747
0
    min /= 1.2f;
748
0
    max *= 1.2f;
749
0
    if (eg < min)
750
0
      eg = scale_under(eg, min);
751
0
    else if (eg > max)
752
0
      eg = scale_over(eg, max);
753
0
    if (eg > channel_maximum[1])
754
0
      eg = channel_maximum[1];
755
0
    else if (eg < channel_minimum[1])
756
0
      eg = channel_minimum[1];
757
0
    nraw[nr_offset(y, x)][1] = eg;
758
0
  }
759
0
}
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
0
{
807
0
  int iwidth = libraw.imgdata.sizes.iwidth;
808
0
  int js = libraw.COLOR(i, 0) & 1;
809
0
  int uc = libraw.COLOR(i, js);
810
0
  int cl = uc ^ 2;
811
  /*
812
   * js -- начальная х-координата, которая попадает на уже интерполированный
813
   * зелёный al -- известный цвет (кроме зелёного) в точке интерполирования cl
814
   * -- неизвестный цвет
815
   */
816
0
  for (int j = js; j < iwidth; j += 2)
817
0
  {
818
0
    int x = j + nr_leftmargin;
819
0
    int y = i + nr_topmargin;
820
0
    int dx, dy, dx2, dy2;
821
0
    if (ndir[nr_offset(y, x)] & LURD)
822
0
    {
823
0
      dx = -1;
824
0
      dx2 = 1;
825
0
      dy = -1;
826
0
      dy2 = 1;
827
0
    }
828
0
    else
829
0
    {
830
0
      dx = -1;
831
0
      dx2 = 1;
832
0
      dy = 1;
833
0
      dy2 = -1;
834
0
    }
835
0
    float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
836
0
                             nraw[nr_offset(y + dy, x + dx)][1]);
837
0
    float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
838
0
                             nraw[nr_offset(y + dy2, x + dx2)][1]);
839
0
    g1 *= g1 * g1;
840
0
    g2 *= g2 * g2;
841
842
0
    float eg;
843
0
    eg = nraw[nr_offset(y, x)][1] *
844
0
         (g1 * nraw[nr_offset(y + dy, x + dx)][cl] /
845
0
              nraw[nr_offset(y + dy, x + dx)][1] +
846
0
          g2 * nraw[nr_offset(y + dy2, x + dx2)][cl] /
847
0
              nraw[nr_offset(y + dy2, x + dx2)][1]) /
848
0
         (g1 + g2);
849
0
    float min, max;
850
0
    min = MIN(nraw[nr_offset(y + dy, x + dx)][cl],
851
0
              nraw[nr_offset(y + dy2, x + dx2)][cl]);
852
0
    max = MAX(nraw[nr_offset(y + dy, x + dx)][cl],
853
0
              nraw[nr_offset(y + dy2, x + dx2)][cl]);
854
0
    min /= 1.2f;
855
0
    max *= 1.2f;
856
0
    if (eg < min)
857
0
      eg = scale_under(eg, min);
858
0
    else if (eg > max)
859
0
      eg = scale_over(eg, max);
860
0
    if (eg > channel_maximum[cl])
861
0
      eg = channel_maximum[cl];
862
0
    else if (eg < channel_minimum[cl])
863
0
      eg = channel_minimum[cl];
864
0
    nraw[nr_offset(y, x)][cl] = eg;
865
0
  }
866
0
}
867
868
/*
869
 * интерполяция красных и синих в точках где был известен только зелёный,
870
 * направления горизонтальные или вертикальные
871
 */
872
873
void DHT::make_rbhv(int i)
874
0
{
875
0
  int iwidth = libraw.imgdata.sizes.iwidth;
876
0
  int js = (libraw.COLOR(i, 0) & 1) ^ 1;
877
0
  for (int j = js; j < iwidth; j += 2)
878
0
  {
879
0
    int x = j + nr_leftmargin;
880
0
    int y = i + nr_topmargin;
881
    /*
882
     * поскольку сверху-снизу и справа-слева уже есть все необходимые красные и
883
     * синие, то можно выбрать наилучшее направление исходя из информации по
884
     * обоим цветам.
885
     */
886
0
    int dx, dy, dx2, dy2;
887
0
    if (ndir[nr_offset(y, x)] & VER)
888
0
    {
889
0
      dx = dx2 = 0;
890
0
      dy = -1;
891
0
      dy2 = 1;
892
0
    }
893
0
    else
894
0
    {
895
0
      dy = dy2 = 0;
896
0
      dx = 1;
897
0
      dx2 = -1;
898
0
    }
899
0
    float g1 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
900
0
                             nraw[nr_offset(y + dy, x + dx)][1]);
901
0
    float g2 = 1 / calc_dist(nraw[nr_offset(y, x)][1],
902
0
                             nraw[nr_offset(y + dy2, x + dx2)][1]);
903
0
    g1 *= g1;
904
0
    g2 *= g2;
905
0
    float eg_r, eg_b;
906
0
    eg_r = nraw[nr_offset(y, x)][1] *
907
0
           (g1 * nraw[nr_offset(y + dy, x + dx)][0] /
908
0
                nraw[nr_offset(y + dy, x + dx)][1] +
909
0
            g2 * nraw[nr_offset(y + dy2, x + dx2)][0] /
910
0
                nraw[nr_offset(y + dy2, x + dx2)][1]) /
911
0
           (g1 + g2);
912
0
    eg_b = nraw[nr_offset(y, x)][1] *
913
0
           (g1 * nraw[nr_offset(y + dy, x + dx)][2] /
914
0
                nraw[nr_offset(y + dy, x + dx)][1] +
915
0
            g2 * nraw[nr_offset(y + dy2, x + dx2)][2] /
916
0
                nraw[nr_offset(y + dy2, x + dx2)][1]) /
917
0
           (g1 + g2);
918
0
    float min_r, max_r;
919
0
    min_r = MIN(nraw[nr_offset(y + dy, x + dx)][0],
920
0
                nraw[nr_offset(y + dy2, x + dx2)][0]);
921
0
    max_r = MAX(nraw[nr_offset(y + dy, x + dx)][0],
922
0
                nraw[nr_offset(y + dy2, x + dx2)][0]);
923
0
    float min_b, max_b;
924
0
    min_b = MIN(nraw[nr_offset(y + dy, x + dx)][2],
925
0
                nraw[nr_offset(y + dy2, x + dx2)][2]);
926
0
    max_b = MAX(nraw[nr_offset(y + dy, x + dx)][2],
927
0
                nraw[nr_offset(y + dy2, x + dx2)][2]);
928
0
    min_r /= 1.2f;
929
0
    max_r *= 1.2f;
930
0
    min_b /= 1.2f;
931
0
    max_b *= 1.2f;
932
933
0
    if (eg_r < min_r)
934
0
      eg_r = scale_under(eg_r, min_r);
935
0
    else if (eg_r > max_r)
936
0
      eg_r = scale_over(eg_r, max_r);
937
0
    if (eg_b < min_b)
938
0
      eg_b = scale_under(eg_b, min_b);
939
0
    else if (eg_b > max_b)
940
0
      eg_b = scale_over(eg_b, max_b);
941
942
0
    if (eg_r > channel_maximum[0])
943
0
      eg_r = channel_maximum[0];
944
0
    else if (eg_r < channel_minimum[0])
945
0
      eg_r = channel_minimum[0];
946
0
    if (eg_b > channel_maximum[2])
947
0
      eg_b = channel_maximum[2];
948
0
    else if (eg_b < channel_minimum[2])
949
0
      eg_b = channel_minimum[2];
950
0
    nraw[nr_offset(y, x)][0] = eg_r;
951
0
    nraw[nr_offset(y, x)][2] = eg_b;
952
0
  }
953
0
}
954
955
void DHT::make_rb()
956
0
{
957
#if defined(LIBRAW_USE_OPENMP)
958
#pragma omp barrier
959
#pragma omp parallel for schedule(guided)
960
#endif
961
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
962
0
  {
963
0
    make_rbdiag(i);
964
0
  }
965
#if defined(LIBRAW_USE_OPENMP)
966
#pragma omp barrier
967
#pragma omp parallel for schedule(guided)
968
#endif
969
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
970
0
  {
971
0
    make_rbhv(i);
972
0
  }
973
0
}
974
975
/*
976
 * перенос изображения в выходной массив
977
 */
978
void DHT::copy_to_image()
979
0
{
980
0
  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
0
  for (int i = 0; i < libraw.imgdata.sizes.iheight; ++i)
989
0
  {
990
0
    for (int j = 0; j < iwidth; ++j)
991
0
    {
992
0
      libraw.imgdata.image[i * iwidth + j][0] =
993
0
          (unsigned short)(nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)]
994
0
                               [0]);
995
0
      libraw.imgdata.image[i * iwidth + j][2] =
996
0
          (unsigned short)(nraw[nr_offset(i + nr_topmargin, j + nr_leftmargin)]
997
0
                               [2]);
998
0
      libraw.imgdata.image[i * iwidth + j][1] =
999
0
          libraw.imgdata.image[i * iwidth + j][3] =
1000
0
              (unsigned short)(nraw[nr_offset(i + nr_topmargin,
1001
0
                                              j + nr_leftmargin)][1]);
1002
0
    }
1003
0
  }
1004
0
}
1005
1006
DHT::~DHT()
1007
0
{
1008
0
  free(nraw);
1009
0
  free(ndir);
1010
0
}
1011
1012
void LibRaw::dht_interpolate()
1013
0
{
1014
0
  if (imgdata.idata.filters != 0x16161616
1015
0
    && imgdata.idata.filters != 0x61616161
1016
0
    && imgdata.idata.filters != 0x49494949
1017
0
    && imgdata.idata.filters != 0x94949494
1018
0
    )
1019
0
  {
1020
0
    ahd_interpolate();
1021
0
    return;
1022
0
  }
1023
0
  DHT dht(*this);
1024
0
  dht.hide_hots();
1025
0
  dht.make_hv_dirs();
1026
  //  dht.illustrate_dirs();
1027
0
  dht.make_greens();
1028
0
  dht.make_diag_dirs();
1029
  //  dht.illustrate_dirs();
1030
0
  dht.make_rb();
1031
0
  dht.restore_hots();
1032
0
  dht.copy_to_image();
1033
0
}