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