Edit comment text.
[synfig.git] / ETL / trunk / ETL / _gaussian.h
1 /*! ========================================================================
2 ** Extended Template Library
3 ** Gaussian Blur Template Implementation
4 ** $Id$
5 **
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
7 **
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
12 **
13 ** This package 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 GNU
16 ** General Public License for more details.
17 **
18 ** === N O T E S ===========================================================
19 **
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
22 **
23 ** ========================================================================= */
24
25 /* === S T A R T =========================================================== */
26
27 #ifndef __ETL_GAUSSIAN_H
28 #define __ETL_GAUSSIAN_H
29
30 /* === H E A D E R S ======================================================= */
31
32 #include <cstring>              // for memset()
33 #include <iterator>
34
35 /* === M A C R O S ========================================================= */
36
37 /* === T Y P E D E F S ===================================================== */
38
39 /* === C L A S S E S & S T R U C T S ======================================= */
40
41 _ETL_BEGIN_NAMESPACE
42
43 template<typename T> void
44 gaussian_blur_5x5_(T pen,int w, int h,
45 typename T::pointer SC0,
46 typename T::pointer SC1,
47 typename T::pointer SC2,
48 typename T::pointer SC3)
49 {
50         int x,y;
51         typename T::value_type Tmp1,Tmp2,SR0,SR1,SR2,SR3;
52
53         //typename T::iterator_x iter;
54
55         // Setup the row buffers
56         for(x=0;x<w;x++)SC0[x+2]=pen.x()[x]*24;
57         memset(SC1,0,(w+2)*sizeof(typename T::value_type));
58         memset(SC2,0,(w+2)*sizeof(typename T::value_type));
59         memset(SC3,0,(w+2)*sizeof(typename T::value_type));
60
61         for(y=0;y<h+2;y++,pen.inc_y())
62         {
63                 int yadj;
64                 if(y>=h)
65                         {yadj=(h-y)-1; SR0=pen.y()[yadj]*1.35;}
66                 else
67                         {yadj=0; SR0=pen.get_value()*1.35; }
68
69                 SR1=SR2=SR3=typename T::value_type();
70                 for(x=0;x<w+2;x++,pen.inc_x())
71                 {
72                         if(x>=w)
73                                 Tmp1=pen[yadj][(w-x)-1];
74                         else
75                                 Tmp1=*pen[yadj];
76
77                         Tmp2=SR0+Tmp1;
78                         SR0=Tmp1;
79                         Tmp1=SR1+Tmp2;
80                         SR1=Tmp2;
81                         Tmp2=SR2+Tmp1;
82                         SR2=Tmp1;
83                         Tmp1=SR3+Tmp2;
84                         SR3=Tmp2;
85
86                         // Column Machine
87                         Tmp2=SC0[x]+Tmp1;
88                         SC0[x]=Tmp1;
89                         Tmp1=SC1[x]+Tmp2;
90                         SC1[x]=Tmp2;
91                         Tmp2=SC2[x]+Tmp1;
92                         SC2[x]=Tmp1;
93                         if(y>1&&x>1)
94                                 pen[-2][-2]=(SC3[x]+Tmp2)/256;
95                         SC3[x]=Tmp2;
96                 }
97                 pen.dec_x(x);
98         }
99
100 }
101
102 template<typename T> void
103 gaussian_blur_5x5(T pen, int w, int h)
104 {
105         typename T::pointer SC0=new typename T::value_type[w+2];
106         typename T::pointer SC1=new typename T::value_type[w+2];
107         typename T::pointer SC2=new typename T::value_type[w+2];
108         typename T::pointer SC3=new typename T::value_type[w+2];
109
110         gaussian_blur_5x5_(pen,w,h,SC0,SC1,SC2,SC3);
111
112         delete [] SC0;
113         delete [] SC1;
114         delete [] SC2;
115         delete [] SC3;
116 }
117
118 template<typename T> void
119 gaussian_blur_5x5(T begin, T end)
120 {
121         typename T::difference_type size(end-begin);
122
123         typename T::pointer SC0=new typename T::value_type[size.x+2];
124         typename T::pointer SC1=new typename T::value_type[size.x+2];
125         typename T::pointer SC2=new typename T::value_type[size.x+2];
126         typename T::pointer SC3=new typename T::value_type[size.x+2];
127
128         gaussian_blur_5x5_(begin,size.x,size.y,SC0,SC1,SC2,SC3);
129
130         delete [] SC0;
131         delete [] SC1;
132         delete [] SC2;
133         delete [] SC3;
134 }
135
136 template<typename T> void
137 gaussian_blur_3x3(T pen,int w, int h)
138 {
139         int x,y;
140         typename T::value_type Tmp1,Tmp2,SR0,SR1;
141
142 //      typename T::iterator_x iter;
143
144         typename T::pointer SC0=new typename T::value_type[w+1];
145         typename T::pointer SC1=new typename T::value_type[w+1];
146
147         // Setup the row buffers
148         for(x=0;x<w;x++)SC0[x+1]=pen.x()[x]*4;
149         memset(SC1,0,(w+1)*sizeof(typename T::value_type));
150
151         for(y=0;y<h+1;y++,pen.inc_y())
152         {
153                 int yadj;
154                 if(y>=h)
155                         {yadj=-1; SR1=SR0=pen.y()[yadj];}
156                 else
157                         {yadj=0; SR1=SR0=pen.get_value(); }
158
159                 for(x=0;x<w+1;x++,pen.inc_x())
160                 {
161                         if(x>=w)
162                                 Tmp1=pen[yadj][(w-x)-2];
163                         else
164                                 Tmp1=*pen[yadj];
165
166                         Tmp2=SR0+Tmp1;
167                         SR0=Tmp1;
168                         Tmp1=SR1+Tmp2;
169                         SR1=Tmp2;
170
171                         Tmp2=SC0[x]+Tmp1;
172                         SC0[x]=Tmp1;
173                         if(y&&x)
174                                 pen[-1][-1]=(SC1[x]+Tmp2)/16;
175                         SC1[x]=Tmp2;
176                 }
177                 pen.dec_x(x);
178         }
179
180         delete [] SC0;
181         delete [] SC1;
182 }
183
184 //! 2D 3x3 pixel gaussian blur
185 template<typename _PEN> void
186 gaussian_blur_3x3(_PEN begin, _PEN end)
187 {
188         typename _PEN::difference_type size(end-begin);
189         gaussian_blur_3x3(begin,size.x,size.y);
190 }
191
192 //! 1D 3 pixel gaussian blur
193 template<typename I> void
194 gaussian_blur_3(I begin, I end, bool endpts = true)
195 {
196 //      typedef typename I _itertype;
197 //      int i;
198         typename std::iterator_traits<I>::value_type Tmp1,Tmp2,SR0,SR1;
199
200         SR0=SR1=*begin;
201         I iter,prev=begin;
202         for(iter=begin;iter!=end;prev=iter++)
203         {
204                 Tmp1=*iter;
205                 Tmp2=SR0+Tmp1;
206                 SR0=Tmp1;
207                 Tmp1=SR1+Tmp2;
208                 SR1=Tmp2;
209                 if(iter!=begin && ( endpts || (prev != begin) ))
210                         *prev=(Tmp1)/4;
211         }
212
213         if(endpts)
214         {
215                 Tmp1=*prev;
216                 Tmp2=SR0+Tmp1;
217                 SR0=Tmp1;
218                 Tmp1=SR1+Tmp2;
219                 SR1=Tmp2;
220                 *prev=(Tmp1)/4;
221         }
222 }
223
224 //! 2D 3x1 pixel gaussian blur
225 template<typename _PEN> void
226 gaussian_blur_3x1(_PEN begin, _PEN end)
227 {
228         typename _PEN::difference_type size=end-begin;
229         for(;size.y>0;size.y--, begin.inc_y())
230                 gaussian_blur_3(begin.x(),begin.x()+size.x);
231 }
232
233 //! 2D 1x3 pixel gaussian blur
234 template<typename _PEN> void
235 gaussian_blur_1x3(_PEN begin, _PEN end)
236 {
237         typename _PEN::difference_type size=end-begin;
238         for(;size.x>0;size.x--,begin.inc_x())
239                 gaussian_blur_3(begin.y(),begin.y()+size.y);
240 }
241
242 template<typename T> void
243 gaussian_blur(T pen, int w, int h, int blur_x, int blur_y)
244 {
245         typename T::pointer SC0=new typename T::value_type[w+2];
246         typename T::pointer SC1=new typename T::value_type[w+2];
247         typename T::pointer SC2=new typename T::value_type[w+2];
248         typename T::pointer SC3=new typename T::value_type[w+2];
249
250         blur_x--;
251         blur_y--;
252
253         while(blur_x&&blur_y)
254         {
255                 if(blur_x>=4 && blur_y>=4)
256                 {
257                         gaussian_blur_5x5_(pen,w,h,SC0,SC1,SC2,SC3);
258                         blur_x-=4,blur_y-=4;
259                 }
260                 else if(blur_x>=2 && blur_y>=2)
261                 {
262                         gaussian_blur_3x3(pen,w,h);
263                         blur_x-=2,blur_y-=2;
264                 }
265                 else
266                         blur_x--,blur_y--;
267         }
268         while(blur_x)
269         {
270                 if(blur_x>=2)
271                 {
272                         gaussian_blur_3x1(pen,T(pen).move(w,h));
273                         blur_x-=2;
274                 }
275                 else
276                         blur_x--;
277         }
278         while(blur_y)
279         {
280                 if(blur_y>=2)
281                 {
282                         gaussian_blur_1x3(pen,T(pen).move(w,h));
283                         blur_y-=2;
284                 }
285                 else
286                         blur_y--;
287         }
288
289         delete [] SC0;
290         delete [] SC1;
291         delete [] SC2;
292         delete [] SC3;
293 }
294
295 template<typename T> void
296 gaussian_blur(T begin, T end,int w, int h)
297 {
298         typename T::difference_type size(end-begin);
299         gaussian_blur(begin,size.x,size.y,w,h);
300 }
301
302 template<typename T> void
303 gaussian_blur(T begin, T end,int w)
304 {
305         typename T::difference_type size(end-begin);
306         gaussian_blur(begin,size.x,size.y,w,w);
307 }
308
309 _ETL_END_NAMESPACE
310
311 /* === E X T E R N S ======================================================= */
312
313 /* === E N D =============================================================== */
314
315 #endif