CRIMP
Artifact [24810ba2bc]
Not logged in

Artifact 24810ba2bc347dbecb78b485a6a87335c4b8f11c:


warp_mbyte_projective_bilinear
Tcl_Obj* imageObj
Tcl_Obj* forwardObj

/*
 * Warp image using the given specified transform. The result is made large
 * enough to contain all of the warped image, and will contain meta data about
 * the location of the actual (0,0) origin point relative to the physical top
 * left corner of the result. This last is required because translations in
 * the transform may move pixels to negative positions which we cannot express
 * with the regular memory grid.
 */

crimp_image* image;
crimp_image* forward;
crimp_image* backward;
crimp_image* result;
int x, y, xt, yt, origx, origy, c;
double xf, yf;

crimp_input_any (imageObj, image);
CRIMP_ASSERT_NOTIMGTYPE (image, float);
CRIMP_ASSERT_NOTIMGTYPE (image, grey16);
CRIMP_ASSERT_NOTIMGTYPE (image, grey32);

crimp_input (forwardObj,  forward,  float);

if (!crimp_require_dim (forward, 3, 3)) {
    Tcl_SetResult(interp, "bad matrix dimensions, expected 3x3", TCL_STATIC);
    return TCL_ERROR;
}

backward = crimp_la_invert_matrix_3x3 (forward);
if (!backward) {
    Tcl_SetResult(interp, "Unable to invert singular matrix", TCL_STATIC);
    return TCL_ERROR;
}

/*
 * Determine size of the result, and the location of the origin point inside
 * based on the four corners of the input image and the forward transformation.
 */

result = crimp_geo_warp_init (image, forward, &origx, &origy);

for (y = 0, yt = origy; y < crimp_h (result); y++, yt++) {
    for (x = 0, xt = origx; x < crimp_w (result); x++, xt++) {
	int ixw, iyw;

	xf = xt;
	yf = yt;
	crimp_geo_warp_point (backward, &xf, &yf);

	/*
	 * Perform bilinear interpolation (1) using the nearest 2x2 pixels
	 * around the sampling location.
	 *
	 * (Ad 1) http://en.wikipedia.org/wiki/Bilinear_interpolation
	 */

        ixw = xf;
        iyw = yf;

        xf -= ixw;
        yf -= iyw;

        for (c = 0; c < 4; ++c) {
            float val = 0;
	    int ix, iy;
            double yft = yf;
            for (iy = MAX(iyw, 0); iy < MIN(iyw + 2, crimp_h (image)); iy++) {
                yft = 1 - yft;
                double xft = xf;
                for (ix = MAX(ixw, 0); ix < MIN(ixw + 2, crimp_w (image)); ix++) {
                    xft = 1 - xft;

		    val += CH (image, c, ix, iy) * yft * xft;
                }
            }

	    CH (result, c, x, y) = val;
        }
    }
}

crimp_del (backward);
Tcl_SetObjResult(interp, crimp_new_image_obj (result));
return TCL_OK;


/* vim: set sts=4 sw=4 tw=80 et ft=c: */
/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */