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
(x,y)=3D(0,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<pixfmt> renderer_base;
typedef agg::renderer_base<pixfmt_pre> =
renderer_base_pre;
typedef agg::renderer_scanline_aa_solid<renderer_base> =
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(-x,-y);
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(x,y);
agg::trans_affine img_mtx;
img_mtx *=3D agg::trans_affine_translation(-x,-y);
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(x,y);
img_mtx.invert();
typedef agg::span_allocator<color_type> 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<color_type, =
component_order,=20
interpolator_type> =
span_gen_type;
typedef agg::renderer_scanline_aa<renderer_base_pre, span_gen_type> =
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( x,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<agg::path_storage> 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 , 20,50 , "bmpeivor.bmp" ) ; // does not work
p_w_picpath ( h , 0,0 , "bmpeivor.bmp" ) ; // works
display ( h , hwndmain ) ; // on screen
}
作者的回答:
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.
困惑:
I have replaced
agg::path_storage path; // partner rectangle
path.move_to( x,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<agg::path_storage> 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 ]
= { 0,100 , 0,0 , 100.0 } ; // 3 points (0,100) (0,0) and (100,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 (x,y)=(0,0), so I defined para points
(0,100), (0,0) and (100,0) just to see what would happen.
but got compilation errors:
..\agg23\include\agg_rasterizer_scanline_aa.h(465) : 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'
作者的回答:
> double para [ 6 ] = { 0,100 , 0,0 , 100,0 } ; // 3 points (0,100) (0,0)
> and (100,0)
> agg::trans_affine mtx(para, 0, 0, imgwd, imght);
> agg::path_storage path; // partner rectangle
> path.move_to( x,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<agg::path_storage, agg::trans_affine> 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();
I'm 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, x1,y1 - bottom
left, x2,y2 - bottom right, x3,y3 - 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(x1,y1);
ras.line_to_d(x2,y2);
ras.line_to_d(x3,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] = {x1,y1,x2,y2,x3,y3};
agg::trans_affine img_mtx(0, 0, imgwd, imght, para);
img_mtx.invert();
Or, which is the same:
double para[6] = {x1,y1,x2,y2,x3,y3};
agg::trans_affine img_mtx(para, 0, 0, imgwd, imght);
The first one construicts a matrix to transform a rectangle to a 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(x1,y1);
path.line_to(x2,y2);
path.line_to(x3,y3);
path.line_to(x1 + x3 - x2, y1 + y3 - y2);
path.close_polygon();
agg::conv_transform<agg::path_storage, agg::trans_affine> trans(path,
master_mtx);
Then you prepare the p_w_picpath matrix:
double para[6] = {x1,y1,x2,y2,x3,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, I'm suffering
from constant problems with the Internet (Verizon in NYC sucks, I'm
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 ] = { 0,100 , 0,0 , 100,0 } ; // 3 points (0,100) (0,0) and
(100,0)
agg::trans_affine mtx(para, 0, 0, imgwd, imght);
agg::path_storage path; // partner rectangle
path.move_to( x,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<agg::path_storage, agg::trans_affine> 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.
摘自:http://sourceforge.net/p/vector-agg/mailman/vector-agg-general/?viewmonth=200511&page=0
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。