convolve_float_hsv 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, hsv); crimp_input (kernelImageObj, kernel, float); if (((kernel->w % 2) == 0) || ((kernel->h % 2) == 0)) { Tcl_SetResult(interp, "bad kernel dimensions, expected odd size", TCL_STATIC); return TCL_ERROR; } kw = kernel->w/2; kh = kernel->h/2; result = crimp_new (image->itype, image->w - 2*kw, image->h - 2*kh); for (yo = 0, yi = kh; yo < result->h; yo++, yi++) { for (xo = 0, xi = kw; xo < result->w; xo++, xi++) { /* * We convolve all channels with the same kernel, but otherwise * identically */ int sumh = 0; int sums = 0; int sumv = 0; for (yk = 0, dy = -kh; yk < kernel->h; yk++, dy++) { for (xk = 0, dx = -kw; xk < kernel->w; xk++, dx++) { sumh += FLOATP (kernel, xk, yk) * H (image, xi-dx, yi-dy); sums += FLOATP (kernel, xk, yk) * S (image, xi-dx, yi-dy); sumv += FLOATP (kernel, xk, yk) * V (image, xi-dx, yi-dy); } } sumh /= scale; sumh += offset; H (result, xo, yo) = CLAMP (0, sumh, 255); sums /= scale; sums += offset; S (result, xo, yo) = CLAMP (0, sums, 255); sumv /= scale; sumv += offset; V (result, xo, yo) = CLAMP (0, sumv, 255); } } 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: */