%ffp // works with tiles and 16 bit images Title :"downsampleGauss" Author :"Alois Zingl" Version :"August 2008" Copyright :"© 2008 GPL" Category :"easy.Filter" Filename :"downsampleGauss.8bf" URL :"http://members.chello.at/easyfilter/gauss.html" Description:"Fast Gaussian blur filter by downsampling." ctl(0): "Blur (pixels)", divisor=10, range=(0,500), page=100, gamma=200 OnFilterStart: { double s = (doingProxy?(ctl(0)+scaleFactor/2)/scaleFactor:ctl(0))/7.4+0.9; // sigma isTileable = !doingProxy; needPadding = s*sqrt(log(256.0)/log(2.0)); // 8-bit resolution radius i0 = max((int)s/4, 1); // downsample scale s = -i0*i0/(s*s); // calc Gaussian bell shape i1 = -32768; // Weight for (i = 0; i <= needPadding/i0; i++) { put((int)(32768.0*exp(i*i*s)), i); i1 += get(i)*2; } bandWidth = 100+needPadding+i0; // no allocArray here since X,x_end,.. are not updated yet after changes return false; } ForEveryTile: { int x, y, z, Blur = needPadding/i0-1; // blur radius int xe = (x_end-x_start)/i0; int ye = (y_end-y_start)/i0; if (getArrayDim(0,0)==0) allocArrayPad(0, xe, ye, 2, 4, Blur+1); // downsampled image buffer for (z=0; z < planesWithoutAlpha; ++z) // for all color planes { if (updateProgress(y_start+(y_end-y_start)*z/Z, Y)) abort(); // box downsampling for (y = -Blur; y < ye+Blur; ++y) for (x = -Blur; x < xe+Blur; ++x) { int xi, yi, s = (i0*i0)>>1; for (yi = 0; yi < i0; ++yi) for (xi = 0; xi < i0; ++xi) s += src(x*i0+xi+x_start, y*i0+y_start+yi, z); putArray(0, x, y, 0, s/(i0*i0)); } // vertical blur... for (x = -Blur; x <= xe+Blur; ++x) for (y = -1; y <= ye; ++y) { double sum = 0; for (i = y-Blur; i <= y+Blur; ++i) sum += getArray(0,x,i,0)*get(abs(i-y)); // pixel * weight putArray(0, x, y, 1, (int)(sum/i1)); } // horizontal blur... for (y = -1; y <= ye; ++y) for (x = -1; x <= xe; ++x) { double sum = 0; for (i = x-Blur; i <= x+Blur; ++i) sum += getArray(0,i,y,1)*get(abs(i-x)); // pixel * weight putArray(0, x, y, 0, (int)(sum/i1)); } // bilinear upsampling for (y = -1; y <= ye; ++y) for (x = -1; x <= xe; ++x) { int xi, yi, i = i0>>1; int a = getArray(0, x, y, 0), b = getArray(0, x+1, y, 0)-a; int c = getArray(0, x, y+1, 0), d = getArray(0, x+1, y+1, 0)-c; for (yi = 0; yi < i0; ++yi) for (xi = 0; xi < i0; ++xi) pset(x*i0+xi+x_start+i, y*i0+y_start+yi+i, z, ((b*xi+a*i0)*(i0-yi)+(d*xi+c*i0)*yi+2*i*i)/(i0*i0)); } } // color plane return true; //Done! } OnFilterEnd: { updateProgress(0, 1); freeArray(0); return false; }