%ffp /* Fast Gaussian blur by extended binomial algorithm of first degree * simple: very easy blur calculation * fast: no run time dependency on blur radius * accurate: correct blur calculation of pixel near the boarder * large blur range of floating point radius * works for all color modes inclusive 16 bit and tiling */ Category: "easy.Filter" Title: "Gaussian Radius" Version: "1.0" Filename: "gauss.8bf" Author: "Alois Zingl" Copyright:"© 2010 GPL" URL: "http://free.pages.at/easyfilter/gauss.html" Description:"Fast Gaussian blur filter algorithm." // i0 = CtlDivisor(0); needed number of cells for get/put: 2.45*2*radius+1 ctl(0): "Radius (pixel)", divisor = (i0=10), range = (0, (int)(N_CELLS*i0/(2.45*2)-1)) OnFilterStart: { // set padding to blur radius int Radius = ctl(0)/(doingProxy ? zoomFactor*i0 : i0) + 1; needPadding = 2.45*Radius+1; // 2.45 = sqr(12/degree) = degree factor bandWidth = 100+3*needPadding; isTileable = !doingProxy; // split large images return false; } ForEveryTile: { float Weight = 2.45*ctl(0)/(i0*scaleFactor), fRadius = sqrt(Weight*Weight+1); int x, y, z, p, Radius = floor(fRadius);// integer blur radius fRadius -= Radius; // fraction of radius Weight = Radius*Radius + fRadius*(2*Radius+1); for (z = 0; z < Z; ++z) // for all color planes { for (x = x_start; x < x_end; ++x) // vertical blur... { float sum = src(x, y_start-Radius-1, z), dif = -sum; for (y = y_start-2*Radius-1; y < y_end; ++y) { // inner vertical Radius loop p = src(x, y+Radius, z); // next pixel put(p, y+Radius); // buffer pixel sum += dif + fRadius*p; dif += p; // accumulate pixel blur if (y >= y_start) { int s = 0, w = 0; // boarder blur correction sum -= get(y-Radius-1)*fRadius; // addition for fraction blur dif += get(y-Radius)-2*get(y); // sum up differences: +1, -2, +1 // cut off accumulated blur area of pixel beyond the boarder // assume: added pixel values beyond boarder = value at boarder p = Radius-y; // top part to cut off if (p > 0) { p = p*(p-1)/2 + fRadius*p; s += get(0)*p; w += p; } p = y+Radius-Y+1; // bottom part to cut off if (p > 0) { p = p*(p-1)/2 + fRadius*p; s += get(Y-1)*p; w += p; } pset(x, y, z, (int)((sum-s)/(Weight-w))); // set blurred pixel } else if (y+Radius >= y_start) dif -= 2*get(y); } // y } // x //Update progress bar and cancel if ESC key was pressed if (updateProgress(y_start+(y_end-y_start)*z/Z, Y)) abort(); for (y = y_start; y < y_end; ++y) // horizontal blur... { float sum = pget(x_start-Radius-1, y, z), dif = -sum; for (x = x_start-2*Radius-1; x < x_end; ++x) { // inner vertical Radius loop p = pget(x+Radius, y, z); // next pixel put(p, x+Radius); // buffer pixel sum += dif + fRadius*p; dif += p; // accumulate pixel blur if (x >= x_start) { int s = 0, w = 0; // boarder blur correction sum -= get(x-Radius-1)*fRadius; // addition for fraction blur dif += get(x-Radius)-2*get(x); // sum up differences: +1, -2, +1 // cut off accumulated blur area of pixel beyond the boarder p = Radius-x; // left part to cut off if (p > 0) { p = p*(p-1)/2 + fRadius*p; s += get(0)*p; w += p; } p = x+Radius-X+1; // right part to cut off if (p > 0) { p = p*(p-1)/2 + fRadius*p; s += get(X-1)*p; w += p; } pset(x, y, z, (int)((sum-s)/(Weight-w))); // set blurred pixel } else if (x+Radius >= x_start) dif -= 2*get(x); } // x } // y } // color plane return true; //Done! } OnFilterEnd: { updateProgress(0, 1); return false; }