Article Purpose
The purpose of this article is to illustrate the tasks required when implementing a colour tint on a Bitmap image. 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 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.
Using the sample Application
The sample source code defined by this article creates a Windows Forms application, 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 Bitmap 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 Bitmap into memory by invoking the Bitmap.LockBits method. Once the source Bitmap 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. The Bitmap 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 byte 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 Bitmap 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
- C# How to: Image filtering by directly manipulating Pixel ARGB values
- C# How to: Image filtering implemented using a ColorMatrix
- C# How to: Blending Bitmap images using colour filters
- C# How to: Bitmap Colour Substitution implementing thresholds
- C# How to: Generating Icons from Images
- C# How to: Swapping Bitmap ARGB Colour Channels
- C# How to: Bitmap Pixel manipulation using LINQ Queries
- C# How to: Linq to Bitmaps – Partial Colour Inversion
- C# How to: Bitmap Colour Balance
- C# How to: Bi-tonal Bitmaps
- C# How to: Bitmap Colour Tint
- C# How to: Bitmap Colour Shading
- C# How to: Image Solarise
- C# How to: Image Contrast
- C# How to: Bitwise Bitmap Blending
41 Responses to “C# How to: Bitmap Colour Tint”