Introduction

The purpose of this article is to explore and illustrate the concept of creating bitonal 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.

 
 

Building the Sample

There are no special requirements or instructions for building the sample source code.

 
 

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 Bitonal 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 bitonal . 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 bitonal images to the local file system the sample application makes provision through the Save Button.

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

 
 

The Bitonal Extension method 

The Bitonal Extension method defines all of the operations involved in creating Bitonal 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:

C#
Edit|Remove
public static Bitmap Bitonal(this Bitmap sourceBitmap, Color darkColor,  
                                     Color lightColor, int threshold)  
{ 
    BitmapData sourceData = sourceBitmap.LockBits(new Rectangle (00,  
                                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 (00,  
                            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.

 
 

Sample Images

The original source used to create all of the bitonal 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

Bitonal Images

Source Code Files

More Information

This article is based on an article originally posted on my http://softwarebydefault.com/2013/04/12/bitonal-bitmaps/ If you have any questions/comments please feel free to make use of the Q&A section on this page, also please remember to rate this article.

Dewald Esterhuizen