File indexing completed on 2025-01-05 03:56:55

0001 /*
0002  *    Copyright (C) 2010,  Jacek Gozdz (cuniek@kft.umcs.lublin.pl)
0003  *
0004  *    This code is licensed under a (3-clause) BSD license as follows :
0005  *
0006  *    Redistribution and use in source and binary forms, with or without
0007  *    modification, are permitted provided that the following
0008  *    conditions are met:
0009  *
0010  *    * Redistributions of source code must retain the above copyright
0011  *      notice, this list of conditions and the following disclaimer.
0012  *    * Redistributions in binary form must reproduce the above
0013  *      copyright notice, this list of conditions and the following
0014  *      disclaimer in the documentation and/or other materials provided
0015  *      with the distribution.
0016  *    * Neither the name of the author nor the names of its
0017  *      contributors may be used to endorse or promote products
0018  *      derived from this software without specific prior written permission.
0019  *
0020  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0021  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0022  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0023  *    FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
0024  *    THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
0025  *    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0026  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0027  *    SERVICES; LOSS OF USE,
0028  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0029  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0030  *    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0031  *    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
0032  *    OF SUCH DAMAGE.
0033  */
0034 
0035 // DCB demosaicing by Jacek Gozdz (cuniek@kft.umcs.lublin.pl)
0036 
0037 // FBDD denoising by Jacek Gozdz (cuniek@kft.umcs.lublin.pl) and
0038 // Luis Sanz Rodríguez (luis.sanz.rodriguez@gmail.com)
0039 
0040 // last modification: 11.07.2010
0041 
0042 #include "../../internal/dcraw_defs.h"
0043 
0044 // interpolates green vertically and saves it to image3
0045 void LibRaw::dcb_ver(float (*image3)[3])
0046 {
0047   int row, col, u = width, indx;
0048 
0049   for (row = 2; row < height - 2; row++)
0050     for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
0051          col += 2, indx += 2)
0052     {
0053 
0054       image3[indx][1] = CLIP((image[indx + u][1] + image[indx - u][1]) / 2.0);
0055     }
0056 }
0057 
0058 // interpolates green horizontally and saves it to image2
0059 void LibRaw::dcb_hor(float (*image2)[3])
0060 {
0061   int row, col, u = width, indx;
0062 
0063   for (row = 2; row < height - 2; row++)
0064     for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
0065          col += 2, indx += 2)
0066     {
0067 
0068       image2[indx][1] = CLIP((image[indx + 1][1] + image[indx - 1][1]) / 2.0);
0069     }
0070 }
0071 
0072 // missing colors are interpolated
0073 void LibRaw::dcb_color()
0074 {
0075   int row, col, c, d, u = width, indx;
0076 
0077   for (row = 1; row < height - 1; row++)
0078     for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
0079         c = 2 - FC(row, col);
0080          col < u - 1; col += 2, indx += 2)
0081     {
0082 
0083       image[indx][c] = CLIP((4 * image[indx][1] - image[indx + u + 1][1] -
0084                              image[indx + u - 1][1] - image[indx - u + 1][1] -
0085                              image[indx - u - 1][1] + image[indx + u + 1][c] +
0086                              image[indx + u - 1][c] + image[indx - u + 1][c] +
0087                              image[indx - u - 1][c]) /
0088                             4.0);
0089     }
0090 
0091   for (row = 1; row < height - 1; row++)
0092     for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
0093         c = FC(row, col + 1), d = 2 - c;
0094          col < width - 1; col += 2, indx += 2)
0095     {
0096 
0097       image[indx][c] =
0098           CLIP((2 * image[indx][1] - image[indx + 1][1] - image[indx - 1][1] +
0099                 image[indx + 1][c] + image[indx - 1][c]) /
0100                2.0);
0101       image[indx][d] =
0102           CLIP((2 * image[indx][1] - image[indx + u][1] - image[indx - u][1] +
0103                 image[indx + u][d] + image[indx - u][d]) /
0104                2.0);
0105     }
0106 }
0107 
0108 // missing R and B are interpolated horizontally and saved in image2
0109 void LibRaw::dcb_color2(float (*image2)[3])
0110 {
0111   int row, col, c, d, u = width, indx;
0112 
0113   for (row = 1; row < height - 1; row++)
0114     for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
0115         c = 2 - FC(row, col);
0116          col < u - 1; col += 2, indx += 2)
0117     {
0118 
0119       image2[indx][c] =
0120           CLIP((4 * image2[indx][1] - image2[indx + u + 1][1] -
0121                 image2[indx + u - 1][1] - image2[indx - u + 1][1] -
0122                 image2[indx - u - 1][1] + image[indx + u + 1][c] +
0123                 image[indx + u - 1][c] + image[indx - u + 1][c] +
0124                 image[indx - u - 1][c]) /
0125                4.0);
0126     }
0127 
0128   for (row = 1; row < height - 1; row++)
0129     for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
0130         c = FC(row, col + 1), d = 2 - c;
0131          col < width - 1; col += 2, indx += 2)
0132     {
0133 
0134       image2[indx][c] = CLIP((image[indx + 1][c] + image[indx - 1][c]) / 2.0);
0135       image2[indx][d] =
0136           CLIP((2 * image2[indx][1] - image2[indx + u][1] -
0137                 image2[indx - u][1] + image[indx + u][d] + image[indx - u][d]) /
0138                2.0);
0139     }
0140 }
0141 
0142 // missing R and B are interpolated vertically and saved in image3
0143 void LibRaw::dcb_color3(float (*image3)[3])
0144 {
0145   int row, col, c, d, u = width, indx;
0146 
0147   for (row = 1; row < height - 1; row++)
0148     for (col = 1 + (FC(row, 1) & 1), indx = row * width + col,
0149         c = 2 - FC(row, col);
0150          col < u - 1; col += 2, indx += 2)
0151     {
0152 
0153       image3[indx][c] =
0154           CLIP((4 * image3[indx][1] - image3[indx + u + 1][1] -
0155                 image3[indx + u - 1][1] - image3[indx - u + 1][1] -
0156                 image3[indx - u - 1][1] + image[indx + u + 1][c] +
0157                 image[indx + u - 1][c] + image[indx - u + 1][c] +
0158                 image[indx - u - 1][c]) /
0159                4.0);
0160     }
0161 
0162   for (row = 1; row < height - 1; row++)
0163     for (col = 1 + (FC(row, 2) & 1), indx = row * width + col,
0164         c = FC(row, col + 1), d = 2 - c;
0165          col < width - 1; col += 2, indx += 2)
0166     {
0167 
0168       image3[indx][c] =
0169           CLIP((2 * image3[indx][1] - image3[indx + 1][1] -
0170                 image3[indx - 1][1] + image[indx + 1][c] + image[indx - 1][c]) /
0171                2.0);
0172       image3[indx][d] = CLIP((image[indx + u][d] + image[indx - u][d]) / 2.0);
0173     }
0174 }
0175 
0176 // decides the primary green interpolation direction
0177 void LibRaw::dcb_decide(float (*image2)[3], float (*image3)[3])
0178 {
0179   int row, col, c, d, u = width, v = 2 * u, indx;
0180   float current, current2, current3;
0181 
0182   for (row = 2; row < height - 2; row++)
0183     for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
0184          col < u - 2; col += 2, indx += 2)
0185     {
0186 
0187       d = ABS(c - 2);
0188 
0189       current = MAX(image[indx + v][c],
0190                     MAX(image[indx - v][c],
0191                         MAX(image[indx - 2][c], image[indx + 2][c]))) -
0192                 MIN(image[indx + v][c],
0193                     MIN(image[indx - v][c],
0194                         MIN(image[indx - 2][c], image[indx + 2][c]))) +
0195                 MAX(image[indx + 1 + u][d],
0196                     MAX(image[indx + 1 - u][d],
0197                         MAX(image[indx - 1 + u][d], image[indx - 1 - u][d]))) -
0198                 MIN(image[indx + 1 + u][d],
0199                     MIN(image[indx + 1 - u][d],
0200                         MIN(image[indx - 1 + u][d], image[indx - 1 - u][d])));
0201 
0202       current2 =
0203           MAX(image2[indx + v][d],
0204               MAX(image2[indx - v][d],
0205                   MAX(image2[indx - 2][d], image2[indx + 2][d]))) -
0206           MIN(image2[indx + v][d],
0207               MIN(image2[indx - v][d],
0208                   MIN(image2[indx - 2][d], image2[indx + 2][d]))) +
0209           MAX(image2[indx + 1 + u][c],
0210               MAX(image2[indx + 1 - u][c],
0211                   MAX(image2[indx - 1 + u][c], image2[indx - 1 - u][c]))) -
0212           MIN(image2[indx + 1 + u][c],
0213               MIN(image2[indx + 1 - u][c],
0214                   MIN(image2[indx - 1 + u][c], image2[indx - 1 - u][c])));
0215 
0216       current3 =
0217           MAX(image3[indx + v][d],
0218               MAX(image3[indx - v][d],
0219                   MAX(image3[indx - 2][d], image3[indx + 2][d]))) -
0220           MIN(image3[indx + v][d],
0221               MIN(image3[indx - v][d],
0222                   MIN(image3[indx - 2][d], image3[indx + 2][d]))) +
0223           MAX(image3[indx + 1 + u][c],
0224               MAX(image3[indx + 1 - u][c],
0225                   MAX(image3[indx - 1 + u][c], image3[indx - 1 - u][c]))) -
0226           MIN(image3[indx + 1 + u][c],
0227               MIN(image3[indx + 1 - u][c],
0228                   MIN(image3[indx - 1 + u][c], image3[indx - 1 - u][c])));
0229 
0230       if (ABS(current - current2) < ABS(current - current3))
0231         image[indx][1] = image2[indx][1];
0232       else
0233         image[indx][1] = image3[indx][1];
0234     }
0235 }
0236 
0237 // saves red and blue in image2
0238 void LibRaw::dcb_copy_to_buffer(float (*image2)[3])
0239 {
0240   int indx;
0241 
0242   for (indx = 0; indx < height * width; indx++)
0243   {
0244     image2[indx][0] = image[indx][0]; // R
0245     image2[indx][2] = image[indx][2]; // B
0246   }
0247 }
0248 
0249 // restores red and blue from image2
0250 void LibRaw::dcb_restore_from_buffer(float (*image2)[3])
0251 {
0252   int indx;
0253 
0254   for (indx = 0; indx < height * width; indx++)
0255   {
0256     image[indx][0] = image2[indx][0]; // R
0257     image[indx][2] = image2[indx][2]; // B
0258   }
0259 }
0260 
0261 // R and B smoothing using green contrast, all pixels except 2 pixel wide border
0262 void LibRaw::dcb_pp()
0263 {
0264   int g1, r1, b1, u = width, indx, row, col;
0265 
0266   for (row = 2; row < height - 2; row++)
0267     for (col = 2, indx = row * u + col; col < width - 2; col++, indx++)
0268     {
0269 
0270       r1 = (image[indx - 1][0] + image[indx + 1][0] + image[indx - u][0] +
0271             image[indx + u][0] + image[indx - u - 1][0] +
0272             image[indx + u + 1][0] + image[indx - u + 1][0] +
0273             image[indx + u - 1][0]) /
0274            8.0;
0275       g1 = (image[indx - 1][1] + image[indx + 1][1] + image[indx - u][1] +
0276             image[indx + u][1] + image[indx - u - 1][1] +
0277             image[indx + u + 1][1] + image[indx - u + 1][1] +
0278             image[indx + u - 1][1]) /
0279            8.0;
0280       b1 = (image[indx - 1][2] + image[indx + 1][2] + image[indx - u][2] +
0281             image[indx + u][2] + image[indx - u - 1][2] +
0282             image[indx + u + 1][2] + image[indx - u + 1][2] +
0283             image[indx + u - 1][2]) /
0284            8.0;
0285 
0286       image[indx][0] = CLIP(r1 + (image[indx][1] - g1));
0287       image[indx][2] = CLIP(b1 + (image[indx][1] - g1));
0288     }
0289 }
0290 
0291 // green blurring correction, helps to get the nyquist right
0292 void LibRaw::dcb_nyquist()
0293 {
0294   int row, col, c, u = width, v = 2 * u, indx;
0295 
0296   for (row = 2; row < height - 2; row++)
0297     for (col = 2 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
0298          col < u - 2; col += 2, indx += 2)
0299     {
0300 
0301       image[indx][1] = CLIP((image[indx + v][1] + image[indx - v][1] +
0302                              image[indx - 2][1] + image[indx + 2][1]) /
0303                                 4.0 +
0304                             image[indx][c] -
0305                             (image[indx + v][c] + image[indx - v][c] +
0306                              image[indx - 2][c] + image[indx + 2][c]) /
0307                                 4.0);
0308     }
0309 }
0310 
0311 // missing colors are interpolated using high quality algorithm by Luis Sanz
0312 // Rodríguez
0313 void LibRaw::dcb_color_full()
0314 {
0315   int row, col, c, d, u = width, w = 3 * u, indx, g1, g2;
0316   float f[4], g[4], (*chroma)[2];
0317 
0318   chroma = (float(*)[2])calloc(width * height, sizeof *chroma);
0319 
0320   for (row = 1; row < height - 1; row++)
0321     for (col = 1 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col),
0322         d = c / 2;
0323          col < u - 1; col += 2, indx += 2)
0324       chroma[indx][d] = image[indx][c] - image[indx][1];
0325 
0326   for (row = 3; row < height - 3; row++)
0327     for (col = 3 + (FC(row, 1) & 1), indx = row * width + col,
0328         c = 1 - FC(row, col) / 2, d = 1 - c;
0329          col < u - 3; col += 2, indx += 2)
0330     {
0331       f[0] = 1.0 /
0332              (float)(1.0 +
0333                      fabs(chroma[indx - u - 1][c] - chroma[indx + u + 1][c]) +
0334                      fabs(chroma[indx - u - 1][c] - chroma[indx - w - 3][c]) +
0335                      fabs(chroma[indx + u + 1][c] - chroma[indx - w - 3][c]));
0336       f[1] = 1.0 /
0337              (float)(1.0 +
0338                      fabs(chroma[indx - u + 1][c] - chroma[indx + u - 1][c]) +
0339                      fabs(chroma[indx - u + 1][c] - chroma[indx - w + 3][c]) +
0340                      fabs(chroma[indx + u - 1][c] - chroma[indx - w + 3][c]));
0341       f[2] = 1.0 /
0342              (float)(1.0 +
0343                      fabs(chroma[indx + u - 1][c] - chroma[indx - u + 1][c]) +
0344                      fabs(chroma[indx + u - 1][c] - chroma[indx + w + 3][c]) +
0345                      fabs(chroma[indx - u + 1][c] - chroma[indx + w - 3][c]));
0346       f[3] = 1.0 /
0347              (float)(1.0 +
0348                      fabs(chroma[indx + u + 1][c] - chroma[indx - u - 1][c]) +
0349                      fabs(chroma[indx + u + 1][c] - chroma[indx + w - 3][c]) +
0350                      fabs(chroma[indx - u - 1][c] - chroma[indx + w + 3][c]));
0351       g[0] = 1.325 * chroma[indx - u - 1][c] - 0.175 * chroma[indx - w - 3][c] -
0352              0.075 * chroma[indx - w - 1][c] - 0.075 * chroma[indx - u - 3][c];
0353       g[1] = 1.325 * chroma[indx - u + 1][c] - 0.175 * chroma[indx - w + 3][c] -
0354              0.075 * chroma[indx - w + 1][c] - 0.075 * chroma[indx - u + 3][c];
0355       g[2] = 1.325 * chroma[indx + u - 1][c] - 0.175 * chroma[indx + w - 3][c] -
0356              0.075 * chroma[indx + w - 1][c] - 0.075 * chroma[indx + u - 3][c];
0357       g[3] = 1.325 * chroma[indx + u + 1][c] - 0.175 * chroma[indx + w + 3][c] -
0358              0.075 * chroma[indx + w + 1][c] - 0.075 * chroma[indx + u + 3][c];
0359       chroma[indx][c] =
0360           (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
0361           (f[0] + f[1] + f[2] + f[3]);
0362     }
0363   for (row = 3; row < height - 3; row++)
0364     for (col = 3 + (FC(row, 2) & 1), indx = row * width + col,
0365         c = FC(row, col + 1) / 2;
0366          col < u - 3; col += 2, indx += 2)
0367       for (d = 0; d <= 1; c = 1 - c, d++)
0368       {
0369         f[0] = 1.0 /
0370                (float)(1.0 + fabs(chroma[indx - u][c] - chroma[indx + u][c]) +
0371                        fabs(chroma[indx - u][c] - chroma[indx - w][c]) +
0372                        fabs(chroma[indx + u][c] - chroma[indx - w][c]));
0373         f[1] = 1.0 /
0374                (float)(1.0 + fabs(chroma[indx + 1][c] - chroma[indx - 1][c]) +
0375                        fabs(chroma[indx + 1][c] - chroma[indx + 3][c]) +
0376                        fabs(chroma[indx - 1][c] - chroma[indx + 3][c]));
0377         f[2] = 1.0 /
0378                (float)(1.0 + fabs(chroma[indx - 1][c] - chroma[indx + 1][c]) +
0379                        fabs(chroma[indx - 1][c] - chroma[indx - 3][c]) +
0380                        fabs(chroma[indx + 1][c] - chroma[indx - 3][c]));
0381         f[3] = 1.0 /
0382                (float)(1.0 + fabs(chroma[indx + u][c] - chroma[indx - u][c]) +
0383                        fabs(chroma[indx + u][c] - chroma[indx + w][c]) +
0384                        fabs(chroma[indx - u][c] - chroma[indx + w][c]));
0385 
0386         g[0] = 0.875 * chroma[indx - u][c] + 0.125 * chroma[indx - w][c];
0387         g[1] = 0.875 * chroma[indx + 1][c] + 0.125 * chroma[indx + 3][c];
0388         g[2] = 0.875 * chroma[indx - 1][c] + 0.125 * chroma[indx - 3][c];
0389         g[3] = 0.875 * chroma[indx + u][c] + 0.125 * chroma[indx + w][c];
0390 
0391         chroma[indx][c] =
0392             (f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
0393             (f[0] + f[1] + f[2] + f[3]);
0394       }
0395 
0396   for (row = 6; row < height - 6; row++)
0397     for (col = 6, indx = row * width + col; col < width - 6; col++, indx++)
0398     {
0399       image[indx][0] = CLIP(chroma[indx][0] + image[indx][1]);
0400       image[indx][2] = CLIP(chroma[indx][1] + image[indx][1]);
0401 
0402       g1 = MIN(
0403           image[indx + 1 + u][0],
0404           MIN(image[indx + 1 - u][0],
0405               MIN(image[indx - 1 + u][0],
0406                   MIN(image[indx - 1 - u][0],
0407                       MIN(image[indx - 1][0],
0408                           MIN(image[indx + 1][0],
0409                               MIN(image[indx - u][0], image[indx + u][0])))))));
0410 
0411       g2 = MAX(
0412           image[indx + 1 + u][0],
0413           MAX(image[indx + 1 - u][0],
0414               MAX(image[indx - 1 + u][0],
0415                   MAX(image[indx - 1 - u][0],
0416                       MAX(image[indx - 1][0],
0417                           MAX(image[indx + 1][0],
0418                               MAX(image[indx - u][0], image[indx + u][0])))))));
0419 
0420       image[indx][0] = ULIM(image[indx][0], g2, g1);
0421 
0422       g1 = MIN(
0423           image[indx + 1 + u][2],
0424           MIN(image[indx + 1 - u][2],
0425               MIN(image[indx - 1 + u][2],
0426                   MIN(image[indx - 1 - u][2],
0427                       MIN(image[indx - 1][2],
0428                           MIN(image[indx + 1][2],
0429                               MIN(image[indx - u][2], image[indx + u][2])))))));
0430 
0431       g2 = MAX(
0432           image[indx + 1 + u][2],
0433           MAX(image[indx + 1 - u][2],
0434               MAX(image[indx - 1 + u][2],
0435                   MAX(image[indx - 1 - u][2],
0436                       MAX(image[indx - 1][2],
0437                           MAX(image[indx + 1][2],
0438                               MAX(image[indx - u][2], image[indx + u][2])))))));
0439 
0440       image[indx][2] = ULIM(image[indx][2], g2, g1);
0441     }
0442 
0443   free(chroma);
0444 }
0445 
0446 // green is used to create an interpolation direction map saved in image[][3]
0447 // 1 = vertical
0448 // 0 = horizontal
0449 void LibRaw::dcb_map()
0450 {
0451   int row, col, u = width, indx;
0452 
0453   for (row = 1; row < height - 1; row++)
0454   {
0455     for (col = 1, indx = row * width + col; col < width - 1; col++, indx++)
0456     {
0457 
0458       if (image[indx][1] > (image[indx - 1][1] + image[indx + 1][1] +
0459                             image[indx - u][1] + image[indx + u][1]) /
0460                                4.0)
0461         image[indx][3] = ((MIN(image[indx - 1][1], image[indx + 1][1]) +
0462                            image[indx - 1][1] + image[indx + 1][1]) <
0463                           (MIN(image[indx - u][1], image[indx + u][1]) +
0464                            image[indx - u][1] + image[indx + u][1]));
0465       else
0466         image[indx][3] = ((MAX(image[indx - 1][1], image[indx + 1][1]) +
0467                            image[indx - 1][1] + image[indx + 1][1]) >
0468                           (MAX(image[indx - u][1], image[indx + u][1]) +
0469                            image[indx - u][1] + image[indx + u][1]));
0470     }
0471   }
0472 }
0473 
0474 // interpolated green pixels are corrected using the map
0475 void LibRaw::dcb_correction()
0476 {
0477   int current, row, col, u = width, v = 2 * u, indx;
0478 
0479   for (row = 2; row < height - 2; row++)
0480     for (col = 2 + (FC(row, 2) & 1), indx = row * width + col; col < u - 2;
0481          col += 2, indx += 2)
0482     {
0483 
0484       current = 4 * image[indx][3] +
0485                 2 * (image[indx + u][3] + image[indx - u][3] +
0486                      image[indx + 1][3] + image[indx - 1][3]) +
0487                 image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
0488                 image[indx - 2][3];
0489 
0490       image[indx][1] =
0491           ((16 - current) * (image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
0492            current * (image[indx - u][1] + image[indx + u][1]) / 2.0) /
0493           16.0;
0494     }
0495 }
0496 
0497 // interpolated green pixels are corrected using the map
0498 // with contrast correction
0499 void LibRaw::dcb_correction2()
0500 {
0501   int current, row, col, c, u = width, v = 2 * u, indx;
0502 
0503   for (row = 4; row < height - 4; row++)
0504     for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
0505          col < u - 4; col += 2, indx += 2)
0506     {
0507 
0508       current = 4 * image[indx][3] +
0509                 2 * (image[indx + u][3] + image[indx - u][3] +
0510                      image[indx + 1][3] + image[indx - 1][3]) +
0511                 image[indx + v][3] + image[indx - v][3] + image[indx + 2][3] +
0512                 image[indx - 2][3];
0513 
0514       image[indx][1] = CLIP(
0515           ((16 - current) * ((image[indx - 1][1] + image[indx + 1][1]) / 2.0 +
0516                              image[indx][c] -
0517                              (image[indx + 2][c] + image[indx - 2][c]) / 2.0) +
0518            current * ((image[indx - u][1] + image[indx + u][1]) / 2.0 +
0519                       image[indx][c] -
0520                       (image[indx + v][c] + image[indx - v][c]) / 2.0)) /
0521           16.0);
0522     }
0523 }
0524 
0525 void LibRaw::dcb_refinement()
0526 {
0527   int row, col, c, u = width, v = 2 * u, w = 3 * u, indx, current;
0528   float f[5], g1, g2;
0529 
0530   for (row = 4; row < height - 4; row++)
0531     for (col = 4 + (FC(row, 2) & 1), indx = row * width + col, c = FC(row, col);
0532          col < u - 4; col += 2, indx += 2)
0533     {
0534 
0535       current = 4 * image[indx][3] +
0536                 2 * (image[indx + u][3] + image[indx - u][3] +
0537                      image[indx + 1][3] + image[indx - 1][3]) +
0538                 image[indx + v][3] + image[indx - v][3] + image[indx - 2][3] +
0539                 image[indx + 2][3];
0540 
0541       if (image[indx][c] > 1)
0542       {
0543 
0544         f[0] = (float)(image[indx - u][1] + image[indx + u][1]) /
0545                (2 * image[indx][c]);
0546 
0547         if (image[indx - v][c] > 0)
0548           f[1] = 2 * (float)image[indx - u][1] /
0549                  (image[indx - v][c] + image[indx][c]);
0550         else
0551           f[1] = f[0];
0552 
0553         if (image[indx - v][c] > 0)
0554           f[2] = (float)(image[indx - u][1] + image[indx - w][1]) /
0555                  (2 * image[indx - v][c]);
0556         else
0557           f[2] = f[0];
0558 
0559         if (image[indx + v][c] > 0)
0560           f[3] = 2 * (float)image[indx + u][1] /
0561                  (image[indx + v][c] + image[indx][c]);
0562         else
0563           f[3] = f[0];
0564 
0565         if (image[indx + v][c] > 0)
0566           f[4] = (float)(image[indx + u][1] + image[indx + w][1]) /
0567                  (2 * image[indx + v][c]);
0568         else
0569           f[4] = f[0];
0570 
0571         g1 = (5 * f[0] + 3 * f[1] + f[2] + 3 * f[3] + f[4]) / 13.0;
0572 
0573         f[0] = (float)(image[indx - 1][1] + image[indx + 1][1]) /
0574                (2 * image[indx][c]);
0575 
0576         if (image[indx - 2][c] > 0)
0577           f[1] = 2 * (float)image[indx - 1][1] /
0578                  (image[indx - 2][c] + image[indx][c]);
0579         else
0580           f[1] = f[0];
0581 
0582         if (image[indx - 2][c] > 0)
0583           f[2] = (float)(image[indx - 1][1] + image[indx - 3][1]) /
0584                  (2 * image[indx - 2][c]);
0585         else
0586           f[2] = f[0];
0587 
0588         if (image[indx + 2][c] > 0)
0589           f[3] = 2 * (float)image[indx + 1][1] /
0590                  (image[indx + 2][c] + image[indx][c]);
0591         else
0592           f[3] = f[0];
0593 
0594         if (image[indx + 2][c] > 0)
0595           f[4] = (float)(image[indx + 1][1] + image[indx + 3][1]) /
0596                  (2 * image[indx + 2][c]);
0597         else
0598           f[4] = f[0];
0599 
0600         g2 = (5 * f[0] + 3 * f[1] + f[2] + 3 * f[3] + f[4]) / 13.0;
0601 
0602         image[indx][1] = CLIP((image[indx][c]) *
0603                               (current * g1 + (16 - current) * g2) / 16.0);
0604       }
0605       else
0606         image[indx][1] = image[indx][c];
0607 
0608       // get rid of overshooted pixels
0609 
0610       g1 = MIN(
0611           image[indx + 1 + u][1],
0612           MIN(image[indx + 1 - u][1],
0613               MIN(image[indx - 1 + u][1],
0614                   MIN(image[indx - 1 - u][1],
0615                       MIN(image[indx - 1][1],
0616                           MIN(image[indx + 1][1],
0617                               MIN(image[indx - u][1], image[indx + u][1])))))));
0618 
0619       g2 = MAX(
0620           image[indx + 1 + u][1],
0621           MAX(image[indx + 1 - u][1],
0622               MAX(image[indx - 1 + u][1],
0623                   MAX(image[indx - 1 - u][1],
0624                       MAX(image[indx - 1][1],
0625                           MAX(image[indx + 1][1],
0626                               MAX(image[indx - u][1], image[indx + u][1])))))));
0627 
0628       image[indx][1] = ULIM(image[indx][1], g2, g1);
0629     }
0630 }
0631 
0632 // converts RGB to LCH colorspace and saves it to image3
0633 void LibRaw::rgb_to_lch(double (*image2)[3])
0634 {
0635   int indx;
0636   for (indx = 0; indx < height * width; indx++)
0637   {
0638 
0639     image2[indx][0] = image[indx][0] + image[indx][1] + image[indx][2]; // L
0640     image2[indx][1] = 1.732050808 * (image[indx][0] - image[indx][1]);  // C
0641     image2[indx][2] =
0642         2.0 * image[indx][2] - image[indx][0] - image[indx][1]; // H
0643   }
0644 }
0645 
0646 // converts LCH to RGB colorspace and saves it back to image
0647 void LibRaw::lch_to_rgb(double (*image2)[3])
0648 {
0649   int indx;
0650   for (indx = 0; indx < height * width; indx++)
0651   {
0652 
0653     image[indx][0] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 +
0654                           image2[indx][1] / 3.464101615);
0655     image[indx][1] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 -
0656                           image2[indx][1] / 3.464101615);
0657     image[indx][2] = CLIP(image2[indx][0] / 3.0 + image2[indx][2] / 3.0);
0658   }
0659 }
0660 
0661 // denoising using interpolated neighbours
0662 void LibRaw::fbdd_correction()
0663 {
0664   int row, col, c, u = width, indx;
0665 
0666   for (row = 2; row < height - 2; row++)
0667   {
0668     for (col = 2, indx = row * width + col; col < width - 2; col++, indx++)
0669     {
0670 
0671       c = fcol(row, col);
0672 
0673       image[indx][c] =
0674           ULIM(image[indx][c],
0675                MAX(image[indx - 1][c],
0676                    MAX(image[indx + 1][c],
0677                        MAX(image[indx - u][c], image[indx + u][c]))),
0678                MIN(image[indx - 1][c],
0679                    MIN(image[indx + 1][c],
0680                        MIN(image[indx - u][c], image[indx + u][c]))));
0681     }
0682   }
0683 }
0684 
0685 // corrects chroma noise
0686 void LibRaw::fbdd_correction2(double (*image2)[3])
0687 {
0688   int indx, v = 2 * width;
0689   int col, row;
0690   double Co, Ho, ratio;
0691 
0692   for (row = 6; row < height - 6; row++)
0693   {
0694     for (col = 6; col < width - 6; col++)
0695     {
0696       indx = row * width + col;
0697 
0698       if (image2[indx][1] * image2[indx][2] != 0)
0699       {
0700         Co = (image2[indx + v][1] + image2[indx - v][1] + image2[indx - 2][1] +
0701               image2[indx + 2][1] -
0702               MAX(image2[indx - 2][1],
0703                   MAX(image2[indx + 2][1],
0704                       MAX(image2[indx - v][1], image2[indx + v][1]))) -
0705               MIN(image2[indx - 2][1],
0706                   MIN(image2[indx + 2][1],
0707                       MIN(image2[indx - v][1], image2[indx + v][1])))) /
0708              2.0;
0709         Ho = (image2[indx + v][2] + image2[indx - v][2] + image2[indx - 2][2] +
0710               image2[indx + 2][2] -
0711               MAX(image2[indx - 2][2],
0712                   MAX(image2[indx + 2][2],
0713                       MAX(image2[indx - v][2], image2[indx + v][2]))) -
0714               MIN(image2[indx - 2][2],
0715                   MIN(image2[indx + 2][2],
0716                       MIN(image2[indx - v][2], image2[indx + v][2])))) /
0717              2.0;
0718         ratio = sqrt((Co * Co + Ho * Ho) / (image2[indx][1] * image2[indx][1] +
0719                                             image2[indx][2] * image2[indx][2]));
0720 
0721         if (ratio < 0.85)
0722         {
0723           image2[indx][0] =
0724               -(image2[indx][1] + image2[indx][2] - Co - Ho) + image2[indx][0];
0725           image2[indx][1] = Co;
0726           image2[indx][2] = Ho;
0727         }
0728       }
0729     }
0730   }
0731 }
0732 
0733 // Cubic Spline Interpolation by Li and Randhawa, modified by Jacek Gozdz and
0734 // Luis Sanz Rodríguez
0735 void LibRaw::fbdd_green()
0736 {
0737   int row, col, c, u = width, v = 2 * u, w = 3 * u, x = 4 * u, y = 5 * u, indx,
0738                    min, max;
0739   float f[4], g[4];
0740 
0741   for (row = 5; row < height - 5; row++)
0742     for (col = 5 + (FC(row, 1) & 1), indx = row * width + col, c = FC(row, col);
0743          col < u - 5; col += 2, indx += 2)
0744     {
0745 
0746       f[0] = 1.0 / (1.0 + abs(image[indx - u][1] - image[indx - w][1]) +
0747                     abs(image[indx - w][1] - image[indx + y][1]));
0748       f[1] = 1.0 / (1.0 + abs(image[indx + 1][1] - image[indx + 3][1]) +
0749                     abs(image[indx + 3][1] - image[indx - 5][1]));
0750       f[2] = 1.0 / (1.0 + abs(image[indx - 1][1] - image[indx - 3][1]) +
0751                     abs(image[indx - 3][1] - image[indx + 5][1]));
0752       f[3] = 1.0 / (1.0 + abs(image[indx + u][1] - image[indx + w][1]) +
0753                     abs(image[indx + w][1] - image[indx - y][1]));
0754 
0755       g[0] = CLIP((23 * image[indx - u][1] + 23 * image[indx - w][1] +
0756                    2 * image[indx - y][1] +
0757                    8 * (image[indx - v][c] - image[indx - x][c]) +
0758                    40 * (image[indx][c] - image[indx - v][c])) /
0759                   48.0);
0760       g[1] = CLIP((23 * image[indx + 1][1] + 23 * image[indx + 3][1] +
0761                    2 * image[indx + 5][1] +
0762                    8 * (image[indx + 2][c] - image[indx + 4][c]) +
0763                    40 * (image[indx][c] - image[indx + 2][c])) /
0764                   48.0);
0765       g[2] = CLIP((23 * image[indx - 1][1] + 23 * image[indx - 3][1] +
0766                    2 * image[indx - 5][1] +
0767                    8 * (image[indx - 2][c] - image[indx - 4][c]) +
0768                    40 * (image[indx][c] - image[indx - 2][c])) /
0769                   48.0);
0770       g[3] = CLIP((23 * image[indx + u][1] + 23 * image[indx + w][1] +
0771                    2 * image[indx + y][1] +
0772                    8 * (image[indx + v][c] - image[indx + x][c]) +
0773                    40 * (image[indx][c] - image[indx + v][c])) /
0774                   48.0);
0775 
0776       image[indx][1] =
0777           CLIP((f[0] * g[0] + f[1] * g[1] + f[2] * g[2] + f[3] * g[3]) /
0778                (f[0] + f[1] + f[2] + f[3]));
0779 
0780       min = MIN(
0781           image[indx + 1 + u][1],
0782           MIN(image[indx + 1 - u][1],
0783               MIN(image[indx - 1 + u][1],
0784                   MIN(image[indx - 1 - u][1],
0785                       MIN(image[indx - 1][1],
0786                           MIN(image[indx + 1][1],
0787                               MIN(image[indx - u][1], image[indx + u][1])))))));
0788 
0789       max = MAX(
0790           image[indx + 1 + u][1],
0791           MAX(image[indx + 1 - u][1],
0792               MAX(image[indx - 1 + u][1],
0793                   MAX(image[indx - 1 - u][1],
0794                       MAX(image[indx - 1][1],
0795                           MAX(image[indx + 1][1],
0796                               MAX(image[indx - u][1], image[indx + u][1])))))));
0797 
0798       image[indx][1] = ULIM(image[indx][1], max, min);
0799     }
0800 }
0801 
0802 // FBDD (Fake Before Demosaicing Denoising)
0803 void LibRaw::fbdd(int noiserd)
0804 {
0805   double(*image2)[3];
0806   // safety net: disable for 4-color bayer or full-color images
0807   if (colors != 3 || !filters)
0808     return;
0809   image2 = (double(*)[3])calloc(width * height, sizeof *image2);
0810 
0811   border_interpolate(4);
0812 
0813   if (noiserd > 1)
0814   {
0815     fbdd_green();
0816     // dcb_color_full(image2);
0817     dcb_color_full();
0818     fbdd_correction();
0819 
0820     dcb_color();
0821     rgb_to_lch(image2);
0822     fbdd_correction2(image2);
0823     fbdd_correction2(image2);
0824     lch_to_rgb(image2);
0825   }
0826   else
0827   {
0828     fbdd_green();
0829     // dcb_color_full(image2);
0830     dcb_color_full();
0831     fbdd_correction();
0832   }
0833 
0834   free(image2);
0835 }
0836 
0837 // DCB demosaicing main routine
0838 void LibRaw::dcb(int iterations, int dcb_enhance)
0839 {
0840 
0841   int i = 1;
0842 
0843   float(*image2)[3];
0844   image2 = (float(*)[3])calloc(width * height, sizeof *image2);
0845 
0846   float(*image3)[3];
0847   image3 = (float(*)[3])calloc(width * height, sizeof *image3);
0848 
0849   border_interpolate(6);
0850 
0851   dcb_hor(image2);
0852   dcb_color2(image2);
0853 
0854   dcb_ver(image3);
0855   dcb_color3(image3);
0856 
0857   dcb_decide(image2, image3);
0858 
0859   free(image3);
0860 
0861   dcb_copy_to_buffer(image2);
0862 
0863   while (i <= iterations)
0864   {
0865     dcb_nyquist();
0866     dcb_nyquist();
0867     dcb_nyquist();
0868     dcb_map();
0869     dcb_correction();
0870     i++;
0871   }
0872 
0873   dcb_color();
0874   dcb_pp();
0875 
0876   dcb_map();
0877   dcb_correction2();
0878 
0879   dcb_map();
0880   dcb_correction();
0881 
0882   dcb_map();
0883   dcb_correction();
0884 
0885   dcb_map();
0886   dcb_correction();
0887 
0888   dcb_map();
0889   dcb_restore_from_buffer(image2);
0890   dcb_color();
0891 
0892   if (dcb_enhance)
0893   {
0894     dcb_refinement();
0895     // dcb_color_full(image2);
0896     dcb_color_full();
0897   }
0898 
0899   free(image2);
0900 }