NEKIBUR RAHMAN
NEKIBUR RAHMAN

Reputation: 212

How to make smooth blur effect in java?

I have blured an image. But it is not smooth.

I heard that if I use the gaussian blur technique then I can remove the box effect.

But I don't know how to implement it with my code (I did some random technique but it messes with the color). Can you suggest me how to do gaussian blur with my code?

public class BlurImageDemo {

Color c[];

BlurImageDemo() throws IOException, InterruptedException {
    File f = new File("D:\\x.jpg");
    BufferedImage im = ImageIO.read(f);

    BufferedImage bi = new BufferedImage(im.getWidth(), im.getHeight(), BufferedImage.TYPE_INT_RGB);
    int i = 0;
    int max = 400, radius = 10;
    int a1 = 0, r1 = 0, g1 = 0, b1 = 0;
    c = new Color[max];
    int x = 1, y = 1, x1, y1, ex = 5, d = 0;
    for (x = radius; x < im.getHeight() - radius; x++) {
        for (y = radius; y < im.getWidth() - radius; y++) {

            //20x20 matrix
            for (x1 = x - radius; x1 < x + radius; x1++) {
                for (y1 = y - radius; y1 < y + radius; y1++) {
                    c[i++] = new Color(im.getRGB(y1, x1));
                    //System.out.println(i);
                }
            }
            i = 0;

            for (d = 0; d < max; d++) {
                a1 = a1 + c[d].getAlpha();
            }
            a1 = a1 / (max);

            for (d = 0; d < max; d++) {
                r1 = r1 + c[d].getRed();
            }
            r1 = r1 / (max);

            for (d = 0; d < max; d++) {
                g1 = g1 + c[d].getGreen();
            }
            g1 = g1 / (max);

            for (d = 0; d < max; d++) {
                b1 = b1 + c[d].getBlue();
            }
            b1 = b1 / (max);
            int sum1 = (a1 << 24) + (r1 << 16) + (g1 << 8) + b1;
            bi.setRGB(y, x, (int) (sum1));

        }
    }
    ImageIO.write(bi, "jpg", new File("D:\\x1.jpg"));
}

public static void main(String[] args) throws IOException, InterruptedException {
    new BlurImageDemo();
}
}

this is the final image, which is not smooth

Upvotes: 3

Views: 4963

Answers (3)

ErShakirAnsari
ErShakirAnsari

Reputation: 652

This is the best article I ever found:

Java Image Processing

Upvotes: 2

user555045
user555045

Reputation: 64933

One really nice property of Gaussian blur is that it is separable, meaning that it can be expressed as the composition of a purely horizontal and a purely vertical blur. The advantage of doing that is that, per pixel, it them takes 2N multiplications (N is the size of the kernel), whereas the 2D non-separated version takes N2 multiplications. For N=7 (as you have), that's already a decent difference. It also has a small downside, the intermediate result is either rounded (losing some precision) or big (3 floats per pixel instead of 1 int), usually a little rounding is not a problem though.

An other thing, more of an implementation detail, is that the division by the total weight of the kernel can be put into the kernel itself, saving a whole bunch of (pretty slow) divisions.

Also your kernel doesn't actually look like a Gaussian, it's too "pointy". That's up to you, but the Gaussian kernel is the only circularly symmetric one that is also separable (if you only look at real-valued kernels) and generally has nice properties, so I would recommend only deviating from it if there is a good reason for it.

Anyway I'll write some example code now, not tested:

BufferedImage transposedHBlur(BufferedImage im) {
    int height = im.getHeight();
    int width = im.getWidth();
    // result is transposed, so the width/height are swapped
    BufferedImage temp =  new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);
    float[] k = new float[7] { 0.00598, 0.060626, 0.241843, 0.383103, 0.241843, 0.060626, 0.00598 };
    // horizontal blur, transpose result
    for (int y = 0; y < height; y++) {
        for (int x = 3; x < width - 3; x++) {
            float r = 0, g = 0, b = 0;
            for (int i = 0; i < 7; i++) {
                int pixel = im.getRGB(x + i - 3, y);
                b += (pixel & 0xFF) * k[i];
                g += ((pixel >> 8) & 0xFF) * k[i];
                r += ((pixel >> 16) & 0xFF) * k[i];
            }
            int p = (int)b + ((int)g << 8) + ((int)r << 16);
            // transpose result!
            temp.setRGB(y, x, p);
        }
    }
    return temp;
}

Since it also transposes, you can simply call it twice and the second time will effectively be a vertical blur that also restores the orientation:

temp = transposedHBlur(input);
result = transposedHBlur(temp);

Upvotes: 3

NEKIBUR RAHMAN
NEKIBUR RAHMAN

Reputation: 212

I got the answer. here it is.

public class BlurImageDemo {

Color c[];

BlurImageDemo() throws IOException, InterruptedException {
    File f = new File("D:\\p.jpg");
    BufferedImage im = ImageIO.read(f);

    BufferedImage bi = new BufferedImage(im.getWidth(), im.getHeight(), BufferedImage.TYPE_INT_RGB);
    int i = 0;
    int max = 49, radius = 3;
    int a1 = 0, r1 = 0, g1 = 0, b1 = 0,t=0;
    c = new Color[max];
    float xx[] = {1,1,1,1,1,1,1,
                  1,3,3,3,3,3,1,
                  1,3,4,4,4,3,1,
                  1,3,4,15,4,3,1,
                  1,3,4,4,4,3,1,
                  1,3,3,3,3,3,1,
                  1,1,1,1,1,1,1,

    };
    float h=0;
    for(t=0;t<xx.length;t++){
        h+=xx[t];
    }
    System.out.println(h);
    int x = 1, y = 1, x1, y1, ex = 5, d = 0, ll = 0;
    for (x = radius;x < im.getHeight()- radius; x++) {
        for (y = radius; y < im.getWidth() - radius; y++) {

            for (x1 = x - radius; x1 <= x + radius; x1++) {
                for (y1 = y - radius; y1 <= y + radius; y1++) {
                    c[i] = new Color(im.getRGB(y1, x1));
                    //System.out.println(i);
                    //ll+=xx[i];
                    //System.out.println(ll);
                    i++;

                }
            }
            i = 0;
            ll = 0;
            for (d = 0; d < max; d++) {
                float o = xx[d] * c[d].getAlpha();
                a1 = (int) (a1 + o);
            }
            a1 = (int) (a1 / h);

            for (d = 0; d < max; d++) {
                float o = xx[d] * c[d].getRed();
                r1 = (int) (r1 + o);
            }
            r1 = (int) (r1 / h);

            for (d = 0; d < max; d++) {
                float o = xx[d] * c[d].getGreen();
                g1 = (int) (g1 + o);
            }
            g1 = (int) (g1 / h);
            //System.out.println(g1);
            for (d = 0; d < max; d++) {
                float o = xx[d] * c[d].getBlue();
                //System.out.println(o);
                b1 = (int) (b1 + o);
            }
            b1 = (int) (b1 / h);
            int sum1 = (r1 << 16) + (g1 << 8) + b1;
            bi.setRGB(y, x, sum1);
            r1 = g1 = b1 = 0;
            //System.out.println(new Color(sum1));
        }
    }

    ImageIO.write(bi,
            "jpg", new File("D:\\p2.jpg"));
}

public static void main(String[] args) throws IOException, InterruptedException {
    new BlurImageDemo();
}
}

Upvotes: 1

Related Questions