Coverage Report

Created: 2026-11-12 07:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libraw/src/demosaic/xtrans_demosaic.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2026 LibRaw LLC (info@libraw.org)
3
 *
4
 LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
5
 dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
6
 LibRaw do not use RESTRICTED code from dcraw.c
7
8
 LibRaw is free software; you can redistribute it and/or modify
9
 it under the terms of the one of two licenses as you choose:
10
11
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
12
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
13
14
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
15
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
16
17
 */
18
19
#include "../../internal/dcraw_defs.h"
20
21
621M
#define fcol(row, col) xtrans[(row + 6) % 6][(col + 6) % 6]
22
/*
23
   Frank Markesteijn's algorithm for Fuji X-Trans sensors
24
 */
25
void LibRaw::xtrans_interpolate(int passes)
26
172
{
27
172
  int cstat[4] = {0, 0, 0, 0};
28
172
  int ndir;
29
172
  static const short orth[12] = {1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1},
30
172
                     patt[2][16] = {{0, 1, 0, -1, 2, 0, -1, 0, 1, 1, 1, -1, 0,
31
172
                                     0, 0, 0},
32
172
                                    {0, 1, 0, -2, 1, 0, -2, 0, 1, 1, -2, -2, 1,
33
172
                                     -1, -1, 1}},
34
172
                     dir[4] = {1, LIBRAW_AHD_TILE, LIBRAW_AHD_TILE + 1,
35
172
                               LIBRAW_AHD_TILE - 1};
36
172
  short allhex[3][3][2][8];
37
172
  ushort sgrow = 0, sgcol = 0;
38
39
172
  if (width < LIBRAW_AHD_TILE || height < LIBRAW_AHD_TILE || filters != 9)
40
5
    throw LIBRAW_EXCEPTION_IO_CORRUPT; // too small image
41
                                       /* Check against right pattern */
42
1.16k
  for (int row = 0; row < 6; row++)
43
7.01k
    for (int col = 0; col < 6; col++)
44
6.01k
      cstat[(unsigned)fcol(row, col)]++;
45
46
167
  if (cstat[0] < 6 || cstat[0] > 10 || cstat[1] < 16 || cstat[1] > 24 ||
47
160
      cstat[2] < 6 || cstat[2] > 10 || cstat[3])
48
9
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
49
50
  // Init allhex table to unreasonable values
51
632
  for (int i = 0; i < 3; i++)
52
1.89k
    for (int j = 0; j < 3; j++)
53
4.26k
      for (int k = 0; k < 2; k++)
54
25.5k
        for (int l = 0; l < 8; l++)
55
22.7k
          allhex[i][j][k][l] = 32700;
56
57
158
  cielab(0, 0);
58
158
  ndir = 4 << int(passes > 1);
59
60
158
  int minv = 0, maxv = 0, minh = 0, maxh = 0;
61
  /* Map a green hexagon around each non-green pixel and vice versa:  */
62
632
  for (int row = 0; row < 3; row++)
63
1.89k
    for (int col = 0; col < 3; col++)
64
8.53k
      for (int ng = 0, d = 0; d < 10; d += 2)
65
7.11k
      {
66
7.11k
        int g = fcol(row, col) == 1;
67
7.11k
        if (fcol(row + orth[d], col + orth[d + 2]) == 1)
68
2.31k
          ng = 0;
69
4.79k
        else
70
4.79k
          ng++;
71
7.11k
        if (ng == 4)
72
287
        {
73
287
          sgrow = row;
74
287
          sgcol = col;
75
287
        }
76
7.11k
        if (ng == g + 1)
77
1.97k
        {
78
1.97k
            int c;
79
1.97k
            FORC(8)
80
15.7k
            {
81
15.7k
                int v = orth[d] * patt[g][c * 2] + orth[d + 1] * patt[g][c * 2 + 1];
82
15.7k
                int h = orth[d + 2] * patt[g][c * 2] + orth[d + 3] * patt[g][c * 2 + 1];
83
15.7k
                minv = MIN(v, minv);
84
15.7k
                maxv = MAX(v, maxv);
85
15.7k
                minh = MIN(h, minh);
86
15.7k
                maxh = MAX(h, maxh);
87
15.7k
                allhex[row][col][0][c ^ (g * 2 & d)] = h + v * width;
88
15.7k
                allhex[row][col][1][c ^ (g * 2 & d)] = h + v * LIBRAW_AHD_TILE;
89
15.7k
            }
90
1.97k
        }
91
7.11k
      }
92
93
  // Check allhex table initialization
94
609
  for (int i = 0; i < 3; i++)
95
1.82k
    for (int j = 0; j < 3; j++)
96
4.08k
      for (int k = 0; k < 2; k++)
97
24.4k
        for (int l = 0; l < 8; l++)
98
21.7k
          if (allhex[i][j][k][l] > maxh + maxv * width + 1 ||
99
21.7k
              allhex[i][j][k][l] < minh + minv * width - 1)
100
9
            throw LIBRAW_EXCEPTION_IO_CORRUPT;
101
149
  int retrycount = 0;
102
103
  /* Set green1 and green3 to the minimum and maximum allowed values: */
104
409k
  for (int row = 2; row < height - 2; row++)
105
409k
  {
106
409k
      int col;
107
409k
      ushort min, max;
108
259M
      for (col = 2, max = 0u, min = 0xffffu; col < int(width) - 2; col++)
109
259M
      {
110
259M
          if (fcol(row, col) == 1 && (min = ~(max = 0)))
111
233M
              continue;
112
26.0M
          ushort(*pix)[4];
113
26.0M
          pix = image + row * width + col;
114
26.0M
          short* hex = allhex[row % 3][col % 3][0];
115
26.0M
          if (!max)
116
19.8M
          {
117
19.8M
              int c;
118
19.8M
              FORC(6)
119
118M
              {
120
118M
                  int val = pix[hex[c]][1];
121
118M
                  if (min > val)
122
22.1M
                      min = val;
123
118M
                  if (max < val)
124
13.9M
                      max = val;
125
118M
              }
126
19.8M
          }
127
26.0M
          pix[0][1] = min;
128
26.0M
          pix[0][3] = max;
129
26.0M
          switch ((row - sgrow) % 3)
130
26.0M
          {
131
6.57M
          case 1:
132
6.57M
              if (row < height - 3)
133
6.56M
              {
134
6.56M
                  row++;
135
6.56M
                  col--;
136
6.56M
              }
137
6.57M
              break;
138
6.91M
          case 2:
139
6.91M
              if ((min = ~(max = 0)) && (col += 2) < width - 3 && row > 2)
140
6.88M
              {
141
6.88M
                  row--;
142
6.88M
                  if (retrycount++ > width * height)
143
6
                      throw LIBRAW_EXCEPTION_IO_CORRUPT;
144
6.88M
              }
145
26.0M
          }
146
26.0M
      }
147
409k
  }
148
149
939
  for (int row = 3; row < 9 && row < height - 3; row++)
150
5.61k
    for (int col = 3; col < 9 && col < width - 3; col++)
151
4.81k
    {
152
4.81k
      if ((fcol(row, col)) == 1)
153
2.26k
        continue;
154
2.55k
          short* hex = allhex[row % 3][col % 3][0];
155
2.55k
          int c;
156
2.55k
      FORC(2)
157
5.11k
      {
158
5.11k
        int idx3 = 3 * hex[4 + c] + row * width + col;
159
5.11k
        int idx4 = -3 * hex[4 + c] + row * width + col;
160
5.11k
        int maxidx = width * height;
161
5.11k
        if (idx3 < 0 || idx3 >= maxidx)
162
2
          throw LIBRAW_EXCEPTION_IO_CORRUPT;
163
5.11k
        if (idx4 < 0 || idx4 >= maxidx)
164
11
          throw LIBRAW_EXCEPTION_IO_CORRUPT;
165
5.11k
      }
166
2.55k
    }
167
168
#if defined(LIBRAW_USE_OPENMP)
169
  int buffer_count = omp_get_max_threads();
170
#else
171
130
  int buffer_count = 1;
172
130
#endif
173
174
130
  size_t buffer_size = LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 11 + 6);
175
130
  char** buffers = malloc_omp_buffers(buffer_count, buffer_size);
176
130
  INT64 allocate_sz = (INT64(iheight) + 6) * (INT64(iwidth) + 6) * sizeof(ushort)*4LL;
177
130
    ushort (*destimage)[4] = (ushort(*)[4])calloc(allocate_sz, 1);
178
  // For border interpolate: keep original pixels
179
130
  memmove(destimage,image,allocate_sz);
180
181
#if defined(LIBRAW_USE_OPENMP)
182
# pragma omp parallel for schedule(dynamic) default(none) firstprivate(buffers, allhex, passes, sgrow, sgcol, ndir) shared(dir, destimage) 
183
#endif
184
392
    for (int top = 3; top < height - 19; top += LIBRAW_AHD_TILE - 16)
185
262
    {
186
#if defined(LIBRAW_USE_OPENMP)
187
        char* buffer = buffers[omp_get_thread_num()];
188
#else
189
262
        char* buffer = buffers[0];
190
262
#endif
191
192
262
        ushort(*rgb)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3], (*rix)[3];
193
262
        short(*lab)[LIBRAW_AHD_TILE][3], (*lix)[3];
194
262
        float(*drv)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE];
195
262
        char(*homo)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE];
196
197
262
        rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer;
198
262
        lab = (short(*)[LIBRAW_AHD_TILE][3])(
199
262
            buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 6));
200
262
        drv = (float(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE])(
201
262
            buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 6 + 6));
202
262
        homo = (char(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE])(
203
262
            buffer + LIBRAW_AHD_TILE * LIBRAW_AHD_TILE * (ndir * 10 + 6));
204
205
792
        for (int left = 3; left < width - 19; left += LIBRAW_AHD_TILE - 16)
206
530
        {
207
530
            int mrow = MIN(top + LIBRAW_AHD_TILE, height - 3);
208
530
            int mcol = MIN(left + LIBRAW_AHD_TILE, width - 3);
209
164k
            for (int row = top; row < mrow; row++)
210
60.3M
                for (int col = left; col < mcol; col++)
211
60.2M
                    memcpy(rgb[0][row - top][col - left], image[row * width + col], 6);
212
530
            int c;
213
1.59k
            FORC3 memcpy(rgb[c + 1], rgb[0], sizeof * rgb);
214
215
            /* Interpolate green horizontally, vertically, and along both diagonals:
216
             */
217
530
            int color[3][8];
218
164k
            for (int row = top; row < mrow; row++)
219
60.3M
                for (int col = left; col < mcol; col++)
220
60.2M
                {
221
60.2M
                    int f;
222
60.2M
                    if ((f = fcol(row, col)) == 1)
223
28.0M
                        continue;
224
32.1M
                    ushort (*pix)[4] = image + row * width + col;
225
32.1M
                    short* hex = allhex[row % 3][col % 3][0];
226
32.1M
                    color[1][0] = 174 * (pix[hex[1]][1] + pix[hex[0]][1]) -
227
32.1M
                        46 * (pix[2 * hex[1]][1] + pix[2 * hex[0]][1]);
228
32.1M
                    color[1][1] = 223 * pix[hex[3]][1] + pix[hex[2]][1] * 33 +
229
32.1M
                        92 * (pix[0][f] - pix[-hex[2]][f]);
230
32.1M
                    FORC(2)
231
64.3M
                        color[1][2 + c] = 164 * pix[hex[4 + c]][1] +
232
64.3M
                        92 * pix[-2 * hex[4 + c]][1] +
233
64.3M
                        33 * (2 * pix[0][f] - pix[3 * hex[4 + c]][f] -
234
64.3M
                            pix[-3 * hex[4 + c]][f]);
235
128M
                    FORC4 rgb[c ^ !((row - sgrow) % 3)][row - top][col - left][1] =
236
128M
                        LIM(color[1][c] >> 8, pix[0][1], pix[0][3]);
237
32.1M
                }
238
239
2.12k
            for (int pass = 0; pass < passes; pass++)
240
1.59k
            {
241
1.59k
                if (pass == 1)
242
530
                    memcpy(rgb += 4, buffer, 4 * sizeof * rgb);
243
244
                /* Recalculate green from interpolated values of closer pixels: */
245
1.59k
                if (pass)
246
1.06k
                {
247
324k
                    for (int row = top + 2; row < mrow - 2; row++)
248
117M
                        for (int col = left + 2; col < mcol - 2; col++)
249
117M
                        {
250
117M
                            int f;
251
117M
                            if ((f = fcol(row, col)) == 1)
252
54.6M
                                continue;
253
62.9M
                            ushort(*pix)[4] = image + row * width + col;
254
62.9M
                            short* hex = allhex[row % 3][col % 3][1];
255
251M
                            for (int d = 3; d < 6; d++)
256
188M
                            {
257
188M
                                rix =
258
188M
                                    &rgb[(d - 2) ^ !((row - sgrow) % 3)][row - top][col - left];
259
188M
                                int val = rix[-2 * hex[d]][1] + 2 * rix[hex[d]][1] -
260
188M
                                    rix[-2 * hex[d]][f] - 2 * rix[hex[d]][f] + 3 * rix[0][f];
261
188M
                                rix[0][1] = LIM(val / 3, pix[0][1], pix[0][3]);
262
188M
                            }
263
62.9M
                        }
264
1.06k
                }
265
266
                /* Interpolate red and blue values for solitary green pixels: */
267
163k
                for (int row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3)
268
10.4M
                    for (int col = (left - sgcol + 4) / 3 * 3 + sgcol; col < mcol - 2; col += 3)
269
10.4M
                {
270
10.4M
                    rix = &rgb[0][row - top][col - left];
271
10.4M
                    int h = fcol(row, col + 1);
272
273
10.4M
          if (h == 1) // Incorrect pattern
274
76.8k
                      break;
275
276
10.3M
                    float diff[6];
277
10.3M
                    memset(diff, 0, sizeof diff);
278
72.3M
                    for (int i = 1, d = 0; d < 6; d++, i ^= LIBRAW_AHD_TILE ^ 1, h ^= 2)
279
62.0M
                    {
280
186M
                        for (c = 0; c < 2; c++, h ^= 2)
281
124M
                        {
282
124M
                            int g = 2 * rix[0][1] - rix[i << c][1] - rix[-i << c][1];
283
124M
                            color[h][d] = g + rix[i << c][h] + rix[-i << c][h];
284
124M
                            if (d > 1)
285
82.6M
                                diff[d] += SQR((float)rix[i << c][1] - (float)rix[-i << c][1] -
286
82.6M
                                    (float)rix[i << c][h] + (float)rix[-i << c][h]) + SQR((float)g);
287
124M
                        }
288
62.0M
                        if (d > 1 && (d & 1))
289
20.6M
                            if (diff[d - 1] < diff[d])
290
12.0M
                                FORC(2) color[c * 2][d] = color[c * 2][d - 1];
291
62.0M
                        if (d < 2 || (d & 1))
292
41.3M
                        {
293
82.6M
                            FORC(2) rix[0][c * 2] = CLIP(color[c * 2][d] / 2);
294
41.3M
                            rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE;
295
41.3M
                        }
296
62.0M
                    }
297
10.3M
                }
298
299
                /* Interpolate red for blue pixels and vice versa:    */
300
483k
                for (int row = top + 3; row < mrow - 3; row++)
301
174M
                    for (int col = left + 3; col < mcol - 3; col++)
302
174M
                    {
303
174M
                        int f;
304
174M
                        if ((f = 2 - fcol(row, col)) == 1)
305
81.0M
                            continue;
306
93.2M
                        rix = &rgb[0][row - top][col - left];
307
93.2M
                        c = (row - sgrow) % 3 ? LIBRAW_AHD_TILE : 1;
308
93.2M
                        int h = 3 * (c ^ LIBRAW_AHD_TILE ^ 1);
309
466M
                        for (int d = 0; d < 4; d++, rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE)
310
372M
                        {
311
372M
                            int i = d > 1 || ((d ^ c) & 1) ||
312
93.2M
                                ((ABS(rix[0][1] - rix[c][1]) +
313
93.2M
                                    ABS(rix[0][1] - rix[-c][1])) <
314
93.2M
                                    2 * (ABS(rix[0][1] - rix[h][1]) +
315
93.2M
                                        ABS(rix[0][1] - rix[-h][1])))
316
372M
                                ? c
317
372M
                                : h;
318
372M
                            rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + 2 * rix[0][1] -
319
372M
                                rix[i][1] - rix[-i][1]) /
320
372M
                                2);
321
372M
                        }
322
93.2M
                    }
323
324
                /* Fill in red and blue for 2x2 blocks of green:    */
325
486k
                for (int row = top + 2; row < mrow - 2; row++)
326
485k
                    if ((row - sgrow) % 3)
327
117M
                        for (int col = left + 2; col < mcol - 2; col++)
328
117M
                            if ((col - sgcol) % 3)
329
78.3M
                            {
330
78.3M
                                rix = &rgb[0][row - top][col - left];
331
78.3M
                                short* hex = allhex[row % 3][col % 3][1];
332
391M
                                for (int d = 0; d < 8;
333
313M
                                    d += 2, rix += LIBRAW_AHD_TILE * LIBRAW_AHD_TILE)
334
313M
                                    if (hex[d] + hex[d + 1])
335
187M
                                    {
336
187M
                                        int g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1];
337
561M
                                        for (c = 0; c < 4; c += 2)
338
374M
                                            rix[0][c] = CLIP(
339
187M
                                                (g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) / 3);
340
187M
                                    }
341
126M
                                    else
342
126M
                                    {
343
126M
                                        int g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1];
344
378M
                                        for (c = 0; c < 4; c += 2)
345
252M
                                            rix[0][c] =
346
252M
                                            CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) / 2);
347
126M
                                    }
348
78.3M
                            }
349
1.59k
            }
350
530
            rgb = (ushort(*)[LIBRAW_AHD_TILE][LIBRAW_AHD_TILE][3])buffer;
351
530
            mrow -= top;
352
530
            mcol -= left;
353
354
            /* Convert to CIELab and differentiate in all directions: */
355
            // no effect
356
4.77k
            for (int d = 0; d < ndir; d++)
357
4.24k
            {
358
1.29M
                for (int row = 2; row < mrow - 2; row++)
359
471M
                    for (int col = 2; col < mcol - 2; col++)
360
470M
                        cielab(rgb[d][row][col], lab[row][col]);
361
1.28M
                for (int f = dir[d & 3], row = 3; row < mrow - 3; row++)
362
465M
                    for (int col = 3; col < mcol - 3; col++)
363
464M
                    {
364
464M
                        lix = &lab[row][col];
365
464M
                        int g = 2 * lix[0][0] - lix[f][0] - lix[-f][0];
366
464M
                        drv[d][row][col] =
367
464M
              float(
368
464M
                            SQR(g) +
369
464M
                            SQR((2 * lix[0][1] - lix[f][1] - lix[-f][1] + g * 500 / 232)) +
370
464M
                            SQR((2 * lix[0][2] - lix[f][2] - lix[-f][2] - g * 500 / 580))
371
464M
                );
372
464M
                    }
373
4.24k
            }
374
375
            /* Build homogeneity maps from the derivatives:     */
376
530
            memset(homo, 0, ndir * LIBRAW_AHD_TILE * LIBRAW_AHD_TILE);
377
160k
            for (int row = 4; row < mrow - 4; row++)
378
57.5M
                for (int col = 4; col < mcol - 4; col++)
379
57.3M
                {
380
57.3M
                    int d;
381
57.3M
                    float tr;
382
516M
                    for (tr = FLT_MAX, d = 0; d < ndir; d++)
383
459M
                        if (tr > drv[d][row][col])
384
93.2M
                            tr = drv[d][row][col];
385
57.3M
                    tr *= 8;
386
516M
                    for (int dd = 0; dd < ndir; dd++)
387
1.83G
                        for (int v = -1; v <= 1; v++)
388
5.50G
                            for (int h = -1; h <= 1; h++)
389
4.13G
                                if (drv[dd][row + v][col + h] <= tr)
390
3.15G
                                    homo[dd][row][col]++;
391
57.3M
                }
392
393
            /* Average the most homogeneous pixels for the final result:  */
394
530
            if (height - top < LIBRAW_AHD_TILE + 4)
395
263
                mrow = height - top + 2;
396
530
            if (width - left < LIBRAW_AHD_TILE + 4)
397
262
                mcol = width - left + 2;
398
158k
            for (int row = MIN(top, 8); row < mrow - 8; row++)
399
56.4M
                for (int col = MIN(left, 8); col < mcol - 8; col++)
400
56.3M
                {
401
56.3M
                    int v;
402
56.3M
                    int hm[8];
403
506M
                    for (int d = 0; d < ndir; d++)
404
2.70G
                        for (v = -2, hm[d] = 0; v <= 2; v++)
405
13.5G
                            for (int h = -2; h <= 2; h++)
406
11.2G
                                hm[d] += homo[d][row + v][col + h];
407
281M
                    for (int d = 0; d < ndir - 4; d++)
408
225M
                        if (hm[d] < hm[d + 4])
409
77.5M
                            hm[d] = 0;
410
147M
                        else if (hm[d] > hm[d + 4])
411
19.4M
                            hm[d + 4] = 0;
412
56.3M
                    ushort max;
413
56.3M
                    int d;
414
450M
                    for (d = 1, max = hm[0]; d < ndir; d++)
415
394M
                        if (max < hm[d])
416
43.2M
                            max = hm[d];
417
56.3M
                    max -= max >> 3;
418
419
56.3M
                    int avg[4];
420
56.3M
                    memset(avg, 0, sizeof avg);
421
506M
                    for (int dd = 0; dd < ndir; dd++)
422
450M
                        if (hm[dd] >= max)
423
316M
                        {
424
949M
                            FORC3 avg[c] += rgb[dd][row][col][c];
425
316M
                            avg[3]++;
426
316M
                        }
427
168M
                    FORC3 destimage[(row + top) * width + col + left][c] = avg[c] / avg[3];
428
56.3M
                }
429
530
        }
430
262
    }
431
  
432
#ifdef LIBRAW_USE_OPENMP
433
#pragma omp barrier
434
#endif
435
436
130
    free_omp_buffers(buffers, buffer_count);
437
130
    free(image);
438
130
    image = destimage;
439
440
130
    border_interpolate(8);
441
130
}
442
#undef fcol