如何使用WinAPI快速逐像素处理图像?

7

我用C#编写了一些带有图形用户界面的简单图像处理程序。例如,我想在HSV颜色模型中更改图像颜色,并将每个像素从RGB转换回来。

我的程序通过用户选择加载一些图片,并在窗体的一个面板中使用其图形上下文显示它。然后,用户可以通过移动滚动条、点击按钮、选择某些图像区域等对这个图片进行一些操作。当用户执行这些操作时,我需要实时逐像素地更改整个图片。因此,我编写了类似以下的代码:

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)

即使我在内存中处理图形(而不是在屏幕上),GetPixel和SetPixel函数的速度非常慢(因此,由于我的程序运行非常缓慢,我对其进行了分析,并解释说这两个函数最大程度地减慢了我的程序)。因此,当用户移动滑块或选中复选框时,我无法在短时间内处理大型图片。
请帮忙!我该怎么做才能让程序更快?我可以考虑使用其他第三方图形库或改变编程语言!

1
使用分析工具,好棒!+1 - asawyer
1个回答

7

是的,Get/SetPixel函数非常慢。使用Bitmap.LockBits() / UnlockBits()代替。它会返回原始位数据供您操作。

来自msdn参考:

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);

}

@Abzac 如果这个速度太慢,你可以考虑使用XNA或托管的DirectX。 - asawyer
1
你可能能够通过使用不安全代码块来提高性能(尽管我不知道这是否会带来显著的节省)。http://www.bobpowell.net/lockingbits.htm - Chris Dunaway
“LockBits”等是正确的选择。我曾用它来处理和显示相机的实时图像。 - Bitterblue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接