Article Purpose
In this article you’ll find a discussion on the topic of blending Bitmap images into a single Image. Various possible methods can be employed in blending images. In this scenario image blending is achieved through means of bitwise operations, implemented on individual colour components Red, Green and Blue.
Sample source code
This article is accompanied by a sample source code Visual Studio project which is available for download here.
Bitwise Operations
In this article we will be implementing the following bitwise operators:
- & Binary And
- | Binary Or
- ^ Exclusive Binary Or (XOR)
A good description of how these operators work can be found on MSDN:
The bitwise-AND operator compares each bit of its first operand to the corresponding bit of its second operand. If both bits are 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
The bitwise-exclusive-OR operator compares each bit of its first operand to the corresponding bit of its second operand. If one bit is 0 and the other bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
The bitwise-inclusive-OR operator compares each bit of its first operand to the corresponding bit of its second operand. If either bit is 1, the corresponding result bit is set to 1. Otherwise, the corresponding result bit is set to 0.
Using the sample Application
Included with this article is a Visual Studio solution containing sample source code and a Windows Forms sample application. The Bitwise Bitmap Blending Sample application allows the user to select two input/source images from the local file system. Selected source images, once specified are displayed as previews with the majority of the application front end being occupied by an output PictureBox.
The following image is a screenshot of the Bitwise Bitmap Blending application in action:
If the user decides to, blended images can be saved to the local file system by clicking the Save button.
The BitwiseBlend Extension method
The Sample Source provides the definition for the BitwiseBlend extension method. This method’s declaration indicates being an extension method targeting the Bitmap class.
The BitwiseBlend method requires 4 parameters: the Bitmap being blended with and three parameters all of enum type BitwiseBlendType. The enumeration defines the available blending types in regards to bitwise operations. The following code snippet provides the definition of the BitwiseBlendType enum:
public enum BitwiseBlendType { None, Or, And, Xor }
The three BitwiseBlendType parameters relate to a pixel’s colour components: Red, Green and Blue.
The code snippet below details the implementation of the BitwiseBlend Extension method:
public static Bitmap BitwiseBlend(this Bitmap sourceBitmap, Bitmap blendBitmap, BitwiseBlendType blendTypeBlue, BitwiseBlendType blendTypeGreen, BitwiseBlendType blendTypeRed) { 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);
BitmapData blendData = blendBitmap.LockBits(new Rectangle(0, 0, blendBitmap.Width, blendBitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] blendBuffer = new byte[blendData.Stride * blendData.Height]; Marshal.Copy(blendData.Scan0, blendBuffer, 0, blendBuffer.Length); blendBitmap.UnlockBits(blendData);
int blue = 0, green = 0, red = 0;
for (int k = 0; (k + 4 < pixelBuffer.Length) && (k + 4 < blendBuffer.Length); k += 4) { if (blendTypeBlue == BitwiseBlendType.And) { blue = pixelBuffer[k] & blendBuffer[k]; } else if (blendTypeBlue == BitwiseBlendType.Or) { blue = pixelBuffer[k] | blendBuffer[k]; } else if (blendTypeBlue == BitwiseBlendType.Xor) { blue = pixelBuffer[k] ^ blendBuffer[k]; }
if (blendTypeGreen == BitwiseBlendType.And) { green = pixelBuffer[k+1] & blendBuffer[k+1]; } else if (blendTypeGreen == BitwiseBlendType.Or) { green = pixelBuffer[k+1] | blendBuffer[k+1]; } else if (blendTypeGreen == BitwiseBlendType.Xor) { green = pixelBuffer[k+1] ^ blendBuffer[k+1]; }
if (blendTypeRed == BitwiseBlendType.And) { red = pixelBuffer[k+2] & blendBuffer[k+2]; } else if (blendTypeRed == BitwiseBlendType.Or) { red = pixelBuffer[k+2] | blendBuffer[k+2]; } else if (blendTypeRed == BitwiseBlendType.Xor) { red = pixelBuffer[k+2] ^ blendBuffer[k+2]; }
if (blue < 0) { blue = 0; } else if (blue > 255) { blue = 255; }
if (green < 0) { green = 0; } else if (green > 255) { green = 255; }
if (red < 0) { red = 0; } else 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; }
All image manipulation tasks performed by the BitwiseBlend Extension method are implemented by directly accessing a Bitmap’s underlying raw pixel data.
A Bitmap first needs to be locked in memory by invoking the Bitmap.LockBits method. Once the Bitmap object has been locked in memory the method instantiates a byte array, representing a pixel data buffer. Each element present in the data buffer reflects an individual colour component: Alpha, Red, Green or Blue.
Take note: Colour component ordering is opposite to the expected ordering. Colour components are ordered: Blue, Green, Red, Alpha. The short explanation for reverse ordering can be attributed to Little Endian CPU architecture and Blue being represented by the least significant bits of a pixel.
In order to perform bitwise operations on each pixel representing the specified Bitmaps the sample source code employs a for loop, iterating both Bitmap data buffers. The possibility exists that the two Bitmaps specified might not have the same size dimensions. Notice how the for loop defines two conditional statements, preventing the loop from iterating past the maximum bounds of the smallest Bitmap.
Did you notice how the for loop increments the defined counter by four at each loop operation? The reasoning being that every four elements of the data buffer represents a pixel, being composed of: Blue, Green, Red and Alpha. Iterating four elements per iteration thus allows us to manipulate all the colour components of a pixel.
The operations performed within the for loop are fairly straight forward. The source code checks to determine which type of bitwise operation to implement per colour component. Colour components can only range from 0 to 255 inclusive, we therefore perform range checking before assigning calculated values back to the data buffer.
The final step performed involves creating a new resulting Bitmap object and populating the new Bitmap with the updated pixel data buffer.
Sample Images
In generating the sample images two source images were specified, a sunflower and bouquet of roses. The sunflower image has been released into the public domain and can be downloaded from Wikipedia. The bouquet of roses image has been licensed under the Creative Commons Attribution-Share Alike 3.0 Unported, 2.5 Generic, 2.0 Generic and 1.0 Generic license and can be downloaded from Wikipedia.
The Original Images |
![]() |
![]() |
The Blended 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