/src/FreeImage/Source/LibRawLite/internal/dcb_demosaicing.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 710 lines · 433 code · 211 blank · 66 comment · 74 complexity · 5f561b30ea41dd4f99f371f6f27d6c61 MD5 · raw file

  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. // DCB demosaicing by Jacek Gozdz (cuniek@kft.umcs.lublin.pl)
  35. // FBDD denoising by Jacek Gozdz (cuniek@kft.umcs.lublin.pl) and
  36. // Luis Sanz Rodríguez (luis.sanz.rodriguez@gmail.com)
  37. // last modification: 11.07.2010
  38. // interpolates green vertically and saves it to image3
  39. void CLASS dcb_ver(float (*image3)[3])
  40. {
  41. int row, col, u=width, v=2*u, indx;
  42. for (row=2; row < height-2; row++)
  43. for (col=2+(FC(row,2)&1),indx=row*width+col; col < u-2; col+=2,indx+=2) {
  44. image3[indx][1] = CLIP((image[indx+u][1] + image[indx-u][1])/2.0);
  45. }
  46. }
  47. // interpolates green horizontally and saves it to image2
  48. void CLASS dcb_hor(float (*image2)[3])
  49. {
  50. int row, col, u=width, v=2*u, indx;
  51. for (row=2; row < height-2; row++)
  52. for (col=2+(FC(row,2)&1),indx=row*width+col; col < u-2; col+=2,indx+=2) {
  53. image2[indx][1] = CLIP((image[indx+1][1] + image[indx-1][1])/2.0);
  54. }
  55. }
  56. // missing colors are interpolated
  57. void CLASS dcb_color()
  58. {
  59. int row, col, c, d, u=width, indx;
  60. for (row=1; row < height-1; row++)
  61. for (col=1+(FC(row,1) & 1), indx=row*width+col, c=2-FC(row,col); col < u-1; col+=2, indx+=2) {
  62. image[indx][c] = CLIP((
  63. 4*image[indx][1]
  64. - image[indx+u+1][1] - image[indx+u-1][1] - image[indx-u+1][1] - image[indx-u-1][1]
  65. + image[indx+u+1][c] + image[indx+u-1][c] + image[indx-u+1][c] + image[indx-u-1][c] )/4.0);
  66. }
  67. for (row=1; row<height-1; row++)
  68. for (col=1+(FC(row,2) & 1), indx=row*width+col,c=FC(row,col+1),d=2-c; col<width-1; col+=2, indx+=2) {
  69. image[indx][c] = CLIP((2*image[indx][1] - image[indx+1][1] - image[indx-1][1] + image[indx+1][c] + image[indx-1][c])/2.0);
  70. image[indx][d] = CLIP((2*image[indx][1] - image[indx+u][1] - image[indx-u][1] + image[indx+u][d] + image[indx-u][d])/2.0);
  71. }
  72. }
  73. // missing R and B are interpolated horizontally and saved in image2
  74. void CLASS dcb_color2(float (*image2)[3])
  75. {
  76. int row, col, c, d, u=width, indx;
  77. for (row=1; row < height-1; row++)
  78. for (col=1+(FC(row,1) & 1), indx=row*width+col, c=2-FC(row,col); col < u-1; col+=2, indx+=2) {
  79. image2[indx][c] = CLIP((
  80. 4*image2[indx][1]
  81. - image2[indx+u+1][1] - image2[indx+u-1][1] - image2[indx-u+1][1] - image2[indx-u-1][1]
  82. + image[indx+u+1][c] + image[indx+u-1][c] + image[indx-u+1][c] + image[indx-u-1][c] )/4.0);
  83. }
  84. for (row=1; row<height-1; row++)
  85. for (col=1+(FC(row,2) & 1), indx=row*width+col,c=FC(row,col+1),d=2-c; col<width-1; col+=2, indx+=2) {
  86. image2[indx][c] = CLIP((image[indx+1][c] + image[indx-1][c])/2.0);
  87. image2[indx][d] = CLIP((2*image2[indx][1] - image2[indx+u][1] - image2[indx-u][1] + image[indx+u][d] + image[indx-u][d])/2.0);
  88. }
  89. }
  90. // missing R and B are interpolated vertically and saved in image3
  91. void CLASS dcb_color3(float (*image3)[3])
  92. {
  93. int row, col, c, d, u=width, indx;
  94. for (row=1; row < height-1; row++)
  95. for (col=1+(FC(row,1) & 1), indx=row*width+col, c=2-FC(row,col); col < u-1; col+=2, indx+=2) {
  96. image3[indx][c] = CLIP((
  97. 4*image3[indx][1]
  98. - image3[indx+u+1][1] - image3[indx+u-1][1] - image3[indx-u+1][1] - image3[indx-u-1][1]
  99. + image[indx+u+1][c] + image[indx+u-1][c] + image[indx-u+1][c] + image[indx-u-1][c] )/4.0);
  100. }
  101. for (row=1; row<height-1; row++)
  102. for (col=1+(FC(row,2) & 1), indx=row*width+col,c=FC(row,col+1),d=2-c; col<width-1; col+=2, indx+=2) {
  103. image3[indx][c] = CLIP((2*image3[indx][1] - image3[indx+1][1] - image3[indx-1][1] + image[indx+1][c] + image[indx-1][c])/2.0);
  104. image3[indx][d] = CLIP((image[indx+u][d] + image[indx-u][d])/2.0);
  105. }
  106. }
  107. // decides the primary green interpolation direction
  108. void CLASS dcb_decide(float (*image2)[3], float (*image3)[3])
  109. {
  110. int row, col, c, d, u=width, v=2*u, indx;
  111. float current, current2, current3;
  112. for (row=2; row < height-2; row++)
  113. for (col=2+(FC(row,2)&1),indx=row*width+col, c=FC(row,col); col < u-2; col+=2,indx+=2) {
  114. d=ABS(c-2);
  115. current = MAX(image[indx+v][c], MAX(image[indx-v][c], MAX(image[indx-2][c], image[indx+2][c]))) -
  116. MIN(image[indx+v][c], MIN(image[indx-v][c], MIN(image[indx-2][c], image[indx+2][c]))) +
  117. MAX(image[indx+1+u][d], MAX(image[indx+1-u][d], MAX(image[indx-1+u][d], image[indx-1-u][d]))) -
  118. MIN(image[indx+1+u][d], MIN(image[indx+1-u][d], MIN(image[indx-1+u][d], image[indx-1-u][d])));
  119. current2 = MAX(image2[indx+v][d], MAX(image2[indx-v][d], MAX(image2[indx-2][d], image2[indx+2][d]))) -
  120. MIN(image2[indx+v][d], MIN(image2[indx-v][d], MIN(image2[indx-2][d], image2[indx+2][d]))) +
  121. MAX(image2[indx+1+u][c], MAX(image2[indx+1-u][c], MAX(image2[indx-1+u][c], image2[indx-1-u][c]))) -
  122. MIN(image2[indx+1+u][c], MIN(image2[indx+1-u][c], MIN(image2[indx-1+u][c], image2[indx-1-u][c])));
  123. current3 = MAX(image3[indx+v][d], MAX(image3[indx-v][d], MAX(image3[indx-2][d], image3[indx+2][d]))) -
  124. MIN(image3[indx+v][d], MIN(image3[indx-v][d], MIN(image3[indx-2][d], image3[indx+2][d]))) +
  125. MAX(image3[indx+1+u][c], MAX(image3[indx+1-u][c], MAX(image3[indx-1+u][c], image3[indx-1-u][c]))) -
  126. MIN(image3[indx+1+u][c], MIN(image3[indx+1-u][c], MIN(image3[indx-1+u][c], image3[indx-1-u][c])));
  127. if (ABS(current-current2) < ABS(current-current3))
  128. image[indx][1] = image2[indx][1];
  129. else
  130. image[indx][1] = image3[indx][1];
  131. }
  132. }
  133. // saves red and blue in image2
  134. void CLASS dcb_copy_to_buffer(float (*image2)[3])
  135. {
  136. int indx;
  137. for (indx=0; indx < height*width; indx++) {
  138. image2[indx][0]=image[indx][0]; //R
  139. image2[indx][2]=image[indx][2]; //B
  140. }
  141. }
  142. // restores red and blue from image2
  143. void CLASS dcb_restore_from_buffer(float (*image2)[3])
  144. {
  145. int indx;
  146. for (indx=0; indx < height*width; indx++) {
  147. image[indx][0]=image2[indx][0]; //R
  148. image[indx][2]=image2[indx][2]; //B
  149. }
  150. }
  151. // R and B smoothing using green contrast, all pixels except 2 pixel wide border
  152. void CLASS dcb_pp()
  153. {
  154. int g1, r1, b1, u=width, indx, row, col;
  155. for (row=2; row < height-2; row++)
  156. for (col=2, indx=row*u+col; col < width-2; col++, indx++) {
  157. r1 = ( image[indx-1][0] + image[indx+1][0] + image[indx-u][0] + image[indx+u][0] + image[indx-u-1][0] + image[indx+u+1][0] + image[indx-u+1][0] + image[indx+u-1][0])/8.0;
  158. g1 = ( image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1] + image[indx-u-1][1] + image[indx+u+1][1] + image[indx-u+1][1] + image[indx+u-1][1])/8.0;
  159. b1 = ( image[indx-1][2] + image[indx+1][2] + image[indx-u][2] + image[indx+u][2] + image[indx-u-1][2] + image[indx+u+1][2] + image[indx-u+1][2] + image[indx+u-1][2])/8.0;
  160. image[indx][0] = CLIP(r1 + ( image[indx][1] - g1 ));
  161. image[indx][2] = CLIP(b1 + ( image[indx][1] - g1 ));
  162. }
  163. }
  164. // green blurring correction, helps to get the nyquist right
  165. void CLASS dcb_nyquist()
  166. {
  167. int row, col, c, u=width, v=2*u, indx;
  168. for (row=2; row < height-2; row++)
  169. for (col=2+(FC(row,2)&1),indx=row*width+col, c=FC(row,col); col < u-2; col+=2,indx+=2) {
  170. image[indx][1] = CLIP((image[indx+v][1] + image[indx-v][1] + image[indx-2][1] + image[indx+2][1])/4.0 +
  171. image[indx][c] - ( image[indx+v][c] + image[indx-v][c] + image[indx-2][c] + image[indx+2][c])/4.0);
  172. }
  173. }
  174. // missing colors are interpolated using high quality algorithm by Luis Sanz Rodríguez
  175. void CLASS dcb_color_full()
  176. {
  177. int row,col,c,d,i,j,u=width,v=2*u,w=3*u,indx, g1, g2;
  178. float f[4],g[4],(*chroma)[2];
  179. chroma = (float (*)[2]) calloc(width*height,sizeof *chroma); merror (chroma, "dcb_color_full()");
  180. for (row=1; row < height-1; row++)
  181. for (col=1+(FC(row,1)&1),indx=row*width+col,c=FC(row,col),d=c/2; col < u-1; col+=2,indx+=2)
  182. chroma[indx][d]=image[indx][c]-image[indx][1];
  183. for (row=3; row<height-3; row++)
  184. for (col=3+(FC(row,1)&1),indx=row*width+col,c=1-FC(row,col)/2,d=1-c; col<u-3; col+=2,indx+=2) {
  185. f[0]=1.0/(float)(1.0+fabs(chroma[indx-u-1][c]-chroma[indx+u+1][c])+fabs(chroma[indx-u-1][c]-chroma[indx-w-3][c])+fabs(chroma[indx+u+1][c]-chroma[indx-w-3][c]));
  186. f[1]=1.0/(float)(1.0+fabs(chroma[indx-u+1][c]-chroma[indx+u-1][c])+fabs(chroma[indx-u+1][c]-chroma[indx-w+3][c])+fabs(chroma[indx+u-1][c]-chroma[indx-w+3][c]));
  187. f[2]=1.0/(float)(1.0+fabs(chroma[indx+u-1][c]-chroma[indx-u+1][c])+fabs(chroma[indx+u-1][c]-chroma[indx+w+3][c])+fabs(chroma[indx-u+1][c]-chroma[indx+w-3][c]));
  188. f[3]=1.0/(float)(1.0+fabs(chroma[indx+u+1][c]-chroma[indx-u-1][c])+fabs(chroma[indx+u+1][c]-chroma[indx+w-3][c])+fabs(chroma[indx-u-1][c]-chroma[indx+w+3][c]));
  189. g[0]=1.325*chroma[indx-u-1][c]-0.175*chroma[indx-w-3][c]-0.075*chroma[indx-w-1][c]-0.075*chroma[indx-u-3][c];
  190. g[1]=1.325*chroma[indx-u+1][c]-0.175*chroma[indx-w+3][c]-0.075*chroma[indx-w+1][c]-0.075*chroma[indx-u+3][c];
  191. g[2]=1.325*chroma[indx+u-1][c]-0.175*chroma[indx+w-3][c]-0.075*chroma[indx+w-1][c]-0.075*chroma[indx+u-3][c];
  192. g[3]=1.325*chroma[indx+u+1][c]-0.175*chroma[indx+w+3][c]-0.075*chroma[indx+w+1][c]-0.075*chroma[indx+u+3][c];
  193. chroma[indx][c]=(f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]);
  194. }
  195. for (row=3; row<height-3; row++)
  196. for (col=3+(FC(row,2)&1),indx=row*width+col,c=FC(row,col+1)/2; col<u-3; col+=2,indx+=2)
  197. for(d=0;d<=1;c=1-c,d++){
  198. f[0]=1.0/(float)(1.0+fabs(chroma[indx-u][c]-chroma[indx+u][c])+fabs(chroma[indx-u][c]-chroma[indx-w][c])+fabs(chroma[indx+u][c]-chroma[indx-w][c]));
  199. f[1]=1.0/(float)(1.0+fabs(chroma[indx+1][c]-chroma[indx-1][c])+fabs(chroma[indx+1][c]-chroma[indx+3][c])+fabs(chroma[indx-1][c]-chroma[indx+3][c]));
  200. f[2]=1.0/(float)(1.0+fabs(chroma[indx-1][c]-chroma[indx+1][c])+fabs(chroma[indx-1][c]-chroma[indx-3][c])+fabs(chroma[indx+1][c]-chroma[indx-3][c]));
  201. f[3]=1.0/(float)(1.0+fabs(chroma[indx+u][c]-chroma[indx-u][c])+fabs(chroma[indx+u][c]-chroma[indx+w][c])+fabs(chroma[indx-u][c]-chroma[indx+w][c]));
  202. g[0]=0.875*chroma[indx-u][c]+0.125*chroma[indx-w][c];
  203. g[1]=0.875*chroma[indx+1][c]+0.125*chroma[indx+3][c];
  204. g[2]=0.875*chroma[indx-1][c]+0.125*chroma[indx-3][c];
  205. g[3]=0.875*chroma[indx+u][c]+0.125*chroma[indx+w][c];
  206. chroma[indx][c]=(f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]);
  207. }
  208. for(row=6; row<height-6; row++)
  209. for(col=6,indx=row*width+col; col<width-6; col++,indx++){
  210. image[indx][0]=CLIP(chroma[indx][0]+image[indx][1]);
  211. image[indx][2]=CLIP(chroma[indx][1]+image[indx][1]);
  212. g1 = MIN(image[indx+1+u][0], MIN(image[indx+1-u][0], MIN(image[indx-1+u][0], MIN(image[indx-1-u][0], MIN(image[indx-1][0], MIN(image[indx+1][0], MIN(image[indx-u][0], image[indx+u][0])))))));
  213. g2 = MAX(image[indx+1+u][0], MAX(image[indx+1-u][0], MAX(image[indx-1+u][0], MAX(image[indx-1-u][0], MAX(image[indx-1][0], MAX(image[indx+1][0], MAX(image[indx-u][0], image[indx+u][0])))))));
  214. image[indx][0] = ULIM(image[indx][0], g2, g1);
  215. g1 = MIN(image[indx+1+u][2], MIN(image[indx+1-u][2], MIN(image[indx-1+u][2], MIN(image[indx-1-u][2], MIN(image[indx-1][2], MIN(image[indx+1][2], MIN(image[indx-u][2], image[indx+u][2])))))));
  216. g2 = MAX(image[indx+1+u][2], MAX(image[indx+1-u][2], MAX(image[indx-1+u][2], MAX(image[indx-1-u][2], MAX(image[indx-1][2], MAX(image[indx+1][2], MAX(image[indx-u][2], image[indx+u][2])))))));
  217. image[indx][2] = ULIM(image[indx][2], g2, g1);
  218. }
  219. free(chroma);
  220. }
  221. // green is used to create an interpolation direction map saved in image[][3]
  222. // 1 = vertical
  223. // 0 = horizontal
  224. void CLASS dcb_map()
  225. {
  226. int current, row, col, c, u=width, v=2*u, indx;
  227. for (row=1; row < height-1; row++) {
  228. for (col=1, indx=row*width+col; col < width-1; col++, indx++) {
  229. if (image[indx][1] > ( image[indx-1][1] + image[indx+1][1] + image[indx-u][1] + image[indx+u][1])/4.0)
  230. image[indx][3] = ((MIN( image[indx-1][1], image[indx+1][1]) + image[indx-1][1] + image[indx+1][1]) <
  231. (MIN( image[indx-u][1], image[indx+u][1]) + image[indx-u][1] + image[indx+u][1]));
  232. else
  233. image[indx][3] = ((MAX( image[indx-1][1], image[indx+1][1]) + image[indx-1][1] + image[indx+1][1]) >
  234. (MAX( image[indx-u][1], image[indx+u][1]) + image[indx-u][1] + image[indx+u][1]));
  235. }
  236. }
  237. }
  238. // interpolated green pixels are corrected using the map
  239. void CLASS dcb_correction()
  240. {
  241. int current, row, col, u=width, v=2*u, indx;
  242. for (row=2; row < height-2; row++)
  243. for (col=2+(FC(row,2)&1),indx=row*width+col; col < u-2; col+=2,indx+=2) {
  244. current = 4*image[indx][3] +
  245. 2*(image[indx+u][3] + image[indx-u][3] + image[indx+1][3] + image[indx-1][3]) +
  246. image[indx+v][3] + image[indx-v][3] + image[indx+2][3] + image[indx-2][3];
  247. image[indx][1] = ((16-current)*(image[indx-1][1] + image[indx+1][1])/2.0 + current*(image[indx-u][1] + image[indx+u][1])/2.0)/16.0;
  248. }
  249. }
  250. // interpolated green pixels are corrected using the map
  251. // with contrast correction
  252. void CLASS dcb_correction2()
  253. {
  254. int current, row, col, c, u=width, v=2*u, indx;
  255. ushort (*pix)[4];
  256. for (row=4; row < height-4; row++)
  257. for (col=4+(FC(row,2)&1),indx=row*width+col, c=FC(row,col); col < u-4; col+=2,indx+=2) {
  258. current = 4*image[indx][3] +
  259. 2*(image[indx+u][3] + image[indx-u][3] + image[indx+1][3] + image[indx-1][3]) +
  260. image[indx+v][3] + image[indx-v][3] + image[indx+2][3] + image[indx-2][3];
  261. image[indx][1] = CLIP(((16-current)*((image[indx-1][1] + image[indx+1][1])/2.0 + image[indx][c] - (image[indx+2][c] + image[indx-2][c])/2.0) + current*((image[indx-u][1] + image[indx+u][1])/2.0 + image[indx][c] - (image[indx+v][c] + image[indx-v][c])/2.0))/16.0);
  262. }
  263. }
  264. void CLASS dcb_refinement()
  265. {
  266. int row, col, c, u=width, v=2*u, w=3*u, indx, current;
  267. float f[5], g1, g2, tmp, tmp2=0, tmp3=0;
  268. for (row=4; row < height-4; row++)
  269. for (col=4+(FC(row,2)&1),indx=row*width+col, c=FC(row,col); col < u-4; col+=2,indx+=2) {
  270. current = 4*image[indx][3] +
  271. 2*(image[indx+u][3] + image[indx-u][3] + image[indx+1][3] + image[indx-1][3])
  272. +image[indx+v][3] + image[indx-v][3] + image[indx-2][3] + image[indx+2][3];
  273. if (image[indx][c] > 1)
  274. {
  275. f[0] = (float)(image[indx-u][1] + image[indx+u][1])/(2*image[indx][c]);
  276. if (image[indx-v][c] > 0)
  277. f[1] = 2*(float)image[indx-u][1]/(image[indx-v][c] + image[indx][c]);
  278. else
  279. f[1] = f[0];
  280. if (image[indx-v][c] > 0)
  281. f[2] = (float)(image[indx-u][1] + image[indx-w][1])/(2*image[indx-v][c]);
  282. else
  283. f[2] = f[0];
  284. if (image[indx+v][c] > 0)
  285. f[3] = 2*(float)image[indx+u][1]/(image[indx+v][c] + image[indx][c]);
  286. else
  287. f[3] = f[0];
  288. if (image[indx+v][c] > 0)
  289. f[4] = (float)(image[indx+u][1] + image[indx+w][1])/(2*image[indx+v][c]);
  290. else
  291. f[4] = f[0];
  292. g1 = (5*f[0] + 3*f[1] + f[2] + 3*f[3] + f[4])/13.0;
  293. f[0] = (float)(image[indx-1][1] + image[indx+1][1])/(2*image[indx][c]);
  294. if (image[indx-2][c] > 0)
  295. f[1] = 2*(float)image[indx-1][1]/(image[indx-2][c] + image[indx][c]);
  296. else
  297. f[1] = f[0];
  298. if (image[indx-2][c] > 0)
  299. f[2] = (float)(image[indx-1][1] + image[indx-3][1])/(2*image[indx-2][c]);
  300. else
  301. f[2] = f[0];
  302. if (image[indx+2][c] > 0)
  303. f[3] = 2*(float)image[indx+1][1]/(image[indx+2][c] + image[indx][c]);
  304. else
  305. f[3] = f[0];
  306. if (image[indx+2][c] > 0)
  307. f[4] = (float)(image[indx+1][1] + image[indx+3][1])/(2*image[indx+2][c]);
  308. else
  309. f[4] = f[0];
  310. g2 = (5*f[0] + 3*f[1] + f[2] + 3*f[3] + f[4])/13.0;
  311. image[indx][1] = CLIP((image[indx][c])*(current*g1 + (16-current)*g2)/16.0);
  312. }
  313. else
  314. image[indx][1] = image[indx][c];
  315. // get rid of overshooted pixels
  316. g1 = MIN(image[indx+1+u][1], MIN(image[indx+1-u][1], MIN(image[indx-1+u][1], MIN(image[indx-1-u][1], MIN(image[indx-1][1], MIN(image[indx+1][1], MIN(image[indx-u][1], image[indx+u][1])))))));
  317. g2 = MAX(image[indx+1+u][1], MAX(image[indx+1-u][1], MAX(image[indx-1+u][1], MAX(image[indx-1-u][1], MAX(image[indx-1][1], MAX(image[indx+1][1], MAX(image[indx-u][1], image[indx+u][1])))))));
  318. image[indx][1] = ULIM(image[indx][1], g2, g1);
  319. }
  320. }
  321. // converts RGB to LCH colorspace and saves it to image3
  322. void CLASS rgb_to_lch(double (*image2)[3])
  323. {
  324. int indx;
  325. for (indx=0; indx < height*width; indx++) {
  326. image2[indx][0] = image[indx][0] + image[indx][1] + image[indx][2]; // L
  327. image2[indx][1] = 1.732050808 *(image[indx][0] - image[indx][1]); // C
  328. image2[indx][2] = 2.0*image[indx][2] - image[indx][0] - image[indx][1]; // H
  329. }
  330. }
  331. // converts LCH to RGB colorspace and saves it back to image
  332. void CLASS lch_to_rgb(double (*image2)[3])
  333. {
  334. int indx;
  335. for (indx=0; indx < height*width; indx++) {
  336. image[indx][0] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 + image2[indx][1] / 3.464101615);
  337. image[indx][1] = CLIP(image2[indx][0] / 3.0 - image2[indx][2] / 6.0 - image2[indx][1] / 3.464101615);
  338. image[indx][2] = CLIP(image2[indx][0] / 3.0 + image2[indx][2] / 3.0);
  339. }
  340. }
  341. // denoising using interpolated neighbours
  342. void CLASS fbdd_correction()
  343. {
  344. int row, col, c, u=width, indx;
  345. ushort (*pix)[4];
  346. for (row=2; row < height-2; row++) {
  347. for (col=2, indx=row*width+col; col < width-2; col++, indx++) {
  348. c = fc(row,col);
  349. image[indx][c] = ULIM(image[indx][c],
  350. MAX(image[indx-1][c], MAX(image[indx+1][c], MAX(image[indx-u][c], image[indx+u][c]))),
  351. MIN(image[indx-1][c], MIN(image[indx+1][c], MIN(image[indx-u][c], image[indx+u][c]))));
  352. }
  353. }
  354. }
  355. // corrects chroma noise
  356. void CLASS fbdd_correction2(double (*image2)[3])
  357. {
  358. int indx, u=width, v=2*width;
  359. int col, row;
  360. double Co, Ho, ratio;
  361. for (row=6; row < height-6; row++)
  362. {
  363. for (col=6; col < width-6; col++)
  364. {
  365. indx = row*width+col;
  366. if ( image2[indx][1]*image2[indx][2] != 0 )
  367. {
  368. Co = (image2[indx+v][1] + image2[indx-v][1] + image2[indx-2][1] + image2[indx+2][1] -
  369. MAX(image2[indx-2][1], MAX(image2[indx+2][1], MAX(image2[indx-v][1], image2[indx+v][1]))) -
  370. MIN(image2[indx-2][1], MIN(image2[indx+2][1], MIN(image2[indx-v][1], image2[indx+v][1]))))/2.0;
  371. Ho = (image2[indx+v][2] + image2[indx-v][2] + image2[indx-2][2] + image2[indx+2][2] -
  372. MAX(image2[indx-2][2], MAX(image2[indx+2][2], MAX(image2[indx-v][2], image2[indx+v][2]))) -
  373. MIN(image2[indx-2][2], MIN(image2[indx+2][2], MIN(image2[indx-v][2], image2[indx+v][2]))))/2.0;
  374. ratio = sqrt ((Co*Co+Ho*Ho) / (image2[indx][1]*image2[indx][1] + image2[indx][2]*image2[indx][2]));
  375. if (ratio < 0.85)
  376. {
  377. image2[indx][0] = -(image2[indx][1] + image2[indx][2] - Co - Ho) + image2[indx][0];
  378. image2[indx][1] = Co;
  379. image2[indx][2] = Ho;
  380. }
  381. }
  382. }
  383. }
  384. }
  385. // Cubic Spline Interpolation by Li and Randhawa, modified by Jacek Gozdz and Luis Sanz Rodríguez
  386. void CLASS fbdd_green()
  387. {
  388. int row, col, c, u=width, v=2*u, w=3*u, x=4*u, y=5*u, indx, min, max, current;
  389. float f[4], g[4];
  390. for (row=5; row < height-5; row++)
  391. for (col=5+(FC(row,1)&1),indx=row*width+col,c=FC(row,col); col < u-5; col+=2,indx+=2) {
  392. f[0]=1.0/(1.0+abs(image[indx-u][1]-image[indx-w][1])+abs(image[indx-w][1]-image[indx+y][1]));
  393. f[1]=1.0/(1.0+abs(image[indx+1][1]-image[indx+3][1])+abs(image[indx+3][1]-image[indx-5][1]));
  394. f[2]=1.0/(1.0+abs(image[indx-1][1]-image[indx-3][1])+abs(image[indx-3][1]-image[indx+5][1]));
  395. f[3]=1.0/(1.0+abs(image[indx+u][1]-image[indx+w][1])+abs(image[indx+w][1]-image[indx-y][1]));
  396. g[0]=CLIP((23*image[indx-u][1]+23*image[indx-w][1]+2*image[indx-y][1]+8*(image[indx-v][c]-image[indx-x][c])+40*(image[indx][c]-image[indx-v][c]))/48.0);
  397. g[1]=CLIP((23*image[indx+1][1]+23*image[indx+3][1]+2*image[indx+5][1]+8*(image[indx+2][c]-image[indx+4][c])+40*(image[indx][c]-image[indx+2][c]))/48.0);
  398. g[2]=CLIP((23*image[indx-1][1]+23*image[indx-3][1]+2*image[indx-5][1]+8*(image[indx-2][c]-image[indx-4][c])+40*(image[indx][c]-image[indx-2][c]))/48.0);
  399. g[3]=CLIP((23*image[indx+u][1]+23*image[indx+w][1]+2*image[indx+y][1]+8*(image[indx+v][c]-image[indx+x][c])+40*(image[indx][c]-image[indx+v][c]))/48.0);
  400. image[indx][1]=CLIP((f[0]*g[0]+f[1]*g[1]+f[2]*g[2]+f[3]*g[3])/(f[0]+f[1]+f[2]+f[3]));
  401. min = MIN(image[indx+1+u][1], MIN(image[indx+1-u][1], MIN(image[indx-1+u][1], MIN(image[indx-1-u][1], MIN(image[indx-1][1], MIN(image[indx+1][1], MIN(image[indx-u][1], image[indx+u][1])))))));
  402. max = MAX(image[indx+1+u][1], MAX(image[indx+1-u][1], MAX(image[indx-1+u][1], MAX(image[indx-1-u][1], MAX(image[indx-1][1], MAX(image[indx+1][1], MAX(image[indx-u][1], image[indx+u][1])))))));
  403. image[indx][1] = ULIM(image[indx][1], max, min);
  404. }
  405. }
  406. // FBDD (Fake Before Demosaicing Denoising)
  407. void CLASS fbdd(int noiserd)
  408. {
  409. double (*image2)[3];
  410. // safety net: disable for 4-color bayer or full-color images
  411. if(colors!=3 || !filters)
  412. return;
  413. image2 = (double (*)[3]) calloc(width*height, sizeof *image2);
  414. border_interpolate(4);
  415. if (noiserd>1)
  416. {
  417. #ifdef DCRAW_VERBOSE
  418. if (verbose) fprintf (stderr,_("FBDD full noise reduction...\n"));
  419. #endif
  420. fbdd_green();
  421. //dcb_color_full(image2);
  422. dcb_color_full();
  423. fbdd_correction();
  424. dcb_color();
  425. rgb_to_lch(image2);
  426. fbdd_correction2(image2);
  427. fbdd_correction2(image2);
  428. lch_to_rgb(image2);
  429. }
  430. else
  431. {
  432. #ifdef DCRAW_VERBOSE
  433. if (verbose) fprintf (stderr,_("FBDD noise reduction...\n"));
  434. #endif
  435. fbdd_green();
  436. //dcb_color_full(image2);
  437. dcb_color_full();
  438. fbdd_correction();
  439. }
  440. free(image2);
  441. }
  442. // DCB demosaicing main routine
  443. void CLASS dcb(int iterations, int dcb_enhance)
  444. {
  445. int i=1;
  446. float (*image2)[3];
  447. image2 = (float (*)[3]) calloc(width*height, sizeof *image2);
  448. float (*image3)[3];
  449. image3 = (float (*)[3]) calloc(width*height, sizeof *image3);
  450. #ifdef DCRAW_VERBOSE
  451. if (verbose) fprintf (stderr,_("DCB demosaicing...\n"));
  452. #endif
  453. border_interpolate(6);
  454. dcb_hor(image2);
  455. dcb_color2(image2);
  456. dcb_ver(image3);
  457. dcb_color3(image3);
  458. dcb_decide(image2, image3);
  459. free(image3);
  460. dcb_copy_to_buffer(image2);
  461. while (i<=iterations)
  462. {
  463. #ifdef DCRAW_VERBOSE
  464. if (verbose) fprintf (stderr,_("DCB correction pass %d...\n"), i);
  465. #endif
  466. dcb_nyquist();
  467. dcb_nyquist();
  468. dcb_nyquist();
  469. dcb_map();
  470. dcb_correction();
  471. i++;
  472. }
  473. dcb_color();
  474. dcb_pp();
  475. #ifdef DCRAW_VERBOSE
  476. if (verbose) fprintf (stderr,_("finishing DCB...\n"));
  477. #endif
  478. dcb_map();
  479. dcb_correction2();
  480. dcb_map();
  481. dcb_correction();
  482. dcb_map();
  483. dcb_correction();
  484. dcb_map();
  485. dcb_correction();
  486. dcb_map();
  487. dcb_restore_from_buffer(image2);
  488. dcb_color();
  489. if (dcb_enhance)
  490. {
  491. #ifdef DCRAW_VERBOSE
  492. if (verbose) fprintf (stderr,_("optional DCB refinement...\n"));
  493. #endif
  494. dcb_refinement();
  495. //dcb_color_full(image2);
  496. dcb_color_full();
  497. }
  498. free(image2);
  499. }