Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process image pixel-by-pixel with WinAPI in a FAST WAY?

So, I make some simple image-processing program with GUI, C#. For example, I want to change image colors in HSV color model, converting each pixel from RGB and back again.

My program loads some picture by user choice and shows it in one of form's panel using its Graphics context. Then user can do something with this picture by moving scrollbars, clicking buttons, selecting some image area etc. When he do that I need in realtime change all the picture pixel-by-pixel. So, I write something like:

for (int x = 0; x < imageWidth; x++)
    for (int y = 0; y < imageHeight; y++)
        Color c = g.GetPixel(x, y);
        c = some_process_color_function_depending_on_user_controls(c);
        g.SetPixel(x, y)

And even if I work with Graphics in memory (not on the screen), functions GetPixel and SetPixel works VERY SLOW (so, as my program works so slow, I profiled it, and explained that these two functions are slowing down my program at most). So, I can't process big pictures in a few time as user moving slider or checking checkbox.

Please help! What can I do to make my program be fast? I nay agree to use other third-party libraries for graphics or change programming language!

like image 481
Abzac Avatar asked Sep 17 '12 21:09

Abzac


1 Answers

Yep, Get/SetPixel functions are very slow. Use Bitmap.LockBits() / UnlockBits() instead. It returns the raw bit data for you to manipulate.

From the msdn reference:

private void LockUnlockBitsExample(PaintEventArgs e)
{

    // Create a new bitmap.
    Bitmap bmp = new Bitmap("c:\\fakePhoto.jpg");

    // Lock the bitmap's bits.  
    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
    System.Drawing.Imaging.BitmapData bmpData = 
        bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
        bmp.PixelFormat);

    // Get the address of the first line.
   IntPtr ptr = bmpData.Scan0;

    // Declare an array to hold the bytes of the bitmap.
    // This code is specific to a bitmap with 24 bits per pixels.
    int bytes = bmp.Width * bmp.Height * 3;
    byte[] rgbValues = new byte[bytes];

    // Copy the RGB values into the array.
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);

    // Set every red value to 255.  
    for (int counter = 2; counter < rgbValues.Length; counter+=3)
        rgbValues[counter] = 255;

    // Copy the RGB values back to the bitmap
    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);

    // Unlock the bits.
    bmp.UnlockBits(bmpData);

    // Draw the modified image.
    e.Graphics.DrawImage(bmp, 0, 150);

}
like image 99
asawyer Avatar answered Nov 09 '22 01:11

asawyer