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 <stdlib.h>
31
32 #include "demosaic_common.hh"
33 #include "../base/processor.hh"
34 #include "../external/librtprocess/src/include/librtprocess.h"
35
36
37
init_CFA(int filters,unsigned cfa[2][2])38 void PF::init_CFA(int filters, unsigned cfa[2][2])
39 {
40 for(int row = 0; row < 2; row++) {
41 for(int col = 0; col < 2; col++) {
42 cfa[row][col] = (filters >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3);
43 }
44 }
45 }
46
47
48
PixelBuffer(float * buf,int w,int h,int rowstride,int roffs,int coffs)49 PF::PixelBuffer::PixelBuffer(float* buf, int w, int h, int rowstride, int roffs, int coffs)
50 {
51 width = w; height = h;
52 ptr = NULL; rows = NULL;
53 ptr = new float*[h];
54 rows = ptr - roffs;
55 for(int i = 0; i < height; i++) {
56 ptr[i] = buf - coffs;
57 buf += rowstride;
58 }
59 //std::cout<<"Initialized pixel matrix "<<width<<"x"<<height<<"+"<<coffs<<","<<roffs<<std::endl;
60 }
61
62
~PixelBuffer()63 PF::PixelBuffer::~PixelBuffer()
64 {
65 if(ptr) delete[] ptr;
66 }
67
68
DemosaicBasePar(int b,bool rgbout)69 PF::DemosaicBasePar::DemosaicBasePar(int b, bool rgbout):
70 OpParBase(), border(b), rgb_output(rgbout)
71 {
72 border2 = border*2;
73 set_demand_hint( VIPS_DEMAND_STYLE_SMALLTILE );
74 }
75
76
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)77 VipsImage* PF::DemosaicBasePar::build(std::vector<VipsImage*>& in, int first,
78 VipsImage* imap, VipsImage* omap,
79 unsigned int& level)
80 {
81 void *data;
82 size_t data_length;
83
84 if( in.size()<1 || in[0]==NULL ) return NULL;
85
86 size_t blobsz;
87 if( PF_VIPS_IMAGE_GET_BLOB( in[0], "raw_image_data", &image_data, &blobsz ) ) {
88 std::cout<<"DemosaicBasePar::build(): could not extract raw_image_data."<<std::endl;
89 return NULL;
90 }
91 if( blobsz != sizeof(dcraw_data_t) ) {
92 std::cout<<"DemosaicBasePar::build(): wrong raw_image_data size."<<std::endl;
93 return NULL;
94 }
95
96 #ifndef NDEBUG
97 std::cout<<"DemosaicBasePar::build(): filters="<<image_data->idata.filters<<std::endl;
98 #endif
99
100 VipsImage* input = in[0];
101 VipsImage* extended = input;
102
103 if( false && border > 0 ) {
104 //VipsImage **t = (VipsImage **)
105 // vips_object_local_array( VIPS_OBJECT( in[0] ), 12 );
106 VipsImage* t[12];
107
108 // TOP BAND
109 int i0 = 0;
110 // Extract an horizontal top band at (0,1) and with size (in[0]->Xsize,border)
111 if( vips_crop(input, &t[i0], 0, 1, input->Xsize, border, NULL) ) {
112 std::cout<<"DemosaicBasePar::build(): vip_crop(#1) failed"<<std::endl;
113 return NULL;
114 }
115 // Flip the band vertically
116 if( vips_flip(t[i0], &t[i0+1], VIPS_DIRECTION_VERTICAL, NULL) ) {
117 std::cout<<"DemosaicBasePar::build(): vip_flip(#1) failed"<<std::endl;
118 return NULL;
119 }
120 PF_UNREF( t[i0], "DemosaicBasePar::build(): t[i0] unref #1" );
121 // Put the vertical band above the original image
122 if( vips_join(t[i0+1], in[0], &t[i0+2], VIPS_DIRECTION_VERTICAL, NULL) ) {
123 std::cout<<"DemosaicBasePar::build(): vip_join(#1) failed"<<std::endl;
124 return NULL;
125 }
126 PF_UNREF( t[i0+1], "DemosaicBasePar::build(): t[i0+1] unref #1" );
127
128
129 // BOTTOM BAND
130 i0 += 3;
131 // Extract an horizontal bottom band at (0,in[0]->Ysize-border-2) and with size (in[0]->Xsize,border)
132 if( vips_crop(in[0], &t[i0], 0, in[0]->Ysize-border-1, in[0]->Xsize, border, NULL) ) {
133 std::cout<<"DemosaicBasePar::build(): vip_crop(#2) failed"<<std::endl;
134 return NULL;
135 }
136 // Flip the band vertically
137 if( vips_flip(t[i0], &t[i0+1], VIPS_DIRECTION_VERTICAL, NULL) ) {
138 std::cout<<"DemosaicBasePar::build(): vip_flip(#2) failed"<<std::endl;
139 return NULL;
140 }
141 PF_UNREF( t[i0], "DemosaicBasePar::build(): t[i0] unref #2" );
142 // Put the vertical band below the previously joined image
143 if( vips_join(t[i0-1], t[i0+1], &t[i0+2], VIPS_DIRECTION_VERTICAL, NULL) ) {
144 std::cout<<"DemosaicBasePar::build(): vip_join(#2) failed"<<std::endl;
145 return NULL;
146 }
147 PF_UNREF( t[i0-1], "DemosaicBasePar::build(): t[i0-1] unref #2" );
148 PF_UNREF( t[i0+1], "DemosaicBasePar::build(): t[i0+1] unref #2" );
149
150
151 // LEFT BAND
152 i0 += 3;
153 // Extract a vertical left band at (1,0) and with size (border,t[i0-1]->Ysize)
154 if( vips_crop(t[i0-1], &t[i0], 1, 0, border, t[i0-1]->Ysize, NULL) ) {
155 std::cout<<"DemosaicBasePar::build(): vip_crop(#3) failed"<<std::endl;
156 return NULL;
157 }
158 // Flip the band horizontally
159 if( vips_flip(t[i0], &t[i0+1], VIPS_DIRECTION_HORIZONTAL, NULL) ) {
160 std::cout<<"DemosaicBasePar::build(): vip_flip(#3) failed"<<std::endl;
161 return NULL;
162 }
163 PF_UNREF( t[i0], "DemosaicBasePar::build(): t[i0] unref #3" );
164 // Put the vertical band left of the previously joined image
165 if( vips_join(t[i0+1], t[i0-1], &t[i0+2], VIPS_DIRECTION_HORIZONTAL, NULL) ) {
166 std::cout<<"DemosaicBasePar::build(): vip_join(#3) failed"<<std::endl;
167 return NULL;
168 }
169 PF_UNREF( t[i0-1], "DemosaicBasePar::build(): t[i0-1] unref #3-2" );
170 PF_UNREF( t[i0+1], "DemosaicBasePar::build(): t[i0+1] unref #3" );
171
172
173 // RIGHT BAND
174 i0 += 3;
175 // Extract a vertical right band at (t[i0-1]->Xsize-2,0) and with size (border,t[i0-1]->Ysize)
176 if( vips_crop(t[i0-1], &t[i0], t[i0-1]->Xsize-border-1, 0, border, t[i0-1]->Ysize, NULL) ) {
177 std::cout<<"DemosaicBasePar::build(): vip_crop(#4) failed"<<std::endl;
178 return NULL;
179 }
180 // Flip the band horizontally
181 if( vips_flip(t[i0], &t[i0+1], VIPS_DIRECTION_HORIZONTAL, NULL) ) {
182 std::cout<<"DemosaicBasePar::build(): vip_flip(#4) failed"<<std::endl;
183 return NULL;
184 }
185 PF_UNREF( t[i0], "DemosaicBasePar::build(): t[i0] unref #4" );
186 // Put the vertical band right of the previously joined image
187 if( vips_join(t[i0-1], t[i0+1], &t[i0+2], VIPS_DIRECTION_HORIZONTAL, NULL) ) {
188 std::cout<<"DemosaicBasePar::build(): vip_join(#4) failed"<<std::endl;
189 return NULL;
190 }
191 PF_UNREF( t[i0-1], "DemosaicBasePar::build(): t[i0-1] unref #4-2" );
192 PF_UNREF( t[i0+1], "DemosaicBasePar::build(): t[i0+1] unref #4" );
193
194 // Copy to extended image
195 if( vips_copy(t[i0+2], &extended, NULL) ) {
196 std::cout<<"DemosaicBasePar::build(): vip_copy(#1) failed"<<std::endl;
197 return NULL;
198 }
199 PF_UNREF( t[i0+2], "DemosaicBasePar::build(): t[i0+2] after vips_copy()" );
200 } else {
201 PF_REF(extended,"DemosaicBasePar::build(): extended ref for border=0");
202 }
203 set_image_hints( extended );
204
205 std::vector<VipsImage*> in2; in2.push_back(extended);
206 VipsImage* img = OpParBase::build( in2, 0, NULL, NULL, level );
207 PF_UNREF( extended, "DemosaicBasePar::build(): extended unref" );
208 //std::cout<<"DemosaicBasePar::build(): RAW image = "<<extended<<std::endl;
209 //std::cout<<"DemosaicBasePar::build(): output image = "<<img<<std::endl;
210 if( !img ) return NULL;
211
212 VipsImage* cropped = img;
213 if( false && border > 0 ) {
214 int result;
215 result = vips_crop(img, &cropped, border, border, in[0]->Xsize, in[0]->Ysize, NULL);
216 PF_UNREF( img, "DemosaicBasePar::build(): img unref" )
217 if( result ) {
218 std::cout<<"DemosaicBasePar::build(): vip_crop() failed"<<std::endl;
219 return NULL;
220 }
221 }
222
223 VipsImage* out;
224 int bands = rgb_output ? 3 : 1;
225 VipsCoding coding = VIPS_CODING_NONE;
226 VipsInterpretation interpretation = rgb_output ? VIPS_INTERPRETATION_RGB : VIPS_INTERPRETATION_B_W;
227 VipsBandFormat format = VIPS_FORMAT_FLOAT;
228 vips_copy( cropped, &out,
229 "format", format,
230 "bands", bands,
231 "coding", coding,
232 "interpretation", interpretation,
233 NULL );
234 PF_UNREF( cropped, "DemosaicBasePar::build(): cropped unref" );
235
236
237 int tw = 160 - border2;
238 int th = tw;
239 int nt = (cropped->Xsize/tw + 1) * 3;
240 VipsAccess acc = VIPS_ACCESS_RANDOM;
241 int threaded = 1, persistent = 0;
242 VipsImage* cached;
243 if( vips_tilecache(out, &cached,
244 "tile_width", tw, "tile_height", th, "max_tiles", nt,
245 "access", acc, "threaded", threaded, "persistent", persistent, NULL) ) {
246 std::cout<<"DemosaicBasePar::build(): vips_tilecache() failed."<<std::endl;
247 return NULL;
248 }
249 PF_UNREF( out, "DemosaicBasePar::build(): out unref" );
250
251 return cached;
252 }
253