Click here to Skip to main content
11,566,437 members (49,577 online)
Click here to Skip to main content

Tagged as

Work with bitmaps faster in C#

, 15 Aug 2011 CPOL 114K 60
Rate this:
Please Sign up or sign in to vote.
The alternative solution, how to work with images faster.

When you are working with bitmaps in C#, you can use the GetPixel(x, y) and SetPixel(x, y, color) functions to get/set the pixel value. But they are very slow.

Here is the alternative way to work with bitmaps faster.

LockBitmap

With the LockBitmap class, we can lock/unlock bitmap data.

public class LockBitmap
{
    Bitmap source = null;
    IntPtr Iptr = IntPtr.Zero;
    BitmapData bitmapData = null;
 
    public byte[] Pixels { get; set; }
    public int Depth { get; private set; }
    public int Width { get; private set; }
    public int Height { get; private set; }
 
    public LockBitmap(Bitmap source)
    {
        this.source = source;
    }
 
    /// <summary>
    /// Lock bitmap data
    /// </summary>
    public void LockBits()
    {
        try
        {
            // Get width and height of bitmap
            Width = source.Width;
            Height = source.Height;
 
            // get total locked pixels count
            int PixelCount = Width * Height;
 
            // Create rectangle to lock
            Rectangle rect = new Rectangle(0, 0, Width, Height);
 
            // get source bitmap pixel format size
            Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
 
            // Check if bpp (Bits Per Pixel) is 8, 24, or 32
            if (Depth != 8 && Depth != 24 && Depth != 32)
            {
                throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
            }
 
            // Lock bitmap and return bitmap data
            bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite, 
                                         source.PixelFormat);
 
            // create byte array to copy pixel values
            int step = Depth / 8;
            Pixels = new byte[PixelCount * step];
            Iptr = bitmapData.Scan0;
 
            // Copy data from pointer to array
            Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
 
    /// <summary>
    /// Unlock bitmap data
    /// </summary>
    public void UnlockBits()
    {
        try
        {
            // Copy data from byte array to pointer
            Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);
 
            // Unlock bitmap data
            source.UnlockBits(bitmapData);
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
 
    /// <summary>
    /// Get the color of the specified pixel
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <returns></returns>
    public Color GetPixel(int x, int y)
    {
        Color clr = Color.Empty;
 
        // Get color components count
        int cCount = Depth / 8;
 
        // Get start index of the specified pixel
        int i = ((y * Width) + x) * cCount;
 
        if (i > Pixels.Length - cCount)
            throw new IndexOutOfRangeException();
 
        if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
        {
            byte b = Pixels[i];
            byte g = Pixels[i + 1];
            byte r = Pixels[i + 2];
            byte a = Pixels[i + 3]; // a
            clr = Color.FromArgb(a, r, g, b);
        }
        if (Depth == 24) // For 24 bpp get Red, Green and Blue
        {
            byte b = Pixels[i];
            byte g = Pixels[i + 1];
            byte r = Pixels[i + 2];
            clr = Color.FromArgb(r, g, b);
        }
        if (Depth == 8)
        // For 8 bpp get color value (Red, Green and Blue values are the same)
        {
            byte c = Pixels[i];
            clr = Color.FromArgb(c, c, c);
        }
        return clr;
    }
 
    /// <summary>
    /// Set the color of the specified pixel
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="color"></param>
    public void SetPixel(int x, int y, Color color)
    {
        // Get color components count
        int cCount = Depth / 8;
 
        // Get start index of the specified pixel
        int i = ((y * Width) + x) * cCount;
 
        if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha
        {
            Pixels[i] = color.B;
            Pixels[i + 1] = color.G;
            Pixels[i + 2] = color.R;
            Pixels[i + 3] = color.A;
        }
        if (Depth == 24) // For 24 bpp set Red, Green and Blue
        {
            Pixels[i] = color.B;
            Pixels[i + 1] = color.G;
            Pixels[i + 2] = color.R;
        }
        if (Depth == 8)
        // For 8 bpp set color value (Red, Green and Blue values are the same)
        {
            Pixels[i] = color.B;
        }
    }
}

Benchmark

To test LockBitmap's performance, we can use the Benchmark class.

public class Benchmark
{
    private static DateTime startDate = DateTime.MinValue;
    private static DateTime endDate = DateTime.MinValue;
 
    public static TimeSpan Span { get { return endDate.Subtract(startDate); } }
 
    public static void Start() { startDate = DateTime.Now; }
 
    public static void End() { endDate = DateTime.Now; }
 
    public static double GetSeconds()
    {
        if (endDate == DateTime.MinValue) return 0.0;
        else return Span.TotalSeconds;
    }
}

Usage

Now we can use the LockBitmap class to work with images very fast.

public void ChangeColor()
{
    Bitmap bmp = (Bitmap)Image.FromFile("d:\\source.png");
    Benchmark.Start();
    LockBitmap lockBitmap = new LockBitmap(bmp);
    lockBitmap.LockBits();
 
    Color compareClr = Color.FromArgb(255, 255, 255, 255);
    for (int y = 0; y < lockBitmap.Height; y++)
    {
        for (int x = 0; x < lockBitmap.Width; x++)
        {
            if (lockBitmap.GetPixel(x, y) == compareClr)
            {
                lockBitmap.SetPixel(x, y, Color.Red);
            }
        }
    }
    lockBitmap.UnlockBits();
    Benchmark.End();
    double seconds = Benchmark.GetSeconds();
    bmp.Save("d:\\result.png");
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Vano Maisuradze
Software Developer (Senior)
Georgia Georgia
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionNeed to correct for stride Pin
Member 1086906713-May-15 6:52
memberMember 1086906713-May-15 6:52 
AnswerRe: Need to correct for stride Pin
Vano Maisuradze13-May-15 8:18
memberVano Maisuradze13-May-15 8:18 
QuestionAn unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll Pin
Member 116585561-May-15 22:46
memberMember 116585561-May-15 22:46 
AnswerRe: An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll Pin
Member 116585562-May-15 1:23
memberMember 116585562-May-15 1:23 
GeneralMy vote of 5 Pin
Member 1071724430-Sep-14 21:32
memberMember 1071724430-Sep-14 21:32 
QuestionAnother samples comparatively Pin
Melih_123_melih5-Sep-14 4:28
memberMelih_123_melih5-Sep-14 4:28 
BugI found a bug Pin
94HellGate26-Sep-13 7:56
member94HellGate26-Sep-13 7:56 
GeneralRe: I found a bug Pin
94HellGate26-Sep-13 8:00
member94HellGate26-Sep-13 8:00 
QuestionNot work for my picture Pin
froxplus24-Jun-13 23:34
memberfroxplus24-Jun-13 23:34 
QuestionLag : 0 inserted at each end of ligne Pin
Member 97338579-Jun-13 1:58
memberMember 97338579-Jun-13 1:58 
AnswerRe: Lag : 0 inserted at each end of ligne Pin
Vano Maisuradze9-Jun-13 18:04
memberVano Maisuradze9-Jun-13 18:04 
QuestionGet XY from 8bpp and then draw it in same bmp but in 24bpp format Pin
Mikgau16-Apr-13 0:09
memberMikgau16-Apr-13 0:09 
AnswerRe: Get XY from 8bpp and then draw it in same bmp but in 24bpp format Pin
Mikgau16-Apr-13 3:18
memberMikgau16-Apr-13 3:18 
QuestionLockBitmap --> Bitmap ? Pin
ssseeegggeee19-Jan-13 0:36
memberssseeegggeee19-Jan-13 0:36 
AnswerRe: LockBitmap --> Bitmap ? Pin
Vano Maisuradze21-Feb-13 5:44
memberVano Maisuradze21-Feb-13 5:44 
GeneralMy vote of 5 Pin
akaki kapanadze17-Nov-12 2:16
memberakaki kapanadze17-Nov-12 2:16 
GeneralMy vote of 5 Pin
Andre Belloti6-Nov-12 6:54
memberAndre Belloti6-Nov-12 6:54 
GeneralMy vote of 5 Pin
PGT29-Oct-12 4:59
memberPGT29-Oct-12 4:59 
great code samples
Questioni get some errors what references did you use ? Pin
PGT26-Oct-12 9:20
memberPGT26-Oct-12 9:20 
AnswerRe: i get some errors what references did you use ? Pin
Vano Maisuradze27-Oct-12 10:57
memberVano Maisuradze27-Oct-12 10:57 
QuestionActual timings, and another code performance enhancement Pin
Rainer Gustin17-Aug-12 9:42
memberRainer Gustin17-Aug-12 9:42 
GeneralReason for my vote of 5 nice one. Pin
nikhi _singh27-Feb-12 2:59
membernikhi _singh27-Feb-12 2:59 
GeneralFor a good explanation of what is happening... http://bobpo... Pin
Steve Wellens17-Nov-11 7:56
memberSteve Wellens17-Nov-11 7:56 
GeneralReason for my vote of 5 There are things to improve... but t... Pin
Paulo Zemek17-Nov-11 2:09
mvpPaulo Zemek17-Nov-11 2:09 
GeneralRe: Thanks Pin
Vano Maisuradze17-Nov-11 3:36
memberVano Maisuradze17-Nov-11 3:36 
GeneralReason for my vote of 5 Very useful. Solves a couple of pro... Pin
Greg Otto22-Aug-11 14:33
memberGreg Otto22-Aug-11 14:33 
GeneralRe: Thank you Pin
Vano Maisuradze22-Aug-11 21:19
memberVano Maisuradze22-Aug-11 21:19 
GeneralReason for my vote of 5 Nice example. Very straightforward. Pin
Tom Welch15-Aug-11 5:36
memberTom Welch15-Aug-11 5:36 
GeneralRe: Thank you. Pin
Vano Maisuradze17-Nov-11 3:36
memberVano Maisuradze17-Nov-11 3:36 
GeneralReason for my vote of 5 Oh nice it helpful Pin
Pritesh Aryan15-Aug-11 2:27
memberPritesh Aryan15-Aug-11 2:27 
GeneralRe: Thank you. Pin
Vano Maisuradze17-Nov-11 3:36
memberVano Maisuradze17-Nov-11 3:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150624.2 | Last Updated 15 Aug 2011
Article Copyright 2011 by Vano Maisuradze
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid