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
gaussian_blur_5x5_(T pen,int w,int h,typename T::accumulator_pointer SC0,typename T::accumulator_pointer SC1,typename T::accumulator_pointer SC2,typename T::accumulator_pointer SC3)44 gaussian_blur_5x5_(T pen,int w, int h,
45 typename T::accumulator_pointer SC0,
46 typename T::accumulator_pointer SC1,
47 typename T::accumulator_pointer SC2,
48 typename T::accumulator_pointer SC3)
49 {
50 	int x,y;
51 	typename T::accumulator_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]=(typename T::accumulator_type)(pen.x()[x])*24;
57 	memset((void *)SC1,0,(w+2)*sizeof(typename T::accumulator_type));
58 	memset((void *)SC2,0,(w+2)*sizeof(typename T::accumulator_type));
59 	memset((void *)SC3,0,(w+2)*sizeof(typename T::accumulator_type));
60 	/*memset(SC1,0,(w+2)*sizeof(typename T::accumulator_type));
61 	memset(SC2,0,(w+2)*sizeof(typename T::accumulator_type));
62 	memset(SC3,0,(w+2)*sizeof(typename T::accumulator_type));*/
63 
64 	for(y=0;y<h+2;y++,pen.inc_y())
65 	{
66 		int yadj;
67 		if(y>=h)
68 			{yadj=(h-y)-1; SR0=(typename T::accumulator_type)(pen.y()[yadj])*1.35;}
69 		else
70 			{yadj=0; SR0=(typename T::accumulator_type)(pen.get_value())*1.35; }
71 
72 		SR1=SR2=SR3=typename T::accumulator_type();
73 		for(x=0;x<w+2;x++,pen.inc_x())
74 		{
75 			if(x>=w)
76 				Tmp1=(typename T::accumulator_type)(pen[yadj][(w-x)-1]);
77 			else
78 				Tmp1=(typename T::accumulator_type)(*pen[yadj]);
79 
80 			Tmp2=SR0+Tmp1;
81 			SR0=Tmp1;
82 			Tmp1=SR1+Tmp2;
83 			SR1=Tmp2;
84 			Tmp2=SR2+Tmp1;
85 			SR2=Tmp1;
86 			Tmp1=SR3+Tmp2;
87 			SR3=Tmp2;
88 
89 			// Column Machine
90 			Tmp2=SC0[x]+Tmp1;
91 			SC0[x]=Tmp1;
92 			Tmp1=SC1[x]+Tmp2;
93 			SC1[x]=Tmp2;
94 			Tmp2=SC2[x]+Tmp1;
95 			SC2[x]=Tmp1;
96 			if(y>1&&x>1)
97 				pen[-2][-2]=(typename T::value_type)((SC3[x]+Tmp2)/256);
98 			SC3[x]=Tmp2;
99 		}
100 		pen.dec_x(x);
101 	}
102 
103 }
104 
105 template<typename T> void
gaussian_blur_5x5(T pen,int w,int h)106 gaussian_blur_5x5(T pen, int w, int h)
107 {
108 	typename T::accumulator_pointer SC0=new typename T::accumulator_type[w+2];
109 	typename T::accumulator_pointer SC1=new typename T::accumulator_type[w+2];
110 	typename T::accumulator_pointer SC2=new typename T::accumulator_type[w+2];
111 	typename T::accumulator_pointer SC3=new typename T::accumulator_type[w+2];
112 
113 	gaussian_blur_5x5_(pen,w,h,SC0,SC1,SC2,SC3);
114 
115 	delete [] SC0;
116 	delete [] SC1;
117 	delete [] SC2;
118 	delete [] SC3;
119 }
120 
121 template<typename T> void
gaussian_blur_5x5(T begin,T end)122 gaussian_blur_5x5(T begin, T end)
123 {
124 	typename T::difference_type size(end-begin);
125 
126 	typename T::accumulator_pointer SC0=new typename T::accumulator_type[size.x+2];
127 	typename T::accumulator_pointer SC1=new typename T::accumulator_type[size.x+2];
128 	typename T::accumulator_pointer SC2=new typename T::accumulator_type[size.x+2];
129 	typename T::accumulator_pointer SC3=new typename T::accumulator_type[size.x+2];
130 
131 	gaussian_blur_5x5_(begin,size.x,size.y,SC0,SC1,SC2,SC3);
132 
133 	delete [] SC0;
134 	delete [] SC1;
135 	delete [] SC2;
136 	delete [] SC3;
137 }
138 
139 template<typename T> void
gaussian_blur_3x3(T pen,int w,int h)140 gaussian_blur_3x3(T pen,int w, int h)
141 {
142 	int x,y;
143 	typename T::accumulator_type Tmp1,Tmp2,SR0,SR1;
144 
145 //	typename T::iterator_x iter;
146 
147 	typename T::accumulator_pointer SC0=new typename T::accumulator_type[w+1];
148 	typename T::accumulator_pointer SC1=new typename T::accumulator_type[w+1];
149 
150 	// Setup the row buffers
151 	for(x=0;x<w;x++)SC0[x+1]=(typename T::accumulator_type)(pen.x()[x])*4;
152 	memset((void *)SC1,0,(w+1)*sizeof(typename T::accumulator_type));
153 
154 	for(y=0;y<h+1;y++,pen.inc_y())
155 	{
156 		int yadj;
157 		if(y>=h)
158 			{yadj=-1; SR1=SR0=(typename T::accumulator_type)(pen.y()[yadj]);}
159 		else
160 			{yadj=0; SR1=SR0=(typename T::accumulator_type)(pen.get_value()); }
161 
162 		for(x=0;x<w+1;x++,pen.inc_x())
163 		{
164 			if(x>=w)
165 				Tmp1=(typename T::accumulator_type)(pen[yadj][(w-x)-2]);
166 			else
167 				Tmp1=(typename T::accumulator_type)(*pen[yadj]);
168 
169 			Tmp2=SR0+Tmp1;
170 			SR0=Tmp1;
171 			Tmp1=SR1+Tmp2;
172 			SR1=Tmp2;
173 
174 			Tmp2=SC0[x]+Tmp1;
175 			SC0[x]=Tmp1;
176 			if(y&&x)
177 				pen[-1][-1]=(typename T::value_type)((SC1[x]+Tmp2)/16);
178 			SC1[x]=Tmp2;
179 		}
180 		pen.dec_x(x);
181 	}
182 
183 	delete [] SC0;
184 	delete [] SC1;
185 }
186 
187 //! 2D 3x3 pixel gaussian blur
188 template<typename _PEN> void
gaussian_blur_3x3(_PEN begin,_PEN end)189 gaussian_blur_3x3(_PEN begin, _PEN end)
190 {
191 	typename _PEN::difference_type size(end-begin);
192 	gaussian_blur_3x3(begin,size.x,size.y);
193 }
194 
195 //! 1D 3 pixel gaussian blur
196 template<typename I> void
197 gaussian_blur_3(I begin, I end, bool endpts = true)
198 {
199 //	typedef typename I _itertype;
200 //	int i;
201 	typename std::iterator_traits<I>::value_type Tmp1,Tmp2,SR0,SR1;
202 
203 	SR0=SR1=*begin;
204 	I iter,prev=begin;
205 	for(iter=begin;iter!=end;prev=iter++)
206 	{
207 		Tmp1=*iter;
208 		Tmp2=SR0+Tmp1;
209 		SR0=Tmp1;
210 		Tmp1=SR1+Tmp2;
211 		SR1=Tmp2;
212 		if(iter!=begin && ( endpts || (prev != begin) ))
213 			*prev=(Tmp1)/4;
214 	}
215 
216 	if(endpts)
217 	{
218 		Tmp1=*prev;
219 		Tmp2=SR0+Tmp1;
220 		SR0=Tmp1;
221 		Tmp1=SR1+Tmp2;
222 		SR1=Tmp2;
223 		*prev=(Tmp1)/4;
224 	}
225 }
226 
227 //! 2D 3x1 pixel gaussian blur
228 template<typename _PEN> void
gaussian_blur_3x1(_PEN begin,_PEN end)229 gaussian_blur_3x1(_PEN begin, _PEN end)
230 {
231 	typename _PEN::difference_type size=end-begin;
232 	for(;size.y>0;size.y--, begin.inc_y())
233 		gaussian_blur_3(begin.x(),begin.x()+size.x);
234 }
235 
236 //! 2D 1x3 pixel gaussian blur
237 template<typename _PEN> void
gaussian_blur_1x3(_PEN begin,_PEN end)238 gaussian_blur_1x3(_PEN begin, _PEN end)
239 {
240 	typename _PEN::difference_type size=end-begin;
241 	for(;size.x>0;size.x--,begin.inc_x())
242 		gaussian_blur_3(begin.y(),begin.y()+size.y);
243 }
244 
245 template<typename T> void
gaussian_blur(T pen,int w,int h,int blur_x,int blur_y)246 gaussian_blur(T pen, int w, int h, int blur_x, int blur_y)
247 {
248 	typename T::accumulator_pointer SC0=new typename T::accumulator_type[w+2];
249 	typename T::accumulator_pointer SC1=new typename T::accumulator_type[w+2];
250 	typename T::accumulator_pointer SC2=new typename T::accumulator_type[w+2];
251 	typename T::accumulator_pointer SC3=new typename T::accumulator_type[w+2];
252 
253 	blur_x--;
254 	blur_y--;
255 
256 	while(blur_x&&blur_y)
257 	{
258 		if(blur_x>=4 && blur_y>=4)
259 		{
260 			gaussian_blur_5x5_(pen,w,h,SC0,SC1,SC2,SC3);
261 			blur_x-=4,blur_y-=4;
262 		}
263 		else if(blur_x>=2 && blur_y>=2)
264 		{
265 			gaussian_blur_3x3(pen,w,h);
266 			blur_x-=2,blur_y-=2;
267 		}
268 		else
269 			blur_x--,blur_y--;
270 	}
271 	while(blur_x)
272 	{
273 		if(blur_x>=2)
274 		{
275 			gaussian_blur_3x1(pen,T(pen).move(w,h));
276 			blur_x-=2;
277 		}
278 		else
279 			blur_x--;
280 	}
281 	while(blur_y)
282 	{
283 		if(blur_y>=2)
284 		{
285 			gaussian_blur_1x3(pen,T(pen).move(w,h));
286 			blur_y-=2;
287 		}
288 		else
289 			blur_y--;
290 	}
291 
292 	delete [] SC0;
293 	delete [] SC1;
294 	delete [] SC2;
295 	delete [] SC3;
296 }
297 
298 template<typename T> void
gaussian_blur(T begin,T end,int w,int h)299 gaussian_blur(T begin, T end,int w, int h)
300 {
301 	typename T::difference_type size(end-begin);
302 	gaussian_blur(begin,size.x,size.y,w,h);
303 }
304 
305 template<typename T> void
gaussian_blur(T begin,T end,int w)306 gaussian_blur(T begin, T end,int w)
307 {
308 	typename T::difference_type size(end-begin);
309 	gaussian_blur(begin,size.x,size.y,w,w);
310 }
311 
312 _ETL_END_NAMESPACE
313 
314 /* === E X T E R N S ======================================================= */
315 
316 /* === E N D =============================================================== */
317 
318 #endif
319