/** * art_rgb_affine: Affine transform source RGB image and composite. * @dst: Destination image RGB buffer. * @x0: Left coordinate of destination rectangle. * @y0: Top coordinate of destination rectangle. * @x1: Right coordinate of destination rectangle. * @y1: Bottom coordinate of destination rectangle. * @dst_rowstride: Rowstride of @dst buffer. * @src: Source image RGB buffer. * @src_width: Width of source image. * @src_height: Height of source image. * @src_rowstride: Rowstride of @src buffer. * @affine: Affine transform. * @level: Filter level. * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing. * * Affine transform the source image stored in @src, compositing over * the area of destination image @dst specified by the rectangle * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges * of this rectangle are included, and the right and bottom edges are * excluded. * * The @alphagamma parameter specifies that the alpha compositing be done * in a gamma-corrected color space. Since the source image is opaque RGB, * this argument only affects the edges. In the current implementation, * it is ignored. * * The @level parameter specifies the speed/quality tradeoff of the * image interpolation. Currently, only ART_FILTER_NEAREST is * implemented. **/ void art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, const art_u8 *src, int src_width, int src_height, int src_rowstride, const double affine[6], ArtFilterLevel level, ArtAlphaGamma *alphagamma) { /* Note: this is a slow implementation, and is missing all filter levels other than NEAREST. It is here for clarity of presentation and to establish the interface. */ int x, y; double inv[6]; art_u8 *dst_p, *dst_linestart; const art_u8 *src_p; ArtPoint pt, src_pt; int src_x, src_y; int run_x0, run_x1; dst_linestart = dst; art_affine_invert (inv, affine); for (y = y0; y < y1; y++) { pt.y = y + 0.5; run_x0 = x0; run_x1 = x1; art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height, inv); dst_p = dst_linestart + (run_x0 - x0) * 3; for (x = run_x0; x < run_x1; x++) { pt.x = x + 0.5; art_affine_point (&src_pt, &pt, inv); src_x = floor (src_pt.x); src_y = floor (src_pt.y); src_p = src + (src_y * src_rowstride) + src_x * 3; dst_p[0] = src_p[0]; dst_p[1] = src_p[1]; dst_p[2] = src_p[2]; dst_p += 3; } dst_linestart += dst_rowstride; } }
static double gnome_canvas_item_invoke_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { #ifdef HACKISH_AFFINE double i2w[6], w2c[6], i2c[6], c2i[6]; ArtPoint c, i; #endif #ifdef HACKISH_AFFINE gnome_canvas_item_i2w_affine (item, i2w); gnome_canvas_w2c_affine (item->canvas, w2c); art_affine_multiply (i2c, i2w, w2c); art_affine_invert (c2i, i2c); c.x = cx; c.y = cy; art_affine_point (&i, &c, c2i); x = i.x; y = i.y; #endif return (* GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT_GET_CLASS (item))->point) ( item, x, y, cx, cy, actual_item); }
static void test_affine (void) { double src[6]; double dst[6]; double src2[6]; char str[128]; int i; ArtPoint ps, pd, ptmp; for (i = 0; i < 6; i++) { src[i] = (rand () * 2.0 / RAND_MAX) - 1.0; src2[i] = (rand () * 2.0 / RAND_MAX) - 1.0; } #if 0 src[0] = 0.9999999; src[1] = -0.000001; src[2] = 0.000001; src[3] = 0.9999999; src[4] = 0; src[5] = 0; #if 1 src[0] = 0.98480775; src[1] = -0.17364818; src[2] = 0.17364818; src[3] = 0.98480775; #endif src2[0] = 0.98480775; src2[1] = -0.17364818; src2[2] = 0.17364818; src2[3] = 0.98480775; #endif ps.x = rand() * 100.0 / RAND_MAX; ps.y = rand() * 100.0 / RAND_MAX; art_affine_point (&pd, &ps, src); art_affine_invert (dst, src); art_affine_point (&ptmp, &pd, dst); art_affine_to_string (str, src); printf ("src = %s\n", str); art_affine_to_string (str, dst); printf ("dst = %s\n", str); printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n", ps.x, ps.y, pd.x, pd.y, ptmp.x, ptmp.y); art_affine_point (&ptmp, &ps, src); art_affine_point (&pd, &ptmp, src2); art_affine_to_string (str, src2); printf ("src2 = %s\n", str); printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n", ps.x, ps.y, ptmp.x, ptmp.y, pd.x, pd.y); art_affine_multiply (dst, src, src2); art_affine_to_string (str, dst); printf ("dst = %s\n", str); art_affine_point (&pd, &ps, dst); printf ("point (%g, %g) -> (%g, %g)\n", ps.x, ps.y, pd.x, pd.y); }