Posts Tagged 'Bitmap Tint'

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.


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);
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


Tinted Images


Related Articles

Dewald Esterhuizen

Blog Stats

  • 813,601 hits

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

Join 226 other followers


Twitter feed

%d bloggers like this: