convolve_float_grey8
Tcl_Obj* imageObj
Tcl_Obj* kernelImageObj
int scale
int offset
/*
* Generic convolution operator. The kernel to convole with is specified as a
* floating-point image together with a scaling factor. This way we do not
* need a separate matrix Tcl_ObjType.
*
* This convolver should be used only for small kernels, as it uses direct
* convolution. For larger kernels it is planned to provide an FFT based
* convolver.
*/
crimp_image* result;
crimp_image* image;
crimp_image* kernel;
int xo, yo, xi, yi, xk, yk, dx, dy, kw, kh;
crimp_input (imageObj, image, grey8);
crimp_input (kernelImageObj, kernel, float);
if (((crimp_w (kernel) % 2) == 0) ||
((crimp_h (kernel) % 2) == 0)) {
Tcl_SetResult(interp, "bad kernel dimensions, expected odd size", TCL_STATIC);
return TCL_ERROR;
}
kw = crimp_w (kernel)/2;
kh = crimp_h (kernel)/2;
result = crimp_new_at (image->itype, crimp_x (image) + kw, crimp_y (image) + kh, crimp_w (image) - 2*kw, crimp_h (image) - 2*kh);
for (yo = 0, yi = kh; yo < crimp_h (result); yo++, yi++) {
for (xo = 0, xi = kw; xo < crimp_w (result); xo++, xi++) {
/*
* We convolve all channels with the same kernel, but otherwise
* identically
*/
double sum = 0;
int isum;
for (yk = 0, dy = -kh; yk < crimp_h (kernel); yk++, dy++) {
for (xk = 0, dx = -kw; xk < crimp_w (kernel); xk++, dx++) {
sum += FLOATP (kernel, xk, yk) * GREY8 (image, xi-dx, yi-dy);
}
}
sum /= scale; sum += offset; isum = sum;
GREY8 (result, xo, yo) = CLAMP (0, isum, MAXVAL_GREY8);
}
}
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:
*/