1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5  *
6  *  RawTherapee is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  RawTherapee is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with RawTherapee.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <algorithm>
20 
21 #include "bayerhelper.h"
22 #include "librtprocess.h"
23 #include "StopWatch.h"
24 #include "xtranshelper.h"
25 
26 using namespace librtprocess;
27 
bayerborder_demosaic(int winw,int winh,int lborders,const float * const * rawData,float ** red,float ** green,float ** blue,const unsigned cfarray[2][2])28 rpError bayerborder_demosaic(int winw, int winh, int lborders, const float * const *rawData, float **red, float **green, float **blue, const unsigned cfarray[2][2])
29 {
30     BENCHFUN
31     if (!validateBayerCfa(3, cfarray)) {
32         return RP_WRONG_CFA;
33     }
34 
35     int bord = lborders;
36     int width = winw;
37     int height = winh;
38 
39     for (int i = 0; i < height; i++) {
40 
41         float sum[6];
42 
43         for (int j = 0; j < bord; j++) { //first few columns
44             for (int c = 0; c < 6; c++) {
45                 sum[c] = 0;
46             }
47 
48             for (int i1 = i - 1; i1 < i + 2; i1++)
49                 for (int j1 = j - 1; j1 < j + 2; j1++) {
50                     if ((i1 > -1) && (i1 < height) && (j1 > -1)) {
51                         int c = fc(cfarray, i1, j1);
52                         sum[c] += rawData[i1][j1];
53                         sum[c + 3]++;
54                     }
55                 }
56 
57             int c = fc(cfarray, i, j);
58 
59             if (c == 1) {
60                 red[i][j] = sum[0] / sum[3];
61                 green[i][j] = rawData[i][j];
62                 blue[i][j] = sum[2] / sum[5];
63             } else {
64                 green[i][j] = sum[1] / sum[4];
65 
66                 if (c == 0) {
67                     red[i][j] = rawData[i][j];
68                     blue[i][j] = sum[2] / sum[5];
69                 } else {
70                     red[i][j] = sum[0] / sum[3];
71                     blue[i][j] = rawData[i][j];
72                 }
73             }
74         }//j
75 
76         for (int j = width - bord; j < width; j++) { //last few columns
77             for (int c = 0; c < 6; c++) {
78                 sum[c] = 0;
79             }
80 
81             for (int i1 = i - 1; i1 < i + 2; i1++)
82                 for (int j1 = j - 1; j1 < j + 2; j1++) {
83                     if ((i1 > -1) && (i1 < height ) && (j1 < width)) {
84                         int c = fc(cfarray, i1, j1);
85                         sum[c] += rawData[i1][j1];
86                         sum[c + 3]++;
87                     }
88                 }
89 
90             int c = fc(cfarray, i, j);
91 
92             if (c == 1) {
93                 red[i][j] = sum[0] / sum[3];
94                 green[i][j] = rawData[i][j];
95                 blue[i][j] = sum[2] / sum[5];
96             } else {
97                 green[i][j] = sum[1] / sum[4];
98 
99                 if (c == 0) {
100                     red[i][j] = rawData[i][j];
101                     blue[i][j] = sum[2] / sum[5];
102                 } else {
103                     red[i][j] = sum[0] / sum[3];
104                     blue[i][j] = rawData[i][j];
105                 }
106             }
107         }//j
108     }//i
109 
110     for (int i = 0; i < bord; i++) {
111 
112         float sum[6];
113 
114         for (int j = bord; j < width - bord; j++) { //first few rows
115             for (int c = 0; c < 6; c++) {
116                 sum[c] = 0;
117             }
118 
119             for (int i1 = i - 1; i1 < i + 2; i1++)
120                 for (int j1 = j - 1; j1 < j + 2; j1++) {
121                     if ((i1 > -1) && (i1 < height) && (j1 > -1)) {
122                         int c = fc(cfarray, i1, j1);
123                         sum[c] += rawData[i1][j1];
124                         sum[c + 3]++;
125                     }
126                 }
127 
128             int c = fc(cfarray, i, j);
129 
130             if (c == 1) {
131                 red[i][j] = sum[0] / sum[3];
132                 green[i][j] = rawData[i][j];
133                 blue[i][j] = sum[2] / sum[5];
134             } else {
135                 green[i][j] = sum[1] / sum[4];
136 
137                 if (c == 0) {
138                     red[i][j] = rawData[i][j];
139                     blue[i][j] = sum[2] / sum[5];
140                 } else {
141                     red[i][j] = sum[0] / sum[3];
142                     blue[i][j] = rawData[i][j];
143                 }
144             }
145         }//j
146     }
147 
148     for (int i = height - bord; i < height; i++) {
149 
150         float sum[6];
151 
152         for (int j = bord; j < width - bord; j++) { //last few rows
153             for (int c = 0; c < 6; c++) {
154                 sum[c] = 0;
155             }
156 
157             for (int i1 = i - 1; i1 < i + 2; i1++)
158                 for (int j1 = j - 1; j1 < j + 2; j1++) {
159                     if ((i1 > -1) && (i1 < height) && (j1 < width)) {
160                         int c = fc(cfarray, i1, j1);
161                         sum[c] += rawData[i1][j1];
162                         sum[c + 3]++;
163                     }
164                 }
165 
166             int c = fc(cfarray, i, j);
167 
168             if (c == 1) {
169                 red[i][j] = sum[0] / sum[3];
170                 green[i][j] = rawData[i][j];
171                 blue[i][j] = sum[2] / sum[5];
172             } else {
173                 green[i][j] = sum[1] / sum[4];
174 
175                 if (c == 0) {
176                     red[i][j] = rawData[i][j];
177                     blue[i][j] = sum[2] / sum[5];
178                 } else {
179                     red[i][j] = sum[0] / sum[3];
180                     blue[i][j] = rawData[i][j];
181                 }
182             }
183         }//j
184     }
185 
186     return RP_NO_ERROR;
187 }
188 
xtransborder_demosaic(int winw,int winh,int border,const float * const * rawData,float ** red,float ** green,float ** blue,const unsigned xtrans[6][6])189 void xtransborder_demosaic(int winw, int winh, int border, const float * const *rawData, float **red, float **green, float **blue, const unsigned xtrans[6][6])
190 {
191     BENCHFUN
192     const int height = winh, width = winw;
193 
194     const float weight[3][3] = {
195                                 {0.25f, 0.5f, 0.25f},
196                                 {0.5f,  0.f,  0.5f},
197                                 {0.25f, 0.5f, 0.25f}
198                                };
199 
200     for (int row = 0; row < height; row++) {
201         for (int col = 0; col < width; col++) {
202             if (col == border && row >= border && row < height - border) {
203                 col = width - border;
204             }
205 
206             float sum[6] = {0.f};
207 
208             for (int y = std::max(0, row - 1), v = row == 0 ? 0 : -1; y <= std::min(row + 1, height - 1); y++, v++)
209                 for (int x = std::max(0, col - 1), h = col == 0 ? 0 : -1; x <= std::min(col + 1, width - 1); x++, h++) {
210                     int f = fc(xtrans, y, x);
211                     sum[f] += rawData[y][x] * weight[v + 1][h + 1];
212                     sum[f + 3] += weight[v + 1][h + 1];
213                 }
214 
215             switch(fc(xtrans, row, col)) {
216                 case 0:
217                     red[row][col] = rawData[row][col];
218                     green[row][col] = (sum[1] / sum[4]);
219                     blue[row][col] = (sum[2] / sum[5]);
220                     break;
221 
222                 case 1:
223                     if(sum[3] == 0.f) { // at the 4 corner pixels it can happen, that we have only green pixels in 2x2 area
224                         red[row][col] = green[row][col] = blue[row][col] = rawData[row][col];
225                     } else {
226                         red[row][col] = (sum[0] / sum[3]);
227                         green[row][col] = rawData[row][col];
228                         blue[row][col] = (sum[2] / sum[5]);
229                     }
230 
231                     break;
232 
233                 case 2:
234                     red[row][col] = (sum[0] / sum[3]);
235                     green[row][col] = (sum[1] / sum[4]);
236                     blue[row][col] = rawData[row][col];
237             }
238         }
239     }
240 }
241