imageComponent.NET - image processing .NET assemblies
Create an Image Filter

It's very easy to create your own image filter in PhotoController. Please make sure you have read the tutorial [Use Image Filter] and understand the filter class hierarchy.

Filter is actually a kind of transformation applied to the image. An Image is composed of many pixels, and each pixel represents a color, which contains Red, Green, and Blue (RGB Space). I don't want to spend too much time to discuss whether a pixel is a dot or a block, but we all agree that when we say image processing, we tend to manipulate the pixels (colors). In general, there are several types of transformations, including geometric transformation and color transformation. It is recommended to take a look at Beyond Photography - The Digital Darkroom, which is a very good book describing many transformation ideas. In the DEMO application, I provide three customer filters for example.

Geometric transformation

Geometric transformation means to change the original pixel (x - horizontal coordinate; y - vertical coordinate) to a new value in order to obtain a different effect. If you want to create a filter that does geometric transformation, you could inherit from BaseOffsetFilter. You must override the method transform, which handles the coordinate change. In the following example, the customer filer perform a horizontal flip by changing the horizontal coordinate. The following is a very simple filter that applies geometric transformation. It basically exchanges each left-most horizontal pixel with its corresponding right-most pixel, hence, it gives a "mirror image", which is the original image flipped horizontally.

C#

1: /// <summary>
2: /// Perform the mirro filter, actually
                it is doing a horizontal flip
3: /// </summary>
4: class MirrorFilter : BaseOffsetFilter
5: {
6:     protected override void transform(float x, float y, out float new_x, out float new_y)
7:     {
8:         new_x = Bounds.Width - x;
9:         new_y = y;
10:     }
11: }

VB.NET

1: Public Class MirrorFilter
2:     Inherits BaseOffsetFilter
3:     Protected Overrides Sub transform(ByVal x As Single, ByVal y As Single, ByRef new_x As Single, ByRef new_y As Single)
4:         new_x = DrawArea.Width - x
5:         new_y = y
6:     End Sub
7: End Class

Color transformation

Color transformation means to change the original color at a specific pixel to a new color. In the following example, I am doing something interesting to simulate a posterization effect by inheriting from BaseColorFilter.

C#

1: /// <summary>
2: /// Performs the posterize filter
3: /// </summary>
4: class PosterizeFilter : BaseColorFilter
5: {
6:     private float _level = 10;
7:  
8:     public float Level
9:     {
10:         get { return _level; }
11:         set { if (value > 0 && value <= 100) _level = value; }
12:     }
13:  
14:     /// <summary>
15:     /// This method change the
                color at every pixel to a new color
16:     /// This effect is not tested
                carefully about the parameter range.
17:     /// It only tends to show a
                customer filter by inheriting the BaseColorFilter
18:     /// </summary>
19:     /// <param name="oldColor"></param>
20:     /// <param name="newColor"></param>
21:     protected override void transformColor(Color oldColor, out Color newColor)
22:     {
23:         byte red = (byte)( Math.Round(oldColor.R / _level) * _level) ;
24:         byte blue = (byte)(Math.Round(oldColor.B / _level) * _level);
25:         byte green = (byte)(Math.Round(oldColor.G / _level) * _level);
26:         newColor = Color.FromArgb(oldColor.A, red, blue, green);
27:     }
28: }

VB.NET

1: Public NotInheritable Class PosterizeFilter
2:     Inherits BaseColorFilter
3:  
4:     Private _level As Single
5:     ''' <summary>
6:     ''' Gets or sets the level.
7:     ''' </summary>
8:     ''' <value>The level.</value>
9:     Public Property Level() As Single
10:         Get
11:             Return _level
12:         End Get
13:  
14:         Set(ByVal value As Single)
15:             _level = value
16:         End Set
17:     End Property
18:  
19:     ''' <summary>
20:     ''' Define an algorithm to
                convert the specified color to a new color value
21:     ''' </summary>
22:     ''' <param name="oldColor">The
                specified original color</param>
23:     ''' <param name="newColor">The
                new color after the transformation</param>
24:     Protected Overrides Sub transformColor(ByVal oldColor As Color, ByRef newColor As Color)
25:         Dim red As Byte = IntToByte(Math.Round(oldColor.R / _level) * _level)
26:         Dim blue As Byte = IntToByte(Math.Round(oldColor.B / _level) * _level)
27:         Dim green As Byte = IntToByte(Math.Round(oldColor.G / _level) * _level)
28:  
29:         newColor = Color.FromArgb(oldColor.A, red, blue, green)
30:     End Sub
31:  
32: End Class

When use the above filter with a Level = 5, it generates the following result image (see the original here):

poterized image filter result

Complex Transformation Logic

Sometimes, you might need a more complex filter, such as reading several pixels' data, then you will have to inherit from BaseFilter and do the loop. In Beyond Photography, chapter 3, there is a formula to perform a fast and simple edge detection. The formula is :

new[ x, y ] = old[ x, y ] + ( Z/2 - old[ x+ 2, y + 2 ] )

If you read the book a little bit, you will know "Z" is defined as the maximum brightness value of the dots (pixels), which is normally 255 in RGB space. old[x,y] is defined as the data at the original pixel, new[x,y] is defined as the new data. So, I am going to use this formula to customer a fast edge detection filter.

C#

1: class FastEdgeDetectFilter : BaseFilter 
2: {
3:     /// <summary>
4:     /// A fast edge detect algorithm
5:     /// the formula is
6:     /// new [x,y] = old[x,y] + (Z/2
            - old[x+2, y+2])
7:     /// </summary>
8:     protected override void ApplyFilter()
9:     {
10:         // store the bitmap information
            first
11:         int width = this.Bounds.Width;
12:         int height = this.Bounds.Height;
13:  
14:         for (int x = 0; x < width; x++)
15:         {
16:             for (int y = 0; y < height; y++)
17:             {
18:                 if (x + 2 < width && y + 2 < height)
19:                 {
20:                     Color offset = getPixel(x + 2, y + 2);
21:                     Color current = getPixel(x, y);
22:                     // apply the
            algorithm
23:                     byte red = (byte)(current.R + (128 - offset.R));
24:                     byte green = (byte)(current.G + (128 - offset.G));
25:                     byte blue = (byte)(current.B + (128 - offset.B));
26:  
27:                     Color newColor = Color.FromArgb(red,green,blue);
28:                     setPixel(x, y, newColor);
29:                 }
30:             }
31:         }
32:     }
33: }

VB.NET

1: Public Class FastEdgeDetectFilter
2:     Inherits IC.PhotoController.Filter.BaseFilter
3:  
4:     ''' <summary>
5:     ''' Apply the filter algorithm
6:     ''' </summary>
7:     Protected Overrides Sub ApplyFilter()
8:  
9:         Dim width As Integer = DrawArea.Width
10:         Dim height As Integer = DrawArea.Height
11:         Dim startX As Integer = DrawArea.Left
12:         Dim startY As Integer = DrawArea.Right
13:  
14:         Dim x As Integer
15:         Dim y As Integer
16:  
17:         For x = startX To width
18:             For y = startY To height
19:                 If (x + 2 < width And y + 2 < height) Then
20:                     Dim offset As Color = getPixel(x + 2, y + 2)
21:                     Dim current As Color = getPixel(x, y)
22:  
23:                     Dim red As Byte
24:                     Dim blue As Byte
25:                     Dim green As Byte
26:  
27:                     red = IntToByte(current.R + (128 - offset.R))
28:                     green = IntToByte(current.G + (128 - offset.G))
29:                     blue = IntToByte(current.B + (128 - offset.B))
30:  
31:                     Dim newColor As Color = Color.FromArgb(red, green, blue)
32:                     setPixel(x, y, newColor)
33:                 End If
34:             Next
35:  
36:             If (NeedUpdatePercentage) Then
37:                 Dim percent As Integer
38:                 percent = CInt((x / (width * 1.0)) * 100)
39:                 UpdatePercentage(percent)
40:             End If
41:         Next
42:     End Sub
43: End Class

And here is the code to convert integer to byte in VB.NET

1: ''' <summary>
2: ''' Convert Integer to Byte in case
            the number is overflow or underflow
3: ''' </summary>
4: ''' <param name="num">The
            num.</param>
5: ''' <returns>a byte</returns>
6: Public Function IntToByte(ByVal num As Integer) As Byte
7:     If (num > 255) Then
8:         Return 255
9:     ElseIf (num < 0) Then
10:         Return 0
11:     Else
12:         Return CByte(num)
13:      End If
14: End Function

I will let you to experience how the result is like. You can try this custom fitler in the Demo application.

[Back to Top]
Comments

If you feel this page can be improved or has any mistake, please enter your valuable opinion here. Or if you cannot find the information you are after, feel free to suggest a subject too. I appreciate any voice.

Your Name:
  
Your Email Address:
  
Comments: