1 /*
2 */
3
4 /*
5
6 Copyright (C) 2014 Ferrero Andrea
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20
21
22 */
23
24 /*
25
26 These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/
27
28 */
29
30 #include "rawimagesource.hh"
31
32 //#define RT_EMU
33
RawImageSource()34 rtengine::RawImageSource::RawImageSource(): FC_roffset(0), FC_coffset(0), image_data(NULL), plistener(NULL)
35 {
36 }
37
38
39
ca_correct(VipsRegion * ir,VipsRegion * oreg,bool autoCA,float cared,float cablue)40 void rtengine::RawImageSource::ca_correct(VipsRegion* ir, VipsRegion* oreg, bool autoCA, float cared, float cablue)
41 {
42 int x, y;
43 int border = 8;
44 int border2 = border*2;
45
46 VipsRect *r = &oreg->valid;
47 int raw_left = (r->left/2)*2;
48 int raw_top = (r->top/2)*2;
49 int raw_right = r->left+r->width-1;
50 int raw_bottom = r->top+r->height-1;
51
52 // Make sure the border is entirely processed
53 //if( raw_left < border ) raw_left = 0;
54 //if( raw_top < border ) raw_top = 0;
55 //if( raw_right > (ir->im->Xsize-border-1) ) raw_right = ir->im->Xsize-1;
56 //if( raw_bottom > (ir->im->Ysize-border-1) ) raw_bottom = ir->im->Ysize-1;
57
58 // Portion of the image to be processed (pixels border is excluded)
59 VipsRect r_img = {border, border, ir->im->Xsize-border2, ir->im->Ysize-border2};
60 //std::cout<<"image: "<<ir->im->Xsize<<","<<ir->im->Ysize<<"+"<<0<<"+"<<0<<std::endl;
61 //std::cout<<"r_img: "<<r_img.width<<","<<r_img.height<<"+"<<r_img.left<<"+"<<r_img.top<<std::endl;
62 //VipsRect r_img = {0, 0, ir->im->Xsize, ir->im->Ysize};
63
64 /*for(int i = 0; i < 3; i++) {
65 for(int j = 0; j < 2; j++) {
66 for(int k = 0; k < 16; k++) {
67 printf("%f ", fitparams[i][j][k]);
68 }
69 printf("\n");
70 }
71 }*/
72
73 // Output region aligned to Bayer pattern and with pixels border excluded
74 VipsRect r_raw = {raw_left, raw_top, raw_right-raw_left+1, raw_bottom-raw_top+1};
75 if( (r_raw.width%2) ) r_raw.width += 1;
76 if( (r_raw.height%2) ) r_raw.height += 1;
77 //std::cout<<"r_raw(1): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
78 vips_rect_intersectrect (&r_raw, &r_img, &r_raw);
79 //std::cout<<"r_raw(2): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
80
81 #ifndef NDEBUG
82 std::cout<<"RawImageSource::ca_correct(): rawData.init( "<<ir->valid.width<<", "<<ir->valid.height<<", "
83 <<ir->valid.top<<", "<<ir->valid.left<<" )"<<std::endl;
84 #endif
85
86 // Initialization of pixel matrices
87 tile_top = ir->valid.top;
88 tile_left = ir->valid.left;
89 rawData.init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left, true );
90 for( y = 0; y < ir->valid.height; y++ ) {
91 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, ir->valid.left, y+ir->valid.top ) : NULL;
92 //rawData.set_row( y+ir->valid.top, ptr );
93 if(ptr) {
94 PF::raw_pixel_t* optr = rawData[y+ir->valid.top].get_pixels() + ir->valid.left;
95 memcpy(optr, ptr, ir->valid.width*sizeof(PF::raw_pixel_t));
96 }
97 }
98 //return;
99 //red.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
100 //green.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
101 //blue.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
102
103 // Call to demosaicing method
104 CA_correct_RT(0, 0, ir->im->Xsize, ir->im->Ysize,
105 r_raw.left, r_raw.top, r_raw.width, r_raw.height,
106 autoCA, cared, cablue);
107
108 VipsRect r_out;
109 vips_rect_intersectrect (r, &r_img, &r_out);
110
111 int xx;
112 for( y = 0; y < r_out.height; y++ ) {
113 //float* ptr = (float*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
114 PF::raw_pixel_t* ptr = (PF::raw_pixel_t*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
115 for( x = 0; x < r_out.width; x++ ) {
116 ptr[x][0] = rawData[y+r_out.top][x+r_out.left];
117 ptr[x][1] = rawData[y+r_out.top].color(x+r_out.left);
118 /*
119 #ifdef RT_EMU
120 // RawTherapee emulation
121 ptr[x*3] = CLAMP( red[y+r_out.top][x+r_out.left]/65535, 0, 95 );
122 ptr[x*3+1] = CLAMP( green[y+r_out.top][x+r_out.left]/65535, 0, 95 );
123 ptr[x*3+2] = CLAMP( blue[y+r_out.top][x+r_out.left]/65535, 0, 95 );
124 #else
125 ptr[xx] = CLAMP( red[y+r_out.top][x+r_out.left], 0, 1 );
126 ptr[xx+1] = CLAMP( green[y+r_out.top][x+r_out.left], 0, 1 );
127 ptr[xx+2] = CLAMP( blue[y+r_out.top][x+r_out.left], 0, 1 );
128 #endif
129 */
130 }
131 }
132 }
133
134
135
no_demosaic(VipsRegion * ir,VipsRegion * oreg)136 void rtengine::RawImageSource::no_demosaic(VipsRegion* ir, VipsRegion* oreg)
137 {
138 int x, xx, y;
139 VipsRect *r = &oreg->valid;
140 // Initialization of pixel matrices
141 for( y = 0; y < r->height; y++ ) {
142 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, r->left, y+r->top ) : NULL;
143 float* optr = (float*)VIPS_REGION_ADDR( oreg, r->left, y+r->top );
144 for( x = 0, xx = 0; x < r->width; x++, xx+=3 ) {
145 optr[xx] = ptr[x][0];
146 optr[xx+1] = ptr[x][0];
147 optr[xx+2] = ptr[x][0];
148 }
149 }
150 }
151
152
153
154
155
156
amaze_demosaic(VipsRegion * ir,VipsRegion * oreg)157 void rtengine::RawImageSource::amaze_demosaic(VipsRegion* ir, VipsRegion* oreg)
158 {
159 int x, y;
160 int border = 16;
161
162 VipsRect *r = &oreg->valid;
163 int raw_left = (r->left/2)*2;
164 int raw_top = (r->top/2)*2;
165 int raw_right = r->left+r->width-1;
166 int raw_bottom = r->top+r->height-1;
167
168 // Make sure the border is entirely processed
169 //if( raw_left < border ) raw_left = 0;
170 //if( raw_top < border ) raw_top = 0;
171 //if( raw_right > (ir->im->Xsize-border-1) ) raw_right = ir->im->Xsize-1;
172 //if( raw_bottom > (ir->im->Ysize-border-1) ) raw_bottom = ir->im->Ysize-1;
173
174 // Portion of the image to be processed (a 16 pixels border is excluded)
175 VipsRect r_img = {16, 16, ir->im->Xsize-32, ir->im->Ysize-32};
176 //std::cout<<"image: "<<ir->im->Xsize<<","<<ir->im->Ysize<<"+"<<0<<"+"<<0<<std::endl;
177 //std::cout<<"r_img: "<<r_img.width<<","<<r_img.height<<"+"<<r_img.left<<"+"<<r_img.top<<std::endl;
178 //VipsRect r_img = {0, 0, ir->im->Xsize, ir->im->Ysize};
179
180 // Output region aligned to Bayer pattern and with 16 pixels border excluded
181 VipsRect r_raw = {raw_left, raw_top, raw_right-raw_left+1, raw_bottom-raw_top+1};
182 if( (r_raw.width%2) ) r_raw.width += 1;
183 if( (r_raw.height%2) ) r_raw.height += 1;
184 //std::cout<<"r_raw(1): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
185 vips_rect_intersectrect (&r_raw, &r_img, &r_raw);
186 //std::cout<<"r_raw(2): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
187
188 #ifndef NDEBUG
189 std::cout<<"rawData.init( "<<ir->valid.width<<", "<<ir->valid.height<<", "
190 <<ir->valid.top<<", "<<ir->valid.left<<" )"<<std::endl;
191
192 {
193 float* p = (float*)VIPS_REGION_ADDR( ir, ir->valid.top, ir->valid.left );
194 std::cout<<"top= "<<ir->valid.top<<std::endl;
195 std::cout<<"left="<<ir->valid.left<<std::endl;
196 std::cout<<"p[0]="<<p[0]<<std::endl;
197 std::cout<<"p[1]="<<p[1]<<std::endl;
198 std::cout<<"p[2]="<<p[2]<<std::endl;
199 std::cout<<"p[3]="<<p[3]<<std::endl;
200 }
201 #endif
202
203 // Initialization of pixel matrices
204 tile_top = ir->valid.top;
205 tile_left = ir->valid.left;
206 rawData.init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
207 for( y = 0; y < ir->valid.height; y++ ) {
208 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, ir->valid.left, y+ir->valid.top ) : NULL;
209 rawData.set_row( y+ir->valid.top, ptr );
210 }
211 red.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
212 green.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
213 blue.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
214
215 // Call to demosaicing method
216 amaze_demosaic_RT(0, 0, ir->im->Xsize, ir->im->Ysize,
217 r_raw.left, r_raw.top, r_raw.width, r_raw.height);
218
219 VipsRect r_out;
220 vips_rect_intersectrect (r, &r_img, &r_out);
221
222 int xx;
223 for( y = 0; y < r_out.height; y++ ) {
224 float* ptr = (float*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
225 for( x = 0, xx = 0; x < r_out.width; x++, xx+=3 ) {
226 #ifdef RT_EMU
227 /* RawTherapee emulation */
228 ptr[x*3] = CLAMP( red[y+r_out.top][x+r_out.left]/65535, 0, 95 );
229 ptr[x*3+1] = CLAMP( green[y+r_out.top][x+r_out.left]/65535, 0, 95 );
230 ptr[x*3+2] = CLAMP( blue[y+r_out.top][x+r_out.left]/65535, 0, 95 );
231 #else
232 ptr[xx] = CLAMP( red[y+r_out.top][x+r_out.left], 0, 1 );
233 ptr[xx+1] = CLAMP( green[y+r_out.top][x+r_out.left], 0, 1 );
234 ptr[xx+2] = CLAMP( blue[y+r_out.top][x+r_out.left], 0, 1 );
235 #endif
236 }
237 }
238 }
239
240
241
rcd_demosaic(VipsRegion * ir,VipsRegion * oreg)242 void rtengine::RawImageSource::rcd_demosaic(VipsRegion* ir, VipsRegion* oreg)
243 {
244 int x, y;
245 int border = 8;
246
247 VipsRect *r = &oreg->valid;
248 int raw_left = (r->left/2)*2;
249 int raw_top = (r->top/2)*2;
250 int raw_right = r->left+r->width-1;
251 int raw_bottom = r->top+r->height-1;
252
253 // Make sure the border is entirely processed
254 //if( raw_left < border ) raw_left = 0;
255 //if( raw_top < border ) raw_top = 0;
256 //if( raw_right > (ir->im->Xsize-border-1) ) raw_right = ir->im->Xsize-1;
257 //if( raw_bottom > (ir->im->Ysize-border-1) ) raw_bottom = ir->im->Ysize-1;
258
259 // Portion of the image to be processed (a 16 pixels border is excluded)
260 VipsRect r_img = {border, border, ir->im->Xsize-border*2, ir->im->Ysize-border*2};
261 //std::cout<<"image: "<<ir->im->Xsize<<","<<ir->im->Ysize<<"+"<<0<<"+"<<0<<std::endl;
262 //std::cout<<"r_img: "<<r_img.width<<","<<r_img.height<<"+"<<r_img.left<<"+"<<r_img.top<<std::endl;
263 //VipsRect r_img = {0, 0, ir->im->Xsize, ir->im->Ysize};
264
265 // Output region aligned to Bayer pattern and with 16 pixels border excluded
266 VipsRect r_raw = {raw_left, raw_top, raw_right-raw_left+1, raw_bottom-raw_top+1};
267 if( (r_raw.width%2) ) r_raw.width += 1;
268 if( (r_raw.height%2) ) r_raw.height += 1;
269 //std::cout<<"r_raw(1): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
270 vips_rect_intersectrect (&r_raw, &r_img, &r_raw);
271 //std::cout<<"r_raw(2): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
272
273 #ifndef NDEBUG
274 std::cout<<"rcd_demosaic(): rawData.init( "<<ir->valid.width<<", "<<ir->valid.height<<", "
275 <<ir->valid.top<<", "<<ir->valid.left<<" )"<<std::endl;
276 #endif
277
278 // Initialization of pixel matrices
279 tile_top = ir->valid.top;
280 tile_left = ir->valid.left;
281 rawData.init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
282 for( y = 0; y < ir->valid.height; y++ ) {
283 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, ir->valid.left, y+ir->valid.top ) : NULL;
284 rawData.set_row( y+ir->valid.top, ptr );
285 }
286 red.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
287 green.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
288 blue.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
289
290 // Call to demosaicing method
291 rcd_demosaic_RT(0, 0, ir->im->Xsize, ir->im->Ysize,
292 ir->valid.left, ir->valid.top, ir->valid.width, ir->valid.height);
293
294 VipsRect r_out;
295 vips_rect_intersectrect (r, &r_img, &r_out);
296
297 int xx;
298 for( y = 0; y < r_out.height; y++ ) {
299 float* ptr = (float*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
300 for( x = 0, xx = 0; x < r_out.width; x++, xx+=3 ) {
301 #ifdef RT_EMU
302 /* RawTherapee emulation */
303 ptr[x*3] = CLAMP( red[y+r_out.top][x+r_out.left]/65535, 0, 95 );
304 ptr[x*3+1] = CLAMP( green[y+r_out.top][x+r_out.left]/65535, 0, 95 );
305 ptr[x*3+2] = CLAMP( blue[y+r_out.top][x+r_out.left]/65535, 0, 95 );
306 #else
307 ptr[xx] = CLAMP( red[y+r_out.top][x+r_out.left], 0, 1 );
308 ptr[xx+1] = CLAMP( green[y+r_out.top][x+r_out.left], 0, 1 );
309 ptr[xx+2] = CLAMP( blue[y+r_out.top][x+r_out.left], 0, 1 );
310 #endif
311 }
312 }
313 }
314
315
316
lmmse_demosaic(VipsRegion * ir,VipsRegion * oreg)317 void rtengine::RawImageSource::lmmse_demosaic(VipsRegion* ir, VipsRegion* oreg)
318 {
319 int x, y;
320 int padding = 10;
321
322 VipsRect *r = &oreg->valid;
323 int raw_left = (r->left/2)*2;
324 int raw_top = (r->top/2)*2;
325 int raw_right = r->left+r->width-1;
326 int raw_bottom = r->top+r->height-1;
327
328 // Make sure the border is entirely processed
329 //if( raw_left < border ) raw_left = 0;
330 //if( raw_top < border ) raw_top = 0;
331 //if( raw_right > (ir->im->Xsize-border-1) ) raw_right = ir->im->Xsize-1;
332 //if( raw_bottom > (ir->im->Ysize-border-1) ) raw_bottom = ir->im->Ysize-1;
333
334 // Portion of the image to be processed (a 10 pixels border is excluded)
335 VipsRect r_img = {padding, padding, ir->im->Xsize-padding*2, ir->im->Ysize-padding*2};
336 //std::cout<<"image: "<<ir->im->Xsize<<","<<ir->im->Ysize<<"+"<<0<<"+"<<0<<std::endl;
337 //std::cout<<"r_img: "<<r_img.width<<","<<r_img.height<<"+"<<r_img.left<<"+"<<r_img.top<<std::endl;
338 //VipsRect r_img = {0, 0, ir->im->Xsize, ir->im->Ysize};
339
340 // Output region aligned to Bayer pattern and with 16 pixels border excluded
341 VipsRect r_raw = {raw_left, raw_top, raw_right-raw_left+1, raw_bottom-raw_top+1};
342 if( (r_raw.width%2) ) r_raw.width += 1;
343 if( (r_raw.height%2) ) r_raw.height += 1;
344 //std::cout<<"r_raw(1): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
345 vips_rect_intersectrect (&r_raw, &r_img, &r_raw);
346 //std::cout<<"r_raw(2): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
347
348 #ifndef NDEBUG
349 std::cout<<"rawData.init( "<<ir->valid.width<<", "<<ir->valid.height<<", "
350 <<ir->valid.top<<", "<<ir->valid.left<<" )"<<std::endl;
351 #endif
352
353 // Initialization of pixel matrices
354 tile_top = ir->valid.top;
355 tile_left = ir->valid.left;
356 rawData.init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
357 for( y = 0; y < ir->valid.height; y++ ) {
358 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, ir->valid.left, y+ir->valid.top ) : NULL;
359 rawData.set_row( y+ir->valid.top, ptr );
360 }
361 red.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
362 green.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
363 blue.Init( r_raw.width, r_raw.height, r_raw.top, r_raw.left );
364
365 // Call to demosaicing method
366 lmmse_demosaic_RT(0, 0, ir->im->Xsize, ir->im->Ysize,
367 r_raw.left, r_raw.top, r_raw.width, r_raw.height, 0);
368
369 VipsRect r_out;
370 vips_rect_intersectrect (r, &r_img, &r_out);
371
372 int xx;
373 for( y = 0; y < r_out.height; y++ ) {
374 float* ptr = (float*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
375 for( x = 0, xx = 0; x < r_out.width; x++, xx+=3 ) {
376 #ifdef RT_EMU
377 /* RawTherapee emulation */
378 ptr[x*3] = CLAMP( red[y+r_out.top][x+r_out.left]/65535, 0, 95 );
379 ptr[x*3+1] = CLAMP( green[y+r_out.top][x+r_out.left]/65535, 0, 95 );
380 ptr[x*3+2] = CLAMP( blue[y+r_out.top][x+r_out.left]/65535, 0, 95 );
381 #else
382 ptr[xx] = CLAMP( red[y+r_out.top][x+r_out.left], 0, 1 );
383 ptr[xx+1] = CLAMP( green[y+r_out.top][x+r_out.left], 0, 1 );
384 ptr[xx+2] = CLAMP( blue[y+r_out.top][x+r_out.left], 0, 1 );
385 #endif
386 }
387 }
388 }
389
390
391
igv_demosaic(VipsRegion * ir,VipsRegion * oreg)392 void rtengine::RawImageSource::igv_demosaic(VipsRegion* ir, VipsRegion* oreg)
393 {
394 int x, y;
395
396 VipsRect *r = &oreg->valid;
397
398 // Portion of the image to be processed (a 16 pixels border is excluded)
399 VipsRect r_img = {7, 7, ir->im->Xsize-14, ir->im->Ysize-14};
400
401 // Initialization of pixel matrices
402 tile_top = ir->valid.top;
403 tile_left = ir->valid.left;
404 rawData.init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
405 for( y = 0; y < ir->valid.height; y++ ) {
406 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, ir->valid.left, y+ir->valid.top ) : NULL;
407 rawData.set_row( y+ir->valid.top, ptr );
408 }
409 red.Init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
410 green.Init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
411 blue.Init( ir->valid.width, ir->valid.height, ir->valid.top, ir->valid.left );
412
413 // Call to demosaicing method
414 igv_demosaic_RT(0, 0, ir->im->Xsize, ir->im->Ysize,
415 ir->valid.left, ir->valid.top, ir->valid.width, ir->valid.height);
416
417 VipsRect r_out;
418 vips_rect_intersectrect (r, &r_img, &r_out);
419
420 int xx;
421 for( y = 0; y < r_out.height; y++ ) {
422 float* ptr = (float*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
423 for( x = 0, xx = 0; x < r_out.width; x++, xx+=3 ) {
424 #ifdef RT_EMU
425 /* RawTherapee emulation */
426 ptr[x*3] = red[y+r_out.top][x+r_out.left]/65535;
427 ptr[x*3+1] = green[y+r_out.top][x+r_out.left]/65535;
428 ptr[x*3+2] = blue[y+r_out.top][x+r_out.left]/65535;
429 #else
430 ptr[xx] = CLAMP( red[y+r_out.top][x+r_out.left], 0, 1 );
431 ptr[xx+1] = CLAMP( green[y+r_out.top][x+r_out.left], 0, 1 );
432 ptr[xx+2] = CLAMP( blue[y+r_out.top][x+r_out.left], 0, 1 );
433 #endif
434 }
435 }
436 }
437
438
439
xtrans_demosaic(VipsRegion * ir,VipsRegion * oreg)440 void rtengine::RawImageSource::xtrans_demosaic(VipsRegion* ir, VipsRegion* oreg)
441 {
442 int x, y;
443 int border = 12;
444
445 VipsRect *r = &oreg->valid;
446 int raw_left = (r->left/2)*2;
447 int raw_top = (r->top/2)*2;
448 int raw_right = r->left+r->width-1;
449 int raw_bottom = r->top+r->height-1;
450
451 // Make sure the border is entirely processed
452 //if( raw_left < border ) raw_left = 0;
453 //if( raw_top < border ) raw_top = 0;
454 //if( raw_right > (ir->im->Xsize-border-1) ) raw_right = ir->im->Xsize-1;
455 //if( raw_bottom > (ir->im->Ysize-border-1) ) raw_bottom = ir->im->Ysize-1;
456
457 // Portion of the image to be processed (a 16 pixels border is excluded)
458 VipsRect r_img = {border, border, ir->im->Xsize-border*2, ir->im->Ysize-border*2};
459 //std::cout<<"image: "<<ir->im->Xsize<<","<<ir->im->Ysize<<"+"<<0<<"+"<<0<<std::endl;
460 //std::cout<<"r_img: "<<r_img.width<<","<<r_img.height<<"+"<<r_img.left<<"+"<<r_img.top<<std::endl;
461 //VipsRect r_img = {0, 0, ir->im->Xsize, ir->im->Ysize};
462
463 // Output region aligned to Bayer pattern and with 16 pixels border excluded
464 VipsRect r_raw = {raw_left, raw_top, raw_right-raw_left+1, raw_bottom-raw_top+1};
465 if( (r_raw.width%2) ) r_raw.width += 1;
466 if( (r_raw.height%2) ) r_raw.height += 1;
467 //std::cout<<"r_raw(1): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
468 vips_rect_intersectrect (&r_raw, &r_img, &r_raw);
469 //std::cout<<"r_raw(2): "<<r_raw.width<<","<<r_raw.height<<"+"<<r_raw.left<<"+"<<r_raw.top<<std::endl;
470
471 #ifndef NDEBUG
472 std::cout<<"X-trans demosaicing: rawData.init( "<<ir->valid.width<<", "<<ir->valid.height<<", "
473 <<ir->valid.top<<", "<<ir->valid.left<<" )"<<std::endl;
474 #endif
475
476 // Initialization of pixel matrices
477 tile_top = ir->valid.top;
478 tile_left = ir->valid.left;
479 rawData.init( ir->valid.width, ir->valid.height, 0, 0 /*ir->valid.top, ir->valid.left*/ );
480 rawDataBuf = (float**)malloc( ir->valid.height * sizeof(float*) );
481 float* tempBuf = (float*)malloc( ir->valid.width * ir->valid.height * sizeof(float) );
482 for( y = 0; y < ir->valid.height; y++ ) {
483 PF::raw_pixel_t* ptr = ir ? (PF::raw_pixel_t*)VIPS_REGION_ADDR( ir, ir->valid.left, y+ir->valid.top ) : NULL;
484 rawData.set_row( y/*+ir->valid.top*/, ptr );
485 }
486
487 float* bufptr = tempBuf;
488 for( y = 0; y < ir->valid.height; y++ ) {
489 rawDataBuf[y] = bufptr;
490 for( x = 0; x < ir->valid.width; x++ ) {
491 *bufptr = rawData[y][x]; bufptr++;
492 }
493 }
494
495 //red.Init( r_raw.width, r_raw.height, 8, 8 /*r_raw.top, r_raw.left*/ );
496 //green.Init( r_raw.width, r_raw.height, 8, 8 /*r_raw.top, r_raw.left*/ );
497 //blue.Init( r_raw.width, r_raw.height, 8, 8 /*r_raw.top, r_raw.left*/ );
498 red.Init( ir->valid.width, ir->valid.height, 0, 0 );
499 green.Init( ir->valid.width, ir->valid.height, 0, 0 );
500 blue.Init( ir->valid.width, ir->valid.height, 0, 0 );
501
502 // Call to demosaicing method
503 xtrans_demosaic_RT(ir->valid.left, ir->valid.top, ir->valid.width, ir->valid.height,
504 r_raw.left, r_raw.top, r_raw.width, r_raw.height);
505
506 free( rawDataBuf );
507 free( tempBuf );
508
509 VipsRect r_out;
510 vips_rect_intersectrect (r, &r_img, &r_out);
511 //std::cout<<"r_out: "<<r_out.width<<","<<r_out.height<<"+"<<r_out.left<<"+"<<r_out.top<<std::endl;
512
513 int xx;
514 for( y = 0; y < r_out.height; y++ ) {
515 float* ptr = (float*)VIPS_REGION_ADDR( oreg, r_out.left, y+r_out.top );
516 for( x = 0, xx = 0; x < r_out.width; x++, xx+=3 ) {
517 #ifdef RT_EMU
518 /* RawTherapee emulation */
519 ptr[x*3] = CLAMP( red[y+border][x+border]/65535, 0, 95 );
520 ptr[x*3+1] = CLAMP( green[y+border][x+border]/65535, 0, 95 );
521 ptr[x*3+2] = CLAMP( blue[y+border][x+border]/65535, 0, 95 );
522 #else
523 //ptr[xx] = CLAMP( red[y+r_out.top][x+r_out.left], 0, 1 );
524 //ptr[xx+1] = CLAMP( green[y+r_out.top][x+r_out.left], 0, 1 );
525 //ptr[xx+2] = CLAMP( blue[y+r_out.top][x+r_out.left], 0, 1 );
526 ptr[xx] = CLAMP( red[y+border][x+border], 0, 1 );
527 ptr[xx+1] = CLAMP( green[y+border][x+border], 0, 1 );
528 ptr[xx+2] = CLAMP( blue[y+border][x+border], 0, 1 );
529 #endif
530 }
531 }
532 }
533
534
535
536