Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cf1a112

Browse files
committed
RendererAgg.draw_image supports affine transform
svn path=/trunk/matplotlib/; revision=8118
1 parent 472ca7f commit cf1a112

3 files changed

Lines changed: 72 additions & 17 deletions

File tree

examples/api/demo_affine_image.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
"""
55
For the backends that supports draw_image with optional affine
6-
transform (e.g., ps backend), the image of the output should
6+
transform (e.g., agg, ps backend), the image of the output should
77
have its boundary matches the red rectangles.
88
"""
99

@@ -33,7 +33,8 @@ def imshow_affine(ax, z, *kl, **kwargs):
3333
ax = plt.subplot(111)
3434
Z = get_image()
3535
im = imshow_affine(ax, Z, interpolation='nearest', cmap=cm.jet,
36-
origin='lower', extent=[-2, 4, -3, 2])
36+
origin='lower',
37+
extent=[-2, 4, -3, 2], clip_on=True)
3738

3839
trans_data2 = mtransforms.Affine2D().rotate_deg(30) + ax.transData
3940
im.set_transform(trans_data2)
@@ -48,4 +49,5 @@ def imshow_affine(ax, z, *kl, **kwargs):
4849
ax.set_xlim(-3, 5)
4950
ax.set_ylim(-4, 4)
5051

51-
plt.savefig("demo_affine_image")
52+
plt.show()
53+
#plt.savefig("demo_affine_image")

lib/matplotlib/backends/backend_agg.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,12 @@ def option_image_nocomposite(self):
261261
# with the Agg backend
262262
return True
263263

264+
def option_scale_image(self):
265+
"""
266+
agg backend support arbitrary scaling of image.
267+
"""
268+
return True
269+
264270
def restore_region(self, region, bbox=None, xy=None):
265271
"""
266272
restore the saved region. if bbox (instance of BboxBase, or

src/_backend_agg.cpp

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -814,55 +814,99 @@ Py::Object
814814
RendererAgg::draw_image(const Py::Tuple& args) {
815815
_VERBOSE("RendererAgg::draw_image");
816816

817-
args.verify_length(4);
817+
args.verify_length(4, 7); // 7 if affine matrix if given
818818

819819
GCAgg gc(args[0], dpi);
820-
double x = mpl_round(Py::Float(args[1]));
821-
double y = mpl_round(Py::Float(args[2]));
822820
Image *image = static_cast<Image*>(args[3].ptr());
823821
bool has_clippath = false;
822+
agg::trans_affine affine_trans;
823+
bool has_affine = false;
824+
double x, y, w, h;
825+
826+
827+
if (args.size() == 7) {
828+
has_affine = true;
829+
x = Py::Float(args[1]);
830+
y = Py::Float(args[2]);
831+
w = Py::Float(args[4]);
832+
h = Py::Float(args[5]);
833+
affine_trans = py_to_agg_transformation_matrix(args[6].ptr());
834+
} else {
835+
x = mpl_round(Py::Float(args[1]));
836+
y = mpl_round(Py::Float(args[2]));
837+
}
838+
824839

825840
theRasterizer.reset_clipping();
826841
rendererBase.reset_clipping(true);
842+
set_clipbox(gc.cliprect, theRasterizer);
827843
has_clippath = render_clippath(gc.clippath, gc.clippath_trans);
828844

829845
Py::Tuple empty;
830846
image->flipud_out(empty);
831847
pixfmt pixf(*(image->rbufOut));
832848

833-
if (has_clippath) {
849+
if (has_affine | has_clippath) {
834850
agg::trans_affine mtx;
835-
mtx *= agg::trans_affine_translation((int)x, (int)(height-(y+image->rowsOut)));
836-
837851
agg::path_storage rect;
852+
853+
if (has_affine) {
854+
mtx *= agg::trans_affine_scaling(1, -1);
855+
mtx *= agg::trans_affine_translation(0, image->rowsOut);
856+
mtx *= agg::trans_affine_scaling(w/(image->colsOut), h/(image->rowsOut));
857+
mtx *= agg::trans_affine_translation(x, y);
858+
mtx *= affine_trans;
859+
mtx *= agg::trans_affine_scaling(1.0, -1.0);
860+
mtx *= agg::trans_affine_translation(0.0, (double) height);
861+
} else {
862+
mtx *= agg::trans_affine_translation((int)x, (int)(height-(y+image->rowsOut)));
863+
}
864+
838865
rect.move_to(0, 0);
839866
rect.line_to(image->colsOut, 0);
840867
rect.line_to(image->colsOut, image->rowsOut);
841868
rect.line_to(0, image->rowsOut);
842869
rect.line_to(0, 0);
870+
843871
agg::conv_transform<agg::path_storage> rect2(rect, mtx);
844872

845873
agg::trans_affine inv_mtx(mtx);
846874
inv_mtx.invert();
847875

876+
848877
typedef agg::span_allocator<agg::rgba8> color_span_alloc_type;
849-
typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
850-
typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
851878
typedef agg::image_accessor_clip<agg::pixfmt_rgba32> image_accessor_type;
852879
typedef agg::span_interpolator_linear<> interpolator_type;
853880
typedef agg::span_image_filter_rgba_nn<image_accessor_type, interpolator_type> image_span_gen_type;
854-
typedef agg::renderer_scanline_aa<amask_ren_type, color_span_alloc_type, image_span_gen_type> renderer_type;
881+
855882

856883
color_span_alloc_type sa;
857884
image_accessor_type ia(pixf, agg::rgba8(0, 0, 0, 0));
858885
interpolator_type interpolator(inv_mtx);
859886
image_span_gen_type image_span_generator(ia, interpolator);
860-
pixfmt_amask_type pfa(pixFmt, alphaMask);
861-
amask_ren_type r(pfa);
862-
renderer_type ri(r, sa, image_span_generator);
863887

864-
theRasterizer.add_path(rect2);
865-
agg::render_scanlines(theRasterizer, slineP8, ri);
888+
889+
if (has_clippath) {
890+
typedef agg::pixfmt_amask_adaptor<pixfmt, alpha_mask_type> pixfmt_amask_type;
891+
typedef agg::renderer_base<pixfmt_amask_type> amask_ren_type;
892+
typedef agg::renderer_scanline_aa<amask_ren_type, color_span_alloc_type, image_span_gen_type> renderer_type_alpha;
893+
894+
pixfmt_amask_type pfa(pixFmt, alphaMask);
895+
amask_ren_type r(pfa);
896+
renderer_type_alpha ri(r, sa, image_span_generator);
897+
898+
theRasterizer.add_path(rect2);
899+
agg::render_scanlines(theRasterizer, slineP8, ri);
900+
} else {
901+
typedef agg::renderer_base<pixfmt> ren_type;
902+
typedef agg::renderer_scanline_aa<ren_type, color_span_alloc_type, image_span_gen_type> renderer_type;
903+
ren_type r(pixFmt);
904+
renderer_type ri(r, sa, image_span_generator);
905+
906+
theRasterizer.add_path(rect2);
907+
agg::render_scanlines(theRasterizer, slineP8, ri);
908+
}
909+
866910
} else {
867911
set_clipbox(gc.cliprect, rendererBase);
868912
rendererBase.blend_from(pixf, 0, (int)x, (int)(height-(y+image->rowsOut)));
@@ -873,6 +917,9 @@ RendererAgg::draw_image(const Py::Tuple& args) {
873917
return Py::Object();
874918
}
875919

920+
921+
922+
876923
template<class path_t>
877924
void RendererAgg::_draw_path(path_t& path, bool has_clippath,
878925
const facepair_t& face, const GCAgg& gc) {

0 commit comments

Comments
 (0)