Edit comment text.
[synfig.git] / ETL / trunk / ETL / _boxblur.h
1 /*! ========================================================================
2 ** Extended Template Library
3 ** Box 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_BOXBLUR_H
28 #define __ETL_BOXBLUR_H
29
30 /* === H E A D E R S ======================================================= */
31
32 /* === M A C R O S ========================================================= */
33
34 /* === T Y P E D E F S ===================================================== */
35
36 /* === C L A S S E S & S T R U C T S ======================================= */
37
38 _ETL_BEGIN_NAMESPACE
39
40 template<typename T1,typename T2> void
41 hbox_blur(T1 pen,int w, int h, int length, T2 outpen)
42 {
43         int x,y;
44         typename T1::iterator_x iter, end;
45
46         length=std::min(w,length);
47         const float divisor(1.0f/(length*2+1));
48
49         for(y=0;y<h;y++,pen.inc_y(),outpen.inc_y())
50         {
51                 iter=pen.x();
52                 end=pen.end_x();
53
54                 typename T1::accumulator_type tot(*iter*(length+1));
55
56                 for (x=0;x<length && iter!=end;x++,++iter) tot+=*iter;
57                 iter=pen.x();
58
59                 for (x=0;x<w && iter!=end;x++,++iter,outpen.inc_x())
60                 {
61                         tot -= (x>length) ? iter[-length-1] : *pen.x();
62                         tot += ((x+length)<w) ? iter[length] : end[-1];
63
64                         outpen.put_value(tot*divisor);
65                 }
66                 outpen.dec_x(x);
67         }
68 }
69
70 #if 1
71 template<typename T1,typename T2> void
72 vbox_blur(T1 pen,const int w, const int h, int length, T2 outpen)
73 {
74         int x,y;
75         typename T1::iterator_y iter, end;
76
77         length=std::min(h,length);
78         const float divisor(1.0f/(length*2+1));
79
80         for(x=0;x<w;x++,pen.inc_x(),outpen.inc_x())
81         {
82                 iter=pen.y();
83                 end=pen.end_y();
84
85                 typename T1::accumulator_type tot(*iter*(length+1));
86
87                 for (y=0;y<length && iter!=end;y++,++iter) tot+=*iter;
88                 iter=pen.y();
89
90                 for (y=0;y<h && iter!=end;y++,++iter,outpen.inc_y())
91                 {
92                         tot -= (y>length) ? iter[-length-1] : *pen.y();
93                         tot += ((y+length)<h) ? iter[length] : end[-1];
94
95                         outpen.put_value(tot*divisor);
96                 }
97                 outpen.dec_y(y);
98         }
99 }
100
101 #else
102
103 template<typename T1,typename T2> void
104 vbox_blur(T1 pen,int w, int h, int length,T2 outpen)
105 {
106         int x,y;
107         typename T1::iterator_y iter, end, biter,eiter;
108
109         //print out the info I need to figure out if this is somehow a buffer overrun...
110         /*char *beginptr=0,*endptr=0;
111         {
112                 T1 ypen = pen;
113                 T1 endpen = pen;
114                 endpen.move(w,h);
115                 ypen.inc_y();
116
117                 T2      open = outpen,
118                         oepen = outpen;
119                 oepen.move(w,h);
120                 printf("V Blur (%d,%d,s-%d) in(%p,%p,st %d) out(%p,%p)\n",
121                                 w,h,length,(char*)pen.x(),(char*)endpen.x(),(char*)ypen.x()-(char*)pen.x(),
122                                 (char*)open.x(),(char*)oepen.x());
123         }*/
124         length=min(h-1,length);
125
126         const float divisor(1.0f/(length*2+1));
127         //const int div = (length*2+1);
128
129         //since the filter range is 2*length+1 we need h-1
130         for(x=0;x<w;x++,pen.inc_x(),outpen.inc_x())
131         {
132                 iter=pen.y();
133                 end=pen.end_y();
134
135                 const typename T1::value_type bval = *iter;
136                 const typename T1::value_type eval = end[-1];
137
138                 typename T1::accumulator_type tot(bval*(length+1));
139                 //beginptr = (char*)&*iter; endptr = (char*)&*end;
140
141                 //printf("\nx line %d (%p,%p)\n",x,beginptr,endptr);
142
143                 //printf("Init %.3f - ",tot);
144                 for (y=0;y<length && iter!=end;y++)
145                 {
146                         tot+=iter[y];
147                         //printf("(%d,%p,+%.3f->%.3f),",y,&iter[y],iter[y],tot);
148                 }
149                 iter=pen.y();
150
151                 //printf(" tot=%.3f\n",tot);
152
153                 biter = iter+(-length-1); //get the first one...
154                 eiter = iter+length;
155
156                 //y will always be > length
157                 //T2 open = outpen;
158                 for (y=0;y<h && iter!=end;y++,++iter,++biter,++eiter,outpen.inc_y())
159                 {
160                         //printf("y line %d - (%f) ",y,tot);
161
162                         if (y>length)
163                         {
164                                 typename T1::value_type &v = *biter;
165                                 /*if( (char*)&v < beginptr ||
166                                         (char*)&v >= endptr)
167                                         printf("crap! %d (%p off %p)\n",y,(char*)&v,(char*)&*iter);*/
168                                 tot -= v;
169                                 //printf("[%.3f,",v);
170                         }
171                         else
172                         {
173                                 tot -= bval;
174                                 //printf("[%.3f,",bval);
175                         }
176
177                         if (y+length<h)
178                         {
179                                 typename T1::value_type &v = *eiter;
180                                 /*if( (char*)&v < beginptr ||
181                                         (char*)&v >= endptr)
182                                         printf("crap! %d (%p off %p)\n",y,(char*)&v,(char*)&*iter);*/
183                                 tot += v;
184                                 //printf("%.3f]",v);
185                         }
186                         else
187                         {
188                                 tot += eval;
189                                 //printf("%.3f]",eval);
190                         }
191
192                         //test handled in the previous case...
193                         //tot -= (y>length) ? *biter : bval;
194                         //tot += (y+length<h) ? *eiter : eval;
195
196                         //printf(" - %.3f\n",tot);
197                         outpen.put_value(tot*divisor);
198                 }
199                 outpen.dec_y(y);
200         }
201 }
202 #endif
203
204 template<typename T1,typename T2> void
205 box_blur(T1 pen,int w, int h, int blur_w, int blur_h, T2 outpen)
206         { hbox_blur(pen,w,h,blur_w,outpen); vbox_blur(pen,w,h,blur_h,outpen); }
207
208 template<typename T1,typename T2> void
209 box_blur(T1 pen,int w, int h, int size, T2 outpen)
210         { hbox_blur(pen,w,h,size,outpen); vbox_blur(pen,w,h,size,outpen); }
211
212 template<typename T1,typename T2> void
213 hbox_blur(T1 begin,T1 end, int len,T2 outpen)
214 {
215         typename T1::difference_type size(end-begin);
216         hbox_blur(begin,size.x,size.y,len,outpen);
217 }
218
219 template<typename T1,typename T2> void
220 vbox_blur(T1 begin,T1 end, int len,T2 outpen)
221 {
222         typename T1::difference_type size(end-begin);
223         vbox_blur(begin,size.x,size.y,len,outpen);
224 }
225
226 template<typename T1,typename T2> void
227 box_blur(T1 begin,T1 end, int blur_w, int blur_h,T2 outpen)
228 {
229         typename T1::difference_type size(end-begin);
230         hbox_blur(begin,size.x,size.y,blur_w,outpen); vbox_blur(begin,size.x,size.y,blur_h,outpen);
231 }
232
233 template<typename T1,typename T2> void
234 box_blur(T1 begin,T1 end, int blursize,T2 outpen)
235 {
236         typename T1::difference_type size(end-begin);
237         hbox_blur(begin,size.x,size.y,blursize,outpen); vbox_blur(begin,size.x,size.y,blursize,outpen);
238 }
239
240 _ETL_END_NAMESPACE
241
242 /* === E X T E R N S ======================================================= */
243
244 /* === E N D =============================================================== */
245
246 #endif