Coverage Report

Created: 2025-12-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libraw/src/demosaic/dcb_demosaic.cpp
Line
Count
Source
1
/*
2
 *    Copyright (C) 2010,  Jacek Gozdz (cuniek@kft.umcs.lublin.pl)
3
 *
4
 *    This code is licensed under a (3-clause) BSD license as follows :
5
 *
6
 *    Redistribution and use in source and binary forms, with or without
7
 *    modification, are permitted provided that the following
8
 *    conditions are met:
9
 *
10
 *    * Redistributions of source code must retain the above copyright
11
 *      notice, this list of conditions and the following disclaimer.
12
 *    * Redistributions in binary form must reproduce the above
13
 *      copyright notice, this list of conditions and the following
14
 *    disclaimer in the documentation and/or other materials provided
15
 *      with the distribution.
16
 *    * Neither the name of the author nor the names of its
17
 *      contributors may be used to endorse or promote products
18
 *    derived from this software without specific prior written permission.
19
 *
20
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
 *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
 *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
23
 *    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
24
 *    THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25
 *    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26
 *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
 *    SERVICES; LOSS OF USE,
28
 *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29
 *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30
 *    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31
 *    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
32
 *    OF SUCH DAMAGE.
33
 */
34
35
// DCB demosaicing by Jacek Gozdz (cuniek@kft.umcs.lublin.pl)
36
37
// FBDD denoising by Jacek Gozdz (cuniek@kft.umcs.lublin.pl) and
38
// Luis Sanz Rodríguez (luis.sanz.rodriguez@gmail.com)
39
40
// last modification: 11.07.2010
41
42
#include "../../internal/dcraw_defs.h"
43
44
// interpolates green vertically and saves it to image3
45
void LibRaw::dcb_ver(float (*image3)[3])
46
3.07k
{
47
3.07k
  int row, col, u = width, indx;
48
49
1.03M
  for (row = 2; row < height - 2; row++)
50
65.6M
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
51
64.6M
         col += 2, indx += 2)
52
64.6M
    {
53
54
64.6M
      image3[indx][1] = float(CLIP((image[indx + u][1] + image[indx - u][1]) / 2.0));
55
64.6M
    }
56
3.07k
}
57
58
// interpolates green horizontally and saves it to image2
59
void LibRaw::dcb_hor(float (*image2)[3])
60
3.07k
{
61
3.07k
  int row, col, u = width, indx;
62
63
1.03M
  for (row = 2; row < height - 2; row++)
64
65.6M
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
65
64.6M
         col += 2, indx += 2)
66
64.6M
    {
67
68
64.6M
      image2[indx][1] = float(CLIP((image[indx + 1][1] + image[indx - 1][1]) / 2.0));
69
64.6M
    }
70
3.07k
}
71
72
// missing colors are interpolated
73
void LibRaw::dcb_color()
74
19.1k
{
75
19.1k
  int row, col, c, d, u = width, indx;
76
77
4.62M
  for (row = 1; row < height - 1; row++)
78
4.60M
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
79
4.60M
        c = 2 - FC(row, col);
80
326M
         col < u - 1; col += 2, indx += 2)
81
321M
    {
82
83
321M
      image[indx][c] = CLIP((4 * image[indx][1] - image[indx + u + 1][1] -
84
321M
                             image[indx + u - 1][1] - image[indx - u + 1][1] -
85
321M
                             image[indx - u - 1][1] + image[indx + u + 1][c] +
86
321M
                             image[indx + u - 1][c] + image[indx - u + 1][c] +
87
321M
                             image[indx - u - 1][c]) /
88
321M
                            4.0);
89
321M
    }
90
91
4.62M
  for (row = 1; row < height - 1; row++)
92
4.60M
    for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
93
4.60M
        c = FC(row, col + 1), d = 2 - c;
94
326M
         col < width - 1; col += 2, indx += 2)
95
321M
    {
96
97
321M
      image[indx][c] =
98
321M
          CLIP((2 * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] +
99
321M
                image[indx + 1][c] + image[indx - 1][c]) /
100
321M
               2.0);
101
321M
      image[indx][d] =
102
321M
          CLIP((2 * image[indx][1] - image[indx + u][1] - image[indx - u][1] +
103
321M
                image[indx + u][d] + image[indx - u][d]) /
104
321M
               2.0);
105
321M
    }
106
19.1k
}
107
108
// missing R and B are interpolated horizontally and saved in image2
109
void LibRaw::dcb_color2(float (*image2)[3])
110
3.07k
{
111
3.07k
  int row, col, c, d, u = width, indx;
112
113
1.04M
  for (row = 1; row < height - 1; row++)
114
1.04M
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
115
1.04M
        c = 2 - FC(row, col);
116
67.5M
         col < u - 1; col += 2, indx += 2)
117
66.5M
    {
118
119
66.5M
      image2[indx][c] =
120
66.5M
      float(
121
66.5M
          CLIP((4 * image2[indx][1] - image2[indx + u + 1][1] -
122
66.5M
                image2[indx + u - 1][1] - image2[indx - u + 1][1] -
123
66.5M
                image2[indx - u - 1][1] + image[indx + u + 1][c] +
124
66.5M
                image[indx + u - 1][c] + image[indx - u + 1][c] +
125
66.5M
                image[indx - u - 1][c]) /
126
66.5M
               4.0)
127
66.5M
        );
128
66.5M
    }
129
130
1.04M
  for (row = 1; row < height - 1; row++)
131
1.04M
    for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
132
1.04M
        c = FC(row, col + 1), d = 2 - c;
133
67.5M
         col < width - 1; col += 2, indx += 2)
134
66.5M
    {
135
136
66.5M
      image2[indx][c] = float(CLIP((image[indx + 1][c] + image[indx - 1][c]) / 2.0));
137
66.5M
      image2[indx][d] =
138
66.5M
          float(CLIP((2 * image2[indx][1] - image2[indx + u][1] -
139
66.5M
                image2[indx - u][1] + image[indx + u][d] + image[indx - u][d]) /
140
66.5M
               2.0));
141
66.5M
    }
142
3.07k
}
143
144
// missing R and B are interpolated vertically and saved in image3
145
void LibRaw::dcb_color3(float (*image3)[3])
146
3.07k
{
147
3.07k
  int row, col, c, d, u = width, indx;
148
149
1.04M
  for (row = 1; row < height - 1; row++)
150
1.04M
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
151
1.04M
        c = 2 - FC(row, col);
152
67.5M
         col < u - 1; col += 2, indx += 2)
153
66.5M
    {
154
155
66.5M
      image3[indx][c] =
156
66.5M
      float(
157
66.5M
          CLIP((4 * image3[indx][1] - image3[indx + u + 1][1] -
158
66.5M
                image3[indx + u - 1][1] - image3[indx - u + 1][1] -
159
66.5M
                image3[indx - u - 1][1] + image[indx + u + 1][c] +
160
66.5M
                image[indx + u - 1][c] + image[indx - u + 1][c] +
161
66.5M
                image[indx - u - 1][c]) /
162
66.5M
               4.0)
163
66.5M
        );
164
66.5M
    }
165
166
1.04M
  for (row = 1; row < height - 1; row++)
167
1.04M
    for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
168
1.04M
        c = FC(row, col + 1), d = 2 - c;
169
67.5M
         col < width - 1; col += 2, indx += 2)
170
66.5M
    {
171
172
66.5M
      image3[indx][c] =
173
66.5M
      float(
174
66.5M
          CLIP((2 * image3[indx][1] - image3[indx + 1][1] -
175
66.5M
                image3[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) /
176
66.5M
               2.0)
177
66.5M
        );
178
66.5M
      image3[indx][d] = float(CLIP((image[indx + u][d] + image[indx - u][d]) / 2.0));
179
66.5M
    }
180
3.07k
}
181
182
// decides the primary green interpolation direction
183
void LibRaw::dcb_decide(float (*image2)[3], float (*image3)[3])
184
3.07k
{
185
3.07k
  int row, col, c, d, u = width, v = 2 * u, indx;
186
3.07k
  float current, current2, current3;
187
188
1.03M
  for (row = 2; row < height - 2; row++)
189
1.03M
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
190
65.6M
         col < u - 2; col += 2, indx += 2)
191
64.6M
    {
192
193
64.6M
      d = ABS(c - 2);
194
195
64.6M
      current = float(MAX(image[indx + v][c],
196
64.6M
                    MAX(image[indx - v][c],
197
64.6M
                        MAX(image[indx - 2][c], image[indx + 2][c]))) -
198
64.6M
                MIN(image[indx + v][c],
199
64.6M
                    MIN(image[indx - v][c],
200
64.6M
                        MIN(image[indx - 2][c], image[indx + 2][c]))) +
201
64.6M
                MAX(image[indx + 1 + u][d],
202
64.6M
                    MAX(image[indx + 1 - u][d],
203
64.6M
                        MAX(image[indx - 1 + u][d], image[indx - 1 - u][d]))) -
204
64.6M
                MIN(image[indx + 1 + u][d],
205
64.6M
                    MIN(image[indx + 1 - u][d],
206
64.6M
                        MIN(image[indx - 1 + u][d], image[indx - 1 - u][d]))));
207
208
64.6M
      current2 =
209
64.6M
      float(
210
64.6M
          MAX(image2[indx + v][d],
211
64.6M
              MAX(image2[indx - v][d],
212
64.6M
                  MAX(image2[indx - 2][d], image2[indx + 2][d]))) -
213
64.6M
          MIN(image2[indx + v][d],
214
64.6M
              MIN(image2[indx - v][d],
215
64.6M
                  MIN(image2[indx - 2][d], image2[indx + 2][d]))) +
216
64.6M
          MAX(image2[indx + 1 + u][c],
217
64.6M
              MAX(image2[indx + 1 - u][c],
218
64.6M
                  MAX(image2[indx - 1 + u][c], image2[indx - 1 - u][c]))) -
219
64.6M
          MIN(image2[indx + 1 + u][c],
220
64.6M
              MIN(image2[indx + 1 - u][c],
221
64.6M
                  MIN(image2[indx - 1 + u][c], image2[indx - 1 - u][c])))
222
64.6M
        );
223
224
64.6M
      current3 =
225
64.6M
      float(
226
64.6M
          MAX(image3[indx + v][d],
227
64.6M
              MAX(image3[indx - v][d],
228
64.6M
                  MAX(image3[indx - 2][d], image3[indx + 2][d]))) -
229
64.6M
          MIN(image3[indx + v][d],
230
64.6M
              MIN(image3[indx - v][d],
231
64.6M
                  MIN(image3[indx - 2][d], image3[indx + 2][d]))) +
232
64.6M
          MAX(image3[indx + 1 + u][c],
233
64.6M
              MAX(image3[indx + 1 - u][c],
234
64.6M
                  MAX(image3[indx - 1 + u][c], image3[indx - 1 - u][c]))) -
235
64.6M
          MIN(image3[indx + 1 + u][c],
236
64.6M
              MIN(image3[indx + 1 - u][c],
237
64.6M
                  MIN(image3[indx - 1 + u][c], image3[indx - 1 - u][c])))
238
64.6M
        );
239
240
64.6M
      if (ABS(current - current2) < ABS(current - current3))
241
11.0M
        image[indx][1] = ushort(image2[indx][1]);
242
53.6M
      else
243
53.6M
        image[indx][1] = ushort(image3[indx][1]);
244
64.6M
    }
245
3.07k
}
246
247
// saves red and blue in image2
248
void LibRaw::dcb_copy_to_buffer(float (*image2)[3])
249
3.07k
{
250
3.07k
  int indx;
251
252
136M
  for (indx = 0; indx < height * width; indx++)
253
136M
  {
254
136M
    image2[indx][0] = image[indx][0]; // R
255
136M
    image2[indx][2] = image[indx][2]; // B
256
136M
  }
257
3.07k
}
258
259
// restores red and blue from image2
260
void LibRaw::dcb_restore_from_buffer(float (*image2)[3])
261
3.07k
{
262
3.07k
  int indx;
263
264
136M
  for (indx = 0; indx < height * width; indx++)
265
136M
  {
266
136M
    image[indx][0] = ushort(image2[indx][0]); // R
267
136M
    image[indx][2] = ushort(image2[indx][2]); // B
268
136M
  }
269
3.07k
}
270
271
// R and B smoothing using green contrast, all pixels except 2 pixel wide border
272
void LibRaw::dcb_pp()
273
3.07k
{
274
3.07k
  int g1, r1, b1, u = width, indx, row, col;
275
276
1.03M
  for (row = 2; row < height - 2; row++)
277
130M
    for (col = 2, indx = row * u + col; col < width - 2; col++, indx++)
278
129M
    {
279
280
129M
      r1 = int((image[indx - 1][0] + image[indx + 1][0] + image[indx - u][0] +
281
129M
            image[indx + u][0] + image[indx - u - 1][0] +
282
129M
            image[indx + u + 1][0] + image[indx - u + 1][0] +
283
129M
            image[indx + u - 1][0]) /
284
129M
           8.0f);
285
129M
      g1 = int((image[indx - 1][1] + image[indx + 1][1] + image[indx - u][1] +
286
129M
            image[indx + u][1] + image[indx - u - 1][1] +
287
129M
            image[indx + u + 1][1] + image[indx - u + 1][1] +
288
129M
            image[indx + u - 1][1]) /
289
129M
           8.0f);
290
129M
      b1 = int((image[indx - 1][2] + image[indx + 1][2] + image[indx - u][2] +
291
129M
            image[indx + u][2] + image[indx - u - 1][2] +
292
129M
            image[indx + u + 1][2] + image[indx - u + 1][2] +
293
129M
            image[indx + u - 1][2]) /
294
129M
           8.0f);
295
296
129M
      image[indx][0] = CLIP(r1 + (image[indx][1] - g1));
297
129M
      image[indx][2] = CLIP(b1 + (image[indx][1] - g1));
298
129M
    }
299
3.07k
}
300
301
// green blurring correction, helps to get the nyquist right
302
void LibRaw::dcb_nyquist()
303
0
{
304
0
  int row, col, c, u = width, v = 2 * u, indx;
305
306
0
  for (row = 2; row < height - 2; row++)
307
0
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
308
0
         col < u - 2; col += 2, indx += 2)
309
0
    {
310
311
0
      image[indx][1] = CLIP((image[indx + v][1] + image[indx - v][1] +
312
0
                             image[indx - 2][1] + image[indx + 2][1]) /
313
0
                                4.0 +
314
0
                            image[indx][c] -
315
0
                            (image[indx + v][c] + image[indx - v][c] +
316
0
                             image[indx - 2][c] + image[indx + 2][c]) /
317
0
                                4.0);
318
0
    }
319
0
}
320
321
// missing colors are interpolated using high quality algorithm by Luis Sanz
322
// Rodríguez
323
void LibRaw::dcb_color_full()
324
16.3k
{
325
16.3k
  int row, col, c, d, u = width, w = 3 * u, indx, g1, g2;
326
16.3k
  float f[4], g[4], (*chroma)[2];
327
328
16.3k
  chroma = (float(*)[2])calloc(width * height, sizeof *chroma);
329
330
3.32M
  for (row = 1; row < height - 1; row++)
331
3.31M
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col),
332
3.31M
        d = c / 2;
333
239M
         col < u - 1; col += 2, indx += 2)
334
236M
      chroma[indx][d] = float(image[indx][c] - image[indx][1]);
335
336
3.26M
  for (row = 3; row < height - 3; row++)
337
3.24M
    for (col = 3 + (FC(row, 1) & 1), indx = row * width + col,
338
3.24M
        c = 1 - FC(row, col) / 2, d = 1 - c;
339
228M
         col < u - 3; col += 2, indx += 2)
340
225M
    {
341
225M
      f[0] = 1.0f /
342
225M
             (float)(1.0 +
343
225M
                     fabsf(chroma[indx - u - 1][c] - chroma[indx + u + 1][c]) +
344
225M
                     fabsf(chroma[indx - u - 1][c] - chroma[indx - w - 3][c]) +
345
225M
                     fabsf(chroma[indx + u + 1][c] - chroma[indx - w - 3][c]));
346
225M
      f[1] = 1.0f /
347
225M
             (float)(1.0 +
348
225M
                     fabsf(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) +
349
225M
                     fabsf(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) +
350
225M
                     fabsf(chroma[indx + u - 1][c] - chroma[indx - w + 3][c]));
351
225M
      f[2] = 1.0f /
352
225M
             (float)(1.0 +
353
225M
                     fabsf(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) +
354
225M
                     fabsf(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) +
355
225M
                     fabsf(chroma[indx - u + 1][c] - chroma[indx + w - 3][c]));
356
225M
      f[3] = 1.0f /
357
225M
             (float)(1.0 +
358
225M
                     fabsf(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) +
359
225M
                     fabsf(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) +
360
225M
                     fabsf(chroma[indx - u - 1][c] - chroma[indx + w + 3][c]));
361
225M
      g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] -
362
225M
             0.075f * chroma[indx - w - 1][c] - 0.075f * chroma[indx - u - 3][c];
363
225M
      g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] -
364
225M
             0.075f * chroma[indx - w + 1][c] - 0.075f * chroma[indx - u + 3][c];
365
225M
      g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] -
366
225M
             0.075f * chroma[indx + w - 1][c] - 0.075f * chroma[indx + u - 3][c];
367
225M
      g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] -
368
225M
             0.075f * chroma[indx + w + 1][c] - 0.075f * chroma[indx + u + 3][c];
369
225M
      chroma[indx][c] =
370
225M
          (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
371
225M
          (f[0] + f[1] + f[2] + f[3]);
372
225M
    }
373
3.26M
  for (row = 3; row < height - 3; row++)
374
3.24M
    for (col = 3 + (FC(row, 2) & 1), indx = row * width + col,
375
3.24M
        c = FC(row, col + 1) / 2;
376
228M
         col < u - 3; col += 2, indx += 2)
377
675M
      for (d = 0; d <= 1; c = 1 - c, d++)
378
450M
      {
379
450M
        f[0] = 1.0f /
380
450M
               (float)(1.0f + fabsf(chroma[indx - u][c] - chroma[indx + u][c]) +
381
450M
                       fabsf(chroma[indx - u][c] - chroma[indx - w][c]) +
382
450M
                       fabsf(chroma[indx + u][c] - chroma[indx - w][c]));
383
450M
        f[1] = 1.0f /
384
450M
               (float)(1.0f + fabsf(chroma[indx + 1][c] - chroma[indx - 1][c]) +
385
450M
                       fabsf(chroma[indx + 1][c] - chroma[indx + 3][c]) +
386
450M
                       fabsf(chroma[indx - 1][c] - chroma[indx + 3][c]));
387
450M
        f[2] = 1.0f /
388
450M
               (float)(1.0 + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) +
389
450M
                       fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) +
390
450M
                       fabs(chroma[indx + 1][c] - chroma[indx - 3][c]));
391
450M
        f[3] = 1.0f /
392
450M
               (float)(1.0 + fabs(chroma[indx + u][c] - chroma[indx - u][c]) +
393
450M
                       fabs(chroma[indx + u][c] - chroma[indx + w][c]) +
394
450M
                       fabs(chroma[indx - u][c] - chroma[indx + w][c]));
395
396
450M
        g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c];
397
450M
        g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c];
398
450M
        g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c];
399
450M
        g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c];
400
401
450M
        chroma[indx][c] =
402
450M
            (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
403
450M
            (f[0] + f[1] + f[2] + f[3]);
404
450M
      }
405
406
3.16M
  for (row = 6; row < height - 6; row++)
407
420M
    for (col = 6, indx = row * width + col; col < width - 6; col++, indx++)
408
416M
    {
409
416M
      image[indx][0] = CLIP(chroma[indx][0] + image[indx][1]);
410
416M
      image[indx][2] = CLIP(chroma[indx][1] + image[indx][1]);
411
412
416M
      g1 = MIN(
413
416M
          image[indx + 1 + u][0],
414
416M
          MIN(image[indx + 1 - u][0],
415
416M
              MIN(image[indx - 1 + u][0],
416
416M
                  MIN(image[indx - 1 - u][0],
417
416M
                      MIN(image[indx - 1][0],
418
416M
                          MIN(image[indx + 1][0],
419
416M
                              MIN(image[indx - u][0], image[indx + u][0])))))));
420
421
416M
      g2 = MAX(
422
416M
          image[indx + 1 + u][0],
423
416M
          MAX(image[indx + 1 - u][0],
424
416M
              MAX(image[indx - 1 + u][0],
425
416M
                  MAX(image[indx - 1 - u][0],
426
416M
                      MAX(image[indx - 1][0],
427
416M
                          MAX(image[indx + 1][0],
428
416M
                              MAX(image[indx - u][0], image[indx + u][0])))))));
429
430
416M
      image[indx][0] = ULIM(image[indx][0], g2, g1);
431
432
416M
      g1 = MIN(
433
416M
          image[indx + 1 + u][2],
434
416M
          MIN(image[indx + 1 - u][2],
435
416M
              MIN(image[indx - 1 + u][2],
436
416M
                  MIN(image[indx - 1 - u][2],
437
416M
                      MIN(image[indx - 1][2],
438
416M
                          MIN(image[indx + 1][2],
439
416M
                              MIN(image[indx - u][2], image[indx + u][2])))))));
440
441
416M
      g2 = MAX(
442
416M
          image[indx + 1 + u][2],
443
416M
          MAX(image[indx + 1 - u][2],
444
416M
              MAX(image[indx - 1 + u][2],
445
416M
                  MAX(image[indx - 1 - u][2],
446
416M
                      MAX(image[indx - 1][2],
447
416M
                          MAX(image[indx + 1][2],
448
416M
                              MAX(image[indx - u][2], image[indx + u][2])))))));
449
450
416M
      image[indx][2] = ULIM(image[indx][2], g2, g1);
451
416M
    }
452
453
16.3k
  free(chroma);
454
16.3k
}
455
456
// green is used to create an interpolation direction map saved in image[][3]
457
// 1 = vertical
458
// 0 = horizontal
459
void LibRaw::dcb_map()
460
15.3k
{
461
15.3k
  int row, col, u = width, indx;
462
463
5.22M
  for (row = 1; row < height - 1; row++)
464
5.20M
  {
465
670M
    for (col = 1, indx = row * width + col; col < width - 1; col++, indx++)
466
665M
    {
467
468
665M
      if (image[indx][1] > (image[indx - 1][1] + image[indx + 1][1] +
469
665M
                            image[indx - u][1] + image[indx + u][1]) /
470
665M
                               4.0)
471
120M
        image[indx][3] = ((MIN(image[indx - 1][1], image[indx + 1][1]) +
472
120M
                           image[indx - 1][1] + image[indx + 1][1]) <
473
120M
                          (MIN(image[indx - u][1], image[indx + u][1]) +
474
120M
                           image[indx - u][1] + image[indx + u][1]));
475
545M
      else
476
545M
        image[indx][3] = ((MAX(image[indx - 1][1], image[indx + 1][1]) +
477
545M
                           image[indx - 1][1] + image[indx + 1][1]) >
478
545M
                          (MAX(image[indx - u][1], image[indx + u][1]) +
479
545M
                           image[indx - u][1] + image[indx + u][1]));
480
665M
    }
481
5.20M
  }
482
15.3k
}
483
484
// interpolated green pixels are corrected using the map
485
void LibRaw::dcb_correction()
486
9.21k
{
487
9.21k
  int current, row, col, u = width, v = 2 * u, indx;
488
489
3.11M
  for (row = 2; row < height - 2; row++)
490
196M
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
491
193M
         col += 2, indx += 2)
492
193M
    {
493
494
193M
      current = 4 * image[indx][3] +
495
193M
                2 * (image[indx + u][3] + image[indx - u][3] +
496
193M
                     image[indx + 1][3] + image[indx - 1][3]) +
497
193M
                image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
498
193M
                image[indx - 2][3];
499
500
193M
      image[indx][1] =
501
193M
      ushort(
502
193M
          ((16 - current) * (image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
503
193M
           current * (image[indx - u][1] + image[indx + u][1]) / 2.0) /
504
193M
          16.0f);
505
193M
    }
506
9.21k
}
507
508
// interpolated green pixels are corrected using the map
509
// with contrast correction
510
void LibRaw::dcb_correction2()
511
3.07k
{
512
3.07k
  int current, row, col, c, u = width, v = 2 * u, indx;
513
514
1.02M
  for (row = 4; row < height - 4; row++)
515
1.02M
    for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
516
61.8M
         col < u - 4; col += 2, indx += 2)
517
60.8M
    {
518
519
60.8M
      current = 4 * image[indx][3] +
520
60.8M
                2 * (image[indx + u][3] + image[indx - u][3] +
521
60.8M
                     image[indx + 1][3] + image[indx - 1][3]) +
522
60.8M
                image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
523
60.8M
                image[indx - 2][3];
524
525
60.8M
      image[indx][1] = CLIP(
526
60.8M
          ((16 - current) * ((image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
527
60.8M
                             image[indx][c] -
528
60.8M
                             (image[indx + 2][c] + image[indx - 2][c]) / 2.0) +
529
60.8M
           current * ((image[indx - u][1] + image[indx + u][1]) / 2.0 +
530
60.8M
                      image[indx][c] -
531
60.8M
                      (image[indx + v][c] + image[indx - v][c]) / 2.0)) /
532
60.8M
          16.0);
533
60.8M
    }
534
3.07k
}
535
536
void LibRaw::dcb_refinement()
537
0
{
538
0
  int row, col, c, u = width, v = 2 * u, w = 3 * u, indx, current;
539
0
  float f[5], g1, g2;
540
541
0
  for (row = 4; row < height - 4; row++)
542
0
    for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
543
0
         col < u - 4; col += 2, indx += 2)
544
0
    {
545
546
0
      current = 4 * image[indx][3] +
547
0
                2 * (image[indx + u][3] + image[indx - u][3] +
548
0
                     image[indx + 1][3] + image[indx - 1][3]) +
549
0
                image[indx + v][3] + image[indx - v][3] + image[indx - 2][3] +
550
0
                image[indx + 2][3];
551
552
0
      if (image[indx][c] > 1)
553
0
      {
554
555
0
        f[0] = (float)(image[indx - u][1] + image[indx + u][1]) /
556
0
               (2 * image[indx][c]);
557
558
0
        if (image[indx - v][c] > 0)
559
0
          f[1] = 2 * (float)image[indx - u][1] /
560
0
                 (image[indx - v][c] + image[indx][c]);
561
0
        else
562
0
          f[1] = f[0];
563
564
0
        if (image[indx - v][c] > 0)
565
0
          f[2] = (float)(image[indx - u][1] + image[indx - w][1]) /
566
0
                 (2 * image[indx - v][c]);
567
0
        else
568
0
          f[2] = f[0];
569
570
0
        if (image[indx + v][c] > 0)
571
0
          f[3] = 2 * (float)image[indx + u][1] /
572
0
                 (image[indx + v][c] + image[indx][c]);
573
0
        else
574
0
          f[3] = f[0];
575
576
0
        if (image[indx + v][c] > 0)
577
0
          f[4] = (float)(image[indx + u][1] + image[indx + w][1]) /
578
0
                 (2 * image[indx + v][c]);
579
0
        else
580
0
          f[4] = f[0];
581
582
0
        g1 = (5.f * f[0] + 3.f * f[1] + f[2] + 3.f * f[3] + f[4]) / 13.0f;
583
584
0
        f[0] = (float)(image[indx - 1][1] + image[indx + 1][1]) /
585
0
               (2 * image[indx][c]);
586
587
0
        if (image[indx - 2][c] > 0)
588
0
          f[1] = 2 * (float)image[indx - 1][1] /
589
0
                 (image[indx - 2][c] + image[indx][c]);
590
0
        else
591
0
          f[1] = f[0];
592
593
0
        if (image[indx - 2][c] > 0)
594
0
          f[2] = (float)(image[indx - 1][1] + image[indx - 3][1]) /
595
0
                 (2 * image[indx - 2][c]);
596
0
        else
597
0
          f[2] = f[0];
598
599
0
        if (image[indx + 2][c] > 0)
600
0
          f[3] = 2 * (float)image[indx + 1][1] /
601
0
                 (image[indx + 2][c] + image[indx][c]);
602
0
        else
603
0
          f[3] = f[0];
604
605
0
        if (image[indx + 2][c] > 0)
606
0
          f[4] = (float)(image[indx + 1][1] + image[indx + 3][1]) /
607
0
                 (2 * image[indx + 2][c]);
608
0
        else
609
0
          f[4] = f[0];
610
611
0
        g2 = (5.f * f[0] + 3.f * f[1] + f[2] + 3.f * f[3] + f[4]) / 13.0f;
612
613
0
        image[indx][1] = CLIP((image[indx][c]) *
614
0
                              (current * g1 + (16 - current) * g2) / 16.0);
615
0
      }
616
0
      else
617
0
        image[indx][1] = image[indx][c];
618
619
      // get rid of overshooted pixels
620
621
0
      g1 = MIN(
622
0
          image[indx + 1 + u][1],
623
0
          MIN(image[indx + 1 - u][1],
624
0
              MIN(image[indx - 1 + u][1],
625
0
                  MIN(image[indx - 1 - u][1],
626
0
                      MIN(image[indx - 1][1],
627
0
                          MIN(image[indx + 1][1],
628
0
                              MIN(image[indx - u][1], image[indx + u][1])))))));
629
630
0
      g2 = MAX(
631
0
          image[indx + 1 + u][1],
632
0
          MAX(image[indx + 1 - u][1],
633
0
              MAX(image[indx - 1 + u][1],
634
0
                  MAX(image[indx - 1 - u][1],
635
0
                      MAX(image[indx - 1][1],
636
0
                          MAX(image[indx + 1][1],
637
0
                              MAX(image[indx - u][1], image[indx + u][1])))))));
638
639
0
      image[indx][1] = ushort(ULIM(image[indx][1], g2, g1));
640
0
    }
641
0
}
642
643
// converts RGB to LCH colorspace and saves it to image3
644
void LibRaw::rgb_to_lch(double (*image2)[3])
645
13.0k
{
646
13.0k
  int indx;
647
385M
  for (indx = 0; indx < height * width; indx++)
648
385M
  {
649
650
385M
    image2[indx][0] = image[indx][0] + image[indx][1] + image[indx][2]; // L
651
385M
    image2[indx][1] = 1.732050808 * (image[indx][0] - image[indx][1]);  // C
652
385M
    image2[indx][2] =
653
385M
        2.0 * image[indx][2] - image[indx][0] - image[indx][1]; // H
654
385M
  }
655
13.0k
}
656
657
// converts LCH to RGB colorspace and saves it back to image
658
void LibRaw::lch_to_rgb(double (*image2)[3])
659
13.0k
{
660
13.0k
  int indx;
661
385M
  for (indx = 0; indx < height * width; indx++)
662
385M
  {
663
664
385M
    image[indx][0] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 +
665
385M
                          image2[indx][1] / 3.464101615);
666
385M
    image[indx][1] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 -
667
385M
                          image2[indx][1] / 3.464101615);
668
385M
    image[indx][2] = CLIP(image2[indx][0] / 3.0 + image2[indx][2] / 3.0);
669
385M
  }
670
13.0k
}
671
672
// denoising using interpolated neighbours
673
void LibRaw::fbdd_correction()
674
16.3k
{
675
16.3k
  int row, col, c, u = width, indx;
676
677
3.29M
  for (row = 2; row < height - 2; row++)
678
3.27M
  {
679
464M
    for (col = 2, indx = row * width + col; col < width - 2; col++, indx++)
680
461M
    {
681
682
461M
      c = fcol(row, col);
683
684
461M
      image[indx][c] =
685
461M
          ULIM(image[indx][c],
686
461M
               MAX(image[indx - 1][c],
687
461M
                   MAX(image[indx + 1][c],
688
461M
                       MAX(image[indx - u][c], image[indx + u][c]))),
689
461M
               MIN(image[indx - 1][c],
690
461M
                   MIN(image[indx + 1][c],
691
461M
                       MIN(image[indx - u][c], image[indx + u][c]))));
692
461M
    }
693
3.27M
  }
694
16.3k
}
695
696
// corrects chroma noise
697
void LibRaw::fbdd_correction2(double (*image2)[3])
698
26.0k
{
699
26.0k
  int indx, v = 2 * width;
700
26.0k
  int col, row;
701
26.0k
  double Co, Ho, ratio;
702
703
4.80M
  for (row = 6; row < height - 6; row++)
704
4.77M
  {
705
671M
    for (col = 6; col < width - 6; col++)
706
666M
    {
707
666M
      indx = row * width + col;
708
709
666M
      if (image2[indx][1] * image2[indx][2] != 0)
710
344M
      {
711
344M
        Co = (image2[indx + v][1] + image2[indx - v][1] + image2[indx - 2][1] +
712
344M
              image2[indx + 2][1] -
713
344M
              MAX(image2[indx - 2][1],
714
344M
                  MAX(image2[indx + 2][1],
715
344M
                      MAX(image2[indx - v][1], image2[indx + v][1]))) -
716
344M
              MIN(image2[indx - 2][1],
717
344M
                  MIN(image2[indx + 2][1],
718
344M
                      MIN(image2[indx - v][1], image2[indx + v][1])))) /
719
344M
             2.0;
720
344M
        Ho = (image2[indx + v][2] + image2[indx - v][2] + image2[indx - 2][2] +
721
344M
              image2[indx + 2][2] -
722
344M
              MAX(image2[indx - 2][2],
723
344M
                  MAX(image2[indx + 2][2],
724
344M
                      MAX(image2[indx - v][2], image2[indx + v][2]))) -
725
344M
              MIN(image2[indx - 2][2],
726
344M
                  MIN(image2[indx + 2][2],
727
344M
                      MIN(image2[indx - v][2], image2[indx + v][2])))) /
728
344M
             2.0;
729
344M
        ratio = sqrt((Co * Co + Ho * Ho) / (image2[indx][1] * image2[indx][1] +
730
344M
                                            image2[indx][2] * image2[indx][2]));
731
732
344M
        if (ratio < 0.85)
733
39.0M
        {
734
39.0M
          image2[indx][0] =
735
39.0M
              -(image2[indx][1] + image2[indx][2] - Co - Ho) + image2[indx][0];
736
39.0M
          image2[indx][1] = Co;
737
39.0M
          image2[indx][2] = Ho;
738
39.0M
        }
739
344M
      }
740
666M
    }
741
4.77M
  }
742
26.0k
}
743
744
// Cubic Spline Interpolation by Li and Randhawa, modified by Jacek Gozdz and
745
// Luis Sanz Rodríguez
746
void LibRaw::fbdd_green()
747
16.3k
{
748
16.3k
  int row, col, c, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, indx,
749
16.3k
                   min, max;
750
16.3k
  float f[4], g[4];
751
752
3.19M
  for (row = 5; row < height - 5; row++)
753
3.17M
    for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col);
754
217M
         col < u - 5; col += 2, indx += 2)
755
213M
    {
756
757
213M
      f[0] = 1.0f / (1.0f + abs(image[indx - u][1] - image[indx - w][1]) +
758
213M
                    abs(image[indx - w][1] - image[indx + y][1]));
759
213M
      f[1] = 1.0f / (1.0f + abs(image[indx + 1][1] - image[indx + 3][1]) +
760
213M
                    abs(image[indx + 3][1] - image[indx - 5][1]));
761
213M
      f[2] = 1.0f / (1.0f + abs(image[indx - 1][1] - image[indx - 3][1]) +
762
213M
                    abs(image[indx - 3][1] - image[indx + 5][1]));
763
213M
      f[3] = 1.0f / (1.0f + abs(image[indx + u][1] - image[indx + w][1]) +
764
213M
                    abs(image[indx + w][1] - image[indx - y][1]));
765
766
213M
      g[0] = float(CLIP((23 * image[indx - u][1] + 23 * image[indx - w][1] +
767
213M
                   2 * image[indx - y][1] +
768
213M
                   8 * (image[indx - v][c] - image[indx - x][c]) +
769
213M
                   40 * (image[indx][c] - image[indx - v][c])) /
770
213M
                  48.0f));
771
213M
      g[1] = float(CLIP((23 * image[indx + 1][1] + 23 * image[indx + 3][1] +
772
213M
                   2 * image[indx + 5][1] +
773
213M
                   8 * (image[indx + 2][c] - image[indx + 4][c]) +
774
213M
                   40 * (image[indx][c] - image[indx + 2][c])) /
775
213M
                  48.f));
776
213M
      g[2] = float(CLIP((23 * image[indx - 1][1] + 23 * image[indx - 3][1] +
777
213M
                   2 * image[indx - 5][1] +
778
213M
                   8 * (image[indx - 2][c] - image[indx - 4][c]) +
779
213M
                   40 * (image[indx][c] - image[indx - 2][c])) /
780
213M
                  48.0f));
781
213M
      g[3] = float(CLIP((23 * image[indx + u][1] + 23 * image[indx + w][1] +
782
213M
                   2 * image[indx + y][1] +
783
213M
                   8 * (image[indx + v][c] - image[indx + x][c]) +
784
213M
                   40 * (image[indx][c] - image[indx + v][c])) /
785
213M
                  48.0f));
786
787
213M
      image[indx][1] =
788
213M
          CLIP((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
789
213M
               (f[0] + f[1] + f[2] + f[3]));
790
791
213M
      min = MIN(
792
213M
          image[indx + 1 + u][1],
793
213M
          MIN(image[indx + 1 - u][1],
794
213M
              MIN(image[indx - 1 + u][1],
795
213M
                  MIN(image[indx - 1 - u][1],
796
213M
                      MIN(image[indx - 1][1],
797
213M
                          MIN(image[indx + 1][1],
798
213M
                              MIN(image[indx - u][1], image[indx + u][1])))))));
799
800
213M
      max = MAX(
801
213M
          image[indx + 1 + u][1],
802
213M
          MAX(image[indx + 1 - u][1],
803
213M
              MAX(image[indx - 1 + u][1],
804
213M
                  MAX(image[indx - 1 - u][1],
805
213M
                      MAX(image[indx - 1][1],
806
213M
                          MAX(image[indx + 1][1],
807
213M
                              MAX(image[indx - u][1], image[indx + u][1])))))));
808
809
213M
      image[indx][1] = ULIM(image[indx][1], max, min);
810
213M
    }
811
16.3k
}
812
813
// FBDD (Fake Before Demosaicing Denoising)
814
void LibRaw::fbdd(int noiserd)
815
16.3k
{
816
16.3k
  double(*image2)[3];
817
  // safety net: disable for 4-color bayer or full-color images
818
16.3k
  if (colors != 3 || !filters)
819
0
    return;
820
16.3k
  image2 = (double(*)[3])calloc(width * height, sizeof *image2);
821
822
16.3k
  border_interpolate(4);
823
824
16.3k
  if (noiserd > 1)
825
13.0k
  {
826
13.0k
    fbdd_green();
827
    // dcb_color_full(image2);
828
13.0k
    dcb_color_full();
829
13.0k
    fbdd_correction();
830
831
13.0k
    dcb_color();
832
13.0k
    rgb_to_lch(image2);
833
13.0k
    fbdd_correction2(image2);
834
13.0k
    fbdd_correction2(image2);
835
13.0k
    lch_to_rgb(image2);
836
13.0k
  }
837
3.32k
  else
838
3.32k
  {
839
3.32k
    fbdd_green();
840
    // dcb_color_full(image2);
841
3.32k
    dcb_color_full();
842
3.32k
    fbdd_correction();
843
3.32k
  }
844
845
16.3k
  free(image2);
846
16.3k
}
847
848
// DCB demosaicing main routine
849
void LibRaw::dcb(int iterations, int dcb_enhance)
850
3.07k
{
851
852
3.07k
  int i = 1;
853
854
3.07k
  float(*image2)[3];
855
3.07k
  image2 = (float(*)[3])calloc(width * height, sizeof *image2);
856
857
3.07k
  float(*image3)[3];
858
3.07k
  image3 = (float(*)[3])calloc(width * height, sizeof *image3);
859
860
3.07k
  border_interpolate(6);
861
862
3.07k
  dcb_hor(image2);
863
3.07k
  dcb_color2(image2);
864
865
3.07k
  dcb_ver(image3);
866
3.07k
  dcb_color3(image3);
867
868
3.07k
  dcb_decide(image2, image3);
869
870
3.07k
  free(image3);
871
872
3.07k
  dcb_copy_to_buffer(image2);
873
874
3.07k
  while (i <= iterations)
875
0
  {
876
0
    dcb_nyquist();
877
0
    dcb_nyquist();
878
0
    dcb_nyquist();
879
0
    dcb_map();
880
0
    dcb_correction();
881
0
    i++;
882
0
  }
883
884
3.07k
  dcb_color();
885
3.07k
  dcb_pp();
886
887
3.07k
  dcb_map();
888
3.07k
  dcb_correction2();
889
890
3.07k
  dcb_map();
891
3.07k
  dcb_correction();
892
893
3.07k
  dcb_map();
894
3.07k
  dcb_correction();
895
896
3.07k
  dcb_map();
897
3.07k
  dcb_correction();
898
899
3.07k
  dcb_map();
900
3.07k
  dcb_restore_from_buffer(image2);
901
3.07k
  dcb_color();
902
903
3.07k
  if (dcb_enhance)
904
0
  {
905
0
    dcb_refinement();
906
    // dcb_color_full(image2);
907
0
    dcb_color_full();
908
0
  }
909
910
3.07k
  free(image2);
911
3.07k
}