-// Based on Exponential blur, Jani Huhtanen, 2006
-
-#define APREC 16
-#define ZPREC 7
-
-static void blurCols( byte *dst, int w, int h, int stride, int alpha )
-{
- int y;
- for( y = 0 ; y < h ; y++ )
- {
- int x, z = 0;
- for( x = 1 ; x < w ; x++ )
- {
- z += ( alpha * ( ( (int)( dst[x] ) << ZPREC ) - z ) ) >> APREC;
- dst[x] = (byte)( z >> ZPREC );
- }
- for( x = w-2 ; x >= 0 ; x-- )
- {
- z += ( alpha * ( ( (int)( dst[x] ) << ZPREC ) - z ) ) >> APREC;
- dst[x] = (byte)( z >> ZPREC );
- }
- dst += stride;
- }
-}
-
-static void blurRows( byte *dst, int w, int h, int stride, int alpha )
-{
- int x;
- for( x = 0 ; x < w ; x++ )
- {
- int y, z = 0;
- for( y = stride ; y < h*stride ; y += stride )
- {
- z += ( alpha * ( ( (int)( dst[y] ) << ZPREC ) - z ) ) >> APREC;
- dst[y] = (byte)( z >> ZPREC );
- }
- for( y = (h-2)*stride ; y >= 0 ; y -= stride )
- {
- z += ( alpha * ( ( (int)( dst[y] ) << ZPREC ) - z ) ) >> APREC;
- dst[y] = (byte)( z >> ZPREC );
- }
- dst++;
- }
-}
-
-static void blur( byte *dst, int width, int height, int stride, int radius )
-{
- if( radius >= 1 )
- {
- int boxcount = 2;
- // Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity)
- float radiusrange = (float)radius * ( 1.0f / sqrtf( 3 ) );
- uint32 alpha = (uint32)roundf( ( 1 << APREC ) * ( 1.0f - expf( -2.3f / ( radiusrange + 1.0f ) ) ) );
- for( ; boxcount ; boxcount-- )
- {
- blurRows( dst, width, height, stride, alpha );
- blurCols( dst, width, height, stride, alpha );
- }
- }
-}
-
-#undef APREC
-#undef ZPREC
-
-
-#define APREC 12
-#define ZPREC 7
-#define SPREC (31-(APREC+ZPREC+8))
-
-static void blurCols32( int *dst, int w, int h, int stride, int alpha )
-{
- int y;
- for( y = 0 ; y < h ; y++ )
- {
- int x, z = 0;
- for( x = 1 ; x < w ; x++ )
- {
- z += ( alpha * ( dst[x] - z ) ) >> APREC;
- dst[x] = z;
- }
- for( x = w - 2 ; x >= 0 ; x-- )
- {
- z += ( alpha * ( dst[x] - z ) ) >> APREC;
- dst[x] = z;
- }
- dst += stride;
- }
-}
-
-static void blurRows32( int *dst, int w, int h, int stride, int alpha )
-{
- int x;
- for( x = 0 ; x < w ; x++ )
- {
- int y, z = 0;
- for( y = 1 * stride ; y < h * stride ; y += stride )
- {
- z += ( alpha * ( dst[y] - z ) ) >> APREC;
- dst[y] = z;
- }
- for( y = ( h - 2 ) * stride ; y >= 0 ; y -= stride )
- {
- z += ( alpha * ( dst[y] - z ) ) >> APREC;
- dst[y] = z;
- }
- dst++;
- }
-}
-
-static void blurScale( byte *dst, int width, int height, int stride, int radius, int scale )
-{
- if( radius >= 1 )
- {
- int x, y, boxcount;
- float radiusrange;
- int alpha;
- int *buffer, *bufferrow;
- byte *dstrow;
-
- if( scale > ( 1 << SPREC ) )
- scale = 1 << SPREC;
-
- buffer = new int[ width * height ];
- for( y = 0 ; y < height ; y++ )
- {
- dstrow = &dst[y*stride];
- bufferrow = &buffer[y*width];
- for( x = 0 ; x < width ; x++ )
- bufferrow[x] = ( (int)dstrow[x] << ZPREC ) * scale;
- }
-
- boxcount = 3;
-
- /* Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity) */
- radiusrange = (float)radius * 0.3f;
- alpha = (uint32)roundf( ( 1 << APREC ) * ( 1.0f - expf( -2.3f / ( radiusrange + 1.0f ) ) ) );
- for( ; boxcount ; boxcount-- )
- {
- blurRows32( buffer, width, height, width, alpha );
- blurCols32( buffer, width, height, width, alpha );
- }
-
- for( y = 0 ; y < height ; y++ )
- {
- dstrow = &dst[y*stride];
- bufferrow = &buffer[y*width];
- for( x = 0 ; x < width ; x++ )
- dstrow[x] = (byte)Min(255, bufferrow[x] >> ZPREC);
- }
- delete buffer;
- }
-}
-
-#undef APREC
-#undef ZPREC
-#undef SPREC
-
-
-////
-