3
// AggPas 2.4 RM3 Demo application
4
// Note: Press F1 key on run to see more info about this demo
6
// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap
15
agg_platform_support ,
24
agg_rendering_buffer ,
26
agg_renderer_scanline ,
27
agg_rasterizer_scanline_aa ,
30
agg_render_scanlines ,
37
agg_trans_perspective ,
38
agg_span_interpolator_linear ,
39
agg_span_interpolator_trans ,
40
agg_span_subdiv_adaptor ,
41
agg_span_image_filter ,
42
agg_span_image_filter_rgba ,
46
interactive_polygon_ ,
60
g_rasterizer : rasterizer_scanline_aa;
61
g_scanline : scanline_u8;
64
the_application = object(platform_support )
65
m_quad : interactive_polygon;
66
m_trans_type : rbox_ctrl;
68
constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
71
procedure on_init; virtual;
72
procedure on_draw; virtual;
74
procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual;
75
procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
76
procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
78
procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
83
constructor the_application.Construct;
85
inherited Construct(format_ ,flip_y_ );
87
m_quad.Construct (4 ,5.0 );
88
m_trans_type.Construct(420 ,5.0 ,420 + 170.0 ,70.0 ,not flip_y_ );
90
m_trans_type.add_item ('Affine Parallelogram' );
91
m_trans_type.add_item ('Bilinear' );
92
m_trans_type.add_item ('Perspective' );
93
m_trans_type.cur_item_(2 );
95
add_ctrl(@m_trans_type );
100
destructor the_application.Destruct;
105
m_trans_type.Destruct;
110
procedure the_application.on_init;
112
x1 ,y1 ,x2 ,y2 ,dx ,dy : double;
117
g_x2:=rbuf_img(0 )._width;
118
g_y2:=rbuf_img(0 )._height;
125
dx:=_width / 2.0 - (x2 - x1 ) / 2.0;
126
dy:=_height / 2.0 - (y2 - y1 ) / 2.0;
128
{ m_quad.xn_ptr(0 )^:=Floor(x1 + dx + 50 );
129
m_quad.yn_ptr(0 )^:=Floor(y1 + dy + 50 );
130
m_quad.xn_ptr(1 )^:=Floor(x2 + dx );
131
m_quad.yn_ptr(1 )^:=Floor(y1 + dy );
132
m_quad.xn_ptr(2 )^:=Floor(x2 + dx );
133
m_quad.yn_ptr(2 )^:=Floor(y2 + dy );
134
m_quad.xn_ptr(3 )^:=Floor(x1 + dx );
135
m_quad.yn_ptr(3 )^:=Floor(y2 + dy ); {}
137
m_quad.xn_ptr(0 )^:=100 + 50;
138
m_quad.yn_ptr(0 )^:=100 + 50;
139
m_quad.xn_ptr(1 )^:=_width - 100;
140
m_quad.yn_ptr(1 )^:=100;
141
m_quad.xn_ptr(2 )^:=_width - 100;
142
m_quad.yn_ptr(2 )^:=_height - 100;
143
m_quad.xn_ptr(3 )^:=100;
144
m_quad.yn_ptr(3 )^:=_height - 100;
149
procedure the_application.on_draw;
151
pixf ,pixf_pre : pixel_formats;
153
rb ,rb_pre : renderer_base;
157
r : renderer_scanline_aa_solid;
160
sg : span_image_filter_ptr;
161
ri : renderer_scanline_aa;
163
trb : trans_bilinear;
164
trp : trans_perspective;
166
interpolator : span_interpolator_linear;
167
interp_trans : span_interpolator_trans;
168
subdiv_adaptor : span_subdiv_adaptor;
170
filter_kernel : image_filter_hermite;
171
filter : image_filter_lut;
174
buf : array[0..63 ] of char;
181
// Initialize structures
182
pixfmt_bgra32 (pixf ,rbuf_window );
183
pixfmt_bgra32_pre(pixf_pre ,rbuf_window );
185
rb.Construct (@pixf );
186
rb_pre.Construct(@pixf_pre );
189
rgba.ConstrDbl(1 ,1 ,1 );
192
if m_trans_type._cur_item = 0 then
194
// For the affine parallelogram transformations we
195
// calculate the 4-th (implicit) point of the parallelogram
196
m_quad.xn_ptr(3 )^:=m_quad.xn(0 ) + (m_quad.xn(2 ) - m_quad.xn(1 ) );
197
m_quad.yn_ptr(3 )^:=m_quad.yn(0 ) + (m_quad.yn(2 ) - m_quad.yn(1 ) );
201
// Render the "quad" tool
202
g_rasterizer.add_path(@m_quad );
204
rgba.ConstrDbl (0 ,0.3 ,0.5 ,0.6 );
206
render_scanlines(@g_rasterizer ,@g_scanline ,@r );
208
// Prepare the polygon to rasterize. Here we need to fill
209
// the destination (transformed) polygon.
210
g_rasterizer.clip_box(0 ,0 ,_width ,_height );
212
g_rasterizer.move_to_d(m_quad.xn(0 ) ,m_quad.yn(0 ) );
213
g_rasterizer.line_to_d(m_quad.xn(1 ) ,m_quad.yn(1 ) );
214
g_rasterizer.line_to_d(m_quad.xn(2 ) ,m_quad.yn(2 ) );
215
g_rasterizer.line_to_d(m_quad.xn(3 ) ,m_quad.yn(3 ) );
218
filter_kernel.Construct;
219
filter.Construct(@filter_kernel ,false );
221
rgba.ConstrPre(0 ,0 ,0 ,0 );
225
case m_trans_type._cur_item of
228
// Note that we consruct an affine matrix that transforms
229
// a parallelogram to a rectangle, i.e., it's inverted.
230
// It's actually the same as:
231
// tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon());
233
tr.Construct(parallelo_ptr(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
235
// Also note that we can use the linear interpolator instead of
236
// arbitrary span_interpolator_trans. It works much faster,
237
// but the transformations must be linear and parellel.
238
interpolator.Construct(@tr );
241
span_image_filter_rgba_nn_ptr ,
243
@sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,bgra_order ) );
245
ri.Construct (@rb_pre ,sg );
246
render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
252
trb.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
256
interpolator.Construct(@trb );
259
span_image_filter_rgba_2x2_ptr ,
261
@sa ,rbuf_img(0 ) ,@rgba ,@interpolator ,@filter ,bgra_order ) );
263
ri.Construct (@rb_pre ,sg );
264
render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
272
trp.Construct(pointer(m_quad.polygon ) ,g_x1 ,g_y1 ,g_x2 ,g_y2 );
276
// interpolator.Construct (@trp );
277
// subdiv_adaptor.Construct(@interpolator );
279
interp_trans.Construct(@trp );
282
span_image_filter_rgba_2x2_ptr ,
284
@sa ,rbuf_img(0 ) ,@rgba ,@interp_trans ,@filter ,bgra_order ) );
286
ri.Construct (@rb_pre ,sg );
287
render_scanlines(@g_rasterizer ,@g_scanline ,@ri );
304
sprintf (@buf[0 ] ,'%3.2f ms' ,tm );
305
t.start_point_(10.0 ,10.0 );
308
g_rasterizer.add_path(@pt );
310
rgba.ConstrDbl (0 ,0 ,0 );
312
render_scanlines(@g_rasterizer ,@g_scanline ,@r );
314
// Render the controls
315
render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_trans_type );
317
// Free AGG resources
322
dispose(sg ,Destruct );
330
procedure the_application.on_mouse_move;
332
if flags and mouse_left <> 0 then
333
if m_quad.on_mouse_move(x ,y ) then
336
if flags and mouse_left = 0 then
337
on_mouse_button_up(x ,y ,flags );
341
{ ON_MOUSE_BUTTON_DOWN }
342
procedure the_application.on_mouse_button_down;
344
buf : array[0..99 ] of char;
347
if flags and mouse_left <> 0 then
348
if m_quad.on_mouse_button_down(x ,y ) then
351
if flags and mouse_right <> 0 then
353
sprintf (@buf[0 ] ,'%d ' ,x );
354
sprintf (@buf[StrLen(@buf ) ] ,'%d' ,y );
361
{ ON_MOUSE_BUTTON_UP }
362
procedure the_application.on_mouse_button_up;
364
if m_quad.on_mouse_button_up(x ,y ) then
370
procedure the_application.on_key;
374
'Image perspective transformations. There are two types of arbitrary quadrangle '#13 +
375
'transformations, Perspective and Bilinear. The image transformer always uses '#13 +
376
'reverse transformations, and there is a problem. The Perspective transformations '#13 +
377
'are perfectly reversible, so they work correctly with images, but the Bilinear '#13 +
378
'transformer behave somehow strange. It can transform a rectangle to a quadrangle, '#13 +
379
'but not vice versa. In this example you can see this effect, when the edges of '#13 +
380
'the image "sag". I''d highly appreciate if someone could help me with math for '#13 +
381
'transformations similar to Bilinear ones, but correctly reversible (i.e., that '#13 +
382
'can transform an arbitrary quadrangle to a rectangle). The bilinear transformations '#13 +
383
'are simple, see agg_trans_bilinear.h and agg_simul_eq.h' +
384
#13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
389
app : the_application;
390
buf : array [0..255 ] of char;
393
img_name ,p ,n ,x : shortstring;
401
g_rasterizer.Construct;
402
g_scanline.Construct;
404
app.Construct(pix_format_bgra32 ,flip_y );
405
app.caption_ ('AGG Example. Image Perspective Transformations (F1-Help)' );
410
if ParamCount > 0 then
412
spread_name(ParamStr(1 ) ,p ,n ,x );
414
img_name:=fold_name(p ,n ,'' );
420
if not app.load_img(0 ,img_name ) then
422
img_name:=img_name + #0;
423
ext :=app._img_ext + #0;
425
if img_name = 'spheres'#0 then
427
sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
428
sprintf(@buf[StrLen(@buf ) ] ,'%s. '#13'Download http://www.antigrain.com/' ,ptrcomp(@ext[1 ] ) );
429
sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@img_name[1 ] ) );
430
sprintf(@buf[StrLen(@buf ) ] ,'%s'#13'or copy it from another directory if available.' ,ptrcomp(@ext[1 ] ) );
435
sprintf(@buf[0 ] ,'File not found: %s' ,ptrcomp(@img_name[1 ] ) );
436
sprintf(@buf[StrLen(@buf ) ] ,'%s' ,ptrcomp(@ext[1 ] ) );
440
app.message_(@buf[0 ] );
444
if app.init(600 ,600 ,window_resize ) then
449
g_rasterizer.Destruct;
b'\\ No newline at end of file'