Posts Tagged 'Bitmap'



C# How to: Image Solarise

Article Purpose

The focus of this is set on exploring the concept of . In this the tasks required to perform   are entirely implemented on pixel data level. manipulation is only implemented in the form of updating the individual Alpha, Red, Green and Blue colour components expressed by pixels.

Sample source code

This is accompanied by a sample source code Visual Studio project which is available for download here.

Download Sample Source Code

What is Image Solarisation?

can be described as a form of Image inversion/colour inversion. A distinction can be made  between solarisation and colour inversion when taking into regard threshold values implemented when performing image solarisation.

Colour inversion can be implemented by subtracting each colour component from the value 255 and then assigning the relevant colour component to the result of subtraction. Colour inversion in terms of a formula can be expressed as follows:

R = 255 – R1

G = 255 – G1

B = 255 – B1

In this expression R1 G2 and B1 represent the original value of a pixel’s Red, Green and Blue colour components prior to being updated. when expressed as a formula could be represented as follows:

R = R1

If R1 < RT   Then R = 255 – R1

G = G1

If G1 < GT   Then G = 255 – G1

B = B1

If B1 < BT   Then B = 255 – B1

When implementing this expression R1 G1 and B1 represent the original value of a pixel’s Red, Green and Blue colour components prior to being updated. RT GT and BT in this scenario represent configurable threshold values applicable to individual colour components. If a colour component’s original value equates to less than the corresponding threshold value only then should colour inversion be implemented.

Using the sample Application

The concepts discussed in this are implemented/tested by means of a Windows Forms application. When using the sample application a user has the ability to browse the local file system in order to specify a source/input image. The user interface includes three trackbar controls, each related to a colour component threshold value. Threshold values can range from 0 to 255 inclusive. A threshold value of 0 results in no change, whereas a value of 255 equates to regular colour inversion.

Updated/filtered images can be saved to the local file system at any stage by clicking the ‘Save Image’ button.

The following image is a screenshot of the Image Solarise sample application in action:


ImageSolarise_Screenshot


The Solarise Extension Method

The sample source code provides the definition for the Solarise extension method. The method has been defined as an extension method targeting the class.

The following code snippet details the implementation of the Solarise extension method:

 public static Bitmap Solarise(this Bitmap sourceBitmap, byte blueValue, 
                              byte greenValue, byte redValue) 
{ 
    BitmapData sourceData = sourceBitmap.LockBits(new Rectangle  (0, 0, 
                            sourceBitmap.Width, sourceBitmap.Height), 
                            ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
byte byte255 = 255;
for (int k = 0; k + 4 < pixelBuffer.Length; k += 4) { if (pixelBuffer[k] < blueValue) { pixelBuffer[k] = (byte)(byte255 - pixelBuffer[k]); }
if (pixelBuffer[k + 1] < greenValue) { pixelBuffer[k + 1] = (byte)(byte255 - pixelBuffer[k + 1]); }
if (pixelBuffer[k + 2] < redValue) { pixelBuffer[k + 2] = (byte)(byte255 - pixelBuffer[k + 2]); } }
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height); BitmapData resultData = resultBitmap.LockBits(new Rectangle (0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(pixelBuffer, 0, resultData.Scan0, pixelBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

In order to manipulate pixel colour component values directly we first need to lock the source into memory by invoking the Bitmap.LockBits method. Once the source is locked into memory we can copy the underlying pixel buffer using the Marshal.Copy method.

The next step involves iterating through the byte buffer of colour components. Notice how each iteration modifies an entire pixel by iterating by 4. As discussed earlier when implementing image solarisation the associated formula employs threshold comparison, which determines whether or not colour inversion should be applied.

The final operation performed by the Solarise method involves copying the modified pixel buffer into a newly created object which will be returned to the calling code.

Sample Images

The original source image used to create all of the solarised sample images in this has been licensed under the Creative Commons Attribution-Share Alike 3.0 Unported, 2.5 Generic, 2.0 Generic and 1.0 Generic license. The original image is attributed to Kenneth Dwain Harrelson and can be downloaded from Wikipedia.

The Original Image

 

Monarch_In_May

Solarised Images

 

Butterfly1 Butterfly2
Butterfly3 Butterfly4
Butterfly5 Butterfly7
Butterfly8 Butterfly10

Related Articles

C# How to: Bitmap Colour Shading

Article Purpose

The objective of this article is focussed on exploring the concept of applying to images. The various Bitmap manipulation operations detailed in this article are all exclusively implemented by processing raw pixel data. No traditional GDI+ drawing operations are required in implementing .

Processor10 Processor11 Processor12 Processor13

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

Download Sample Source Code

Processor5 Processor6 Processor7 Processor9

Using the sample Application

This article has been written from a practical implementation point of view. The concepts detailed throughout this article are all coupled with a corresponding source code implementation. A sample application has been provided with this article. The  sample application has been implemented in the architecture of a , of which a complete source code implementation has also been provided. The sample application facilitates implementing and testing the concepts surrounding as discussed in this article.

Processor31 Processor22 Processor16 Processor47

In using the Bitmap Shading sample application users have the ability to select a source/input from the local file system. The user interface facilitates implementing through three trackbar controls, each associated with a  colour component. The value range of each trackbar control is defined from 0 to 100 inclusive. A value of 100 equates to no change and a value of 0 equating to the most possible change.

Processor51 Processor50 Processor49 Processor57

Users are able to save to the local file system any modified images by clicking the ‘Save Image’ button and providing a file path and file name.

The screenshot below illustrates the Bitmap Shading application in action:


BitmapShading_Screenshot


Processor25 Processor24 Processor23 Processor22

The ColorShade Extension method

The ColorShade extension method forms the crux of this article. The ColorShade method has been defined as an extension method targeting the class. It is within this method that all raw pixel manipulation occurs. In essence each pixel expressed by the specified image will be extracted upon which calculations are performed updating the value of Alpha, Red, Green and Blue colour components.

Processor28 Processor29 Processor30 Processor31

The following code snippet details the implementation of the ColorShade extension method:

 public static Bitmap ColorShade(this Bitmap sourceBitmap, float blueShade, 
                                float greenShade, float redShade) 
{
    BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, 
                            sourceBitmap.Width, sourceBitmap.Height), 
                            ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
float blue = 0; float green = 0; float red = 0;
for (int k = 0; k + 4 < pixelBuffer.Length; k += 4) { blue = pixelBuffer[k] * blueShade; green = pixelBuffer[k + 1] * greenShade; red = pixelBuffer[k + 2] * redShade;
if (blue < 0) { blue = 0; }
if (green < 0) { green = 0; }
if (red < 0) { red = 0; }
pixelBuffer[k] = (byte)blue; pixelBuffer[k + 1] = (byte)green; pixelBuffer[k + 2] = (byte)red; }
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(pixelBuffer, 0, resultData.Scan0, pixelBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }
Processor26 Processor1 Processor51 Processor24

In order to manipulate pixel colour component values directly we first need to lock the source into memory by invoking the method. Once the source is locked into memory we can copy the underlying pixel buffer using the method.

Processor39 Processor13 Processor64 Processor16

The next step involves iterating through the buffer of colour components. Notice how each iteration modifies an entire pixel by iterating by 4. The formula being implemented can be expressed as:

R = R1 * RS

G = G1 * GS

B = B1 * BS

In the stated equation R1 G1 and B1 represents the original value of a colour component and RS GS and BS equates to the percentage of shading expressed by each colour component. Take note that in this scenario shading percentages are defined in terms of a fractional value. As an example 45% would result in a shading factor of 0.45.

Processor59 Processor60 Processor61 Processor62

Sample Images

The original image file used in this article was authored by Konstantin Lanzet and is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported license, and can be downloaded from Wikipedia.

The Original Image

KL_Intel_D8086

Colour Shaded Images

Processor6
Processor11
Processor38
Processor20
Processor22
Processor31

Related Articles

C# How to: Bitmap Colour Tint

Article Purpose

The purpose of this article is to illustrate the tasks required when implementing a colour tint on a  . The various manipulation operations detailed in this article are all exclusively implemented by processing raw pixel data. No traditional GDI+ drawing operations are required in achieving the objective of this article.

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

Download Sample Source Code

Using the sample Application

The sample source code defined by this article creates a , allowing for easily replicating/testing the scenarios illustrated. The Bitmap Tint sample application provides the user with the ability to select a source/input image from browsing the local file system.

The user interface enables the user to apply colour tinting to the selected source image through 3 trackbar controls. Each trackbar control represents a colour component, Red, Green or Blue. Trackbar input translate to a percentage value, where 0% equates to no change and 100% equating to the most possible change.

Modified images can persisted to the local file system through the functionality expressed by the Save Button.

The following image is a screenshot of the Bitmap Tint sample application.


BitmapTint


The ColorTint Extension method

This sample source code that accompanies this article provides the definition of the ColorTint method, an extension method targeting the class. The ColorTint method manipulates pixel colour components directly, processing the Alpha, Red, Green and Blue values expressed in a pixel.

The code snippet below details the implementation of the ColorTint extension method:

 public static Bitmap ColorTint(this Bitmap sourceBitmap, float blueTint,  
                                 float greenTint, float redTint) 
{
    BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0, 
                            sourceBitmap.Width, sourceBitmap.Height), 
                            ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
float blue = 0; float green = 0; float red = 0;
for (int k = 0; k + 4 < pixelBuffer.Length; k += 4) { blue = pixelBuffer[k] + (255 - pixelBuffer[k]) * blueTint; green = pixelBuffer[k + 1] + (255 - pixelBuffer[k + 1]) * greenTint; red = pixelBuffer[k + 2] + (255 - pixelBuffer[k + 2]) * redTint;
if (blue > 255) { blue = 255; }
if (green > 255) { green = 255; }
if (red > 255) { red = 255; }
pixelBuffer[k] = (byte)blue; pixelBuffer[k + 1] = (byte)green; pixelBuffer[k + 2] = (byte)red;
}
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(pixelBuffer, 0, resultData.Scan0, pixelBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

In order to manipulate pixel colour component values directly we first need to lock the source into memory by invoking the method. Once the source is locked into memory we can copy the underlying pixel buffer using the method.

The next step involves iterating through the buffer of colour components. Notice how each iteration modifies an entire pixel by iterating by 4. The tint formula can be expressed as follows:

R = R1 + (255 – R1)* RT

G = G1 + (255 – G1)* GT

B = B1 + (255 – B1)* BT

In formula above R1 G1 and B1 represents the original value of a colour component, RT GT and BT in turn represents a colour component tint percentage. Note that tint values are expressed as fractional values. As an example, if the user specified a Blue tint value of 75% on the front end, the value used in the formula equates to 0.75.

Red, Green and Blue colour component values cannot exceed 255 as a result of being values. Before assigning the newly calculated colour component values the source code first determines if calculated values exceed 255. All values exceeding 255 will be set to 255.

The last step performed is to copy the modified pixel buffer into a new object.

Sample Images

The original image has been released under the Creative Commons Attribution 3.0 License. The original image can be downloaded from Wikipedia.

The Original Image

800px-Before-sunrise-perse-rock

Tinted Images

Sunrise1
Sunrise2
Sunrise3
Sunrise4
Sunrise5
Sunrise6

Related Articles

C# How to: Bi-tonal Bitmaps

Article Purpose

The purpose of this article is to explore and illustrate the concept of creating bi-tonal images. Colour images are manipulated in such a fashion to only express two colours. The colours expressed are configurable. A threshold value determines which of the two configured colours will be applied to a pixel.

Bitonal_Banner1

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download here.

Download Sample Source Code

Bitonal_Banner2

Using the sample Application

The concepts explored in this article are easily illustrated using the Sample Application provided with the sample source code. The sample application is implemented as a Windows Forms application.

The Bi-tonal Bitmap application enables the user to load an input image file from the local file system. The user interface defines two panels representing the two colours used when creating the resulting bi-tonal . When clicking on either panel the user will be presented with a colour dialog, allowing the user to change the colour of the specific panel.

The user interface also provides a trackbar which allows the user to set the threshold used to calculate if a pixel colour should be set to the dark colour or light colour value.

If the user desires to save resulting bi-tonal images to the local file system the sample application makes provision through the Save Button.

The following image provides a screenshot of the Bi-tonal Bitmap application in action:


BiTonalBitmap_Screenshot


The Bitonal Extension Method

The Bitonal Extension method defines all of the operations involved in creating Bi-tonal images. This method is an extension method targeting the class. Note that the Bitonal extension method manipulates pixel colour components directly, in other words updating a pixel’s Alpha, Red, Green and Blue values directly.

The following code snippet provides the definition of the Bitonal method:

 public static Bitmap Bitonal(this Bitmap sourceBitmap, Color darkColor, 
                                     Color lightColor, int threshold) 
{
    BitmapData sourceData = sourceBitmap.LockBits(new Rectangle (0, 0, 
                                sourceBitmap.Width, sourceBitmap.Height), 
                                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
for (int k = 0; k + 4 < pixelBuffer.Length; k += 4) { if (pixelBuffer[k] + pixelBuffer[k + 1] + pixelBuffer[k + 2] <= threshold) { pixelBuffer[k] = darkColor.B; pixelBuffer[k + 1] = darkColor.G; pixelBuffer[k + 2] = darkColor.R; } else { pixelBuffer[k] = lightColor.B; pixelBuffer[k + 1] = lightColor.G; pixelBuffer[k + 2] = lightColor.R; } }
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle (0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(pixelBuffer, 0, resultData.Scan0, pixelBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

In order to manipulate pixel colour component values directly we first need to lock the source into memory by invoking the method. Once the source is locked into memory we can copy the underlying pixel buffer using the method.

The next step involves iterating through the buffer of colour components. Notice how each iteration modifies an entire pixel by iterating by 4. In order to determine to which colour a pixel should be set, the sum of Red, Green and Blue colour components is to the threshold parameter.

The last step performed is to copy the modified pixel buffer into a new object.

Bitonal_Banner1

Sample Images

The original source used to create all of the bi-tonal sample images in this article has been licensed under the Creative Commons Attribution-Share Alike 3.0 Unported, 2.5 Generic, 2.0 Generic and 1.0 Generic license. The original image is attributed to Kenneth Dwain Harrelson and can be downloaded from Wikipedia.

The Original Image


Monarch_In_May


Bi-tonal Images

 

Butterfly1 Butterfly2
Butterfly3 Butterfly4
Butterfly5 Butterfly6
Butterfly7 Butterfly8
Butterfly9 Butterfly10
Butterfly11 Butterfly12

Related Articles

C# How to: Bitmap Colour Balance

Article Purpose

This explores the concept of manipulating the of a  . values are updated by directly manipulating a ’s underlying pixel data, no GDI drawing code required.

Sample source code

This is accompanied by a sample source code Visual Studio project which is available for download here.

Download Sample Source Code

Using the sample Application

The concepts explored in this are easily illustrated using the Sample Application provided with the sample source code. The sample application is implemented as a .

The Bitmap Colour Balance application enables the user to load an input image file from the local file system. The user interface provides three trackbar controls representing the colour components Blue, Green and Red. Possible values range from 0 to 255 inclusive. The application performs image filtering on the specified image as the user moves the colour component sliders.

If the user desires to save modified/filtered images to the local file system the sample application makes provision through the Save Button.

The following image provides a screenshot of the Bitmap Colour Balance application in action:


BitmapColorBalance


Colour Balance

Whilst developing the sample source code and writing this I found the article on to be very informative and comprehensive. I would recommend it as a must read for developers with little or no experience around colour representation in digital imaging.

From Wikipedia we get the following quote:

In and , color balance is the global adjustment of the intensities of the colors (typically red, green, and blue ). An important goal of this adjustment is to render specific colors – particularly neutral colors – correctly; hence, the general method is sometimes called gray balance, neutral balance, or white balance. Color balance changes the overall mixture of colors in an image and is used for color correction; generalized versions of color balance are used to get colors other than neutrals to also appear correct or pleasing.

From the quoted text we determine that refers to a method of implementing image filtering as a corrective action when the colours expressed by an image vary from the expected norm.

Literally as the name implies filtering attempts to provide greater balance in image colours. The colours considered to be out of balance with the rest of the image will be filtered out to varying degrees resulting in an image having a more natural appearance.

Accessing Pixel data directly

In this we do not perform traditional drawing operations such as the functionality exposed by the GDI+ Library. We are going to explore the tasks involved in directly accessing and manipulating the pixel buffer data that underlies a object instance. In order for our changes to persist we will also explore the tasks required to re-create an instance of the class and explicitly set/populate pixel data. The tasks referred to are discussed and implemented in the following section.

Locking the bytes inside a Bitmap

In this section we’ll be exploring a brief overview of how to access a ’s underlying array of colour components. Its important to remember that colour components are ordered: Blue, Green, Red, Alpha.

To access a ’s internal array of colour components we make use of the method. From :

Use the method to lock an existing bitmap in system memory so that it can be changed programmatically. You can change the color of an image with the method, although the LockBits method offers better performance for large-scale changes.

The specifies the attributes of the , such as size, pixel format, the starting address of the pixel data in memory, and length of each scan line (stride).

When calling this method, you should use a member of the enumeration that contains a specific bits-per-pixel (BPP) value. Using values such as and will throw an . Also, passing the incorrect pixel format for a bitmap will throw an .

Why lock a in memory? The architecture behind the and memory management through the necessitates locking a in memory before accessing the underlying data. As an application executes periodically the invokes various operations. Part of the ’s function involves relocating objects in memory. As described by :

A garbage collection has the following phases:

  • A marking phase that finds and creates a list of all live objects.

  • A relocating phase that updates the references to the objects that will be compacted.

  • A compacting phase that reclaims the space occupied by the dead objects and compacts the surviving objects. The compacting phase moves objects that have survived a garbage collection toward the older end of the segment.

When locking a through invoking the method you are effectively signalling the to not relocate in memory the being locked. Consider a scenario where, whilst accessing and manipulating a array of colour components, the starts to relocate the associated instance in memory. Without warning the memory being referenced is no longer associated with the object initially referenced.

Note: If you lock a into memory you must also unlock the object by invoking the method.

The method defines a return value of type . Properties exposed by the class to pay attention to: and , as discussed in the following section.

Copying  bytes from a Bitmap

The property is described by as follows:

The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.

In essence a scan line refers to how many are required to represent a row of pixels. A 32 bits per pixel Argb equates to each pixel occupying 4 bytes of memory. The value of the property can be calculated as [Bitmap Width x 4] : rounded up to the first multiple of 4.

Also defined by the class is the property . We can consider a as a grid of rows and columns, essentially a two dimensional array with each element being 1 . The property provides us with how many colour components are expressed by a ’s row of pixels. To determine the total number of colour components expressed by a we simply have to multiply the properties and .

The property, which is of type , is described by as follows:

Gets or sets the address of the first pixel data in the bitmap. This can also be thought of as the first scan line in the bitmap.

We now know the size of the data we want to copy, we also know the address in memory where to start copying a ’s internal colour component array. To perform the actual copy operation we invoke the method.

The ColorBalance Extension method

The crux of this can be found in the ColorBalance extension method. It is only within the ColorBalance method that we will be referencing pixel data directly. Note that this method is defined as an extension method targeting the class.

The ColorBalance method requires 3 parameters. The parameters represent the values to be used in calculating resulting Blue, Green and Red colour component values. The following code snippet details the definition of the ColorBalance method:

 public static Bitmap ColorBalance(this Bitmap sourceBitmap, byte blueLevel,  
                                    byte greenLevel, byte redLevel) 
{ 
     BitmapData sourceData = sourceBitmap.LockBits(new  ectangle (0, 0,  
                                 sourceBitmap.Width, sourceBitmap.Height),  
                                 ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); 

byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
float blue = 0; float green = 0; float red = 0;
float blueLevelFloat = blueLevel; float greenLevelFloat = greenLevel; float redLevelFloat = redLevel;
for (int k = 0; k + 4 < pixelBuffer.Length; k += 4) { blue = 255.0f / blueLevelFloat * (float )pixelBuffer[k]; green = 255.0f / greenLevelFloat * (float)pixelBuffer[k + 1]; red = 255.0f / redLevelFloat * (float)pixelBuffer[k + 2]; if (blue > 255) {blue = 255;} else if (blue < 0) {blue = 0;} if (green > 255) {green = 255;} else if (green < 0) {green = 0;} if (red > 255) {red = 255;} else if (red < 0) {red = 0;} pixelBuffer[k] = (byte)blue; pixelBuffer[k + 1] = (byte)green; pixelBuffer[k + 2] = (byte)red; }
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0, resultBitmap.Width,resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(pixelBuffer, 0, resultData.Scan0, pixelBuffer.Length); resultBitmap.UnlockBits(resultData);
return resultBitmap; }

As discussed in previous sections we create an array of and copy the specified object’s underlying values.

The bulk of the work performed by this method happens within the for loop which iterates through the buffer of colour components. Notice how with each loop we increment by 4, the reason being each loop operation modifies 4 at a time. One pixel in terms of the ARGB format equates to 4 , thus each time we loop, we modify 1 pixel.

The formula implemented can be expressed as follows:

R = 255 / Rw * R1

G = 255 / Gw * G1

B = 255 / Bw * B1

Where Rw  Gw and Bw represents the value of a colour component believed to represent White and R1 G1 and B1 representing the original value of a colour component before implementing the colour balance formula.

The value of a colour component can only range between 0 and 255 inclusive. Before setting the newly calculated values we have to check if calculated values range between 0 and 255.

The last operation performed by the ColorBalance Extension method involves creating a new image based on the same size dimensions as the source image. Once the has been locked into memory we copy the modified buffer using the method.

Sample Images

This section illustrates a few scenarios implementing the filter.

Fun Fact: The first image is a photograph I snapped at OR Tambo International Airport, Johannesburg, South Africa. The second photograph I snapped at Hosea Kutako International Airport, Windhoek, Namibia.

The Original Image


Airport_Original1


Colour Balanced Images

 

Airport1 Airport2
Airport3 Airport4
Airport5 Airport6

The Original Image


Airport_Original2


Colour Balanced Images

 

Airport7 Airport8
Airport9 Airport10
Airport11 Airport12

Related Articles


Dewald Esterhuizen

Blog Stats

  • 728,523 hits

Enter your email address to follow and receive notifications of new posts by email.

Join 222 other followers

Archives

Twitter feed


%d bloggers like this: