summaryrefslogtreecommitdiff
path: root/src/corelib/render/software/agg_blur.pas
diff options
context:
space:
mode:
authorGraeme Geldenhuys <graeme@mastermaths.co.za>2012-03-09 12:37:16 +0200
committerGraeme Geldenhuys <graeme@mastermaths.co.za>2012-03-09 12:37:16 +0200
commit5fdae25f717a7f0b55d2b1849b4812a06597c59e (patch)
treeb41d481cbc36a8139625c330f8a7e5c3df92f47c /src/corelib/render/software/agg_blur.pas
parentf8597f3dc0e65fc6ac2f1cf1666ed94fc7f0baba (diff)
downloadfpGUI-5fdae25f717a7f0b55d2b1849b4812a06597c59e.tar.xz
aggpas: fixes EOL style and file permissions.
Diffstat (limited to 'src/corelib/render/software/agg_blur.pas')
-rw-r--r--src/corelib/render/software/agg_blur.pas3248
1 files changed, 1624 insertions, 1624 deletions
diff --git a/src/corelib/render/software/agg_blur.pas b/src/corelib/render/software/agg_blur.pas
index ec0da0df..5ddda2bc 100644
--- a/src/corelib/render/software/agg_blur.pas
+++ b/src/corelib/render/software/agg_blur.pas
@@ -1,1624 +1,1624 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-//----------------------------------------------------------------------------
-//
-// The Stack Blur Algorithm was invented by Mario Klingemann,
-// mario@quasimondo.com and described here:
-// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
-// (search phrase "Stackblur: Fast But Goodlooking").
-// The major improvement is that there's no more division table
-// that was very expensive to create for large blur radii. Insted,
-// for 8-bit per channel and radius not exceeding 254 the division is
-// replaced by multiplication and shift.
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 11.10.2007-Milano: recursive_blur & finished OK
-// 10.10.2007-Milano: stack_blur
-// 09.10.2007-Milano: Unit port establishment
-//
-{ agg_blur.pas }
-unit
- agg_blur ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-{$Q- }
-{$R- }
-uses
- agg_basics ,
- agg_array ,
- agg_color ,
- agg_pixfmt ,
- agg_pixfmt_transposer ;
-
-{ GLOBAL VARIABLES & CONSTANTS }
-
-{ TYPES DEFINITION }
-type
- stack_blur = object
- private
- m_buf ,
- m_stack : pod_vector;
-
- public
- constructor Construct;
- destructor Destruct;
-
- procedure blur_x(img : pixel_formats_ptr; radius : unsigned );
- procedure blur_y(img : pixel_formats_ptr; radius : unsigned );
-
- procedure blur(img : pixel_formats_ptr; radius : unsigned );
-
- end;
-
- recursive_blur = object
- private
- m_sum1 ,
- m_sum2 ,
- m_buf : pod_vector;
-
- public
- constructor Construct;
- destructor Destruct;
-
- procedure blur_x(img : pixel_formats_ptr; radius : double );
- procedure blur_y(img : pixel_formats_ptr; radius : double );
-
- procedure blur(img : pixel_formats_ptr; radius : double );
-
- end;
-
-{ GLOBAL PROCEDURES }
- procedure stack_blur_gray8 (img : pixel_formats_ptr; rx ,ry : unsigned );
- procedure stack_blur_rgb24 (img : pixel_formats_ptr; rx ,ry : unsigned );
- procedure stack_blur_rgba32(img : pixel_formats_ptr; rx ,ry : unsigned );
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-const
- g_stack_blur8_mul : array[0..254 ] of int16u = (
- 512 ,512 ,456 ,512 ,328 ,456 ,335 ,512 ,405 ,328 ,271 ,456 ,388 ,335 ,292 ,512 ,
- 454 ,405 ,364 ,328 ,298 ,271 ,496 ,456 ,420 ,388 ,360 ,335 ,312 ,292 ,273 ,512 ,
- 482 ,454 ,428 ,405 ,383 ,364 ,345 ,328 ,312 ,298 ,284 ,271 ,259 ,496 ,475 ,456 ,
- 437 ,420 ,404 ,388 ,374 ,360 ,347 ,335 ,323 ,312 ,302 ,292 ,282 ,273 ,265 ,512 ,
- 497 ,482 ,468 ,454 ,441 ,428 ,417 ,405 ,394 ,383 ,373 ,364 ,354 ,345 ,337 ,328 ,
- 320 ,312 ,305 ,298 ,291 ,284 ,278 ,271 ,265 ,259 ,507 ,496 ,485 ,475 ,465 ,456 ,
- 446 ,437 ,428 ,420 ,412 ,404 ,396 ,388 ,381 ,374 ,367 ,360 ,354 ,347 ,341 ,335 ,
- 329 ,323 ,318 ,312 ,307 ,302 ,297 ,292 ,287 ,282 ,278 ,273 ,269 ,265 ,261 ,512 ,
- 505 ,497 ,489 ,482 ,475 ,468 ,461 ,454 ,447 ,441 ,435 ,428 ,422 ,417 ,411 ,405 ,
- 399 ,394 ,389 ,383 ,378 ,373 ,368 ,364 ,359 ,354 ,350 ,345 ,341 ,337 ,332 ,328 ,
- 324 ,320 ,316 ,312 ,309 ,305 ,301 ,298 ,294 ,291 ,287 ,284 ,281 ,278 ,274 ,271 ,
- 268 ,265 ,262 ,259 ,257 ,507 ,501 ,496 ,491 ,485 ,480 ,475 ,470 ,465 ,460 ,456 ,
- 451 ,446 ,442 ,437 ,433 ,428 ,424 ,420 ,416 ,412 ,408 ,404 ,400 ,396 ,392 ,388 ,
- 385 ,381 ,377 ,374 ,370 ,367 ,363 ,360 ,357 ,354 ,350 ,347 ,344 ,341 ,338 ,335 ,
- 332 ,329 ,326 ,323 ,320 ,318 ,315 ,312 ,310 ,307 ,304 ,302 ,299 ,297 ,294 ,292 ,
- 289 ,287 ,285 ,282 ,280 ,278 ,275 ,273 ,271 ,269 ,267 ,265 ,263 ,261 ,259 );
-
- g_stack_blur8_shr : array[0..254 ] of int8u = (
- 9 ,11 ,12 ,13 ,13 ,14 ,14 ,15 ,15 ,15 ,15 ,16 ,16 ,16 ,16 ,17 ,
- 17 ,17 ,17 ,17 ,17 ,17 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,19 ,
- 19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,20 ,20 ,20 ,
- 20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,21 ,
- 21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,
- 21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,22 ,22 ,22 ,22 ,22 ,22 ,
- 22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,
- 22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,23 ,
- 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
- 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
- 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
- 23 ,23 ,23 ,23 ,23 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
- 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
- 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
- 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
- 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 );
-
-type
- stack_calculator_ptr = ^stack_calculator;
- stack_calculator = object
- v ,
- r ,
- g ,
- b ,
- a : unsigned;
-
- procedure clear;
-
- procedure add (c : aggclr );
- procedure add_ (c : aggclr; k : unsigned );
- procedure add__(c : stack_calculator );
- procedure sub (c : aggclr );
- procedure sub_ (c : stack_calculator );
-
- procedure calc_pix (c : aggclr_ptr; div_ : unsigned );
- procedure calc_pix_(c : aggclr_ptr; mul_ ,shr_ : unsigned );
-
- end;
-
- gauss_calculator_ptr = ^gauss_calculator;
- gauss_calculator = object
- v ,
- r ,
- g ,
- b ,
- a : double;
-
- procedure from_pix(c : aggclr );
-
- procedure calc(
- b1 ,b2 ,b3 ,b4 : double;
- c1 ,c2 ,c3 ,c4 : gauss_calculator_ptr );
-
- procedure to_pix(c : aggclr_ptr );
-
- end;
-
-{ UNIT IMPLEMENTATION }
-{ CLEAR }
-procedure stack_calculator.clear;
-begin
- v:=0;
- r:=0;
- g:=0;
- b:=0;
- a:=0;
-
-end;
-
-{ ADD }
-procedure stack_calculator.add(c : aggclr );
-begin
- inc(v ,c.v );
- inc(r ,c.r );
- inc(g ,c.g );
- inc(b ,c.b );
- inc(a ,c.a );
-
-end;
-
-{ ADD__ }
-procedure stack_calculator.add__(c : stack_calculator );
-begin
- inc(v ,c.v );
- inc(r ,c.r );
- inc(g ,c.g );
- inc(b ,c.b );
- inc(a ,c.a );
-
-end;
-
-{ ADD_ }
-procedure stack_calculator.add_(c : aggclr; k : unsigned );
-begin
- inc(v ,c.v * k );
- inc(r ,c.r * k );
- inc(g ,c.g * k );
- inc(b ,c.b * k );
- inc(a ,c.a * k );
-
-end;
-
-{ SUB }
-procedure stack_calculator.sub(c : aggclr );
-begin
- dec(v ,c.v );
- dec(r ,c.r );
- dec(g ,c.g );
- dec(b ,c.b );
- dec(a ,c.a );
-
-end;
-
-{ SUB_ }
-procedure stack_calculator.sub_(c : stack_calculator );
-begin
- dec(v ,c.v );
- dec(r ,c.r );
- dec(g ,c.g );
- dec(b ,c.b );
- dec(a ,c.a );
-
-end;
-
-{ CALC_PIX }
-procedure stack_calculator.calc_pix(c : aggclr_ptr; div_ : unsigned );
-begin
- c.v:=int8u(v div div_ );
- c.r:=int8u(r div div_ );
- c.g:=int8u(g div div_ );
- c.b:=int8u(b div div_ );
- c.a:=int8u(a div div_ );
-
-end;
-
-{ CALC_PIX_ }
-procedure stack_calculator.calc_pix_(c : aggclr_ptr; mul_ ,shr_ : unsigned );
-begin
- c.v:=int8u((v * mul_ ) shr shr_ );
- c.r:=int8u((r * mul_ ) shr shr_ );
- c.g:=int8u((g * mul_ ) shr shr_ );
- c.b:=int8u((b * mul_ ) shr shr_ );
- c.a:=int8u((a * mul_ ) shr shr_ );
-
-end;
-
-{ FROM_PIX }
-procedure gauss_calculator.from_pix(c : aggclr );
-begin
- v:=c.v;
- r:=c.r;
- g:=c.g;
- b:=c.b;
- a:=c.a;
-
-end;
-
-{ CALC }
-procedure gauss_calculator.calc(
- b1 ,b2 ,b3 ,b4 : double;
- c1 ,c2 ,c3 ,c4 : gauss_calculator_ptr );
-begin
- v:=b1 * c1.v + b2 * c2.v + b3 * c3.v + b4 * c4.v;
- r:=b1 * c1.r + b2 * c2.r + b3 * c3.r + b4 * c4.r;
- g:=b1 * c1.g + b2 * c2.g + b3 * c3.g + b4 * c4.g;
- b:=b1 * c1.b + b2 * c2.b + b3 * c3.b + b4 * c4.b;
- a:=b1 * c1.a + b2 * c2.a + b3 * c3.a + b4 * c4.a;
-
-end;
-
-{ TO_PIX }
-procedure gauss_calculator.to_pix(c : aggclr_ptr );
-begin
- c.v:=int8u(uround(v ) );
- c.r:=int8u(uround(r ) );
- c.g:=int8u(uround(g ) );
- c.b:=int8u(uround(b ) );
- c.a:=int8u(uround(a ) );
-
-end;
-
-{ CONSTRUCT }
-constructor stack_blur.Construct;
-begin
- m_buf.Construct (sizeof(aggclr ) );
- m_stack.Construct(sizeof(aggclr ) );
-
-end;
-
-{ DESTRUCT }
-destructor stack_blur.Destruct;
-begin
- m_buf.Destruct;
- m_stack.Destruct;
-
-end;
-
-{ BLUR_X }
-procedure stack_blur.blur_x(img : pixel_formats_ptr; radius : unsigned );
-var
- x ,y ,xp ,i ,stack_ptr ,stack_start ,
-
- w ,h ,wm ,div_ ,div_sum ,mul_sum ,shr_sum ,max_val : unsigned;
-
- pix : aggclr;
-
- stack_pix ,_c : aggclr_ptr;
-
- sum ,sum_in ,sum_out : stack_calculator;
-
-begin
- if radius < 1 then
- exit;
-
- w :=img._width;
- h :=img._height;
- wm :=w - 1;
- div_:=radius * 2 + 1;
-
- div_sum:=(radius + 1 ) * (radius + 1 );
- mul_sum:=0;
- shr_sum:=0;
- max_val:=base_mask;
-
- if (max_val <= 255 ) and
- (radius < 255 ) then
- begin
- mul_sum:=g_stack_blur8_mul[radius ];
- shr_sum:=g_stack_blur8_shr[radius ];
-
- end;
-
- m_buf.allocate (w ,128 );
- m_stack.allocate(div_ ,32 );
-
- y:=0;
-
- while y < h do
- begin
- sum.clear;
- sum_in.clear;
- sum_out.clear;
-
- pix:=img.pixel(img ,0 ,y );
-
- i:=0;
-
- while i <= radius do
- begin
- move(pix ,m_stack.array_operator(i )^ ,sizeof(aggclr ) );
-
- sum.add_ (pix ,i + 1 );
- sum_out.add(pix );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= radius do
- begin
- if i > wm then
- pix:=img.pixel(img ,wm ,y )
- else
- pix:=img.pixel(img ,i ,y );
-
- move(pix ,m_stack.array_operator(i + radius )^ ,sizeof(aggclr ) );
-
- sum.add_ (pix ,radius + 1 - i );
- sum_in.add(pix );
-
- inc(i );
-
- end;
-
- stack_ptr:=radius;
-
- x:=0;
-
- while x < w do
- begin
- if mul_sum <> 0 then
- sum.calc_pix_(aggclr_ptr(m_buf.array_operator(x ) ) ,mul_sum ,shr_sum )
- else
- sum.calc_pix(aggclr_ptr(m_buf.array_operator(x ) ) ,div_sum );
-
- sum.sub_(sum_out );
-
- stack_start:=stack_ptr + div_ - radius;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- stack_pix:=m_stack.array_operator(stack_start );
-
- sum_out.sub(stack_pix^ );
-
- xp:=x + radius + 1;
-
- if xp > wm then
- xp:=wm;
-
- pix:=img.pixel(img ,xp ,y );
-
- stack_pix^:=pix;
-
- sum_in.add(pix );
- sum.add__ (sum_in );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix:=m_stack.array_operator(stack_ptr );
-
- sum_out.add(stack_pix^ );
- sum_in.sub (stack_pix^ );
-
- inc(x );
-
- end;
-
- _c:=m_buf.array_operator(0 );
-
- img.copy_color_hspan(img ,0 ,y ,w ,_c );
-
- inc(y );
-
- end;
-
-end;
-
-{ BLUR_Y }
-procedure stack_blur.blur_y(img : pixel_formats_ptr; radius : unsigned );
-var
- img2 : pixel_formats_transposer;
-
-begin
- pixfmt_transposer(img2 ,img );
- blur_x (@img2 ,radius );
-
-end;
-
-{ BLUR }
-procedure stack_blur.blur(img : pixel_formats_ptr; radius : unsigned );
-var
- img2 : pixel_formats_transposer;
-
-begin
- blur_x (img ,radius );
- pixfmt_transposer(img2 ,img );
- blur_x (@img2 ,radius );
-
-end;
-
-{ CONSTRUCT }
-constructor recursive_blur.Construct;
-begin
- m_sum1.Construct(sizeof(gauss_calculator ) );
- m_sum2.Construct(sizeof(gauss_calculator ) );
- m_buf.Construct (sizeof(aggclr ) );
-
-end;
-
-{ DESTRUCT }
-destructor recursive_blur.Destruct;
-begin
- m_sum1.Destruct;
- m_sum2.Destruct;
- m_buf.Destruct;
-
-end;
-
-{ BLUR_X }
-procedure recursive_blur.blur_x(img : pixel_formats_ptr; radius : double );
-var
- s ,q ,q2 ,q3 ,b0 ,b1 ,b2 ,b3 ,b : double;
-
- w ,h ,wm ,x ,y : int;
-
- c : gauss_calculator;
-
- g0 ,g1 : gauss_calculator_ptr;
-
-begin
- if radius < 0.62 then
- exit;
-
- if img._width < 3 then
- exit;
-
- s:=radius * 0.5;
-
- if s < 2.5 then
- q:=3.97156 - 4.14554 * Sqrt(1 - 0.26891 * s )
- else
- q:=0.98711 * s - 0.96330;
-
- q2:=q * q;
- q3:=q2 * q;
- b0:=1.0 / (1.578250 + 2.444130 * q + 1.428100 * q2 + 0.422205 * q3 );
- b1:=2.44413 * q + 2.85619 * q2 + 1.26661 * q3;
- b2:=-1.42810 * q2 + -1.26661 * q3;
- b3:=0.422205 * q3;
- b :=1 - (b1 + b2 + b3 ) * b0;
- b1:=b1 * b0;
- b2:=b2 * b0;
- b3:=b3 * b0;
- w :=img._width;
- h :=img._height;
- wm:=w - 1;
-
- m_sum1.allocate(w );
- m_sum2.allocate(w );
- m_buf.allocate (w );
-
- y:=0;
-
- while y < h do
- begin
- g0:=gauss_calculator_ptr(m_sum1.array_operator(0 ) );
-
- c.from_pix(img.pixel(img ,0 ,y ) );
- g0.calc(
- b ,b1 ,b2 ,b3 ,
- @c ,@c ,@c ,@c );
-
- g1:=gauss_calculator_ptr(m_sum1.array_operator(1 ) );
-
- c.from_pix(img.pixel(img ,1 ,y ) );
- g1.calc(
- b ,b1 ,b2 ,b3 ,
- @c ,g0 ,g0 ,g0 );
-
- c.from_pix (img.pixel(img ,2 ,y ) );
- gauss_calculator_ptr(m_sum1.array_operator(2 ) ).calc(
- b ,b1 ,b2 ,b3 ,
- @c ,g1 ,g0 ,g0 );
-
- x:=3;
-
- while x < w do
- begin
- c.from_pix(img.pixel(img ,x ,y ) );
-
- gauss_calculator_ptr(m_sum1.array_operator(x ) ).calc(
- b ,b1 ,b2 ,b3 ,
- @c ,
- gauss_calculator_ptr(m_sum1.array_operator(x - 1 ) ) ,
- gauss_calculator_ptr(m_sum1.array_operator(x - 2 ) ) ,
- gauss_calculator_ptr(m_sum1.array_operator(x - 3 ) ) );
-
- inc(x );
-
- end;
-
- g0:=gauss_calculator_ptr(m_sum1.array_operator(wm ) );
- g1:=gauss_calculator_ptr(m_sum2.array_operator(wm ) );
-
- g1.calc(
- b ,b1 ,b2 ,b3 ,
- g0 ,g0 ,g0 ,g0 );
-
- gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ).calc(
- b ,b1 ,b2 ,b3 ,
- gauss_calculator_ptr(m_sum1.array_operator(wm - 1 ) ) ,
- g1 ,g1 ,g1 );
-
- gauss_calculator_ptr(m_sum2.array_operator(wm - 2 ) ).calc(
- b ,b1 ,b2 ,b3 ,
- gauss_calculator_ptr(m_sum1.array_operator(wm - 2 ) ) ,
- gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ) ,
- g1 ,g1 );
-
- g1.to_pix(
- aggclr_ptr(m_buf.array_operator(wm ) ) );
-
- gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ).to_pix(
- aggclr_ptr(m_buf.array_operator(wm - 1 ) ) );
-
- gauss_calculator_ptr(m_sum2.array_operator(wm - 2 ) ).to_pix(
- aggclr_ptr(m_buf.array_operator(wm - 2 ) ) );
-
- x:=wm - 3;
-
- while x >= 0 do
- begin
- gauss_calculator_ptr(m_sum2.array_operator(x ) ).calc(
- b ,b1 ,b2 ,b3 ,
- gauss_calculator_ptr(m_sum1.array_operator(x ) ) ,
- gauss_calculator_ptr(m_sum2.array_operator(x + 1 ) ) ,
- gauss_calculator_ptr(m_sum2.array_operator(x + 2 ) ) ,
- gauss_calculator_ptr(m_sum2.array_operator(x + 3 ) ) );
-
- gauss_calculator_ptr(m_sum2.array_operator(x ) ).to_pix(
- aggclr_ptr(m_buf.array_operator(x ) ) );
-
- dec(x );
-
- end;
-
- img.copy_color_hspan(img ,0 ,y ,w ,m_buf.array_operator(0 ) );
-
- inc(y );
-
- end;
-
-end;
-
-{ BLUR_Y }
-procedure recursive_blur.blur_y(img : pixel_formats_ptr; radius : double );
-var
- img2 : pixel_formats_transposer;
-
-begin
- pixfmt_transposer(img2 ,img );
- blur_x (@img2 ,radius );
-
-end;
-
-{ BLUR }
-procedure recursive_blur.blur(img : pixel_formats_ptr; radius : double );
-var
- img2 : pixel_formats_transposer;
-
-begin
- blur_x (img ,radius );
- pixfmt_transposer(img2 ,img );
- blur_x (@img2 ,radius );
-
-end;
-
-{ STACK_BLUR_GRAY8 }
-procedure stack_blur_gray8(img : pixel_formats_ptr; rx ,ry : unsigned );
-var
- stride : int;
-
- x ,y ,xp ,yp ,i ,pix ,stack_pix ,sum ,sum_in ,sum_out ,
-
- stack_ptr ,stack_start ,w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
-
- src_pix_ptr ,dst_pix_ptr : int8u_ptr;
-
- stack : pod_vector;
-
-begin
- w :=img._width;
- h :=img._height;
- wm:=w - 1;
- hm:=h - 1;
-
- stack.Construct(sizeof(int8u ) );
-
- if rx > 0 then
- begin
- if rx > 254 then
- rx:=254;
-
- div_:=rx * 2 + 1;
-
- mul_sum:=g_stack_blur8_mul[rx ];
- shr_sum:=g_stack_blur8_shr[rx ];
-
- stack.allocate(div_ );
-
- y:=0;
-
- while y < h do
- begin
- sum :=0;
- sum_in :=0;
- sum_out:=0;
-
- src_pix_ptr:=img.pix_ptr(0 ,y );
- pix :=src_pix_ptr^;
-
- i:=0;
-
- while i <= rx do
- begin
- int8u_ptr(stack.array_operator(i ) )^:=pix;
-
- inc(sum ,pix * (i + 1 ) );
- inc(sum_out ,pix );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= rx do
- begin
- if i <= wm then
- inc(ptrcomp(src_pix_ptr ) ,img.m_step );
-
- pix:=src_pix_ptr^;
-
- int8u_ptr(stack.array_operator(i + rx ) )^:=pix;
-
- inc(sum ,pix * (rx + 1 - i ) );
- inc(sum_in ,pix );
-
- inc(i );
-
- end;
-
- stack_ptr:=rx;
- xp :=rx;
-
- if xp > wm then
- xp:=wm;
-
- src_pix_ptr:=img.pix_ptr(xp ,y );
- dst_pix_ptr:=img.pix_ptr(0 ,y );
-
- x:=0;
-
- while x < w do
- begin
- dst_pix_ptr^:=int8u((sum * mul_sum ) shr shr_sum );
-
- inc(ptrcomp(dst_pix_ptr ) ,img.m_step );
- dec(sum ,sum_out );
-
- stack_start:=stack_ptr + div_ - rx;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- dec(sum_out ,int8u_ptr(stack.array_operator(stack_start ) )^ );
-
- if xp < wm then
- begin
- inc(ptrcomp(src_pix_ptr ) ,img.m_step );
-
- pix:=src_pix_ptr^;
-
- inc(xp );
-
- end;
-
- int8u_ptr(stack.array_operator(stack_start ) )^:=pix;
-
- inc(sum_in ,pix );
- inc(sum ,sum_in );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix:=int8u_ptr(stack.array_operator(stack_ptr ) )^;
-
- inc(sum_out ,stack_pix );
- dec(sum_in ,stack_pix );
-
- inc(x );
-
- end;
-
- inc(y );
-
- end;
-
- end;
-
- if ry > 0 then
- begin
- if ry > 254 then
- ry:=254;
-
- div_:=ry * 2 + 1;
-
- mul_sum:=g_stack_blur8_mul[ry ];
- shr_sum:=g_stack_blur8_shr[ry ];
-
- stack.allocate(div_ );
-
- stride:=img._stride;
-
- x:=0;
-
- while x < w do
- begin
- sum :=0;
- sum_in :=0;
- sum_out:=0;
-
- src_pix_ptr:=img.pix_ptr(x ,0 );
- pix :=src_pix_ptr^;
-
- i:=0;
-
- while i <= ry do
- begin
- int8u_ptr(stack.array_operator(i ) )^:=pix;
-
- inc(sum ,pix * (i + 1 ) );
- inc(sum_out ,pix );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= ry do
- begin
- if i <= hm then
- inc(ptrcomp(src_pix_ptr ) ,stride );
-
- pix:=src_pix_ptr^;
-
- int8u_ptr(stack.array_operator(i + ry ) )^:=pix;
-
- inc(sum ,pix * (ry + 1 - i ) );
- inc(sum_in ,pix );
-
- inc(i );
-
- end;
-
- stack_ptr:=ry;
- yp :=ry;
-
- if yp > hm then
- yp:=hm;
-
- src_pix_ptr:=img.pix_ptr(x ,yp );
- dst_pix_ptr:=img.pix_ptr(x ,0 );
-
- y:=0;
-
- while y < h do
- begin
- dst_pix_ptr^:=int8u((sum * mul_sum ) shr shr_sum );
-
- inc(ptrcomp(dst_pix_ptr ) ,stride );
- dec(sum ,sum_out );
-
- stack_start:=stack_ptr + div_ - ry;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- dec(sum_out ,int8u_ptr(stack.array_operator(stack_start ) )^ );
-
- if yp < hm then
- begin
- inc(ptrcomp(src_pix_ptr ) ,stride );
-
- pix:=src_pix_ptr^;
-
- inc(yp );
-
- end;
-
- int8u_ptr(stack.array_operator(stack_start ) )^:=pix;
-
- inc(sum_in ,pix );
- inc(sum ,sum_in );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix:=int8u_ptr(stack.array_operator(stack_ptr ) )^;
-
- inc(sum_out ,stack_pix );
- dec(sum_in ,stack_pix );
-
- inc(y );
-
- end;
-
- inc(x );
-
- end;
-
- end;
-
- stack.Destruct;
-
-end;
-
-{ STACK_BLUR_RGB24 }
-procedure stack_blur_rgb24(img : pixel_formats_ptr; rx ,ry : unsigned );
-var
- R ,G ,B ,stride : int;
-
- x ,y ,xp ,yp ,i ,stack_ptr ,stack_start ,
-
- sum_r ,sum_g ,sum_b ,
-
- sum_in_r ,sum_in_g ,sum_in_b ,
-
- sum_out_r ,sum_out_g ,sum_out_b ,
-
- w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
-
- src_pix_ptr ,dst_pix_ptr : int8u_ptr;
-
- stack_pix_ptr : aggclr_ptr;
-
- stack : pod_array;
-
-begin
- R:=img.m_order.R;
- G:=img.m_order.G;
- B:=img.m_order.B;
-
- w :=img._width;
- h :=img._height;
- wm:=w - 1;
- hm:=h - 1;
-
- stack.Construct(sizeof(aggclr ) );
-
- if rx > 0 then
- begin
- if rx > 254 then
- rx:=254;
-
- div_ :=rx * 2 + 1;
- mul_sum:=g_stack_blur8_mul[rx ];
- shr_sum:=g_stack_blur8_shr[rx ];
-
- stack.allocate(div_ );
-
- y:=0;
-
- while y < h do
- begin
- sum_r :=0;
- sum_g :=0;
- sum_b :=0;
- sum_in_r :=0;
- sum_in_g :=0;
- sum_in_b :=0;
- sum_out_r:=0;
- sum_out_g:=0;
- sum_out_b:=0;
-
- src_pix_ptr:=img.pix_ptr(0 ,y );
-
- i:=0;
-
- while i <= rx do
- begin
- stack_pix_ptr:=stack.array_operator(i );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
-
- inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= rx do
- begin
- if i <= wm then
- inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
-
- stack_pix_ptr:=stack.array_operator(i + rx );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (rx + 1 - i ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (rx + 1 - i ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (rx + 1 - i ) );
-
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
-
- inc(i );
-
- end;
-
- stack_ptr:=rx;
- xp :=rx;
-
- if xp > wm then
- xp:=wm;
-
- src_pix_ptr:=img.pix_ptr(xp ,y );
- dst_pix_ptr:=img.pix_ptr(0 ,y );
-
- x:=0;
-
- while x < w do
- begin
- int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
-
- inc(ptrcomp(dst_pix_ptr ) ,img.m_pix_width );
-
- dec(sum_r ,sum_out_r );
- dec(sum_g ,sum_out_g );
- dec(sum_b ,sum_out_b );
-
- stack_start:=stack_ptr + div_ - rx;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- stack_pix_ptr:=stack.array_operator(stack_start );
-
- dec(sum_out_r ,stack_pix_ptr.r );
- dec(sum_out_g ,stack_pix_ptr.g );
- dec(sum_out_b ,stack_pix_ptr.b );
-
- if xp < wm then
- begin
- inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
- inc(xp );
-
- end;
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
-
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
-
- inc(sum_r ,sum_in_r );
- inc(sum_g ,sum_in_g );
- inc(sum_b ,sum_in_b );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix_ptr:=stack.array_operator(stack_ptr );
-
- inc(sum_out_r ,stack_pix_ptr.r );
- inc(sum_out_g ,stack_pix_ptr.g );
- inc(sum_out_b ,stack_pix_ptr.b );
- dec(sum_in_r ,stack_pix_ptr.r );
- dec(sum_in_g ,stack_pix_ptr.g );
- dec(sum_in_b ,stack_pix_ptr.b );
-
- inc(x );
-
- end;
-
- inc(y );
-
- end;
-
- end;
-
- if ry > 0 then
- begin
- if ry > 254 then
- ry:=254;
-
- div_:=ry * 2 + 1;
-
- mul_sum:=g_stack_blur8_mul[ry ];
- shr_sum:=g_stack_blur8_shr[ry ];
-
- stack.allocate(div_ );
-
- stride:=img._stride;
-
- x:=0;
-
- while x < w do
- begin
- sum_r :=0;
- sum_g :=0;
- sum_b :=0;
- sum_in_r :=0;
- sum_in_g :=0;
- sum_in_b :=0;
- sum_out_r:=0;
- sum_out_g:=0;
- sum_out_b:=0;
-
- src_pix_ptr:=img.pix_ptr(x ,0 );
-
- i:=0;
-
- while i <= ry do
- begin
- stack_pix_ptr:=stack.array_operator(i );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
- inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= ry do
- begin
- if i <= hm then
- inc(ptrcomp(src_pix_ptr ) ,stride );
-
- stack_pix_ptr:=stack.array_operator(i + ry );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (ry + 1 - i ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (ry + 1 - i ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (ry + 1 - i ) );
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
-
- inc(i );
-
- end;
-
- stack_ptr:=ry;
- yp :=ry;
-
- if yp > hm then
- yp:=hm;
-
- src_pix_ptr:=img.pix_ptr(x ,yp );
- dst_pix_ptr:=img.pix_ptr(x ,0 );
-
- y:=0;
-
- while y < h do
- begin
- int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
-
- inc(ptrcomp(dst_pix_ptr ) ,stride );
-
- dec(sum_r ,sum_out_r );
- dec(sum_g ,sum_out_g );
- dec(sum_b ,sum_out_b );
-
- stack_start:=stack_ptr + div_ - ry;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- stack_pix_ptr:=stack.array_operator(stack_start );
-
- dec(sum_out_r ,stack_pix_ptr.r );
- dec(sum_out_g ,stack_pix_ptr.g );
- dec(sum_out_b ,stack_pix_ptr.b );
-
- if yp < hm then
- begin
- inc(ptrcomp(src_pix_ptr ) ,stride );
-
- inc(yp );
-
- end;
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
-
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_r ,sum_in_r );
- inc(sum_g ,sum_in_g );
- inc(sum_b ,sum_in_b );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix_ptr:=stack.array_operator(stack_ptr );
-
- inc(sum_out_r ,stack_pix_ptr.r );
- inc(sum_out_g ,stack_pix_ptr.g );
- inc(sum_out_b ,stack_pix_ptr.b );
- dec(sum_in_r ,stack_pix_ptr.r );
- dec(sum_in_g ,stack_pix_ptr.g );
- dec(sum_in_b ,stack_pix_ptr.b );
-
- inc(y );
-
- end;
-
- inc(x );
-
- end;
-
- end;
-
- stack.Destruct;
-
-end;
-
-{ STACK_BLUR_RGBA32 }
-procedure stack_blur_rgba32(img : pixel_formats_ptr; rx ,ry : unsigned );
-var
- R ,G ,B ,A ,stride : int;
-
- x ,y ,xp ,yp ,i ,stack_ptr ,stack_start ,
-
- sum_r ,sum_g ,sum_b ,sum_a ,
-
- sum_in_r ,sum_in_g ,sum_in_b ,sum_in_a ,
-
- sum_out_r ,sum_out_g ,sum_out_b ,sum_out_a ,
-
- w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
-
- src_pix_ptr ,dst_pix_ptr : int8u_ptr;
-
- stack_pix_ptr : aggclr_ptr;
-
- stack : pod_array;
-
-begin
- R:=img.m_order.R;
- G:=img.m_order.G;
- B:=img.m_order.B;
- A:=img.m_order.A;
-
- w :=img._width;
- h :=img._height;
- wm:=w - 1;
- hm:=h - 1;
-
- stack.Construct(sizeof(aggclr ) );
-
- if rx > 0 then
- begin
- if rx > 254 then
- rx:=254;
-
- div_ :=rx * 2 + 1;
- mul_sum:=g_stack_blur8_mul[rx ];
- shr_sum:=g_stack_blur8_shr[rx ];
-
- stack.allocate(div_ );
-
- y:=0;
-
- while y < h do
- begin
- sum_r :=0;
- sum_g :=0;
- sum_b :=0;
- sum_a :=0;
- sum_in_r :=0;
- sum_in_g :=0;
- sum_in_b :=0;
- sum_in_a :=0;
- sum_out_r:=0;
- sum_out_g:=0;
- sum_out_b:=0;
- sum_out_a:=0;
-
- src_pix_ptr:=img.pix_ptr(0 ,y );
-
- i:=0;
-
- while i <= rx do
- begin
- stack_pix_ptr:=stack.array_operator(i );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
- stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
- inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (i + 1 ) );
-
- inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_out_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= rx do
- begin
- if i <= wm then
- inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
-
- stack_pix_ptr:=stack.array_operator(i + rx );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
- stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (rx + 1 - i ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (rx + 1 - i ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (rx + 1 - i ) );
- inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (rx + 1 - i ) );
-
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
-
- inc(i );
-
- end;
-
- stack_ptr:=rx;
- xp :=rx;
-
- if xp > wm then
- xp:=wm;
-
- src_pix_ptr:=img.pix_ptr(xp ,y );
- dst_pix_ptr:=img.pix_ptr(0 ,y );
-
- x:=0;
-
- while x < w do
- begin
- int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + A )^:=int8u((sum_a * mul_sum ) shr shr_sum );
-
- inc(ptrcomp(dst_pix_ptr ) ,img.m_pix_width );
-
- dec(sum_r ,sum_out_r );
- dec(sum_g ,sum_out_g );
- dec(sum_b ,sum_out_b );
- dec(sum_a ,sum_out_a );
-
- stack_start:=stack_ptr + div_ - rx;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- stack_pix_ptr:=stack.array_operator(stack_start );
-
- dec(sum_out_r ,stack_pix_ptr.r );
- dec(sum_out_g ,stack_pix_ptr.g );
- dec(sum_out_b ,stack_pix_ptr.b );
- dec(sum_out_a ,stack_pix_ptr.a );
-
- if xp < wm then
- begin
- inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
- inc(xp );
-
- end;
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
- stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
-
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
-
- inc(sum_r ,sum_in_r );
- inc(sum_g ,sum_in_g );
- inc(sum_b ,sum_in_b );
- inc(sum_a ,sum_in_a );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix_ptr:=stack.array_operator(stack_ptr );
-
- inc(sum_out_r ,stack_pix_ptr.r );
- inc(sum_out_g ,stack_pix_ptr.g );
- inc(sum_out_b ,stack_pix_ptr.b );
- inc(sum_out_a ,stack_pix_ptr.a );
- dec(sum_in_r ,stack_pix_ptr.r );
- dec(sum_in_g ,stack_pix_ptr.g );
- dec(sum_in_b ,stack_pix_ptr.b );
- dec(sum_in_a ,stack_pix_ptr.a );
-
- inc(x );
-
- end;
-
- inc(y );
-
- end;
-
- end;
-
- if ry > 0 then
- begin
- if ry > 254 then
- ry:=254;
-
- div_:=ry * 2 + 1;
-
- mul_sum:=g_stack_blur8_mul[ry ];
- shr_sum:=g_stack_blur8_shr[ry ];
-
- stack.allocate(div_ );
-
- stride:=img._stride;
-
- x:=0;
-
- while x < w do
- begin
- sum_r :=0;
- sum_g :=0;
- sum_b :=0;
- sum_a :=0;
- sum_in_r :=0;
- sum_in_g :=0;
- sum_in_b :=0;
- sum_in_a :=0;
- sum_out_r:=0;
- sum_out_g:=0;
- sum_out_b:=0;
- sum_out_a:=0;
-
- src_pix_ptr:=img.pix_ptr(x ,0 );
-
- i:=0;
-
- while i <= ry do
- begin
- stack_pix_ptr:=stack.array_operator(i );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
- stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
- inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (i + 1 ) );
- inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_out_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
-
- inc(i );
-
- end;
-
- i:=1;
-
- while i <= ry do
- begin
- if i <= hm then
- inc(ptrcomp(src_pix_ptr ) ,stride );
-
- stack_pix_ptr:=stack.array_operator(i + ry );
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
- stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
-
- inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (ry + 1 - i ) );
- inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (ry + 1 - i ) );
- inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (ry + 1 - i ) );
- inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (ry + 1 - i ) );
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
-
- inc(i );
-
- end;
-
- stack_ptr:=ry;
- yp :=ry;
-
- if yp > hm then
- yp:=hm;
-
- src_pix_ptr:=img.pix_ptr(x ,yp );
- dst_pix_ptr:=img.pix_ptr(x ,0 );
-
- y:=0;
-
- while y < h do
- begin
- int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
- int8u_ptr(ptrcomp(dst_pix_ptr ) + A )^:=int8u((sum_a * mul_sum ) shr shr_sum );
-
- inc(ptrcomp(dst_pix_ptr ) ,stride );
-
- dec(sum_r ,sum_out_r );
- dec(sum_g ,sum_out_g );
- dec(sum_b ,sum_out_b );
- dec(sum_a ,sum_out_a );
-
- stack_start:=stack_ptr + div_ - ry;
-
- if stack_start >= div_ then
- dec(stack_start ,div_ );
-
- stack_pix_ptr:=stack.array_operator(stack_start );
-
- dec(sum_out_r ,stack_pix_ptr.r );
- dec(sum_out_g ,stack_pix_ptr.g );
- dec(sum_out_b ,stack_pix_ptr.b );
- dec(sum_out_a ,stack_pix_ptr.a );
-
- if yp < hm then
- begin
- inc(ptrcomp(src_pix_ptr ) ,stride );
-
- inc(yp );
-
- end;
-
- stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
- stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
- stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
- stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
-
- inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
- inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
- inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
- inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
- inc(sum_r ,sum_in_r );
- inc(sum_g ,sum_in_g );
- inc(sum_b ,sum_in_b );
- inc(sum_a ,sum_in_a );
-
- inc(stack_ptr );
-
- if stack_ptr >= div_ then
- stack_ptr:=0;
-
- stack_pix_ptr:=stack.array_operator(stack_ptr );
-
- inc(sum_out_r ,stack_pix_ptr.r );
- inc(sum_out_g ,stack_pix_ptr.g );
- inc(sum_out_b ,stack_pix_ptr.b );
- inc(sum_out_a ,stack_pix_ptr.a );
- dec(sum_in_r ,stack_pix_ptr.r );
- dec(sum_in_g ,stack_pix_ptr.g );
- dec(sum_in_b ,stack_pix_ptr.b );
- dec(sum_in_a ,stack_pix_ptr.a );
-
- inc(y );
-
- end;
-
- inc(x );
-
- end;
-
- end;
-
- stack.Destruct;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// The Stack Blur Algorithm was invented by Mario Klingemann,
+// mario@quasimondo.com and described here:
+// http://incubator.quasimondo.com/processing/fast_blur_deluxe.php
+// (search phrase "Stackblur: Fast But Goodlooking").
+// The major improvement is that there's no more division table
+// that was very expensive to create for large blur radii. Insted,
+// for 8-bit per channel and radius not exceeding 254 the division is
+// replaced by multiplication and shift.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 11.10.2007-Milano: recursive_blur & finished OK
+// 10.10.2007-Milano: stack_blur
+// 09.10.2007-Milano: Unit port establishment
+//
+{ agg_blur.pas }
+unit
+ agg_blur ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$Q- }
+{$R- }
+uses
+ agg_basics ,
+ agg_array ,
+ agg_color ,
+ agg_pixfmt ,
+ agg_pixfmt_transposer ;
+
+{ GLOBAL VARIABLES & CONSTANTS }
+
+{ TYPES DEFINITION }
+type
+ stack_blur = object
+ private
+ m_buf ,
+ m_stack : pod_vector;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ procedure blur_x(img : pixel_formats_ptr; radius : unsigned );
+ procedure blur_y(img : pixel_formats_ptr; radius : unsigned );
+
+ procedure blur(img : pixel_formats_ptr; radius : unsigned );
+
+ end;
+
+ recursive_blur = object
+ private
+ m_sum1 ,
+ m_sum2 ,
+ m_buf : pod_vector;
+
+ public
+ constructor Construct;
+ destructor Destruct;
+
+ procedure blur_x(img : pixel_formats_ptr; radius : double );
+ procedure blur_y(img : pixel_formats_ptr; radius : double );
+
+ procedure blur(img : pixel_formats_ptr; radius : double );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ procedure stack_blur_gray8 (img : pixel_formats_ptr; rx ,ry : unsigned );
+ procedure stack_blur_rgb24 (img : pixel_formats_ptr; rx ,ry : unsigned );
+ procedure stack_blur_rgba32(img : pixel_formats_ptr; rx ,ry : unsigned );
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+const
+ g_stack_blur8_mul : array[0..254 ] of int16u = (
+ 512 ,512 ,456 ,512 ,328 ,456 ,335 ,512 ,405 ,328 ,271 ,456 ,388 ,335 ,292 ,512 ,
+ 454 ,405 ,364 ,328 ,298 ,271 ,496 ,456 ,420 ,388 ,360 ,335 ,312 ,292 ,273 ,512 ,
+ 482 ,454 ,428 ,405 ,383 ,364 ,345 ,328 ,312 ,298 ,284 ,271 ,259 ,496 ,475 ,456 ,
+ 437 ,420 ,404 ,388 ,374 ,360 ,347 ,335 ,323 ,312 ,302 ,292 ,282 ,273 ,265 ,512 ,
+ 497 ,482 ,468 ,454 ,441 ,428 ,417 ,405 ,394 ,383 ,373 ,364 ,354 ,345 ,337 ,328 ,
+ 320 ,312 ,305 ,298 ,291 ,284 ,278 ,271 ,265 ,259 ,507 ,496 ,485 ,475 ,465 ,456 ,
+ 446 ,437 ,428 ,420 ,412 ,404 ,396 ,388 ,381 ,374 ,367 ,360 ,354 ,347 ,341 ,335 ,
+ 329 ,323 ,318 ,312 ,307 ,302 ,297 ,292 ,287 ,282 ,278 ,273 ,269 ,265 ,261 ,512 ,
+ 505 ,497 ,489 ,482 ,475 ,468 ,461 ,454 ,447 ,441 ,435 ,428 ,422 ,417 ,411 ,405 ,
+ 399 ,394 ,389 ,383 ,378 ,373 ,368 ,364 ,359 ,354 ,350 ,345 ,341 ,337 ,332 ,328 ,
+ 324 ,320 ,316 ,312 ,309 ,305 ,301 ,298 ,294 ,291 ,287 ,284 ,281 ,278 ,274 ,271 ,
+ 268 ,265 ,262 ,259 ,257 ,507 ,501 ,496 ,491 ,485 ,480 ,475 ,470 ,465 ,460 ,456 ,
+ 451 ,446 ,442 ,437 ,433 ,428 ,424 ,420 ,416 ,412 ,408 ,404 ,400 ,396 ,392 ,388 ,
+ 385 ,381 ,377 ,374 ,370 ,367 ,363 ,360 ,357 ,354 ,350 ,347 ,344 ,341 ,338 ,335 ,
+ 332 ,329 ,326 ,323 ,320 ,318 ,315 ,312 ,310 ,307 ,304 ,302 ,299 ,297 ,294 ,292 ,
+ 289 ,287 ,285 ,282 ,280 ,278 ,275 ,273 ,271 ,269 ,267 ,265 ,263 ,261 ,259 );
+
+ g_stack_blur8_shr : array[0..254 ] of int8u = (
+ 9 ,11 ,12 ,13 ,13 ,14 ,14 ,15 ,15 ,15 ,15 ,16 ,16 ,16 ,16 ,17 ,
+ 17 ,17 ,17 ,17 ,17 ,17 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,18 ,19 ,
+ 19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,19 ,20 ,20 ,20 ,
+ 20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,20 ,21 ,
+ 21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,
+ 21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,21 ,22 ,22 ,22 ,22 ,22 ,22 ,
+ 22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,
+ 22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,22 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,23 ,
+ 23 ,23 ,23 ,23 ,23 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,
+ 24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 ,24 );
+
+type
+ stack_calculator_ptr = ^stack_calculator;
+ stack_calculator = object
+ v ,
+ r ,
+ g ,
+ b ,
+ a : unsigned;
+
+ procedure clear;
+
+ procedure add (c : aggclr );
+ procedure add_ (c : aggclr; k : unsigned );
+ procedure add__(c : stack_calculator );
+ procedure sub (c : aggclr );
+ procedure sub_ (c : stack_calculator );
+
+ procedure calc_pix (c : aggclr_ptr; div_ : unsigned );
+ procedure calc_pix_(c : aggclr_ptr; mul_ ,shr_ : unsigned );
+
+ end;
+
+ gauss_calculator_ptr = ^gauss_calculator;
+ gauss_calculator = object
+ v ,
+ r ,
+ g ,
+ b ,
+ a : double;
+
+ procedure from_pix(c : aggclr );
+
+ procedure calc(
+ b1 ,b2 ,b3 ,b4 : double;
+ c1 ,c2 ,c3 ,c4 : gauss_calculator_ptr );
+
+ procedure to_pix(c : aggclr_ptr );
+
+ end;
+
+{ UNIT IMPLEMENTATION }
+{ CLEAR }
+procedure stack_calculator.clear;
+begin
+ v:=0;
+ r:=0;
+ g:=0;
+ b:=0;
+ a:=0;
+
+end;
+
+{ ADD }
+procedure stack_calculator.add(c : aggclr );
+begin
+ inc(v ,c.v );
+ inc(r ,c.r );
+ inc(g ,c.g );
+ inc(b ,c.b );
+ inc(a ,c.a );
+
+end;
+
+{ ADD__ }
+procedure stack_calculator.add__(c : stack_calculator );
+begin
+ inc(v ,c.v );
+ inc(r ,c.r );
+ inc(g ,c.g );
+ inc(b ,c.b );
+ inc(a ,c.a );
+
+end;
+
+{ ADD_ }
+procedure stack_calculator.add_(c : aggclr; k : unsigned );
+begin
+ inc(v ,c.v * k );
+ inc(r ,c.r * k );
+ inc(g ,c.g * k );
+ inc(b ,c.b * k );
+ inc(a ,c.a * k );
+
+end;
+
+{ SUB }
+procedure stack_calculator.sub(c : aggclr );
+begin
+ dec(v ,c.v );
+ dec(r ,c.r );
+ dec(g ,c.g );
+ dec(b ,c.b );
+ dec(a ,c.a );
+
+end;
+
+{ SUB_ }
+procedure stack_calculator.sub_(c : stack_calculator );
+begin
+ dec(v ,c.v );
+ dec(r ,c.r );
+ dec(g ,c.g );
+ dec(b ,c.b );
+ dec(a ,c.a );
+
+end;
+
+{ CALC_PIX }
+procedure stack_calculator.calc_pix(c : aggclr_ptr; div_ : unsigned );
+begin
+ c.v:=int8u(v div div_ );
+ c.r:=int8u(r div div_ );
+ c.g:=int8u(g div div_ );
+ c.b:=int8u(b div div_ );
+ c.a:=int8u(a div div_ );
+
+end;
+
+{ CALC_PIX_ }
+procedure stack_calculator.calc_pix_(c : aggclr_ptr; mul_ ,shr_ : unsigned );
+begin
+ c.v:=int8u((v * mul_ ) shr shr_ );
+ c.r:=int8u((r * mul_ ) shr shr_ );
+ c.g:=int8u((g * mul_ ) shr shr_ );
+ c.b:=int8u((b * mul_ ) shr shr_ );
+ c.a:=int8u((a * mul_ ) shr shr_ );
+
+end;
+
+{ FROM_PIX }
+procedure gauss_calculator.from_pix(c : aggclr );
+begin
+ v:=c.v;
+ r:=c.r;
+ g:=c.g;
+ b:=c.b;
+ a:=c.a;
+
+end;
+
+{ CALC }
+procedure gauss_calculator.calc(
+ b1 ,b2 ,b3 ,b4 : double;
+ c1 ,c2 ,c3 ,c4 : gauss_calculator_ptr );
+begin
+ v:=b1 * c1.v + b2 * c2.v + b3 * c3.v + b4 * c4.v;
+ r:=b1 * c1.r + b2 * c2.r + b3 * c3.r + b4 * c4.r;
+ g:=b1 * c1.g + b2 * c2.g + b3 * c3.g + b4 * c4.g;
+ b:=b1 * c1.b + b2 * c2.b + b3 * c3.b + b4 * c4.b;
+ a:=b1 * c1.a + b2 * c2.a + b3 * c3.a + b4 * c4.a;
+
+end;
+
+{ TO_PIX }
+procedure gauss_calculator.to_pix(c : aggclr_ptr );
+begin
+ c.v:=int8u(uround(v ) );
+ c.r:=int8u(uround(r ) );
+ c.g:=int8u(uround(g ) );
+ c.b:=int8u(uround(b ) );
+ c.a:=int8u(uround(a ) );
+
+end;
+
+{ CONSTRUCT }
+constructor stack_blur.Construct;
+begin
+ m_buf.Construct (sizeof(aggclr ) );
+ m_stack.Construct(sizeof(aggclr ) );
+
+end;
+
+{ DESTRUCT }
+destructor stack_blur.Destruct;
+begin
+ m_buf.Destruct;
+ m_stack.Destruct;
+
+end;
+
+{ BLUR_X }
+procedure stack_blur.blur_x(img : pixel_formats_ptr; radius : unsigned );
+var
+ x ,y ,xp ,i ,stack_ptr ,stack_start ,
+
+ w ,h ,wm ,div_ ,div_sum ,mul_sum ,shr_sum ,max_val : unsigned;
+
+ pix : aggclr;
+
+ stack_pix ,_c : aggclr_ptr;
+
+ sum ,sum_in ,sum_out : stack_calculator;
+
+begin
+ if radius < 1 then
+ exit;
+
+ w :=img._width;
+ h :=img._height;
+ wm :=w - 1;
+ div_:=radius * 2 + 1;
+
+ div_sum:=(radius + 1 ) * (radius + 1 );
+ mul_sum:=0;
+ shr_sum:=0;
+ max_val:=base_mask;
+
+ if (max_val <= 255 ) and
+ (radius < 255 ) then
+ begin
+ mul_sum:=g_stack_blur8_mul[radius ];
+ shr_sum:=g_stack_blur8_shr[radius ];
+
+ end;
+
+ m_buf.allocate (w ,128 );
+ m_stack.allocate(div_ ,32 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum.clear;
+ sum_in.clear;
+ sum_out.clear;
+
+ pix:=img.pixel(img ,0 ,y );
+
+ i:=0;
+
+ while i <= radius do
+ begin
+ move(pix ,m_stack.array_operator(i )^ ,sizeof(aggclr ) );
+
+ sum.add_ (pix ,i + 1 );
+ sum_out.add(pix );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= radius do
+ begin
+ if i > wm then
+ pix:=img.pixel(img ,wm ,y )
+ else
+ pix:=img.pixel(img ,i ,y );
+
+ move(pix ,m_stack.array_operator(i + radius )^ ,sizeof(aggclr ) );
+
+ sum.add_ (pix ,radius + 1 - i );
+ sum_in.add(pix );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=radius;
+
+ x:=0;
+
+ while x < w do
+ begin
+ if mul_sum <> 0 then
+ sum.calc_pix_(aggclr_ptr(m_buf.array_operator(x ) ) ,mul_sum ,shr_sum )
+ else
+ sum.calc_pix(aggclr_ptr(m_buf.array_operator(x ) ) ,div_sum );
+
+ sum.sub_(sum_out );
+
+ stack_start:=stack_ptr + div_ - radius;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix:=m_stack.array_operator(stack_start );
+
+ sum_out.sub(stack_pix^ );
+
+ xp:=x + radius + 1;
+
+ if xp > wm then
+ xp:=wm;
+
+ pix:=img.pixel(img ,xp ,y );
+
+ stack_pix^:=pix;
+
+ sum_in.add(pix );
+ sum.add__ (sum_in );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix:=m_stack.array_operator(stack_ptr );
+
+ sum_out.add(stack_pix^ );
+ sum_in.sub (stack_pix^ );
+
+ inc(x );
+
+ end;
+
+ _c:=m_buf.array_operator(0 );
+
+ img.copy_color_hspan(img ,0 ,y ,w ,_c );
+
+ inc(y );
+
+ end;
+
+end;
+
+{ BLUR_Y }
+procedure stack_blur.blur_y(img : pixel_formats_ptr; radius : unsigned );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ BLUR }
+procedure stack_blur.blur(img : pixel_formats_ptr; radius : unsigned );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ blur_x (img ,radius );
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ CONSTRUCT }
+constructor recursive_blur.Construct;
+begin
+ m_sum1.Construct(sizeof(gauss_calculator ) );
+ m_sum2.Construct(sizeof(gauss_calculator ) );
+ m_buf.Construct (sizeof(aggclr ) );
+
+end;
+
+{ DESTRUCT }
+destructor recursive_blur.Destruct;
+begin
+ m_sum1.Destruct;
+ m_sum2.Destruct;
+ m_buf.Destruct;
+
+end;
+
+{ BLUR_X }
+procedure recursive_blur.blur_x(img : pixel_formats_ptr; radius : double );
+var
+ s ,q ,q2 ,q3 ,b0 ,b1 ,b2 ,b3 ,b : double;
+
+ w ,h ,wm ,x ,y : int;
+
+ c : gauss_calculator;
+
+ g0 ,g1 : gauss_calculator_ptr;
+
+begin
+ if radius < 0.62 then
+ exit;
+
+ if img._width < 3 then
+ exit;
+
+ s:=radius * 0.5;
+
+ if s < 2.5 then
+ q:=3.97156 - 4.14554 * Sqrt(1 - 0.26891 * s )
+ else
+ q:=0.98711 * s - 0.96330;
+
+ q2:=q * q;
+ q3:=q2 * q;
+ b0:=1.0 / (1.578250 + 2.444130 * q + 1.428100 * q2 + 0.422205 * q3 );
+ b1:=2.44413 * q + 2.85619 * q2 + 1.26661 * q3;
+ b2:=-1.42810 * q2 + -1.26661 * q3;
+ b3:=0.422205 * q3;
+ b :=1 - (b1 + b2 + b3 ) * b0;
+ b1:=b1 * b0;
+ b2:=b2 * b0;
+ b3:=b3 * b0;
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+
+ m_sum1.allocate(w );
+ m_sum2.allocate(w );
+ m_buf.allocate (w );
+
+ y:=0;
+
+ while y < h do
+ begin
+ g0:=gauss_calculator_ptr(m_sum1.array_operator(0 ) );
+
+ c.from_pix(img.pixel(img ,0 ,y ) );
+ g0.calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,@c ,@c ,@c );
+
+ g1:=gauss_calculator_ptr(m_sum1.array_operator(1 ) );
+
+ c.from_pix(img.pixel(img ,1 ,y ) );
+ g1.calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,g0 ,g0 ,g0 );
+
+ c.from_pix (img.pixel(img ,2 ,y ) );
+ gauss_calculator_ptr(m_sum1.array_operator(2 ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,g1 ,g0 ,g0 );
+
+ x:=3;
+
+ while x < w do
+ begin
+ c.from_pix(img.pixel(img ,x ,y ) );
+
+ gauss_calculator_ptr(m_sum1.array_operator(x ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ @c ,
+ gauss_calculator_ptr(m_sum1.array_operator(x - 1 ) ) ,
+ gauss_calculator_ptr(m_sum1.array_operator(x - 2 ) ) ,
+ gauss_calculator_ptr(m_sum1.array_operator(x - 3 ) ) );
+
+ inc(x );
+
+ end;
+
+ g0:=gauss_calculator_ptr(m_sum1.array_operator(wm ) );
+ g1:=gauss_calculator_ptr(m_sum2.array_operator(wm ) );
+
+ g1.calc(
+ b ,b1 ,b2 ,b3 ,
+ g0 ,g0 ,g0 ,g0 );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ gauss_calculator_ptr(m_sum1.array_operator(wm - 1 ) ) ,
+ g1 ,g1 ,g1 );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 2 ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ gauss_calculator_ptr(m_sum1.array_operator(wm - 2 ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ) ,
+ g1 ,g1 );
+
+ g1.to_pix(
+ aggclr_ptr(m_buf.array_operator(wm ) ) );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 1 ) ).to_pix(
+ aggclr_ptr(m_buf.array_operator(wm - 1 ) ) );
+
+ gauss_calculator_ptr(m_sum2.array_operator(wm - 2 ) ).to_pix(
+ aggclr_ptr(m_buf.array_operator(wm - 2 ) ) );
+
+ x:=wm - 3;
+
+ while x >= 0 do
+ begin
+ gauss_calculator_ptr(m_sum2.array_operator(x ) ).calc(
+ b ,b1 ,b2 ,b3 ,
+ gauss_calculator_ptr(m_sum1.array_operator(x ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(x + 1 ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(x + 2 ) ) ,
+ gauss_calculator_ptr(m_sum2.array_operator(x + 3 ) ) );
+
+ gauss_calculator_ptr(m_sum2.array_operator(x ) ).to_pix(
+ aggclr_ptr(m_buf.array_operator(x ) ) );
+
+ dec(x );
+
+ end;
+
+ img.copy_color_hspan(img ,0 ,y ,w ,m_buf.array_operator(0 ) );
+
+ inc(y );
+
+ end;
+
+end;
+
+{ BLUR_Y }
+procedure recursive_blur.blur_y(img : pixel_formats_ptr; radius : double );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ BLUR }
+procedure recursive_blur.blur(img : pixel_formats_ptr; radius : double );
+var
+ img2 : pixel_formats_transposer;
+
+begin
+ blur_x (img ,radius );
+ pixfmt_transposer(img2 ,img );
+ blur_x (@img2 ,radius );
+
+end;
+
+{ STACK_BLUR_GRAY8 }
+procedure stack_blur_gray8(img : pixel_formats_ptr; rx ,ry : unsigned );
+var
+ stride : int;
+
+ x ,y ,xp ,yp ,i ,pix ,stack_pix ,sum ,sum_in ,sum_out ,
+
+ stack_ptr ,stack_start ,w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
+
+ src_pix_ptr ,dst_pix_ptr : int8u_ptr;
+
+ stack : pod_vector;
+
+begin
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+ hm:=h - 1;
+
+ stack.Construct(sizeof(int8u ) );
+
+ if rx > 0 then
+ begin
+ if rx > 254 then
+ rx:=254;
+
+ div_:=rx * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[rx ];
+ shr_sum:=g_stack_blur8_shr[rx ];
+
+ stack.allocate(div_ );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum :=0;
+ sum_in :=0;
+ sum_out:=0;
+
+ src_pix_ptr:=img.pix_ptr(0 ,y );
+ pix :=src_pix_ptr^;
+
+ i:=0;
+
+ while i <= rx do
+ begin
+ int8u_ptr(stack.array_operator(i ) )^:=pix;
+
+ inc(sum ,pix * (i + 1 ) );
+ inc(sum_out ,pix );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= rx do
+ begin
+ if i <= wm then
+ inc(ptrcomp(src_pix_ptr ) ,img.m_step );
+
+ pix:=src_pix_ptr^;
+
+ int8u_ptr(stack.array_operator(i + rx ) )^:=pix;
+
+ inc(sum ,pix * (rx + 1 - i ) );
+ inc(sum_in ,pix );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=rx;
+ xp :=rx;
+
+ if xp > wm then
+ xp:=wm;
+
+ src_pix_ptr:=img.pix_ptr(xp ,y );
+ dst_pix_ptr:=img.pix_ptr(0 ,y );
+
+ x:=0;
+
+ while x < w do
+ begin
+ dst_pix_ptr^:=int8u((sum * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,img.m_step );
+ dec(sum ,sum_out );
+
+ stack_start:=stack_ptr + div_ - rx;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ dec(sum_out ,int8u_ptr(stack.array_operator(stack_start ) )^ );
+
+ if xp < wm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,img.m_step );
+
+ pix:=src_pix_ptr^;
+
+ inc(xp );
+
+ end;
+
+ int8u_ptr(stack.array_operator(stack_start ) )^:=pix;
+
+ inc(sum_in ,pix );
+ inc(sum ,sum_in );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix:=int8u_ptr(stack.array_operator(stack_ptr ) )^;
+
+ inc(sum_out ,stack_pix );
+ dec(sum_in ,stack_pix );
+
+ inc(x );
+
+ end;
+
+ inc(y );
+
+ end;
+
+ end;
+
+ if ry > 0 then
+ begin
+ if ry > 254 then
+ ry:=254;
+
+ div_:=ry * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[ry ];
+ shr_sum:=g_stack_blur8_shr[ry ];
+
+ stack.allocate(div_ );
+
+ stride:=img._stride;
+
+ x:=0;
+
+ while x < w do
+ begin
+ sum :=0;
+ sum_in :=0;
+ sum_out:=0;
+
+ src_pix_ptr:=img.pix_ptr(x ,0 );
+ pix :=src_pix_ptr^;
+
+ i:=0;
+
+ while i <= ry do
+ begin
+ int8u_ptr(stack.array_operator(i ) )^:=pix;
+
+ inc(sum ,pix * (i + 1 ) );
+ inc(sum_out ,pix );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= ry do
+ begin
+ if i <= hm then
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ pix:=src_pix_ptr^;
+
+ int8u_ptr(stack.array_operator(i + ry ) )^:=pix;
+
+ inc(sum ,pix * (ry + 1 - i ) );
+ inc(sum_in ,pix );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=ry;
+ yp :=ry;
+
+ if yp > hm then
+ yp:=hm;
+
+ src_pix_ptr:=img.pix_ptr(x ,yp );
+ dst_pix_ptr:=img.pix_ptr(x ,0 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ dst_pix_ptr^:=int8u((sum * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,stride );
+ dec(sum ,sum_out );
+
+ stack_start:=stack_ptr + div_ - ry;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ dec(sum_out ,int8u_ptr(stack.array_operator(stack_start ) )^ );
+
+ if yp < hm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ pix:=src_pix_ptr^;
+
+ inc(yp );
+
+ end;
+
+ int8u_ptr(stack.array_operator(stack_start ) )^:=pix;
+
+ inc(sum_in ,pix );
+ inc(sum ,sum_in );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix:=int8u_ptr(stack.array_operator(stack_ptr ) )^;
+
+ inc(sum_out ,stack_pix );
+ dec(sum_in ,stack_pix );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;
+
+ stack.Destruct;
+
+end;
+
+{ STACK_BLUR_RGB24 }
+procedure stack_blur_rgb24(img : pixel_formats_ptr; rx ,ry : unsigned );
+var
+ R ,G ,B ,stride : int;
+
+ x ,y ,xp ,yp ,i ,stack_ptr ,stack_start ,
+
+ sum_r ,sum_g ,sum_b ,
+
+ sum_in_r ,sum_in_g ,sum_in_b ,
+
+ sum_out_r ,sum_out_g ,sum_out_b ,
+
+ w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
+
+ src_pix_ptr ,dst_pix_ptr : int8u_ptr;
+
+ stack_pix_ptr : aggclr_ptr;
+
+ stack : pod_array;
+
+begin
+ R:=img.m_order.R;
+ G:=img.m_order.G;
+ B:=img.m_order.B;
+
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+ hm:=h - 1;
+
+ stack.Construct(sizeof(aggclr ) );
+
+ if rx > 0 then
+ begin
+ if rx > 254 then
+ rx:=254;
+
+ div_ :=rx * 2 + 1;
+ mul_sum:=g_stack_blur8_mul[rx ];
+ shr_sum:=g_stack_blur8_shr[rx ];
+
+ stack.allocate(div_ );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+
+ src_pix_ptr:=img.pix_ptr(0 ,y );
+
+ i:=0;
+
+ while i <= rx do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= rx do
+ begin
+ if i <= wm then
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+
+ stack_pix_ptr:=stack.array_operator(i + rx );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (rx + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (rx + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (rx + 1 - i ) );
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=rx;
+ xp :=rx;
+
+ if xp > wm then
+ xp:=wm;
+
+ src_pix_ptr:=img.pix_ptr(xp ,y );
+ dst_pix_ptr:=img.pix_ptr(0 ,y );
+
+ x:=0;
+
+ while x < w do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,img.m_pix_width );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+
+ stack_start:=stack_ptr + div_ - rx;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+
+ if xp < wm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+ inc(xp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+
+ inc(x );
+
+ end;
+
+ inc(y );
+
+ end;
+
+ end;
+
+ if ry > 0 then
+ begin
+ if ry > 254 then
+ ry:=254;
+
+ div_:=ry * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[ry ];
+ shr_sum:=g_stack_blur8_shr[ry ];
+
+ stack.allocate(div_ );
+
+ stride:=img._stride;
+
+ x:=0;
+
+ while x < w do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+
+ src_pix_ptr:=img.pix_ptr(x ,0 );
+
+ i:=0;
+
+ while i <= ry do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= ry do
+ begin
+ if i <= hm then
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ stack_pix_ptr:=stack.array_operator(i + ry );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (ry + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (ry + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (ry + 1 - i ) );
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=ry;
+ yp :=ry;
+
+ if yp > hm then
+ yp:=hm;
+
+ src_pix_ptr:=img.pix_ptr(x ,yp );
+ dst_pix_ptr:=img.pix_ptr(x ,0 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,stride );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+
+ stack_start:=stack_ptr + div_ - ry;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+
+ if yp < hm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ inc(yp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;
+
+ stack.Destruct;
+
+end;
+
+{ STACK_BLUR_RGBA32 }
+procedure stack_blur_rgba32(img : pixel_formats_ptr; rx ,ry : unsigned );
+var
+ R ,G ,B ,A ,stride : int;
+
+ x ,y ,xp ,yp ,i ,stack_ptr ,stack_start ,
+
+ sum_r ,sum_g ,sum_b ,sum_a ,
+
+ sum_in_r ,sum_in_g ,sum_in_b ,sum_in_a ,
+
+ sum_out_r ,sum_out_g ,sum_out_b ,sum_out_a ,
+
+ w ,h ,wm ,hm ,div_ ,mul_sum ,shr_sum : unsigned;
+
+ src_pix_ptr ,dst_pix_ptr : int8u_ptr;
+
+ stack_pix_ptr : aggclr_ptr;
+
+ stack : pod_array;
+
+begin
+ R:=img.m_order.R;
+ G:=img.m_order.G;
+ B:=img.m_order.B;
+ A:=img.m_order.A;
+
+ w :=img._width;
+ h :=img._height;
+ wm:=w - 1;
+ hm:=h - 1;
+
+ stack.Construct(sizeof(aggclr ) );
+
+ if rx > 0 then
+ begin
+ if rx > 254 then
+ rx:=254;
+
+ div_ :=rx * 2 + 1;
+ mul_sum:=g_stack_blur8_mul[rx ];
+ shr_sum:=g_stack_blur8_shr[rx ];
+
+ stack.allocate(div_ );
+
+ y:=0;
+
+ while y < h do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_a :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_in_a :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+ sum_out_a:=0;
+
+ src_pix_ptr:=img.pix_ptr(0 ,y );
+
+ i:=0;
+
+ while i <= rx do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (i + 1 ) );
+
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_out_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= rx do
+ begin
+ if i <= wm then
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+
+ stack_pix_ptr:=stack.array_operator(i + rx );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (rx + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (rx + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (rx + 1 - i ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (rx + 1 - i ) );
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=rx;
+ xp :=rx;
+
+ if xp > wm then
+ xp:=wm;
+
+ src_pix_ptr:=img.pix_ptr(xp ,y );
+ dst_pix_ptr:=img.pix_ptr(0 ,y );
+
+ x:=0;
+
+ while x < w do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + A )^:=int8u((sum_a * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,img.m_pix_width );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+ dec(sum_a ,sum_out_a );
+
+ stack_start:=stack_ptr + div_ - rx;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_out_a ,stack_pix_ptr.a );
+
+ if xp < wm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,img.m_pix_width );
+ inc(xp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+ inc(sum_a ,sum_in_a );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ inc(sum_out_a ,stack_pix_ptr.a );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+ dec(sum_in_a ,stack_pix_ptr.a );
+
+ inc(x );
+
+ end;
+
+ inc(y );
+
+ end;
+
+ end;
+
+ if ry > 0 then
+ begin
+ if ry > 254 then
+ ry:=254;
+
+ div_:=ry * 2 + 1;
+
+ mul_sum:=g_stack_blur8_mul[ry ];
+ shr_sum:=g_stack_blur8_shr[ry ];
+
+ stack.allocate(div_ );
+
+ stride:=img._stride;
+
+ x:=0;
+
+ while x < w do
+ begin
+ sum_r :=0;
+ sum_g :=0;
+ sum_b :=0;
+ sum_a :=0;
+ sum_in_r :=0;
+ sum_in_g :=0;
+ sum_in_b :=0;
+ sum_in_a :=0;
+ sum_out_r:=0;
+ sum_out_g:=0;
+ sum_out_b:=0;
+ sum_out_a:=0;
+
+ src_pix_ptr:=img.pix_ptr(x ,0 );
+
+ i:=0;
+
+ while i <= ry do
+ begin
+ stack_pix_ptr:=stack.array_operator(i );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (i + 1 ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (i + 1 ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (i + 1 ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (i + 1 ) );
+ inc(sum_out_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_out_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_out_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_out_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ i:=1;
+
+ while i <= ry do
+ begin
+ if i <= hm then
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ stack_pix_ptr:=stack.array_operator(i + ry );
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ * (ry + 1 - i ) );
+ inc(sum_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ * (ry + 1 - i ) );
+ inc(sum_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ * (ry + 1 - i ) );
+ inc(sum_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ * (ry + 1 - i ) );
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+
+ inc(i );
+
+ end;
+
+ stack_ptr:=ry;
+ yp :=ry;
+
+ if yp > hm then
+ yp:=hm;
+
+ src_pix_ptr:=img.pix_ptr(x ,yp );
+ dst_pix_ptr:=img.pix_ptr(x ,0 );
+
+ y:=0;
+
+ while y < h do
+ begin
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + R )^:=int8u((sum_r * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + G )^:=int8u((sum_g * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + B )^:=int8u((sum_b * mul_sum ) shr shr_sum );
+ int8u_ptr(ptrcomp(dst_pix_ptr ) + A )^:=int8u((sum_a * mul_sum ) shr shr_sum );
+
+ inc(ptrcomp(dst_pix_ptr ) ,stride );
+
+ dec(sum_r ,sum_out_r );
+ dec(sum_g ,sum_out_g );
+ dec(sum_b ,sum_out_b );
+ dec(sum_a ,sum_out_a );
+
+ stack_start:=stack_ptr + div_ - ry;
+
+ if stack_start >= div_ then
+ dec(stack_start ,div_ );
+
+ stack_pix_ptr:=stack.array_operator(stack_start );
+
+ dec(sum_out_r ,stack_pix_ptr.r );
+ dec(sum_out_g ,stack_pix_ptr.g );
+ dec(sum_out_b ,stack_pix_ptr.b );
+ dec(sum_out_a ,stack_pix_ptr.a );
+
+ if yp < hm then
+ begin
+ inc(ptrcomp(src_pix_ptr ) ,stride );
+
+ inc(yp );
+
+ end;
+
+ stack_pix_ptr.r:=int8u_ptr(ptrcomp(src_pix_ptr ) + R )^;
+ stack_pix_ptr.g:=int8u_ptr(ptrcomp(src_pix_ptr ) + G )^;
+ stack_pix_ptr.b:=int8u_ptr(ptrcomp(src_pix_ptr ) + B )^;
+ stack_pix_ptr.a:=int8u_ptr(ptrcomp(src_pix_ptr ) + A )^;
+
+ inc(sum_in_r ,int8u_ptr(ptrcomp(src_pix_ptr ) + R )^ );
+ inc(sum_in_g ,int8u_ptr(ptrcomp(src_pix_ptr ) + G )^ );
+ inc(sum_in_b ,int8u_ptr(ptrcomp(src_pix_ptr ) + B )^ );
+ inc(sum_in_a ,int8u_ptr(ptrcomp(src_pix_ptr ) + A )^ );
+ inc(sum_r ,sum_in_r );
+ inc(sum_g ,sum_in_g );
+ inc(sum_b ,sum_in_b );
+ inc(sum_a ,sum_in_a );
+
+ inc(stack_ptr );
+
+ if stack_ptr >= div_ then
+ stack_ptr:=0;
+
+ stack_pix_ptr:=stack.array_operator(stack_ptr );
+
+ inc(sum_out_r ,stack_pix_ptr.r );
+ inc(sum_out_g ,stack_pix_ptr.g );
+ inc(sum_out_b ,stack_pix_ptr.b );
+ inc(sum_out_a ,stack_pix_ptr.a );
+ dec(sum_in_r ,stack_pix_ptr.r );
+ dec(sum_in_g ,stack_pix_ptr.g );
+ dec(sum_in_b ,stack_pix_ptr.b );
+ dec(sum_in_a ,stack_pix_ptr.a );
+
+ inc(y );
+
+ end;
+
+ inc(x );
+
+ end;
+
+ end;
+
+ stack.Destruct;
+
+end;
+
+END.
+