%ffp Category: "FM Tutorial" Title: "GB Test 004" Version: "1.1" Filename: "GB Test 004" Author: "Alex Hunter" Organization:"AFH Systems" Description: "Code derived from the Gimp Gaussian Blur RLE plugin, " "which is Copyright (C) 1995 by Spencer Kimball and Peter Mattis, " "and the Gimp blur2 filter, which is Copyright (C) 1996 by " "Torsten Martinsen, with contributions by Johan Klockars." Copyright: "©1999-2001 AFH Systems" URL: "www.filtermeister.com" Dialog: color=steelblue ctl(0):"&Radius * 10", val=10 ForEveryTile: { double radius = ctl(0)/10.0; double sigma, sigma2; double l; int n; int length; int i, j, high, low, high1, low1, val; const bool PLOT = ctl(2); const bool PRINT = ctl(4); const bool DEBUG = ctl(6); const bool USE_CNV = ctl(8); radius = radius * 2.0 + 1.0; //scale approx same as Photoshop radius = fabs(radius) + 1.0; if (radius < 2.0) { if (Warn("Sub-pixel radii yield spurious results.") != IDOK) { abort(); } } sigma = sqrt(-(radius*radius)/(2.0*log(1.0/255.0))); sigma2 = 2.0 * sigma * sigma; ; l = sqrt(-sigma2 * log(1.0/255.0)); n = ceil(l) * 2; //round n up to an odd value. n |= 1; if (n > 256) { //exceeds number of put() cells... Error("Specified radius would require too many cells (%d).", n); abort(); } length = n / 2; //generate the bell-shaped Gaussian distribution curve... //curve[0] = 255; put(255, length); for (i = 1; i <= length; i++) { int temp = exp(-(i*i)/sigma2) * 255.0; //curve[-i] = curve[i] = temp; put(temp, length - i); put(temp, length + i); } if (PRINT) { // Print the curve. for (i = -length; i <= length; i++) { if (YesNo("curve[%d] = %d\n\nContinue?", i, get(length + i)) == IDNO) break; } } if (PLOT) { // Plot the Gaussian bell-shaped curve over a darkened // image background. // This updates fast, so set real-time tracking ON. setCtlProperties(0, CTP_TRACK); // Copy over a darkened version of the input image, // setting the alpha channel (if present) to fully opaque. for (y = y_start; y < y_end; y++) { if (updateProgress(y-y_start,y_end-y_start)) abort(); for (x = x_start; x < x_end; x++) { for (z = 0; z < Z; z++) { pset(x, y, z, z==3?255:src(x,y,z)/3); } } } // Draw the Y-axis. for (y = y_start; y < y_end; y++) { pset(X/2, y, 2, 255);//blue } // Draw the X-axis. for (x = x_start; x < x_end; x++) { pset(x, Y/2, 0, 255);//red } // Plot the Gaussian curve. for (i = -length; i <= length; i++) { pset(X/2 + i*10, Y/2 - get(length + i)*Y/512, 1, 255); //green } } else { // Apply Gaussian blur in the vertical and horizontal // directions. int sum, total; int xWork = x_end - x_start; int yWork = y_end - y_start; int totalWork = xWork + yWork; // This updates slowly, so set real-time tracking OFF. clearCtlProperties(0, CTP_TRACK); // Compute total weight total = 0; for (i = -length; i <= length; i++) { total += get(length + i); } if (DEBUG) Info("total = %d", total); // Apply vertical Gaussian blur... for (x = x_start; x < x_end; x++) { if (updateProgress(x-x_start, totalWork)) abort(); for (y = y_start; y < y_end; y++) { for (z = 0; z < Z; z++) { { sum = 0; for (i = -length; i <= length; ++i) { sum += src(x, y+i, z)*get(length + i); val = sum/total; high = val>>8; low = val<<24; low = low>>24; val = high<<8; val = val + low; tset(x,y,z,high); t2set(x,y,z,low); } } } } } // Apply horizontal Gaussian blur... for (y = y_start; y < y_end; y++) { if (updateProgress(y-y_start+xWork, totalWork)) abort(); for (x = x_start; x < x_end; x++) { for (z = 0; z < Z; z++) { { sum = 0; for (i = -length; i <= length; ++i) { high = tget(x+i, y, z)<<8; low = t2get(x+i, y, z); val = high + low; sum += val*get(length + i); } pset(x, y, z, sum/total); } } } } }//if // Reset the progress bar. updateProgress(0,100); return true; //Done! }//ForEveryTile