1
//----------------------------------------------------------------------------
2
// Anti-Grain Geometry - Version 2.4 (Public License)
3
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
5
// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
6
// Pascal Port By: Milan Marusinec alias Milano
8
// http://www.aggpas.org
9
// Copyright (c) 2005-2006
11
// Permission to copy, use, modify, sell and distribute this software
12
// is granted provided this copyright notice appears in all copies.
13
// This software is provided "as is" without express or implied
14
// warranty, and with no claim as to its suitability for any purpose.
16
//----------------------------------------------------------------------------
17
// Contact: mcseem@antigrain.com
18
// mcseemagg@yahoo.com
19
// http://www.antigrain.com
21
//----------------------------------------------------------------------------
23
// Image transformation filters,
24
// Filtering classes (image_filter_lut, image_filter),
25
// Basic filter shape classes
27
// [Pascal Port History] -----------------------------------------------------
29
// 23.06.2006-Milano: ptrcomp adjustments
30
// 01.03.2006-Milano: Unit port establishment
32
{ agg_image_filters.pas }
48
image_filter_shift = 14; //----image_filter_shift
49
image_filter_size = 1 shl image_filter_shift; //----image_filter_size
50
image_filter_mask = image_filter_size - 1; //----image_filter_mask
52
image_subpixel_shift = 8; //----image_subpixel_shift
53
image_subpixel_size = 1 shl image_subpixel_shift; //----image_subpixel_size
54
image_subpixel_mask = image_subpixel_size - 1; //----image_subpixel_mask
57
image_filter_base_ptr = ^image_filter_base;
58
image_filter_base = object
59
constructor Construct;
61
function radius : double; virtual; abstract;
62
function calc_weight(x : double ) : double; virtual; abstract;
64
procedure set_radius(r : double ); virtual;
68
image_filter_lut_ptr = ^image_filter_lut;
69
image_filter_lut = object
71
m_diameter : unsigned;
74
m_weight_array : int16_ptr;
75
m_max_size : unsigned;
77
constructor Construct; overload;
78
constructor Construct(filter : image_filter_base_ptr; normalization : boolean = true ); overload;
81
procedure calculate(filter : image_filter_base_ptr; normalization : boolean = true );
83
function radius : double;
84
function diameter : unsigned;
86
function weight_array : int16_ptr;
89
procedure realloc_lut(radius_ : double );
93
image_filter_ptr = ^image_filter;
94
image_filter = object(image_filter_lut )
95
m_filter_function : image_filter_base_ptr;
97
constructor Construct(filter : image_filter_base_ptr );
101
image_filter_bilinear_ptr = ^image_filter_bilinear;
102
image_filter_bilinear = object(image_filter_base )
103
function radius : double; virtual;
104
function calc_weight(x : double ) : double; virtual;
108
image_filter_hanning_ptr = ^image_filter_hanning;
109
image_filter_hanning = object(image_filter_base )
110
function radius : double; virtual;
111
function calc_weight(x : double ) : double; virtual;
115
image_filter_hamming_ptr = ^image_filter_hamming;
116
image_filter_hamming = object(image_filter_base )
117
function radius : double; virtual;
118
function calc_weight(x : double ) : double; virtual;
122
image_filter_hermite_ptr = ^image_filter_hermite;
123
image_filter_hermite = object(image_filter_base )
124
function radius : double; virtual;
125
function calc_weight(x : double ) : double; virtual;
129
image_filter_quadric_ptr = ^image_filter_quadric;
130
image_filter_quadric = object(image_filter_base )
131
function radius : double; virtual;
132
function calc_weight(x : double ) : double; virtual;
136
image_filter_bicubic_ptr = ^image_filter_bicubic;
137
image_filter_bicubic = object(image_filter_base )
138
function pow3(x : double ) : double;
140
function radius : double; virtual;
141
function calc_weight(x : double ) : double; virtual;
145
image_filter_kaiser_ptr = ^image_filter_kaiser;
146
image_filter_kaiser = object(image_filter_base )
147
a ,i0a ,epsilon : double;
149
constructor Construct(b : double = 6.33 );
151
function radius : double; virtual;
152
function calc_weight(x : double ) : double; virtual;
154
function bessel_i0(x : double ) : double;
158
image_filter_catrom_ptr = ^image_filter_catrom;
159
image_filter_catrom = object(image_filter_base )
160
function radius : double; virtual;
161
function calc_weight(x : double ) : double; virtual;
165
image_filter_mitchell_ptr = ^image_filter_mitchell;
166
image_filter_mitchell = object(image_filter_base )
168
q0 ,q1 ,q2 ,q3 : double;
170
constructor Construct(b : double = 1.0 / 3.0; c : double = 1.0 / 3.0 );
172
function radius : double; virtual;
173
function calc_weight(x : double ) : double; virtual;
177
image_filter_spline16_ptr = ^image_filter_spline16;
178
image_filter_spline16 = object(image_filter_base )
179
function radius : double; virtual;
180
function calc_weight(x : double ) : double; virtual;
184
image_filter_spline36_ptr = ^image_filter_spline36;
185
image_filter_spline36 = object(image_filter_base )
186
function radius : double; virtual;
187
function calc_weight(x : double ) : double; virtual;
191
image_filter_gaussian_ptr = ^image_filter_gaussian;
192
image_filter_gaussian = object(image_filter_base )
193
function radius : double; virtual;
194
function calc_weight(x : double ) : double; virtual;
198
image_filter_bessel_ptr = ^image_filter_bessel;
199
image_filter_bessel = object(image_filter_base )
200
function radius : double; virtual;
201
function calc_weight(x : double ) : double; virtual;
205
image_filter_sinc_ptr = ^image_filter_sinc;
206
image_filter_sinc = object(image_filter_base )
209
constructor Construct(r : double );
211
function radius : double; virtual;
212
function calc_weight(x : double ) : double; virtual;
214
procedure set_radius(r : double ); virtual;
218
image_filter_lanczos_ptr = ^image_filter_lanczos;
219
image_filter_lanczos = object(image_filter_base )
222
constructor Construct(r : double );
224
function radius : double; virtual;
225
function calc_weight(x : double ) : double; virtual;
227
procedure set_radius(r : double ); virtual;
231
image_filter_blackman_ptr = ^image_filter_blackman;
232
image_filter_blackman = object(image_filter_base )
235
constructor Construct(r : double );
237
function radius : double; virtual;
238
function calc_weight(x : double ) : double; virtual;
240
procedure set_radius(r : double ); virtual;
244
image_filter_sinc36_ptr = ^image_filter_sinc36;
245
image_filter_sinc36 = object(image_filter_sinc )
246
constructor Construct;
250
image_filter_sinc64_ptr = ^image_filter_sinc64;
251
image_filter_sinc64 = object(image_filter_sinc )
252
constructor Construct;
256
image_filter_sinc100_ptr = ^image_filter_sinc100;
257
image_filter_sinc100 = object(image_filter_sinc )
258
constructor Construct;
262
image_filter_sinc144_ptr = ^image_filter_sinc144;
263
image_filter_sinc144 = object(image_filter_sinc )
264
constructor Construct;
268
image_filter_sinc196_ptr = ^image_filter_sinc196;
269
image_filter_sinc196 = object(image_filter_sinc )
270
constructor Construct;
274
image_filter_sinc256_ptr = ^image_filter_sinc256;
275
image_filter_sinc256 = object(image_filter_sinc )
276
constructor Construct;
280
image_filter_lanczos36_ptr = ^image_filter_lanczos36;
281
image_filter_lanczos36 = object(image_filter_lanczos )
282
constructor Construct;
286
image_filter_lanczos64_ptr = ^image_filter_lanczos64;
287
image_filter_lanczos64 = object(image_filter_lanczos )
288
constructor Construct;
292
image_filter_lanczos100_ptr = ^image_filter_lanczos100;
293
image_filter_lanczos100 = object(image_filter_lanczos )
294
constructor Construct;
298
image_filter_lanczos144_ptr = ^image_filter_lanczos144;
299
image_filter_lanczos144 = object(image_filter_lanczos )
300
constructor Construct;
304
image_filter_lanczos196_ptr = ^image_filter_lanczos196;
305
image_filter_lanczos196 = object(image_filter_lanczos )
306
constructor Construct;
310
image_filter_lanczos256_ptr = ^image_filter_lanczos256;
311
image_filter_lanczos256 = object(image_filter_lanczos )
312
constructor Construct;
316
image_filter_blackman36_ptr = ^image_filter_blackman36;
317
image_filter_blackman36 = object(image_filter_blackman )
318
constructor Construct;
322
image_filter_blackman64_ptr = ^image_filter_blackman64;
323
image_filter_blackman64 = object(image_filter_blackman )
324
constructor Construct;
328
image_filter_blackman100_ptr = ^image_filter_blackman100;
329
image_filter_blackman100 = object(image_filter_blackman )
330
constructor Construct;
334
image_filter_blackman144_ptr = ^image_filter_blackman144;
335
image_filter_blackman144 = object(image_filter_blackman )
336
constructor Construct;
340
image_filter_blackman196_ptr = ^image_filter_blackman196;
341
image_filter_blackman196 = object(image_filter_blackman )
342
constructor Construct;
346
image_filter_blackman256_ptr = ^image_filter_blackman256;
347
image_filter_blackman256 = object(image_filter_blackman )
348
constructor Construct;
352
{ GLOBAL PROCEDURES }
356
{ LOCAL VARIABLES & CONSTANTS }
357
{ UNIT IMPLEMENTATION }
359
constructor image_filter_base.Construct;
364
procedure image_filter_base.set_radius;
369
constructor image_filter_lut.Construct;
377
constructor image_filter_lut.Construct(filter : image_filter_base_ptr; normalization : boolean = true );
382
calculate(filter ,normalization );
387
destructor image_filter_lut.Destruct;
389
agg_freemem(pointer(m_weight_array ) ,m_max_size * sizeof(int16 ) );
394
procedure image_filter_lut.calculate;
398
i ,pivot ,end_ : unsigned;
405
pivot:=diameter shl (image_subpixel_shift - 1 );
411
x:=i / image_subpixel_size;
412
y:=filter.calc_weight(x );
414
int16_ptr(ptrcomp(m_weight_array ) + (pivot + i ) * sizeof(int16 ) )^:=
415
int16(trunc(y * image_filter_size + 0.5 ) );
417
int16_ptr(ptrcomp(m_weight_array ) + (pivot - i ) * sizeof(int16 ) )^:=
418
int16_ptr(ptrcomp(m_weight_array ) + (pivot + i ) * sizeof(int16 ) )^;
424
end_:=(diameter shl image_subpixel_shift ) - 1;
426
int16_ptr(ptrcomp(m_weight_array ) + 0 * sizeof(int16 ) )^:=
427
int16_ptr(ptrcomp(m_weight_array ) + end_ * sizeof(int16 ) )^;
429
if normalization then
435
function image_filter_lut.radius;
442
function image_filter_lut.diameter;
449
function image_filter_lut.start;
456
function image_filter_lut.weight_array;
458
result:=m_weight_array;
463
// This function normalizes integer values and corrects the rounding
464
// errors. It doesn't do anything with the source floating point values
465
// (m_weight_array_dbl), it corrects only integers according to the rule
466
// of 1.0 which means that any sum of pixel weights must be equal to 1.0.
467
// So, the filter function must produce a graph of the proper shape.
468
procedure image_filter_lut.normalize;
472
i ,j ,idx ,pivot ,end_ : unsigned;
474
flip ,sum ,inc_ ,v : int;
480
while i < image_subpixel_size do
485
for j:=0 to m_diameter - 1 do
488
int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^ );
490
if sum = image_filter_size then
493
k :=image_filter_size / sum;
496
for j:=0 to m_diameter - 1 do
498
int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^:=
499
int16(trunc(int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^ * k ) );
501
inc(sum ,int16_ptr(ptrcomp(m_weight_array ) + (j * image_subpixel_size + i ) * sizeof(int16 ) )^ );
505
dec(sum ,image_filter_size );
514
while (j < m_diameter ) and
520
idx:=m_diameter div 2 + j div 2
522
idx:=m_diameter div 2 - j div 2;
524
v:=int16_ptr(ptrcomp(m_weight_array ) + (idx * image_subpixel_size + i ) * sizeof(int16 ) )^;
526
if v < image_filter_size then
529
int16_ptr(ptrcomp(m_weight_array ) + (idx * image_subpixel_size + i ) * sizeof(int16 ) )^ ,
546
pivot:=m_diameter shl (image_subpixel_shift - 1 );
548
for i:=0 to pivot - 1 do
549
int16_ptr(ptrcomp(m_weight_array ) + (pivot + i ) * sizeof(int16 ) )^:=
550
int16_ptr(ptrcomp(m_weight_array ) + (pivot - i ) * sizeof(int16 ) )^;
552
end_:=(diameter shl image_subpixel_shift ) - 1;
554
int16_ptr(ptrcomp(m_weight_array ) + 0 * sizeof(int16 ) )^:=
555
int16_ptr(ptrcomp(m_weight_array ) + end_ * sizeof(int16 ) )^;
560
procedure image_filter_lut.realloc_lut;
566
m_diameter:=unsigned(trunc(Ceil(radius_ ) ) ) * 2 ;
567
m_start :=-int(m_diameter div 2 - 1 );
569
size:=m_diameter shl image_subpixel_shift;
571
if size > m_max_size then
573
agg_freemem(pointer(m_weight_array ) ,m_max_size * sizeof(int16 ) );
574
agg_getmem (pointer(m_weight_array ) ,size * sizeof(int16 ) );
583
constructor image_filter.Construct;
587
m_filter_function:=filter;
589
calculate(m_filter_function );
594
function image_filter_bilinear.radius;
600
function image_filter_bilinear.calc_weight;
607
function image_filter_hanning.radius;
614
function image_filter_hanning.calc_weight;
616
result:=0.5 + 0.5 * Cos(pi * x );
621
function image_filter_hamming.radius;
628
function image_filter_hamming.calc_weight;
630
result:=0.54 + 0.46 * Cos(pi * x );
635
function image_filter_hermite.radius;
642
function image_filter_hermite.calc_weight;
644
result:=(2.0 * x - 3.0 ) * x * x + 1.0;
649
function image_filter_quadric.radius;
656
function image_filter_quadric.calc_weight;
677
function image_filter_bicubic.pow3;
687
function image_filter_bicubic.radius;
694
function image_filter_bicubic.calc_weight;
698
(pow3(x + 2 ) - 4 * pow3(x + 1 ) + 6 * pow3(x ) - 4 * pow3(x - 1 ) );
703
constructor image_filter_kaiser.Construct;
709
i0a:=1.0 / bessel_i0(b );
714
function image_filter_kaiser.radius;
721
function image_filter_kaiser.calc_weight;
723
result:=bessel_i0(a * Sqrt(1.0 - x * x ) ) * i0a;
728
function image_filter_kaiser.bessel_i0;
745
t:=t * (y / (i * i ) );
756
function image_filter_catrom.radius;
763
function image_filter_catrom.calc_weight;
766
result:=0.5 * (2.0 + x * x * (-5.0 + x * 3.0 ) )
769
result:=0.5 * (4.0 + x * (-8.0 + x * (5.0 - x ) ) )
776
constructor image_filter_mitchell.Construct;
778
p0:=(6.0 - 2.0 * b ) / 6.0;
779
p2:=(-18.0 + 12.0 * b + 6.0 * c ) / 6.0;
780
p3:=(12.0 - 9.0 * b - 6.0 * c ) / 6.0;
781
q0:=(8.0 * b + 24.0 * c ) / 6.0;
782
q1:=(-12.0 * b - 48.0 * c ) / 6.0;
783
q2:=(6.0 * b + 30.0 * c ) / 6.0;
784
q3:=(-b - 6.0 * c ) / 6.0;
789
function image_filter_mitchell.radius;
796
function image_filter_mitchell.calc_weight;
799
result:=p0 + x * x * (p2 + x * p3 )
802
result:=q0 + x * (q1 + x * (q2 + x * q3 ) )
809
function image_filter_spline16.radius;
816
function image_filter_spline16.calc_weight;
819
result:=((x - 9.0 / 5.0 ) * x - 1.0 / 5.0 ) * x + 1.0
821
result:=((-1.0 / 3.0 * (x - 1 ) + 4.0 / 5.0) * (x - 1 ) - 7.0 / 15.0 ) * (x - 1 );
826
function image_filter_spline36.radius;
833
function image_filter_spline36.calc_weight;
836
result:=((13.0 / 11.0 * x - 453.0 / 209.0 ) * x - 3.0 / 209.0 ) * x + 1.0
839
result:=((-6.0 / 11.0 * (x - 1 ) + 270.0 / 209.0 ) * (x - 1 ) - 156.0 / 209.0 ) * (x - 1 )
841
result:=((1.0 / 11.0 * (x - 2 ) - 45.0 / 209.0 ) * (x - 2 ) + 26.0 / 209.0 ) * (x - 2 );
846
function image_filter_gaussian.radius;
853
function image_filter_gaussian.calc_weight;
855
result:=Exp(-2.0 * x * x ) * Sqrt(2.0 / pi );
860
function image_filter_bessel.radius;
867
function image_filter_bessel.calc_weight;
872
result:=besj(pi * x ,1 ) / (2.0 * x );
877
constructor image_filter_sinc.Construct;
887
function image_filter_sinc.radius;
894
function image_filter_sinc.calc_weight;
909
procedure image_filter_sinc.set_radius;
919
constructor image_filter_lanczos.Construct;
929
function image_filter_lanczos.radius;
936
function image_filter_lanczos.calc_weight;
951
result:=(Sin(x ) / x ) * (Sin(xr ) / xr );
958
procedure image_filter_lanczos.set_radius;
968
constructor image_filter_blackman.Construct;
978
function image_filter_blackman.radius;
985
function image_filter_blackman.calc_weight;
1000
result:=(Sin(x ) / x ) * (0.42 + 0.5 * Cos(xr ) + 0.08 * Cos(2 * xr ) );
1007
procedure image_filter_blackman.set_radius;
1017
constructor image_filter_sinc36.Construct;
1019
inherited Construct(3.0 );
1024
constructor image_filter_sinc64.Construct;
1026
inherited Construct(4.0 );
1031
constructor image_filter_sinc100.Construct;
1033
inherited Construct(5.0 );
1038
constructor image_filter_sinc144.Construct;
1040
inherited Construct(6.0 );
1045
constructor image_filter_sinc196.Construct;
1047
inherited Construct(7.0 );
1052
constructor image_filter_sinc256.Construct;
1054
inherited Construct(8.0 );
1059
constructor image_filter_lanczos36.Construct;
1061
inherited Construct(3.0 );
1066
constructor image_filter_lanczos64.Construct;
1068
inherited Construct(4.0 );
1073
constructor image_filter_lanczos100.Construct;
1075
inherited Construct(5.0 );
1080
constructor image_filter_lanczos144.Construct;
1082
inherited Construct(6.0 );
1087
constructor image_filter_lanczos196.Construct;
1089
inherited Construct(7.0 );
1094
constructor image_filter_lanczos256.Construct;
1096
inherited Construct(8.0 );
1101
constructor image_filter_blackman36.Construct;
1103
inherited Construct(3.0 );
1108
constructor image_filter_blackman64.Construct;
1110
inherited Construct(4.0 );
1115
constructor image_filter_blackman100.Construct;
1117
inherited Construct(5.0 );
1122
constructor image_filter_blackman144.Construct;
1124
inherited Construct(6.0 );
1129
constructor image_filter_blackman196.Construct;
1131
inherited Construct(7.0 );
1136
constructor image_filter_blackman256.Construct;
1138
inherited Construct(8.0 );