Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Gausian and Alpha Blurring

0.00/5 (No votes)
22 Feb 2004 1  
Step by step instructions and theory

Sample Image - screenshot.png

Introduction

I created this as a part of my icon builder project. Let me back up a sec and explain. In my icon project I deal extensively with icons. A problem creeps up when the user resizes a lowres icon to a larger size. What ends up happening is edges of the icon get frayed. My objective here was to write something to un fray the edges. Ok fast forward a bit :-)

I was contemplating how to accomplish my goal when I though "What I need here is a gausian blur function". Unfortunately, there is nothing like this in the standard GDI+ functions. So (yet again) I decided to roll my own solution of creating a gausian blur (like) function. The reason it isn't exactly the same as the real mccoy is it doesn't take into account a transform matrix, so as a result the colors all have the same weighted values (but you can't really tell a difference).

Demystifying the "Image"

Image stuff has always made me step back and say ouch. Until you really think about it, it can seem like a really complex issue when in reality it is no harder then that address book program everyone wrote in school (Many eon's ago, in pascal). I will try to break this concept down and reduce it to bear bones for you.

If nothing else remember this:
An image is just a 2D array of colors, and we "could" represent an image in an array, like so:

        For PixelX = 0 To Image.Width - 1
            For PixelY = 0 To Image.Height - 1
                ImagePixel(PixelX, PixelY) = Image.getpixel(PixelX, PixelY)
            Next
        Next
This will loop picture and create an array of colors for the entire image (luckily we don't have to do this, I am just trying to make a point). An image is nothing more then an array of colors that we can modify.

Blurring the line

What happens when we take red and add green to it? (we get yellow) What happens when we take the same concept and apply it to a 2D array? (we get a blur effect). In the last sample snipit of code we learned that GetPixel returns the color of a point in an image. So consider this:

        For PixelX = 0 To Image.Width - 2
            For PixelY = 0 To Image.Height - 2
                Dim Color1 As Color = Image.getpixel(PixelX, PixelY)
                Dim Color2 As Color = Image.getpixel(PixelX + 1, PixelY)
                Dim Merge As Color = Color.FromArgb( _
                          (Color1.A + Color2.A) / 2, _
                          (Color1.R + Color2.R) / 2, _
                          (Color1.G + Color2.G) / 2, _
                          (Color1.B + Color2.B) / 2)
                SetPixel(PixelX, PixelY, Merge)

            Next
        Next

Each color (for our purposes here) is made up of four values A = Alpha, R = Red, G = Green, B = Blue. So in essence what we are doing is taking these "color channels" and averaging them with the next pixel. So lets say pixel (1, 1) is red and pixel (2, 1) is green, we mix then and set pixel (1, 1) to the resulting color, yellow. Congrats, you just made a blur! Actually it resembles more of a streak.

Building a better blur

Instead of blurring two pixels lets take a greater sampling and average a 3X3 group of pixels, this will give you a better blur effect. The first thing we need to do is have a function that weeds out those pesky pixels that don't exist. As I have demonstrated above the 3X3 sample of pixels for (1,1) will render five points that don't exist.

        dim pixels as new arraylist
        dim x as integer, y as integer
        dim size as new size(3, 3)
        dim imageSize as new size(10, 10)


        For x = PixelX - CInt(Size.Width / 2) To PixelX + _
              CInt(Size.Width / 2)
            For y = Pixely - CInt(Size.Height / 2) To Pixely + _
                CInt(Size.Height / 2)
                If (x > 0 And x < imageSize.Width) And _
                   (y > 0 And y < imageSize.Height) Then
                    pixels.Add(bmp.GetPixel(x, y))
                End If
            Next
        Next

What this little gem does is take PixelX and PixelY (1, 1 in this case) and create an array of the pixel colors. This array of pixel colors will contain the color information for four pixels (1,1) (2,1) (1,2) and (2,2). Here are two more examples:

Example one (2,1) will yeild 6 points. Example 2 will yield 9 points.

As you can see this is a multi-purpose function that will return up to nine pixels color, depending on where the pixel is located.
Now that we have an array of the pixels to use in this blur lets see how we can average them together.

        Dim thisColor As Color


        Dim alpha As Integer = 0
        Dim red As Integer = 0
        Dim green As Integer = 0
        Dim blue As Integer = 0


        For Each thisColor In pixels
            alpha += thisColor.A
            red += thisColor.R
            green += thisColor.G
            blue += thisColor.B
        Next



        Return Color.FromArgb(alpha / pixels.Count, _
                              red / pixels.Count, _
                              green / pixels.Count, _
                              blue / pixels.Count)

This will loop the collection of pixels adding up the color channels as it goes along. Then when its done it will return a color with the averages of all the colors, This resulting color is what you set that pixel (1, 1) to.

What is an alpha channel

An alpha channel is a color channel that represents the transparency of that color. In the above all three squares are red but the alpha channels are different. The first square is solid and the alpha channel is set to 255. The second square is 50% solid or (127.5) and the last square is completely transparent with an alpha of 0% or (0).

Alpha channels are used most commonly in GIF, PNG and ICO files. For this reason you can load up a transparent gif and check the alpha channel of every pixel and get an outline of the solid parts of the image.

Alpha Blur

Using the same technique as before we can test to see if the pixel is not solid and send it to our blur function thus blurring the alpha channels or edges of the object.
Note
the object must be transparent for this to work!

Putting it all together

Here is a full example of the program I built that does this gausianesk blurring.

    Private Function Average(ByVal Size As Size, ByVal imageSize As SizeF, _
               ByVal PixelX As Integer, ByVal Pixely As Integer) As Color


        Dim pixels As New ArrayList
        Dim x As Integer, y As Integer
        Dim bmp As Bitmap = PictureBox1.Image.Clone


        ' Find the color for each pixel and add it to a new array.

        '

        ' Remember a 5X5 area on or near the edge will ask 

        ' for pixels that don't

        ' exist in our image, this will filter those out.

        '

        For x = PixelX - CInt(Size.Width / 2) To PixelX + _
               CInt(Size.Width / 2)
            For y = Pixely - CInt(Size.Height / 2) To Pixely + _
                   CInt(Size.Height / 2)
                If (x > 0 And x < imageSize.Width) And _
                   (y > 0 And y < imageSize.Height) Then
                    pixels.Add(bmp.GetPixel(x, y))
                End If
            Next
        Next

        ' Adverage the A, R, G, B channels 

        ' reflected in the array


        Dim thisColor As Color
        Dim alpha As Integer = 0
        Dim red As Integer = 0
        Dim green As Integer = 0
        Dim blue As Integer = 0

        For Each thisColor In pixels
            alpha += thisColor.A
            red += thisColor.R
            green += thisColor.G
            blue += thisColor.B
        Next

        ' Return the sum of the colors / the number of colors (The average)

        '

        Return Color.FromArgb(alpha / pixels.Count, _
                              red / pixels.Count, _
                              green / pixels.Count, _
                              blue / pixels.Count)
    End Function


    Private Sub gausianBlur(ByVal alphaEdgesOnly As Boolean, _
                            ByVal blurSize As Size)

        Dim PixelY As Integer
        Dim PixelX As Integer
        Dim bmp As Bitmap = PictureBox1.Image.Clone

        ' UI Stuff

        Label1.Text = "Applying Gausian Blur of " & blurSize.ToString

        Progress.Maximum = bmp.Height * bmp.Width
        Progress.Minimum = 0
        Progress.Value = 0

        ' Loop the rows of the image

        For PixelY = 0 To bmp.Width - 1

            ' Loop the cols of the image

            For PixelX = 0 To bmp.Height - 1
                If Not alphaEdgesOnly Then     ' Blur everything

                    bmp.SetPixel(PixelX, PixelY, Average(blurSize, _      
                                 bmp.PhysicalDimension, PixelX, PixelY))
                ElseIf bmp.GetPixel(PixelX, PixelY).A _
                       <> 255 Then  ' Alpha blur channel check

                    bmp.SetPixel(PixelX, PixelY, Average(blurSize, _      
                                 bmp.PhysicalDimension, PixelX, PixelY))
                End If
                Progress.Value += 1
                Application.DoEvents()
            Next
        Next

        PictureBox1.Image = bmp.Clone
        bmp.Dispose()
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, _
              ByVal e As System.EventArgs) Handles Button1.Click
        gausianBlur(False, New Size(6, 6))
    End Sub

It looks kind of mind numbing at first until you break it down like I have just done for you. Basically when you click button1 it sends the information to the gausianBlur sub to build the blur. The gausianBlur sub checks if that part of the image needs to be blurred and if it does sets that pixel to the output color of the adverage function.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here