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 #ifndef FAST_DEMOSAIC_H
31 #define FAST_DEMOSAIC_H
32 
33 #include <string>
34 
35 //#include <libraw/libraw.h>
36 
37 #include "../base/operation.hh"
38 #include "../base/rawmatrix.hh"
39 
40 
41 // bit representations of flags
42 #define PF_LUT_CLIP_BELOW 1
43 #define PF_LUT_CLIP_ABOVE 2
44 
45 #define PF_LUTf PF::LUT<float>
46 #define PF_LUTi PF::LUT<int>
47 #define PF_LUTu PF::LUT<unsigned int>
48 #define PF_LUTd PF::LUT<double>
49 
50 #include <cstring>
51 
52 namespace PF
53 {
54 
55 template<typename T>
56 class LUT {
57 private:
58   // list of variables ordered to improve cache speed
59   unsigned int maxs;
60   T * data;
61   unsigned int clip, size, owner;
62 public:
LUT(int s,int flags=0xfffffff)63   LUT(int s, int flags = 0xfffffff) {
64     clip = flags;
65     data = new T[s];
66     owner = 1;
67     size = s;
68     maxs=size-2;
69   }
operator ()(int s,int flags=0xfffffff)70   void operator ()(int s, int flags = 0xfffffff) {
71     if (owner&&data)
72       delete[] data;
73     clip = flags;
74     data = new T[s];
75     owner = 1;
76     size = s;
77     maxs=size-2;
78   }
79 
LUT(int s,T * source,int flags=0xfffffff)80   LUT(int s, T * source, int flags = 0xfffffff) {
81     clip = flags;
82     data = new T[s];
83     owner = 1;
84     size = s;
85     maxs=size-2;
86     for (int i = 0; i < s; i++) {
87       data[i] = source[i];
88     }
89   }
90 
LUT(void)91   LUT(void) {
92     data = NULL;
93     reset();
94   }
95 
~LUT()96   ~LUT() {
97     if (owner)
98       delete[] data;
99   }
100 
setClip(int flags)101   void setClip(int flags) {
102     clip = flags;
103   }
104 
operator =(const LUT<T> & rhs)105   LUT<T> & operator=(const LUT<T> &rhs) {
106     if (this != &rhs) {
107       if (rhs.size>this->size)
108       {
109         delete [] this->data;
110         this->data=NULL;
111       }
112       if (this->data==NULL) this->data=new T[rhs.size];
113       this->clip=rhs.clip;
114       this->owner=1;
115       memcpy(this->data,rhs.data,rhs.size*sizeof(T));
116       this->size=rhs.size;
117       this->maxs=this->size-2;
118     }
119 
120     return *this;
121   }
122   // use with integer indices
operator [](int index) const123   T& operator[](int index) const {
124     if (((unsigned int)index)<size) return data[index];
125     else
126     {
127       if (index < 0)
128         return data[0];
129       else
130         return data[size - 1];
131     }
132 
133   }
134   // use with float indices
operator [](float index) const135   T operator[](float index) const {
136     int idx = (int)index;  // don't use floor! The difference in negative space is no problems here
137     if (((unsigned int)idx) > maxs) {
138       if (idx<0)
139       {
140         if (clip & PF_LUT_CLIP_BELOW)
141           return data[0];
142         idx=0;
143       }
144       else
145       {
146         if (clip & PF_LUT_CLIP_ABOVE)
147           return data[size - 1];
148         idx =maxs;
149       }
150     }
151     float diff = index - (float) idx;
152     T p1 = data[idx];
153     T p2 = data[idx + 1]-p1;
154     return (p1 + p2*diff);
155   }
156 
157 
operator bool(void) const158   operator bool (void) const
159         {
160     return size>0;
161         }
162 
clear(void)163   void clear(void) {
164     memset(data, 0, size * sizeof(T));
165   }
166 
reset(void)167   void reset(void) {
168     delete[] data;
169     data = NULL;
170     owner = 1;
171     size = 0;
172     maxs=0;
173   }
174 };
175 
176 
177 static const int MAXVAL = 0xffff;
178 static const float MAXVALF = float(MAXVAL);  // float version of MAXVAL
179 static const double MAXVALD = double(MAXVAL); // double version of MAXVAL
180 
181 template <typename _Tp>
SQR(_Tp x)182 inline const _Tp SQR (_Tp x) {
183   //		return std::pow(x,2); Slower than:
184   return (x*x);
185 }
186 
187 template<typename _Tp>
min(const _Tp & a,const _Tp & b)188 inline const _Tp& min(const _Tp& a, const _Tp& b) {
189   return std::min(a,b);
190 }
191 
192 template<typename _Tp>
max(const _Tp & a,const _Tp & b)193 inline const _Tp& max(const _Tp& a, const _Tp& b) {
194   return std::max(a,b);
195 }
196 
197 
198 template<typename _Tp>
LIM(const _Tp & a,const _Tp & b,const _Tp & c)199 inline const _Tp LIM(const _Tp& a, const _Tp& b, const _Tp& c) {
200   return std::max(b,std::min(a,c));
201 }
202 
203 template<typename _Tp>
LIM01(const _Tp & a)204 inline const _Tp LIM01(const _Tp& a) {
205   return std::max(_Tp(1),std::min(a,_Tp(0)));
206 }
207 
208 template<typename _Tp>
ULIM(const _Tp & a,const _Tp & b,const _Tp & c)209 inline const _Tp ULIM(const _Tp& a, const _Tp& b, const _Tp& c) {
210   return ((b < c) ? LIM(a,b,c) : LIM(a,c,b));
211 }
212 
213 template<typename _Tp>
CLIP(const _Tp & a)214 inline const _Tp CLIP(const _Tp& a) {
215   return LIM(a, static_cast<_Tp>(0), static_cast<_Tp>(MAXVAL));
216 }
217 
218 
219 template<typename _Tp>
min(const _Tp & a,const _Tp & b,const _Tp & c)220 inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c) {
221   return std::min(c,std::min(a,b));
222 }
223 
224 template<typename _Tp>
max(const _Tp & a,const _Tp & b,const _Tp & c)225 inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c) {
226   return std::max(c,std::max(a,b));
227 }
228 
229 template<typename _Tp>
min(const _Tp & a,const _Tp & b,const _Tp & c,const _Tp & d)230 inline const _Tp& min(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) {
231   return std::min(d,std::min(c,std::min(a,b)));
232 }
233 
234 template<typename _Tp>
max(const _Tp & a,const _Tp & b,const _Tp & c,const _Tp & d)235 inline const _Tp& max(const _Tp& a, const _Tp& b, const _Tp& c, const _Tp& d) {
236   return std::max(d,std::max(c,std::max(a,b)));
237 }
238 
239 
240 
241 
242 class FastDemosaicPar: public OpParBase
243 {
244   PF_LUTf invGrad;
245 
246 public:
247   FastDemosaicPar();
has_intensity()248   bool has_intensity() { return false; }
has_opacity()249   bool has_opacity() { return false; }
needs_input()250   bool needs_input() { return true; }
251 
get_inv_grad()252   PF_LUTf& get_inv_grad() { return invGrad; }
253 
set_image_hints(VipsImage * img)254   void set_image_hints( VipsImage* img )
255   {
256     if( !img ) return;
257     OpParBase::set_image_hints( img );
258     rgb_image( get_xsize(), get_ysize() );
259     set_demand_hint( VIPS_DEMAND_STYLE_FATSTRIP );
260   }
261 
262   /* Function to derive the output area from the input area
263    */
transform(const VipsRect * rin,VipsRect * rout,int)264    virtual void transform(const VipsRect* rin, VipsRect* rout, int /*id*/)
265    {
266      rout->left = rin->left+5;
267      rout->top = rin->top+5;
268      rout->width = rin->width-10;
269      rout->height = rin->height-10;
270    }
271 
272    /* Function to derive the area to be read from input images,
273        based on the requested output area
274     */
transform_inv(const VipsRect * rout,VipsRect * rin,int)275    virtual void transform_inv(const VipsRect* rout, VipsRect* rin, int /*id*/)
276    {
277      rin->left = rout->left-5;
278      rin->top = rout->top-5;
279      rin->width = rout->width+10;
280      rin->height = rout->height+10;
281    }
282 
283 
284 
285    VipsImage* build(std::vector<VipsImage*>& in, int first,
286        VipsImage* imap, VipsImage* omap,
287        unsigned int& level);
288 };
289 
290 
291 
292 void fast_demosaic(VipsRegion** ir, int n, int in_first,
293     VipsRegion* imap, VipsRegion* omap,
294     VipsRegion* oreg, FastDemosaicPar* par);
295 
296 
297 template < OP_TEMPLATE_DEF >
298 class FastDemosaicProc
299 {
300 public:
render(VipsRegion ** in,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * out,FastDemosaicPar * par)301   void render(VipsRegion** in, int n, int in_first,
302       VipsRegion* imap, VipsRegion* omap,
303       VipsRegion* out, FastDemosaicPar* par)
304   {
305     //fast_demosaic( in, n, in_first,
306     //	     imap, omap, out, par );
307   }
308 };
309 
310 
311 template < OP_TEMPLATE_DEF_TYPE_SPEC >
312 class FastDemosaicProc< OP_TEMPLATE_IMP_TYPE_SPEC(float) >
313 {
314 public:
render(VipsRegion ** in,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * out,FastDemosaicPar * par)315   void render(VipsRegion** in, int n, int in_first,
316       VipsRegion* imap, VipsRegion* omap,
317       VipsRegion* out, FastDemosaicPar* par)
318   {
319     fast_demosaic( in, n, in_first,
320         imap, omap, out, par );
321   }
322 };
323 
324 
325 ProcessorBase* new_fast_demosaic();
326 }
327 
328 
329 #endif
330