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