440,199 Members | 1,474 Online
Need help? Post your question and get tips & solutions from a community of 440,199 IT Pros & Developers. It's quick & easy.

# Gaussian blur CovolveOp producing weird black border result

 P: n/a Hi all you Java 2D gurus out there. I wonder if you might be able to help me. I've been dipping my toe into the world of Gaussian blurring and with the help of a few articles and some bashing my head against the screen, I've managed to get it to work... sort of. Right now, though, when I make multiple passes with my bluring ConvolveOp objects, I get progressively more and more black border around the image I am blurring. You can see the results for yourself in this test class I am posting at the end of this message. Does anyone have ideas for how to prevent such an obnoxious thing from happening? Anyone have pointers to something premade that might be better than a two-pass convolve operation solution? Thanks for any help, - Mike Allen -------------------------------------------------------------------------- /** * GaussianBlur * * This class contains static methods and data for executing Gaussian blurs * on Java BufferedImages. * * @author Michael Allen */ public class GaussianBlur { public static final int NUM_KERNELS = 16; public static final float[][] GAUSSIAN_BLUR_KERNELS = generateGaussianBlurKernels(NUM_KERNELS); public static BufferedImage blurImage(BufferedImage sourceImage, int kerneSize) { return blurImage(sourceImage, kerneSize, 1); } public static BufferedImage blurImage(BufferedImage sourceImage, int kernelSize, int numOfPasses) { if (kernelSize < 1 || kernelSize > NUM_KERNELS) { return sourceImage; } if (numOfPasses < 1) { return sourceImage; } float[] matrix = GAUSSIAN_BLUR_KERNELS[kernelSize - 1]; Kernel gaussianBlur1 = new Kernel(matrix.length, 1, matrix); Kernel gaussianBlur2 = new Kernel(1, matrix.length, matrix); ConvolveOp gaussianOp1 = new ConvolveOp(gaussianBlur1); ConvolveOp gaussianOp2 = new ConvolveOp(gaussianBlur2); BufferedImage tempImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), sourceImage.getType()); BufferedImage finalImage = new BufferedImage(sourceImage.getWidth(), sourceImage.getHeight(), sourceImage.getType()); BufferedImage nextSource = sourceImage; for (int i = 0; i < numOfPasses; i++) { tempImage = gaussianOp1.filter(nextSource, tempImage); finalImage = gaussianOp2.filter(tempImage, finalImage); //System.out.println("Pass "+i+": Value at 0,0 of source is "+Integer.toString(nextSource.getRGB(0,0), 16)); //System.out.println("Pass "+i+": Value at 0,0 is "+Integer.toString(finalImage.getRGB(0,0), 16)); nextSource = finalImage; } return finalImage; } public static float[][] generateGaussianBlurKernels(int level) { float[][] pascalsTriangle = generatePascalsTriangle(level); float[][] gaussianTriangle = new float[pascalsTriangle.length][]; for (int i = 0; i < gaussianTriangle.length; i++) { float total = 0.0f; gaussianTriangle[i] = new float[pascalsTriangle[i].length]; for (int j = 0; j < pascalsTriangle[i].length; j++) { total += pascalsTriangle[i][j]; } float coefficient = 1 / total; for (int j = 0; j < pascalsTriangle[i].length; j++) { gaussianTriangle[i][j] = coefficient * pascalsTriangle[i][j]; } float checksum = 0.0f; for (int j = 0; j < gaussianTriangle[i].length; j++) { checksum += gaussianTriangle[i][j]; } if (checksum == 1.0) { // hurrah } } return gaussianTriangle; } public static float[][] generatePascalsTriangle(int level) { if (level < 2) { level = 2; } float[][] triangle = new float[level][]; triangle[0] = new float[1]; triangle[1] = new float[2]; triangle[0][0] = 1.0f; triangle[1][0] = 1.0f; triangle[1][1] = 1.0f; for (int i = 2; i < level; i++) { triangle[i] = new float[i+1]; triangle[i][0] = 1.0f; triangle[i][i] = 1.0f; for (int j = 1; j < triangle[i].length-1;j++) { triangle[i][j] = triangle[i-1][j-1] + triangle[i-1][j]; } } return triangle; } public static void main(String[] args) throws IOException { BufferedImage image = null; if (args.length > 0) { image = ImageIO.read(new File(args[0])); } else { int size = 100; image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); g2.setStroke(new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER)); g2.setPaint(Color.white); g2.fillRect(0,0,size,size); g2.setPaint(Color.black); g2.drawLine(size / 10, size / 10, 9 * (size / 10), 9 * (size / 10)); g2.dispose(); } int rows = 5; int columns = 3; BufferedImage blurComposite = new BufferedImage(image.getWidth() * columns, image.getHeight() * rows, image.getType()); Graphics2D g2 = blurComposite.createGraphics(); for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { BufferedImage blurredImage = blurImage(image, (i+1) * 3, j + 1); int x = j * image.getWidth(); int y = i * image.getHeight(); g2.drawImage(blurredImage, x,y, null); } } PngEncoder encoder = new PngEncoder(blurComposite); byte[] pngData = encoder.pngEncode(); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("blurComparison.png")); out.write(pngData); out.close(); g2.dispose(); } } Jul 17 '05 #1