By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,199 Members | 1,474 Online
Bytes IT Community
+ Ask a Question
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
Share this Question
Share on Google+
1 Reply


P: n/a
Try using the alternate ConvolveOp constructor, specifying the
edgeCondition argument as EDGE_NO_OP. Convolution at a given
point processes all the points around it, up to the "radius" of
the kernel. At edge points, some neighbors will, of course, be
missing. So the filter must either make up data, or throw some
away. The Java2D approach is to either copy the original edge
pixels, or set them black (the default).

Michael Allen wrote:
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?


---------------------------------------------------------------------
Kevin Weiner FM Software 610-997-3930 http://www.fmsware.com

Jul 17 '05 #2

This discussion thread is closed

Replies have been disabled for this discussion.