Coverage Report

Created: 2025-08-12 07:37

/src/libraw/src/demosaic/dcb_demosaic.cpp
Line
Count
Source (jump to first uncovered line)
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
0
{
47
0
  int row, col, u = width, indx;
48
49
0
  for (row = 2; row < height - 2; row++)
50
0
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
51
0
         col += 2, indx += 2)
52
0
    {
53
54
0
      image3[indx][1] = float(CLIP((image[indx + u][1] + image[indx - u][1]) / 2.0));
55
0
    }
56
0
}
57
58
// interpolates green horizontally and saves it to image2
59
void LibRaw::dcb_hor(float (*image2)[3])
60
0
{
61
0
  int row, col, u = width, indx;
62
63
0
  for (row = 2; row < height - 2; row++)
64
0
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
65
0
         col += 2, indx += 2)
66
0
    {
67
68
0
      image2[indx][1] = float(CLIP((image[indx + 1][1] + image[indx - 1][1]) / 2.0));
69
0
    }
70
0
}
71
72
// missing colors are interpolated
73
void LibRaw::dcb_color()
74
0
{
75
0
  int row, col, c, d, u = width, indx;
76
77
0
  for (row = 1; row < height - 1; row++)
78
0
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
79
0
        c = 2 - FC(row, col);
80
0
         col < u - 1; col += 2, indx += 2)
81
0
    {
82
83
0
      image[indx][c] = CLIP((4 * image[indx][1] - image[indx + u + 1][1] -
84
0
                             image[indx + u - 1][1] - image[indx - u + 1][1] -
85
0
                             image[indx - u - 1][1] + image[indx + u + 1][c] +
86
0
                             image[indx + u - 1][c] + image[indx - u + 1][c] +
87
0
                             image[indx - u - 1][c]) /
88
0
                            4.0);
89
0
    }
90
91
0
  for (row = 1; row < height - 1; row++)
92
0
    for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
93
0
        c = FC(row, col + 1), d = 2 - c;
94
0
         col < width - 1; col += 2, indx += 2)
95
0
    {
96
97
0
      image[indx][c] =
98
0
          CLIP((2 * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] +
99
0
                image[indx + 1][c] + image[indx - 1][c]) /
100
0
               2.0);
101
0
      image[indx][d] =
102
0
          CLIP((2 * image[indx][1] - image[indx + u][1] - image[indx - u][1] +
103
0
                image[indx + u][d] + image[indx - u][d]) /
104
0
               2.0);
105
0
    }
106
0
}
107
108
// missing R and B are interpolated horizontally and saved in image2
109
void LibRaw::dcb_color2(float (*image2)[3])
110
0
{
111
0
  int row, col, c, d, u = width, indx;
112
113
0
  for (row = 1; row < height - 1; row++)
114
0
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
115
0
        c = 2 - FC(row, col);
116
0
         col < u - 1; col += 2, indx += 2)
117
0
    {
118
119
0
      image2[indx][c] =
120
0
      float(
121
0
          CLIP((4 * image2[indx][1] - image2[indx + u + 1][1] -
122
0
                image2[indx + u - 1][1] - image2[indx - u + 1][1] -
123
0
                image2[indx - u - 1][1] + image[indx + u + 1][c] +
124
0
                image[indx + u - 1][c] + image[indx - u + 1][c] +
125
0
                image[indx - u - 1][c]) /
126
0
               4.0)
127
0
        );
128
0
    }
129
130
0
  for (row = 1; row < height - 1; row++)
131
0
    for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
132
0
        c = FC(row, col + 1), d = 2 - c;
133
0
         col < width - 1; col += 2, indx += 2)
134
0
    {
135
136
0
      image2[indx][c] = float(CLIP((image[indx + 1][c] + image[indx - 1][c]) / 2.0));
137
0
      image2[indx][d] =
138
0
          float(CLIP((2 * image2[indx][1] - image2[indx + u][1] -
139
0
                image2[indx - u][1] + image[indx + u][d] + image[indx - u][d]) /
140
0
               2.0));
141
0
    }
142
0
}
143
144
// missing R and B are interpolated vertically and saved in image3
145
void LibRaw::dcb_color3(float (*image3)[3])
146
0
{
147
0
  int row, col, c, d, u = width, indx;
148
149
0
  for (row = 1; row < height - 1; row++)
150
0
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
151
0
        c = 2 - FC(row, col);
152
0
         col < u - 1; col += 2, indx += 2)
153
0
    {
154
155
0
      image3[indx][c] =
156
0
      float(
157
0
          CLIP((4 * image3[indx][1] - image3[indx + u + 1][1] -
158
0
                image3[indx + u - 1][1] - image3[indx - u + 1][1] -
159
0
                image3[indx - u - 1][1] + image[indx + u + 1][c] +
160
0
                image[indx + u - 1][c] + image[indx - u + 1][c] +
161
0
                image[indx - u - 1][c]) /
162
0
               4.0)
163
0
        );
164
0
    }
165
166
0
  for (row = 1; row < height - 1; row++)
167
0
    for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
168
0
        c = FC(row, col + 1), d = 2 - c;
169
0
         col < width - 1; col += 2, indx += 2)
170
0
    {
171
172
0
      image3[indx][c] =
173
0
      float(
174
0
          CLIP((2 * image3[indx][1] - image3[indx + 1][1] -
175
0
                image3[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) /
176
0
               2.0)
177
0
        );
178
0
      image3[indx][d] = float(CLIP((image[indx + u][d] + image[indx - u][d]) / 2.0));
179
0
    }
180
0
}
181
182
// decides the primary green interpolation direction
183
void LibRaw::dcb_decide(float (*image2)[3], float (*image3)[3])
184
0
{
185
0
  int row, col, c, d, u = width, v = 2 * u, indx;
186
0
  float current, current2, current3;
187
188
0
  for (row = 2; row < height - 2; row++)
189
0
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
190
0
         col < u - 2; col += 2, indx += 2)
191
0
    {
192
193
0
      d = ABS(c - 2);
194
195
0
      current = float(MAX(image[indx + v][c],
196
0
                    MAX(image[indx - v][c],
197
0
                        MAX(image[indx - 2][c], image[indx + 2][c]))) -
198
0
                MIN(image[indx + v][c],
199
0
                    MIN(image[indx - v][c],
200
0
                        MIN(image[indx - 2][c], image[indx + 2][c]))) +
201
0
                MAX(image[indx + 1 + u][d],
202
0
                    MAX(image[indx + 1 - u][d],
203
0
                        MAX(image[indx - 1 + u][d], image[indx - 1 - u][d]))) -
204
0
                MIN(image[indx + 1 + u][d],
205
0
                    MIN(image[indx + 1 - u][d],
206
0
                        MIN(image[indx - 1 + u][d], image[indx - 1 - u][d]))));
207
208
0
      current2 =
209
0
      float(
210
0
          MAX(image2[indx + v][d],
211
0
              MAX(image2[indx - v][d],
212
0
                  MAX(image2[indx - 2][d], image2[indx + 2][d]))) -
213
0
          MIN(image2[indx + v][d],
214
0
              MIN(image2[indx - v][d],
215
0
                  MIN(image2[indx - 2][d], image2[indx + 2][d]))) +
216
0
          MAX(image2[indx + 1 + u][c],
217
0
              MAX(image2[indx + 1 - u][c],
218
0
                  MAX(image2[indx - 1 + u][c], image2[indx - 1 - u][c]))) -
219
0
          MIN(image2[indx + 1 + u][c],
220
0
              MIN(image2[indx + 1 - u][c],
221
0
                  MIN(image2[indx - 1 + u][c], image2[indx - 1 - u][c])))
222
0
        );
223
224
0
      current3 =
225
0
      float(
226
0
          MAX(image3[indx + v][d],
227
0
              MAX(image3[indx - v][d],
228
0
                  MAX(image3[indx - 2][d], image3[indx + 2][d]))) -
229
0
          MIN(image3[indx + v][d],
230
0
              MIN(image3[indx - v][d],
231
0
                  MIN(image3[indx - 2][d], image3[indx + 2][d]))) +
232
0
          MAX(image3[indx + 1 + u][c],
233
0
              MAX(image3[indx + 1 - u][c],
234
0
                  MAX(image3[indx - 1 + u][c], image3[indx - 1 - u][c]))) -
235
0
          MIN(image3[indx + 1 + u][c],
236
0
              MIN(image3[indx + 1 - u][c],
237
0
                  MIN(image3[indx - 1 + u][c], image3[indx - 1 - u][c])))
238
0
        );
239
240
0
      if (ABS(current - current2) < ABS(current - current3))
241
0
        image[indx][1] = ushort(image2[indx][1]);
242
0
      else
243
0
        image[indx][1] = ushort(image3[indx][1]);
244
0
    }
245
0
}
246
247
// saves red and blue in image2
248
void LibRaw::dcb_copy_to_buffer(float (*image2)[3])
249
0
{
250
0
  int indx;
251
252
0
  for (indx = 0; indx < height * width; indx++)
253
0
  {
254
0
    image2[indx][0] = image[indx][0]; // R
255
0
    image2[indx][2] = image[indx][2]; // B
256
0
  }
257
0
}
258
259
// restores red and blue from image2
260
void LibRaw::dcb_restore_from_buffer(float (*image2)[3])
261
0
{
262
0
  int indx;
263
264
0
  for (indx = 0; indx < height * width; indx++)
265
0
  {
266
0
    image[indx][0] = ushort(image2[indx][0]); // R
267
0
    image[indx][2] = ushort(image2[indx][2]); // B
268
0
  }
269
0
}
270
271
// R and B smoothing using green contrast, all pixels except 2 pixel wide border
272
void LibRaw::dcb_pp()
273
0
{
274
0
  int g1, r1, b1, u = width, indx, row, col;
275
276
0
  for (row = 2; row < height - 2; row++)
277
0
    for (col = 2, indx = row * u + col; col < width - 2; col++, indx++)
278
0
    {
279
280
0
      r1 = int((image[indx - 1][0] + image[indx + 1][0] + image[indx - u][0] +
281
0
            image[indx + u][0] + image[indx - u - 1][0] +
282
0
            image[indx + u + 1][0] + image[indx - u + 1][0] +
283
0
            image[indx + u - 1][0]) /
284
0
           8.0f);
285
0
      g1 = int((image[indx - 1][1] + image[indx + 1][1] + image[indx - u][1] +
286
0
            image[indx + u][1] + image[indx - u - 1][1] +
287
0
            image[indx + u + 1][1] + image[indx - u + 1][1] +
288
0
            image[indx + u - 1][1]) /
289
0
           8.0f);
290
0
      b1 = int((image[indx - 1][2] + image[indx + 1][2] + image[indx - u][2] +
291
0
            image[indx + u][2] + image[indx - u - 1][2] +
292
0
            image[indx + u + 1][2] + image[indx - u + 1][2] +
293
0
            image[indx + u - 1][2]) /
294
0
           8.0f);
295
296
0
      image[indx][0] = CLIP(r1 + (image[indx][1] - g1));
297
0
      image[indx][2] = CLIP(b1 + (image[indx][1] - g1));
298
0
    }
299
0
}
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
0
{
325
0
  int row, col, c, d, u = width, w = 3 * u, indx, g1, g2;
326
0
  float f[4], g[4], (*chroma)[2];
327
328
0
  chroma = (float(*)[2])calloc(width * height, sizeof *chroma);
329
330
0
  for (row = 1; row < height - 1; row++)
331
0
    for (col = 1 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col),
332
0
        d = c / 2;
333
0
         col < u - 1; col += 2, indx += 2)
334
0
      chroma[indx][d] = float(image[indx][c] - image[indx][1]);
335
336
0
  for (row = 3; row < height - 3; row++)
337
0
    for (col = 3 + (FC(row, 1) & 1), indx = row * width + col,
338
0
        c = 1 - FC(row, col) / 2, d = 1 - c;
339
0
         col < u - 3; col += 2, indx += 2)
340
0
    {
341
0
      f[0] = 1.0f /
342
0
             (float)(1.0 +
343
0
                     fabsf(chroma[indx - u - 1][c] - chroma[indx + u + 1][c]) +
344
0
                     fabsf(chroma[indx - u - 1][c] - chroma[indx - w - 3][c]) +
345
0
                     fabsf(chroma[indx + u + 1][c] - chroma[indx - w - 3][c]));
346
0
      f[1] = 1.0f /
347
0
             (float)(1.0 +
348
0
                     fabsf(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) +
349
0
                     fabsf(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) +
350
0
                     fabsf(chroma[indx + u - 1][c] - chroma[indx - w + 3][c]));
351
0
      f[2] = 1.0f /
352
0
             (float)(1.0 +
353
0
                     fabsf(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) +
354
0
                     fabsf(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) +
355
0
                     fabsf(chroma[indx - u + 1][c] - chroma[indx + w - 3][c]));
356
0
      f[3] = 1.0f /
357
0
             (float)(1.0 +
358
0
                     fabsf(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) +
359
0
                     fabsf(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) +
360
0
                     fabsf(chroma[indx - u - 1][c] - chroma[indx + w + 3][c]));
361
0
      g[0] = 1.325f * chroma[indx - u - 1][c] - 0.175f * chroma[indx - w - 3][c] -
362
0
             0.075f * chroma[indx - w - 1][c] - 0.075f * chroma[indx - u - 3][c];
363
0
      g[1] = 1.325f * chroma[indx - u + 1][c] - 0.175f * chroma[indx - w + 3][c] -
364
0
             0.075f * chroma[indx - w + 1][c] - 0.075f * chroma[indx - u + 3][c];
365
0
      g[2] = 1.325f * chroma[indx + u - 1][c] - 0.175f * chroma[indx + w - 3][c] -
366
0
             0.075f * chroma[indx + w - 1][c] - 0.075f * chroma[indx + u - 3][c];
367
0
      g[3] = 1.325f * chroma[indx + u + 1][c] - 0.175f * chroma[indx + w + 3][c] -
368
0
             0.075f * chroma[indx + w + 1][c] - 0.075f * chroma[indx + u + 3][c];
369
0
      chroma[indx][c] =
370
0
          (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
371
0
          (f[0] + f[1] + f[2] + f[3]);
372
0
    }
373
0
  for (row = 3; row < height - 3; row++)
374
0
    for (col = 3 + (FC(row, 2) & 1), indx = row * width + col,
375
0
        c = FC(row, col + 1) / 2;
376
0
         col < u - 3; col += 2, indx += 2)
377
0
      for (d = 0; d <= 1; c = 1 - c, d++)
378
0
      {
379
0
        f[0] = 1.0f /
380
0
               (float)(1.0f + fabsf(chroma[indx - u][c] - chroma[indx + u][c]) +
381
0
                       fabsf(chroma[indx - u][c] - chroma[indx - w][c]) +
382
0
                       fabsf(chroma[indx + u][c] - chroma[indx - w][c]));
383
0
        f[1] = 1.0f /
384
0
               (float)(1.0f + fabsf(chroma[indx + 1][c] - chroma[indx - 1][c]) +
385
0
                       fabsf(chroma[indx + 1][c] - chroma[indx + 3][c]) +
386
0
                       fabsf(chroma[indx - 1][c] - chroma[indx + 3][c]));
387
0
        f[2] = 1.0f /
388
0
               (float)(1.0 + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) +
389
0
                       fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) +
390
0
                       fabs(chroma[indx + 1][c] - chroma[indx - 3][c]));
391
0
        f[3] = 1.0f /
392
0
               (float)(1.0 + fabs(chroma[indx + u][c] - chroma[indx - u][c]) +
393
0
                       fabs(chroma[indx + u][c] - chroma[indx + w][c]) +
394
0
                       fabs(chroma[indx - u][c] - chroma[indx + w][c]));
395
396
0
        g[0] = 0.875f * chroma[indx - u][c] + 0.125f * chroma[indx - w][c];
397
0
        g[1] = 0.875f * chroma[indx + 1][c] + 0.125f * chroma[indx + 3][c];
398
0
        g[2] = 0.875f * chroma[indx - 1][c] + 0.125f * chroma[indx - 3][c];
399
0
        g[3] = 0.875f * chroma[indx + u][c] + 0.125f * chroma[indx + w][c];
400
401
0
        chroma[indx][c] =
402
0
            (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
403
0
            (f[0] + f[1] + f[2] + f[3]);
404
0
      }
405
406
0
  for (row = 6; row < height - 6; row++)
407
0
    for (col = 6, indx = row * width + col; col < width - 6; col++, indx++)
408
0
    {
409
0
      image[indx][0] = CLIP(chroma[indx][0] + image[indx][1]);
410
0
      image[indx][2] = CLIP(chroma[indx][1] + image[indx][1]);
411
412
0
      g1 = MIN(
413
0
          image[indx + 1 + u][0],
414
0
          MIN(image[indx + 1 - u][0],
415
0
              MIN(image[indx - 1 + u][0],
416
0
                  MIN(image[indx - 1 - u][0],
417
0
                      MIN(image[indx - 1][0],
418
0
                          MIN(image[indx + 1][0],
419
0
                              MIN(image[indx - u][0], image[indx + u][0])))))));
420
421
0
      g2 = MAX(
422
0
          image[indx + 1 + u][0],
423
0
          MAX(image[indx + 1 - u][0],
424
0
              MAX(image[indx - 1 + u][0],
425
0
                  MAX(image[indx - 1 - u][0],
426
0
                      MAX(image[indx - 1][0],
427
0
                          MAX(image[indx + 1][0],
428
0
                              MAX(image[indx - u][0], image[indx + u][0])))))));
429
430
0
      image[indx][0] = ULIM(image[indx][0], g2, g1);
431
432
0
      g1 = MIN(
433
0
          image[indx + 1 + u][2],
434
0
          MIN(image[indx + 1 - u][2],
435
0
              MIN(image[indx - 1 + u][2],
436
0
                  MIN(image[indx - 1 - u][2],
437
0
                      MIN(image[indx - 1][2],
438
0
                          MIN(image[indx + 1][2],
439
0
                              MIN(image[indx - u][2], image[indx + u][2])))))));
440
441
0
      g2 = MAX(
442
0
          image[indx + 1 + u][2],
443
0
          MAX(image[indx + 1 - u][2],
444
0
              MAX(image[indx - 1 + u][2],
445
0
                  MAX(image[indx - 1 - u][2],
446
0
                      MAX(image[indx - 1][2],
447
0
                          MAX(image[indx + 1][2],
448
0
                              MAX(image[indx - u][2], image[indx + u][2])))))));
449
450
0
      image[indx][2] = ULIM(image[indx][2], g2, g1);
451
0
    }
452
453
0
  free(chroma);
454
0
}
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
0
{
461
0
  int row, col, u = width, indx;
462
463
0
  for (row = 1; row < height - 1; row++)
464
0
  {
465
0
    for (col = 1, indx = row * width + col; col < width - 1; col++, indx++)
466
0
    {
467
468
0
      if (image[indx][1] > (image[indx - 1][1] + image[indx + 1][1] +
469
0
                            image[indx - u][1] + image[indx + u][1]) /
470
0
                               4.0)
471
0
        image[indx][3] = ((MIN(image[indx - 1][1], image[indx + 1][1]) +
472
0
                           image[indx - 1][1] + image[indx + 1][1]) <
473
0
                          (MIN(image[indx - u][1], image[indx + u][1]) +
474
0
                           image[indx - u][1] + image[indx + u][1]));
475
0
      else
476
0
        image[indx][3] = ((MAX(image[indx - 1][1], image[indx + 1][1]) +
477
0
                           image[indx - 1][1] + image[indx + 1][1]) >
478
0
                          (MAX(image[indx - u][1], image[indx + u][1]) +
479
0
                           image[indx - u][1] + image[indx + u][1]));
480
0
    }
481
0
  }
482
0
}
483
484
// interpolated green pixels are corrected using the map
485
void LibRaw::dcb_correction()
486
0
{
487
0
  int current, row, col, u = width, v = 2 * u, indx;
488
489
0
  for (row = 2; row < height - 2; row++)
490
0
    for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
491
0
         col += 2, indx += 2)
492
0
    {
493
494
0
      current = 4 * image[indx][3] +
495
0
                2 * (image[indx + u][3] + image[indx - u][3] +
496
0
                     image[indx + 1][3] + image[indx - 1][3]) +
497
0
                image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
498
0
                image[indx - 2][3];
499
500
0
      image[indx][1] =
501
0
      ushort(
502
0
          ((16 - current) * (image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
503
0
           current * (image[indx - u][1] + image[indx + u][1]) / 2.0) /
504
0
          16.0f);
505
0
    }
506
0
}
507
508
// interpolated green pixels are corrected using the map
509
// with contrast correction
510
void LibRaw::dcb_correction2()
511
0
{
512
0
  int current, row, col, c, u = width, v = 2 * u, indx;
513
514
0
  for (row = 4; row < height - 4; row++)
515
0
    for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
516
0
         col < u - 4; col += 2, indx += 2)
517
0
    {
518
519
0
      current = 4 * image[indx][3] +
520
0
                2 * (image[indx + u][3] + image[indx - u][3] +
521
0
                     image[indx + 1][3] + image[indx - 1][3]) +
522
0
                image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
523
0
                image[indx - 2][3];
524
525
0
      image[indx][1] = CLIP(
526
0
          ((16 - current) * ((image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
527
0
                             image[indx][c] -
528
0
                             (image[indx + 2][c] + image[indx - 2][c]) / 2.0) +
529
0
           current * ((image[indx - u][1] + image[indx + u][1]) / 2.0 +
530
0
                      image[indx][c] -
531
0
                      (image[indx + v][c] + image[indx - v][c]) / 2.0)) /
532
0
          16.0);
533
0
    }
534
0
}
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
0
{
646
0
  int indx;
647
0
  for (indx = 0; indx < height * width; indx++)
648
0
  {
649
650
0
    image2[indx][0] = image[indx][0] + image[indx][1] + image[indx][2]; // L
651
0
    image2[indx][1] = 1.732050808 * (image[indx][0] - image[indx][1]);  // C
652
0
    image2[indx][2] =
653
0
        2.0 * image[indx][2] - image[indx][0] - image[indx][1]; // H
654
0
  }
655
0
}
656
657
// converts LCH to RGB colorspace and saves it back to image
658
void LibRaw::lch_to_rgb(double (*image2)[3])
659
0
{
660
0
  int indx;
661
0
  for (indx = 0; indx < height * width; indx++)
662
0
  {
663
664
0
    image[indx][0] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 +
665
0
                          image2[indx][1] / 3.464101615);
666
0
    image[indx][1] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 -
667
0
                          image2[indx][1] / 3.464101615);
668
0
    image[indx][2] = CLIP(image2[indx][0] / 3.0 + image2[indx][2] / 3.0);
669
0
  }
670
0
}
671
672
// denoising using interpolated neighbours
673
void LibRaw::fbdd_correction()
674
0
{
675
0
  int row, col, c, u = width, indx;
676
677
0
  for (row = 2; row < height - 2; row++)
678
0
  {
679
0
    for (col = 2, indx = row * width + col; col < width - 2; col++, indx++)
680
0
    {
681
682
0
      c = fcol(row, col);
683
684
0
      image[indx][c] =
685
0
          ULIM(image[indx][c],
686
0
               MAX(image[indx - 1][c],
687
0
                   MAX(image[indx + 1][c],
688
0
                       MAX(image[indx - u][c], image[indx + u][c]))),
689
0
               MIN(image[indx - 1][c],
690
0
                   MIN(image[indx + 1][c],
691
0
                       MIN(image[indx - u][c], image[indx + u][c]))));
692
0
    }
693
0
  }
694
0
}
695
696
// corrects chroma noise
697
void LibRaw::fbdd_correction2(double (*image2)[3])
698
0
{
699
0
  int indx, v = 2 * width;
700
0
  int col, row;
701
0
  double Co, Ho, ratio;
702
703
0
  for (row = 6; row < height - 6; row++)
704
0
  {
705
0
    for (col = 6; col < width - 6; col++)
706
0
    {
707
0
      indx = row * width + col;
708
709
0
      if (image2[indx][1] * image2[indx][2] != 0)
710
0
      {
711
0
        Co = (image2[indx + v][1] + image2[indx - v][1] + image2[indx - 2][1] +
712
0
              image2[indx + 2][1] -
713
0
              MAX(image2[indx - 2][1],
714
0
                  MAX(image2[indx + 2][1],
715
0
                      MAX(image2[indx - v][1], image2[indx + v][1]))) -
716
0
              MIN(image2[indx - 2][1],
717
0
                  MIN(image2[indx + 2][1],
718
0
                      MIN(image2[indx - v][1], image2[indx + v][1])))) /
719
0
             2.0;
720
0
        Ho = (image2[indx + v][2] + image2[indx - v][2] + image2[indx - 2][2] +
721
0
              image2[indx + 2][2] -
722
0
              MAX(image2[indx - 2][2],
723
0
                  MAX(image2[indx + 2][2],
724
0
                      MAX(image2[indx - v][2], image2[indx + v][2]))) -
725
0
              MIN(image2[indx - 2][2],
726
0
                  MIN(image2[indx + 2][2],
727
0
                      MIN(image2[indx - v][2], image2[indx + v][2])))) /
728
0
             2.0;
729
0
        ratio = sqrt((Co * Co + Ho * Ho) / (image2[indx][1] * image2[indx][1] +
730
0
                                            image2[indx][2] * image2[indx][2]));
731
732
0
        if (ratio < 0.85)
733
0
        {
734
0
          image2[indx][0] =
735
0
              -(image2[indx][1] + image2[indx][2] - Co - Ho) + image2[indx][0];
736
0
          image2[indx][1] = Co;
737
0
          image2[indx][2] = Ho;
738
0
        }
739
0
      }
740
0
    }
741
0
  }
742
0
}
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
0
{
748
0
  int row, col, c, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, indx,
749
0
                   min, max;
750
0
  float f[4], g[4];
751
752
0
  for (row = 5; row < height - 5; row++)
753
0
    for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col);
754
0
         col < u - 5; col += 2, indx += 2)
755
0
    {
756
757
0
      f[0] = 1.0f / (1.0f + abs(image[indx - u][1] - image[indx - w][1]) +
758
0
                    abs(image[indx - w][1] - image[indx + y][1]));
759
0
      f[1] = 1.0f / (1.0f + abs(image[indx + 1][1] - image[indx + 3][1]) +
760
0
                    abs(image[indx + 3][1] - image[indx - 5][1]));
761
0
      f[2] = 1.0f / (1.0f + abs(image[indx - 1][1] - image[indx - 3][1]) +
762
0
                    abs(image[indx - 3][1] - image[indx + 5][1]));
763
0
      f[3] = 1.0f / (1.0f + abs(image[indx + u][1] - image[indx + w][1]) +
764
0
                    abs(image[indx + w][1] - image[indx - y][1]));
765
766
0
      g[0] = float(CLIP((23 * image[indx - u][1] + 23 * image[indx - w][1] +
767
0
                   2 * image[indx - y][1] +
768
0
                   8 * (image[indx - v][c] - image[indx - x][c]) +
769
0
                   40 * (image[indx][c] - image[indx - v][c])) /
770
0
                  48.0f));
771
0
      g[1] = float(CLIP((23 * image[indx + 1][1] + 23 * image[indx + 3][1] +
772
0
                   2 * image[indx + 5][1] +
773
0
                   8 * (image[indx + 2][c] - image[indx + 4][c]) +
774
0
                   40 * (image[indx][c] - image[indx + 2][c])) /
775
0
                  48.f));
776
0
      g[2] = float(CLIP((23 * image[indx - 1][1] + 23 * image[indx - 3][1] +
777
0
                   2 * image[indx - 5][1] +
778
0
                   8 * (image[indx - 2][c] - image[indx - 4][c]) +
779
0
                   40 * (image[indx][c] - image[indx - 2][c])) /
780
0
                  48.0f));
781
0
      g[3] = float(CLIP((23 * image[indx + u][1] + 23 * image[indx + w][1] +
782
0
                   2 * image[indx + y][1] +
783
0
                   8 * (image[indx + v][c] - image[indx + x][c]) +
784
0
                   40 * (image[indx][c] - image[indx + v][c])) /
785
0
                  48.0f));
786
787
0
      image[indx][1] =
788
0
          CLIP((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
789
0
               (f[0] + f[1] + f[2] + f[3]));
790
791
0
      min = MIN(
792
0
          image[indx + 1 + u][1],
793
0
          MIN(image[indx + 1 - u][1],
794
0
              MIN(image[indx - 1 + u][1],
795
0
                  MIN(image[indx - 1 - u][1],
796
0
                      MIN(image[indx - 1][1],
797
0
                          MIN(image[indx + 1][1],
798
0
                              MIN(image[indx - u][1], image[indx + u][1])))))));
799
800
0
      max = MAX(
801
0
          image[indx + 1 + u][1],
802
0
          MAX(image[indx + 1 - u][1],
803
0
              MAX(image[indx - 1 + u][1],
804
0
                  MAX(image[indx - 1 - u][1],
805
0
                      MAX(image[indx - 1][1],
806
0
                          MAX(image[indx + 1][1],
807
0
                              MAX(image[indx - u][1], image[indx + u][1])))))));
808
809
0
      image[indx][1] = ULIM(image[indx][1], max, min);
810
0
    }
811
0
}
812
813
// FBDD (Fake Before Demosaicing Denoising)
814
void LibRaw::fbdd(int noiserd)
815
0
{
816
0
  double(*image2)[3];
817
  // safety net: disable for 4-color bayer or full-color images
818
0
  if (colors != 3 || !filters)
819
0
    return;
820
0
  image2 = (double(*)[3])calloc(width * height, sizeof *image2);
821
822
0
  border_interpolate(4);
823
824
0
  if (noiserd > 1)
825
0
  {
826
0
    fbdd_green();
827
    // dcb_color_full(image2);
828
0
    dcb_color_full();
829
0
    fbdd_correction();
830
831
0
    dcb_color();
832
0
    rgb_to_lch(image2);
833
0
    fbdd_correction2(image2);
834
0
    fbdd_correction2(image2);
835
0
    lch_to_rgb(image2);
836
0
  }
837
0
  else
838
0
  {
839
0
    fbdd_green();
840
    // dcb_color_full(image2);
841
0
    dcb_color_full();
842
0
    fbdd_correction();
843
0
  }
844
845
0
  free(image2);
846
0
}
847
848
// DCB demosaicing main routine
849
void LibRaw::dcb(int iterations, int dcb_enhance)
850
0
{
851
852
0
  int i = 1;
853
854
0
  float(*image2)[3];
855
0
  image2 = (float(*)[3])calloc(width * height, sizeof *image2);
856
857
0
  float(*image3)[3];
858
0
  image3 = (float(*)[3])calloc(width * height, sizeof *image3);
859
860
0
  border_interpolate(6);
861
862
0
  dcb_hor(image2);
863
0
  dcb_color2(image2);
864
865
0
  dcb_ver(image3);
866
0
  dcb_color3(image3);
867
868
0
  dcb_decide(image2, image3);
869
870
0
  free(image3);
871
872
0
  dcb_copy_to_buffer(image2);
873
874
0
  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
0
  dcb_color();
885
0
  dcb_pp();
886
887
0
  dcb_map();
888
0
  dcb_correction2();
889
890
0
  dcb_map();
891
0
  dcb_correction();
892
893
0
  dcb_map();
894
0
  dcb_correction();
895
896
0
  dcb_map();
897
0
  dcb_correction();
898
899
0
  dcb_map();
900
0
  dcb_restore_from_buffer(image2);
901
0
  dcb_color();
902
903
0
  if (dcb_enhance)
904
0
  {
905
0
    dcb_refinement();
906
    // dcb_color_full(image2);
907
0
    dcb_color_full();
908
0
  }
909
910
0
  free(image2);
911
0
}