AGG lesson 43 example image1 replacement problem from ellipse to rectangle
I am basing my code on the p_w_picpaths1 example and I have changed
The p_w_picpath 'partner' shape from an ellipse to a rectangle.
The partner rectangle comes out at X,Y and scales and rotates
But the top left-hand corner of the p_w_picpath is always stuck at
(xmeny) = 3D (0pr 0). Only the part of the p_w_picpath that overlaps the=20
Rectangle is visible, but that part scales and rotates properly.=20
When there is no overlap, there is no p_w_picpath.
I do not understand much of the the p_w_picpath2 example, so I am
Lost as to what might be.the cause. Code is attached.
Would be most grateful for help and/or example code.
Void p_w_picpath (HAGG * h, int x, int y, TCHAR * imgfilename)
{
If (! loadp_w_picpath (h, imgfilename)) / / sets p_w_picpath details in h
{
Return
}
Agg::rendering_buffer rbuf (h-> pixels
H-> frame_width, = 20
H-> frame_height, = 20
-(h-> frame_width * h-> bytesperpixel); = 20
Typedef agg::renderer_base renderer_base
Typedef agg::renderer_base =
Renderer_base_pre
Typedef agg::renderer_scanline_aa_solid =
Renderer_solid
Pixfmt pixf (rbuf)
Pixfmt_pre pixf_pre (rbuf)
Renderer_base rb (pixf)
Renderer_base_pre rb_pre (pixf_pre)
Renderer_solid rs (rb)
Rb.clear (agg::rgba (1.0,1.0,1.0))
Agg::rasterizer_scanline_aa pf
Agg::scanline_u8 sl
IMGINFO * I = 3D & h-> imgs [0]
Double imgwd = 3D I-> width; / / p_w_picpath width
Double imght = 3D I-> height; / / p_w_picpath height
Agg::trans_affine src_mtx
Src_mtx * = 3D agg::trans_affine_translation (- xmai Mury)
Src_mtx * = 3D agg::trans_affine_rotation (- h-> t.angle); / / in radians
Src_mtx * = 3D agg::trans_affine_scaling (h-> t.scalex, h-> t.scaley)
Src_mtx * = 3D agg::trans_affine_translation (xQuery y)
Agg::trans_affine img_mtx
Img_mtx * = 3D agg::trans_affine_translation (- xmai Mury)
Img_mtx * = 3D agg::trans_affine_rotation (- h-> t.angle)
Img_mtx * = 3D agg::trans_affine_scaling (h-> t.scalex, h-> t.scaley)
Img_mtx * = 3D agg::trans_affine_translation (xQuery y)
Img_mtx.invert ()
Typedef agg::span_allocator span_alloc_type
Span_alloc_type sa
Typedef agg::span_interpolator_linear interpolator_type
Interpolator_type interpolator (img_mtx)
/ / "hardcoded" bilinear filter
Typedef agg::span_p_w_picpath_filter_rgb_bilinear =
Span_gen_type
Typedef agg::renderer_scanline_aa =
Renderer_type
Agg::rendering_buffer rbuf_img (I-> pixels
(int) imgwd, = 20
(int) imght, = 20
-I-> stride); = 20
Span_gen_type sg (sa,=20
Rbuf_img, / / rendering buf with p_w_picpath pixels
Agg::rgba_pre (0,0.4,0,0.5)
Interpolator)
Renderer_type ri (rb_pre, sg)
Agg::path_storage path; / / partner rectangle
Path.move_to (XBI y)
Path.line_to (x+imgwd, y)
Path.line_to (x+imgwd, y+imght)
Path.line_to (x, y+imght)
Path.close_polygon ()
Agg::conv_transform tr (path, src_mtx)
= 20
Pf.add_path (tr)
Agg::render_scanlines (pf, sl, ri)
}
Static void drawp_w_picpath ()
{
RECT rt
GetClientRect (hwndmain, & rt)
Int width = 3D rt.right-rt.left
Int height = 3D rt.bottom-rt.top
HAGG * h = 3D gethandle (mybuf, width, height, 4)
Settrans_scale (h, scale)
Settrans_rotate (h, degrees)
/ / p_w_picpath (h, 2050, "bmpeivor.bmp"); / / does not work
P_w_picpath (h, 0B0, "bmpeivor.bmp"); / / works
Display (h, hwndmain); / / on screen
}
The author's answer:
Transforming p_w_picpaths is tricky, especially proper calculation of the affine
Matrix.
But first, if you don't need to transform it you can directly copy or blend
The p_w_picpath, it will work much faster. See renderer_base::copy_from ()
Blend_from ().
For the transformer there's a simple way of calculating the matrix as a
Parallelogram, see p_w_picpath_perspective.cpp
/ / Note that we consruct an affine matrix that transforms
/ / a parallelogram to a rectangle, i.e., it's inverted.
/ / It's actually the same as:
/ / tr (0,0, img_width, img_height, para); tr.invert ()
Agg::trans_affine tr (para, 0,0, img_width, img_height)
Where "para" is double [6] that defines 3 point of the parallelogram.
Perplexity:
I have replaced
Agg::path_storage path; / / partner rectangle
Path.move_to (XBI y)
Path.line_to (x+imgwd, y)
Pathmline_to (x+imgwd, y+imght)
Path.line_to (x, y+imght)
Path.close_polygon ()
Agg::conv_transform tr (path, src_mtx)
Pf.add_path (tr)
Agg::render_scanlines (pf, sl, ri)
At the and of my p_w_picpath proc (code of the whole proc is at
The end of my original post (and at the end of this email))
By
Double para [6]
= {0100, 0jue 0, 100.0}; / / 3 points (0100) (0je 0) and (100jue 0)
Agg::trans_affine tr (para, 0,0, imgwd, imght)
Pf.add_path (tr)
Agg::render_scanlines (pf, sl, ri)
Q1. Is this the right way?
Q2. What should the para points be expressed as functions of
P_w_picpath top-left hand corner, p_w_picpath width and p_w_picpath height, i.e.
X,y, imgwd, imght?
My test cases includes p_w_picpath (xmemy) = (0penol 0), so I defined para points
(0100), (0) and (100) just to see what would happen.
But got compilation errors:
..\ agg23\ include\ agg_rasterizer_scanline_aa.h: error C2039: 'rewind':
Is not a member of 'trans_affine'
..\ agg23\ include\ agg_trans_affine.h (88): see declaration of
'trans_affine'
And one more very similar: 'vertex': is not a member of' trans_affine'
The author's answer:
> double para [6] = {0100, 0jue 0100jin0}; / / 3 points (0100) (0Jing 0)
> and (100Pol 0)
> agg::trans_affine mtx (para, 0,0, imgwd, imght)
> agg::path_storage path; / / partner rectangle
> path.move_to (XBI y)
> path.line_to (x+imgwd, y)
> path.line_to (x+imgwd, y+imght)
> path.line_to (x, y+imght)
> path.close_polygon ()
> agg::conv_transform trans (path
> mtx)
>
> pf.add_path (trans); / / Note you add "trans"
>
> Then, if you want your p_w_picpath to fit exactly your parallelogram path (you
> also may want to do differently!), you need to create a copy of the matrix
> and invert it:
>
> agg::trans_affine img_mtx (mtx)
> img_mtx.invert ()
ITunm sorry, Ken, this is not correct; I have confused myself, so, please
Discard the code above. :)
So, suppose you have an p_w_picpath of imgwd, imght and a destination
Parallelogram. To define the parallelogram you need 3 points, x1jiny1-bottom
Left, x2jiny2-bottom right, x3jiny3-top right. The parallelogram can also
Define a 2D affine matrix: rotation, scaling, translation and skewing. You
Can rasterize your destination parallelogram directly:
Agg::rasterizer_scanline_aa ras
Ras.move_to_d (x1Query y1)
Ras.line_to_d (x2jiny2)
Ras.line_to_d (x3ther y3)
Ras.line_to_d (x1 + x3-x2, y1 + y3-y2)
So that, you can draw a solid parallelogram (well, you can also use the
Path_storage if you want).
To map an p_w_picpath to it you need to create the matrix:
Double para [6] = {x1meng y1pr x2jiny2pr x3je y3}
Agg::trans_affine img_mtx (0,0, imgwd, imght, para)
Img_mtx.invert ()
Or, which is the same:
Double para [6] = {x1meng y1pr x2jiny2pr x3je y3}
Agg::trans_affine img_mtx (para, 0,0, imgwd, imght)
The first one construicts a matrix to transform a rectangle to an a
Parellelogram, the second one-parallelogram to rectangle. The p_w_picpath
Transformer requires namely inverse matrix, so that, you transform your
Parallelogram (destination) to rectangle (p_w_picpath).
Technically that's it. But you may want to apply additional transformations.
To do that you will need two matrices:
Agg::trans_affine master_mtx
Master_mtx * = agg::trans_affine_translation (. . .)
Master_mtx * = agg::trans_affine_rotation (. . .)
. . .
Agg::rasterizer_scanline_aa ras
Agg::path_storage path; / / partner rectangle
Path.move_to (x1Query y1)
Path.line_to (x2jiny2)
Path.line_to (x3ther y3)
Path.line_to (x1 + x3-x2, y1 + y3-y2)
Path.close_polygon ()
Agg::conv_transform trans (path
Master_mtx)
Then you prepare the p_w_picpath matrix:
Double para [6] = {x1meng y1pr x2jiny2pr x3je y3}
Agg::trans_affine img_mtx (0,0, imgwd, imght, para)
Img_mtx * = master_mtx; / /! Integrate the master transforms
Img_mtx.invert ()
Ras.add_path (trans)
. . .Render
Now, whatever transformations you use in the master_mtx à they will be
Synchronized with the p_w_picpath.
Sorry for the delay, I was kinda busy last time. And besides, iTunm suffering
From constant problems with the Internet (Verizon in NYC sucks, iTunm)
Switching to cable).
Well, I understand everyone is busy, but could someone else answer the
Questions too?
First, you need to understand that a path is the primary thing in AGG.
Without path you can't draw anything. So that, to rotate an p_w_picpath you need
To create a respective path as if you wanted to fill this area with a solid
Color. And then, you just substitute an p_w_picpath renderer for your solid fill.
Obviously, to transform the whole p_w_picpath you need to create a parallelogram
Path (a rectangle in particular). You can do that calculating the points
Manually:
Ras.move_to_d (x1, y1)
Ras.line_to_d (x2, y2)
. . .
You you can use transformations.
Next, trans_affine doesn't have any "VertexSource" interface, it can't
Generate vertices. It can only transform them: affine.transform (& x, & y); To
Add affine transformer into your pipeline you also need conv_transform:
Double para [6] = {0100, 0 points 0}; / / 3 points (0100) (0 minute 0) and
(100pi 0)
Agg::trans_affine mtx (para, 0,0, imgwd, imght)
Agg::path_storage path; / / partner rectangle
Path.move_to (XBI y)
Path.line_to (x+imgwd, y)
Path.line_to (x+imgwd, y+imght)
Path.line_to (x, y+imght)
Path.close_polygon ()
Agg::conv_transform trans (path, mtx)
Pf.add_path (trans); / / Note you add "trans"
Then, if you want your p_w_picpath to fit exactly your parallelogram path (you
Also may want to do differently!), you need to create a copy of the matrix
And invert it:
Agg::trans_affine img_mtx (mtx)
Img_mtx.invert ()
Well, I realize that it all is pretty confusing. But this kind of a design
Is most flexible.
Extracted from: http://sourceforge.net/p/vector-agg/mailman/vector-agg-general/?viewmonth=200511&page=0