lazarus/components/aggpas/src/agg_span_image_resample_gray.pas
mattias 36a2b1ea07 added aggpas
git-svn-id: trunk@21942 -
2009-10-01 12:24:32 +00:00

446 lines
10 KiB
ObjectPascal

//----------------------------------------------------------------------------
// 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
//
// [Pascal Port History] -----------------------------------------------------
//
// 23.06.2006-Milano: ptrcomp adjustments
// 05.03.2006-Milano: Unit port establishment
//
{ agg_span_image_resample_gray.pas }
unit
agg_span_image_resample_gray ;
INTERFACE
{$I agg_mode.inc }
uses
agg_basics ,
agg_color ,
agg_span_image_resample ,
agg_span_interpolator_linear ,
agg_rendering_buffer ,
agg_span_allocator ,
agg_image_filters ;
{ TYPES DEFINITION }
const
base_shift = agg_color.base_shift;
base_mask = agg_color.base_mask;
downscale_shift = image_filter_shift;
type
span_image_resample_gray_affine_ptr = ^span_image_resample_gray_affine;
span_image_resample_gray_affine = object(span_image_resample_affine )
constructor Construct(alloc : span_allocator_ptr ); overload;
constructor Construct(
alloc : span_allocator_ptr;
src : rendering_buffer_ptr;
back_color : aggclr_ptr;
interpolator : span_interpolator_ptr;
filter : image_filter_lut_ptr ); overload;
function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
end;
span_image_resample_gray_ptr = ^span_image_resample_gray;
span_image_resample_gray = object(span_image_resample )
constructor Construct(alloc : span_allocator_ptr ); overload;
constructor Construct(
alloc : span_allocator_ptr;
src : rendering_buffer_ptr;
back_color : aggclr_ptr;
interpolator : span_interpolator_ptr;
filter : image_filter_lut_ptr ); overload;
function generate(x ,y : int; len : unsigned ) : aggclr_ptr; virtual;
end;
{ GLOBAL PROCEDURES }
IMPLEMENTATION
{ LOCAL VARIABLES & CONSTANTS }
{ UNIT IMPLEMENTATION }
{ CONSTRUCT }
constructor span_image_resample_gray_affine.Construct(alloc : span_allocator_ptr );
begin
inherited Construct(alloc );
end;
{ CONSTRUCT }
constructor span_image_resample_gray_affine.Construct(
alloc : span_allocator_ptr;
src : rendering_buffer_ptr;
back_color : aggclr_ptr;
interpolator : span_interpolator_ptr;
filter : image_filter_lut_ptr );
begin
inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
end;
{ GENERATE }
function span_image_resample_gray_affine.generate;
var
fg ,src_alpha ,diameter ,filter_size ,radius_x ,radius_y ,maxx ,maxy ,
y_lr ,y_hr ,total_weight ,x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
back_v ,back_a : int8u;
span : aggclr_ptr;
fg_ptr : int8u_ptr;
weight_array : int16_ptr;
begin
_interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
back_v:=_background_color.v;
back_a:=_background_color.a;
span:=_allocator.span;
diameter :=_filter.diameter;
filter_size:=diameter shl image_subpixel_shift;
radius_x:=shr_int32(diameter * m_rx ,1 );
radius_y:=shr_int32(diameter * m_ry ,1 );
maxx:=_source_image._width - 1;
maxy:=_source_image._height - 1;
weight_array:=_filter.weight_array;
repeat
_interpolator.coordinates(@x ,@y );
inc(x ,filter_dx_int - radius_x );
inc(y ,filter_dy_int - radius_y );
fg :=image_filter_size div 2;
src_alpha:=fg;
y_lr:=shr_int32(y ,image_subpixel_shift );
y_hr:=
shr_int32(
(image_subpixel_mask - (y and image_subpixel_mask ) ) *
m_ry_inv ,image_subpixel_shift );
total_weight:=0;
x_lr_ini:=shr_int32(x ,image_subpixel_shift );
x_hr_ini:=
shr_int32(
(image_subpixel_mask - (x and image_subpixel_mask ) ) *
m_rx_inv ,image_subpixel_shift );
repeat
weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
x_lr:=x_lr_ini;
x_hr:=x_hr_ini;
if (y_lr >= 0 ) and
(y_lr <= maxy ) then
begin
fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
repeat
weight:=
shr_int32(
weight_y *
int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
image_filter_size div 2 ,downscale_shift );
if (x_lr >= 0 ) and
(x_lr <= maxx ) then
begin
inc(fg ,fg_ptr^ * weight );
inc(src_alpha ,base_mask * weight );
end
else
begin
inc(fg ,back_v * weight );
inc(src_alpha ,back_a * weight );
end;
inc(total_weight ,weight );
inc(x_hr ,m_rx_inv );
inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
inc(x_lr );
until x_hr >= filter_size;
end
else
repeat
weight:=
shr_int32(
weight_y *
int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
image_filter_size div 2 ,downscale_shift );
inc(total_weight ,weight );
inc(fg ,back_v * weight );
inc(src_alpha ,back_a * weight );
inc(x_hr ,m_rx_inv );
until x_hr >= filter_size;
inc(y_hr ,m_ry_inv );
inc(y_lr );
until y_hr >= filter_size;
fg :=fg div total_weight;
src_alpha:=src_alpha div total_weight;
if fg < 0 then
fg:=0;
if src_alpha < 0 then
src_alpha:=0;
if src_alpha > base_mask then
src_alpha:=base_mask;
if fg > src_alpha then
fg:=src_alpha;
span.v:=int8u(fg );
span.a:=int8u(src_alpha );
inc(ptrcomp(span ) ,sizeof(aggclr ) );
_interpolator.inc_operator;
dec(len );
until len = 0;
result:=_allocator.span;
end;
{ CONSTRUCT }
constructor span_image_resample_gray.Construct(alloc : span_allocator_ptr );
begin
inherited Construct(alloc );
end;
{ CONSTRUCT }
constructor span_image_resample_gray.Construct(
alloc : span_allocator_ptr;
src : rendering_buffer_ptr;
back_color : aggclr_ptr;
interpolator : span_interpolator_ptr;
filter : image_filter_lut_ptr );
begin
inherited Construct(alloc ,src ,back_color ,interpolator ,filter );
end;
{ GENERATE }
function span_image_resample_gray.generate;
var
span : aggclr_ptr;
fg ,src_alpha ,diameter ,filter_size ,rx ,ry ,rx_inv ,ry_inv ,
radius_x ,radius_y ,maxx ,maxy ,y_lr ,y_hr ,total_weight ,
x_lr_ini ,x_hr_ini ,weight_y ,x_lr ,x_hr ,weight : int;
back_v ,back_a : int8u;
weight_array : int16_ptr;
fg_ptr : int8u_ptr;
begin
span:=_allocator.span;
_interpolator.begin_(x + filter_dx_dbl ,y + filter_dy_dbl ,len );
back_v:=_background_color.v;
back_a:=_background_color.a;
diameter :=_filter.diameter;
filter_size:=diameter shl image_subpixel_shift;
weight_array:=_filter.weight_array;
repeat
rx_inv:=image_subpixel_size;
ry_inv:=image_subpixel_size;
_interpolator.coordinates(@x ,@y );
_interpolator.local_scale(@rx ,@ry );
rx:=shr_int32(rx * m_blur_x ,image_subpixel_shift );
ry:=shr_int32(ry * m_blur_y ,image_subpixel_shift );
if rx < image_subpixel_size then
rx:=image_subpixel_size
else
begin
if rx > image_subpixel_size * m_scale_limit then
rx:=image_subpixel_size * m_scale_limit;
rx_inv:=image_subpixel_size * image_subpixel_size div rx;
end;
if ry < image_subpixel_size then
ry:=image_subpixel_size
else
begin
if ry > image_subpixel_size * m_scale_limit then
ry:=image_subpixel_size * m_scale_limit;
ry_inv:=image_subpixel_size * image_subpixel_size div ry;
end;
radius_x:=shr_int32(diameter * rx ,1 );
radius_y:=shr_int32(diameter * ry ,1 );
maxx:=_source_image._width - 1;
maxy:=_source_image._height - 1;
inc(x ,filter_dx_int - radius_x );
inc(y ,filter_dy_int - radius_y );
fg :=image_filter_size div 2;
src_alpha:=fg;
y_lr:=shr_int32(y ,image_subpixel_shift );
y_hr:=
shr_int32(
(image_subpixel_mask - (y and image_subpixel_mask ) ) *
ry_inv ,image_subpixel_shift );
total_weight:=0;
x_lr_ini:=shr_int32(x ,image_subpixel_shift );
x_hr_ini:=
shr_int32(
(image_subpixel_mask - (x and image_subpixel_mask ) ) *
rx_inv ,image_subpixel_shift );
repeat
weight_y:=int16_ptr(ptrcomp(weight_array ) + y_hr * sizeof(int16 ) )^;
x_lr:=x_lr_ini;
x_hr:=x_hr_ini;
if (y_lr >= 0 ) and
(y_lr <= maxy ) then
begin
fg_ptr:=int8u_ptr(ptrcomp(_source_image.row(y_lr ) ) + x_lr * sizeof(int8u ) );
repeat
weight:=
shr_int32(
weight_y *
int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
image_filter_size div 2 ,downscale_shift );
if (x_lr >= 0 ) and
(x_lr <= maxx ) then
begin
inc(fg ,fg_ptr^ * weight );
inc(src_alpha ,base_mask * weight );
end
else
begin
inc(fg ,back_v * weight );
inc(src_alpha ,back_a * weight );
end;
inc(total_weight ,weight );
inc(x_hr ,rx_inv );
inc(ptrcomp(fg_ptr ) ,sizeof(int8u ) );
inc(x_lr );
until x_hr >= filter_size;
end
else
repeat
weight:=
shr_int32(
weight_y *
int16_ptr(ptrcomp(weight_array ) + x_hr * sizeof(int16 ) )^ +
image_filter_size div 2 ,downscale_shift );
inc(total_weight ,weight );
inc(fg ,back_v * weight );
inc(src_alpha ,back_a * weight );
inc(x_hr ,rx_inv );
until x_hr >= filter_size;
inc(y_hr ,ry_inv );
inc(y_lr );
until y_hr >= filter_size;
fg :=fg div total_weight;
src_alpha:=src_alpha div total_weight;
if fg < 0 then
fg:=0;
if src_alpha < 0 then
src_alpha:=0;
if src_alpha > base_mask then
src_alpha:=base_mask;
if fg > src_alpha then
fg:=src_alpha;
span.v:=int8u(fg );
span.a:=int8u(src_alpha );
inc(ptrcomp(span ) ,sizeof(aggclr ) );
_interpolator.inc_operator;
dec(len );
until len = 0;
result:=_allocator.span;
end;
END.