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 }