1//
2// AggPas 2.4 RM3 Demo application
3// Note: Press F1 key on run to see more info about this demo
4//
5// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
6//
7program
8 image_fltr_graph ;
9
10uses
11 Math ,
12
13 agg_basics ,
14 agg_platform_support ,
15
16 agg_color ,
17 agg_pixfmt ,
18 agg_pixfmt_rgb ,
19
20 agg_ctrl ,
21 agg_slider_ctrl ,
22 agg_rbox_ctrl ,
23 agg_cbox_ctrl ,
24
25 agg_rendering_buffer ,
26 agg_renderer_base ,
27 agg_renderer_scanline ,
28 agg_rasterizer_scanline_aa ,
29 agg_scanline ,
30 agg_scanline_u ,
31 agg_scanline_p ,
32 agg_render_scanlines ,
33
34 agg_ellipse ,
35 agg_trans_affine ,
36 agg_conv_transform ,
37 agg_conv_stroke ,
38 agg_span_allocator ,
39 agg_span_interpolator_linear ,
40 agg_span_image_filter ,
41 agg_span_image_filter_rgb ,
42 agg_image_filters ,
43 agg_path_storage ;
44
45{$I agg_mode.inc }
46
47const
48 flip_y = true;
49
50type
51 filter_adaptor_ptr = ^filter_adaptor;
52 filter_adaptor = object
53   m_filter : image_filter_base_ptr;
54
55   constructor Construct(filter : image_filter_base_ptr );
56   destructor  Destruct;
57
58   function  radius : double;
59   function  calc_weight(x : double ) : double;
60
61   procedure set_radius(r : double );
62
63  end;
64
65 the_application = object(platform_support )
66   m_radius   : slider_ctrl;
67   m_bilinear ,
68   m_bicubic  ,
69   m_spline16 ,
70   m_spline36 ,
71   m_hanning  ,
72   m_hamming  ,
73   m_hermite  ,
74   m_kaiser   ,
75   m_quadric  ,
76   m_catrom   ,
77   m_gaussian ,
78   m_bessel   ,
79   m_mitchell ,
80   m_sinc     ,
81   m_lanczos  ,
82   m_blackman : cbox_ctrl;
83
84   m_filters : array[0..31 ] of cbox_ctrl_ptr;
85
86   m_filter_bilinear ,
87   m_filter_bicubic  ,
88   m_filter_spline16 ,
89   m_filter_spline36 ,
90   m_filter_hanning  ,
91   m_filter_hamming  ,
92   m_filter_hermite  ,
93   m_filter_kaiser   ,
94   m_filter_quadric  ,
95   m_filter_catrom   ,
96   m_filter_gaussian ,
97   m_filter_bessel   ,
98   m_filter_mitchell ,
99   m_filter_sinc     ,
100   m_filter_lanczos  ,
101   m_filter_blackman : filter_adaptor;
102
103   m_filter_func : array[0..31 ] of filter_adaptor_ptr;
104   m_num_filters : unsigned;
105
106   constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
107   destructor  Destruct;
108
109   procedure on_draw; virtual;
110
111   procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
112
113  end;
114
115{ CONSTRUCT }
116constructor filter_adaptor.Construct;
117begin
118 m_filter:=filter;
119
120end;
121
122{ DESTRUCT }
123destructor filter_adaptor.Destruct;
124begin
125 if m_filter <> NIL then
126  dispose(m_filter );
127
128end;
129
130{ RADIUS }
131function filter_adaptor.radius;
132begin
133 if m_filter <> NIL then
134  result:=m_filter.radius
135 else
136  result:=0;
137
138end;
139
140{ CALC_WEIGHT }
141function filter_adaptor.calc_weight;
142begin
143 if m_filter <> NIL then
144  result:=m_filter.calc_weight(Abs(x ) )
145 else
146  result:=0;
147
148end;
149
150{ SET_RADIUS }
151procedure filter_adaptor.set_radius;
152begin
153 if m_filter <> NIL then
154  m_filter.set_radius(r );
155
156end;
157
158{ CONSTRUCT }
159constructor the_application.Construct;
160var
161 i : unsigned;
162
163begin
164 inherited Construct(format_ ,flip_y_ );
165
166 m_radius.Construct  (5.0 ,5.0 ,780 - 5 ,10.0 ,not flip_y_ );
167 m_bilinear.Construct(8.0 ,30.0 + 15 * 0  ,'bilinear' ,not flip_y_ );
168 m_bicubic.Construct (8.0 ,30.0 + 15 * 1  ,'bicubic ' ,not flip_y_ );
169 m_spline16.Construct(8.0 ,30.0 + 15 * 2  ,'spline16' ,not flip_y_ );
170 m_spline36.Construct(8.0 ,30.0 + 15 * 3  ,'spline36' ,not flip_y_ );
171 m_hanning.Construct (8.0 ,30.0 + 15 * 4  ,'hanning ' ,not flip_y_ );
172 m_hamming.Construct (8.0 ,30.0 + 15 * 5  ,'hamming ' ,not flip_y_ );
173 m_hermite.Construct (8.0 ,30.0 + 15 * 6  ,'hermite ' ,not flip_y_ );
174 m_kaiser.Construct  (8.0 ,30.0 + 15 * 7  ,'kaiser  ' ,not flip_y_ );
175 m_quadric.Construct (8.0 ,30.0 + 15 * 8  ,'quadric ' ,not flip_y_ );
176 m_catrom.Construct  (8.0 ,30.0 + 15 * 9  ,'catrom  ' ,not flip_y_ );
177 m_gaussian.Construct(8.0 ,30.0 + 15 * 10 ,'gaussian' ,not flip_y_ );
178 m_bessel.Construct  (8.0 ,30.0 + 15 * 11 ,'bessel  ' ,not flip_y_ );
179 m_mitchell.Construct(8.0 ,30.0 + 15 * 12 ,'mitchell' ,not flip_y_ );
180 m_sinc.Construct    (8.0 ,30.0 + 15 * 13 ,'sinc    ' ,not flip_y_ );
181 m_lanczos.Construct (8.0 ,30.0 + 15 * 14 ,'lanczos ' ,not flip_y_ );
182 m_blackman.Construct(8.0 ,30.0 + 15 * 15 ,'blackman' ,not flip_y_ );
183
184 m_filter_bilinear.Construct(new(image_filter_bilinear_ptr ,Construct ) );
185 m_filter_bicubic.Construct (new(image_filter_bicubic_ptr ,Construct ) );
186 m_filter_spline16.Construct(new(image_filter_spline16_ptr ,Construct ) );
187 m_filter_spline36.Construct(new(image_filter_spline36_ptr ,Construct ) );
188 m_filter_hanning.Construct (new(image_filter_hanning_ptr ,Construct ) );
189 m_filter_hamming.Construct (new(image_filter_hamming_ptr ,Construct ) );
190 m_filter_hermite.Construct (new(image_filter_hermite_ptr ,Construct ) );
191 m_filter_kaiser.Construct  (new(image_filter_kaiser_ptr ,Construct ) );
192 m_filter_quadric.Construct (new(image_filter_quadric_ptr ,Construct ) );
193 m_filter_catrom.Construct  (new(image_filter_catrom_ptr ,Construct ) );
194 m_filter_gaussian.Construct(new(image_filter_gaussian_ptr ,Construct ) );
195 m_filter_bessel.Construct  (new(image_filter_bessel_ptr ,Construct ) );
196 m_filter_mitchell.Construct(new(image_filter_mitchell_ptr ,Construct ) );
197 m_filter_sinc.Construct    (new(image_filter_sinc_ptr ,Construct(2.0 ) ) );
198 m_filter_lanczos.Construct (new(image_filter_lanczos_ptr ,Construct(2.0 ) ) );
199 m_filter_blackman.Construct(new(image_filter_blackman_ptr ,Construct(2.0 ) ) );
200
201 m_num_filters:=0;
202
203 m_filters[m_num_filters ]:=@m_bilinear; inc(m_num_filters );
204 m_filters[m_num_filters ]:=@m_bicubic;  inc(m_num_filters );
205 m_filters[m_num_filters ]:=@m_spline16; inc(m_num_filters );
206 m_filters[m_num_filters ]:=@m_spline36; inc(m_num_filters );
207 m_filters[m_num_filters ]:=@m_hanning;  inc(m_num_filters );
208 m_filters[m_num_filters ]:=@m_hamming;  inc(m_num_filters );
209 m_filters[m_num_filters ]:=@m_hermite;  inc(m_num_filters );
210 m_filters[m_num_filters ]:=@m_kaiser;   inc(m_num_filters );
211 m_filters[m_num_filters ]:=@m_quadric;  inc(m_num_filters );
212 m_filters[m_num_filters ]:=@m_catrom;   inc(m_num_filters );
213 m_filters[m_num_filters ]:=@m_gaussian; inc(m_num_filters );
214 m_filters[m_num_filters ]:=@m_bessel;   inc(m_num_filters );
215 m_filters[m_num_filters ]:=@m_mitchell; inc(m_num_filters );
216 m_filters[m_num_filters ]:=@m_sinc;     inc(m_num_filters );
217 m_filters[m_num_filters ]:=@m_lanczos;  inc(m_num_filters );
218 m_filters[m_num_filters ]:=@m_blackman; inc(m_num_filters );
219
220 i:=0;
221
222 m_filter_func[i ]:=@m_filter_bilinear; inc(i );
223 m_filter_func[i ]:=@m_filter_bicubic;  inc(i );
224 m_filter_func[i ]:=@m_filter_spline16; inc(i );
225 m_filter_func[i ]:=@m_filter_spline36; inc(i );
226 m_filter_func[i ]:=@m_filter_hanning;  inc(i );
227 m_filter_func[i ]:=@m_filter_hamming;  inc(i );
228 m_filter_func[i ]:=@m_filter_hermite;  inc(i );
229 m_filter_func[i ]:=@m_filter_kaiser;   inc(i );
230 m_filter_func[i ]:=@m_filter_quadric;  inc(i );
231 m_filter_func[i ]:=@m_filter_catrom;   inc(i );
232 m_filter_func[i ]:=@m_filter_gaussian; inc(i );
233 m_filter_func[i ]:=@m_filter_bessel;   inc(i );
234 m_filter_func[i ]:=@m_filter_mitchell; inc(i );
235 m_filter_func[i ]:=@m_filter_sinc;     inc(i );
236 m_filter_func[i ]:=@m_filter_lanczos;  inc(i );
237 m_filter_func[i ]:=@m_filter_blackman; inc(i );
238
239 for i:=0 to m_num_filters - 1 do
240  add_ctrl(m_filters[i ] );
241
242 m_radius.range_(2.0 ,8.0 );
243 m_radius.value_(4.0 );
244 m_radius.label_('Radius=%.3f' );
245
246 add_ctrl(@m_radius );
247
248end;
249
250{ DESTRUCT }
251destructor the_application.Destruct;
252begin
253 inherited Destruct;
254
255 m_radius.Destruct;
256 m_bilinear.Destruct;
257 m_bicubic.Destruct;
258 m_spline16.Destruct;
259 m_spline36.Destruct;
260 m_hanning.Destruct;
261 m_hamming.Destruct;
262 m_hermite.Destruct;
263 m_kaiser.Destruct;
264 m_quadric.Destruct;
265 m_catrom.Destruct;
266 m_gaussian.Destruct;
267 m_bessel.Destruct;
268 m_mitchell.Destruct;
269 m_sinc.Destruct;
270 m_lanczos.Destruct;
271 m_blackman.Destruct;
272
273 m_filter_bilinear.Destruct;
274 m_filter_bicubic.Destruct;
275 m_filter_spline16.Destruct;
276 m_filter_spline36.Destruct;
277 m_filter_hanning.Destruct;
278 m_filter_hamming.Destruct;
279 m_filter_hermite.Destruct;
280 m_filter_kaiser.Destruct;
281 m_filter_quadric.Destruct;
282 m_filter_catrom.Destruct;
283 m_filter_gaussian.Destruct;
284 m_filter_bessel.Destruct;
285 m_filter_mitchell.Destruct;
286 m_filter_sinc.Destruct;
287 m_filter_lanczos.Destruct;
288 m_filter_blackman.Destruct;
289
290end;
291
292{ ON_DRAW }
293procedure the_application.on_draw;
294var
295 pixf : pixel_formats;
296 rgba : aggclr;
297
298 rb : renderer_base;
299 rs : renderer_scanline_aa_solid;
300 sl : scanline_p8;
301
302 ras : rasterizer_scanline_aa;
303
304 normalized : image_filter_lut;
305 weights    : int16_ptr;
306
307 x_start ,x_end ,y_start ,y_end ,x_center ,x ,y ,ys ,radius ,dy ,xs ,dx ,sum ,xf : double;
308
309 xfract ,ir : int;
310
311 i ,j ,n ,xint ,nn : unsigned;
312
313 p  : path_storage;
314 pl : conv_stroke;
315 tr : conv_transform;
316
317begin
318// Initialize structures
319 pixfmt_bgr24(pixf ,rbuf_window );
320
321 rb.Construct(@pixf );
322 rs.Construct(@rb );
323
324 rgba.ConstrDbl(1.0 ,1.0 ,1.0 );
325 rb.clear      (@rgba );
326
327 ras.Construct;
328 sl.Construct;
329
330// Render
331 x_start :=125.0;
332 x_end   :=_initial_width - 15.0;
333 y_start :=10.0;
334 y_end   :=_initial_height - 10.0;
335 x_center:=(x_start + x_end ) / 2;
336
337 p.Construct;
338 pl.Construct(@p );
339 tr.Construct(@pl ,_trans_affine_resizing );
340
341 for i:=0 to 15 do
342  begin
343   x:=x_start + (x_end - x_start ) * i / 16.0;
344
345   p.remove_all;
346   p.move_to(x + 0.5 ,y_start );
347   p.line_to(x + 0.5 ,y_end );
348
349   ras.add_path(@tr );
350
351   if i = 8 then
352    rgba.ConstrInt(0 ,0 ,0 ,255 )
353   else
354    rgba.ConstrInt(0 ,0 ,0 ,100 );
355
356   rs.color_       (@rgba );
357   render_scanlines(@ras ,@sl ,@rs );
358
359  end;
360
361 ys:=y_start + (y_end - y_start ) / 6.0;
362
363 p.remove_all;
364 p.move_to       (x_start ,ys );
365 p.line_to       (x_end ,ys );
366 ras.add_path    (@tr );
367 rgba.ConstrInt  (0 ,0 ,0 );
368 rs.color_       (@rgba );
369 render_scanlines(@ras ,@sl ,@rs );
370
371 pl.width_(1.0 );
372
373 for i:=0 to m_num_filters - 1 do
374  if m_filters[i ]._status then
375   begin
376    m_filter_func[i ].set_radius(m_radius._value );
377
378    radius:=m_filter_func[i ].radius;
379
380    n :=trunc(radius * 256 * 2 );
381    dy:=y_end - ys;
382
383    xs:=(x_end + x_start ) / 2.0 - (radius * (x_end - x_start ) / 16.0 );
384    dx:=(x_end - x_start ) * radius / 8.0;
385
386    p.remove_all;
387    p.move_to(xs + 0.5 ,ys + dy * m_filter_func[i ].calc_weight(-radius ) );
388
389    j:=1;
390
391    while j < n do
392     begin
393      p.line_to(
394       xs + dx * j / n + 0.5 ,
395       ys + dy * m_filter_func[i ].calc_weight(j / 256.0 - radius ) );
396
397      inc(j );
398
399     end;
400
401    ras.add_path    (@tr );
402    rgba.ConstrInt  (100 ,0 ,0 );
403    rs.color_       (@rgba );
404    render_scanlines(@ras ,@sl ,@rs );
405
406    p.remove_all;
407
408    ir:=trunc(Ceil(radius ) + 0.1 );
409
410    for xint:=0 to 255 do
411     begin
412      sum:=0;
413
414      xfract:=-ir;
415
416      while xfract < ir do
417       begin
418        xf:=xint / 256.0 + xfract;
419
420        if (xf >= -radius ) or
421           (xf <= radius ) then
422         sum:=sum + m_filter_func[i ].calc_weight(xf );
423
424        inc(xfract );
425
426       end;
427
428      x:=x_center + ((-128.0 + xint ) / 128.0 ) * radius * (x_end - x_start ) / 16.0;
429      y:=ys + sum * 256 - 256;
430
431      if xint = 0 then
432       p.move_to(x ,y )
433      else
434       p.line_to(x ,y );
435
436     end;
437
438    ras.add_path    (@tr );
439    rgba.ConstrInt  (0 ,100 ,0 );
440    rs.color_       (@rgba );
441    render_scanlines(@ras ,@sl ,@rs );
442
443    normalized.Construct(m_filter_func[i ].m_filter );
444
445    weights:=normalized.weight_array;
446
447    xs:=(x_end + x_start ) / 2.0 - (normalized.diameter * (x_end - x_start ) / 32.0 );
448    nn:=normalized.diameter * 256;
449
450    p.remove_all;
451    p.move_to(xs + 0.5 ,ys + dy * int16_ptr(weights )^ / image_filter_size );
452
453    j:=1;
454
455    while j < nn do
456     begin
457      p.line_to(
458       xs + dx * j / n + 0.5 ,
459       ys + dy * int16_ptr(ptrcomp(weights ) + j * sizeof(int16 ) )^ / image_filter_size );
460
461      inc(j );
462
463     end;
464
465    ras.add_path    (@tr );
466    rgba.ConstrInt  (0 ,0 ,100 ,255 );
467    rs.color_       (@rgba );
468    render_scanlines(@ras ,@sl ,@rs );
469
470   // Free
471    normalized.Destruct;
472
473   end;
474
475// Render the controls
476 for i:=0 to m_num_filters - 1 do
477  render_ctrl(@ras ,@sl ,@rs ,m_filters[i ] );
478
479 if m_sinc._status or
480    m_lanczos._status or
481    m_blackman._status then
482  render_ctrl(@ras ,@sl ,@rs ,@m_radius );
483
484// Free AGG resources
485 ras.Destruct;
486 sl.Destruct;
487
488 p.Destruct;
489 pl.Destruct;
490
491end;
492
493{ ON_KEY }
494procedure the_application.on_key;
495begin
496 if key = key_f1 then
497  message_(
498   'Demonstration of the shapes of different interpolation filters. '#13 +
499   'Just in case if you are curious.' +
500   #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory.  ' );
501
502end;
503
504VAR
505 app : the_application;
506
507BEGIN
508 app.Construct(pix_format_bgr24 ,flip_y );
509 app.caption_ ('Image filters'' shape comparison (F1-Help)' );
510
511 if app.init(780 ,300 ,window_resize ) then
512  app.run;
513
514 app.Destruct;
515
516END.