46

如何在 C# 中处理像素级别的图像?

我需要能够分别读取/修改每个位图像素 RGB 值。

代码示例将不胜感激。

4

4 回答 4

51

如果你想要速度,那么LockBits请参阅此处了解 Bob Powell 的精彩演练。如果你只想编辑一些,那么GetPixel / SetPixel应该做你想做的。

于 2008-10-10T07:19:05.583 回答
16

一个示例代码例程(我将其用于简单的合并和比较功能。它需要两张图像并生成第三张灰度图像,以灰度色调级别显示两幅图像之间的差异。它越暗,差异越大。):

    public static Bitmap Diff(Bitmap src1, Bitmap src2, int x1, int y1, int x2, int y2, int width, int height)
{
    Bitmap diffBM = new Bitmap(width, height, PixelFormat.Format24bppRgb);

    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {
            //Get Both Colours at the pixel point
            Color col1 = src1.GetPixel(x1 + x, y1 + y);
            Color col2 = src2.GetPixel(x2 + x, y2 + y);

            // Get the difference RGB
            int r = 0, g = 0, b = 0;
            r = Math.Abs(col1.R - col2.R);
            g = Math.Abs(col1.G - col2.G);
            b = Math.Abs(col1.B - col2.B);

            // Invert the difference average
            int dif = 255 - ((r+g+b) / 3);

            // Create new grayscale RGB colour
            Color newcol = Color.FromArgb(dif, dif, dif);

            diffBM.SetPixel(x, y, newcol);

        }
    }

    return diffBM;
}

Marc 的帖子记录了 LockBits 并使用它直接在内存中修改图像。如果性能是一个问题,我建议查看它而不是我发布的内容。谢谢马克!

于 2008-10-10T07:31:28.287 回答
5

System.Drawing.Bitmap 有一个返回 System.Drawing.Color 结构的 GetPixel(int x, int y) 公共方法。该结构具有字节成员 R、G、B 和 A,您可以直接修改它们,然后再次在 Bitmap 上调用 SetPixel(Color)。
不幸的是,这会相对较慢,但这是在 C# 中最简单的方法。如果您经常使用单个像素并发现性能不足,并且您需要更快的东西,您可以使用 LockBits...不过它要复杂得多,因为您需要了解该颜色深度和类型的位结构, 并使用位图的步幅,什么不是......所以如果你发现它是必要的,请确保你找到一个好的教程!网上有几个,谷歌搜索“C# LockBits”

于 2008-10-10T07:27:53.240 回答
3

如果性能至关重要,LockBits 的另一种替代方法是托管 DirectX。

有关更多信息,请参阅前面的 Stack Overflow 问题Rendering graphics in C#

与 Lockbits 一样,您将需要使用 unsafe 关键字/编译器开关,但您可以获得高性能的像素级访问。

与使用普通的 Bitmap 类和 PictureBox 控件相比,您还可以通过 DirectX 后缓冲获得更高性能的屏幕渲染。

于 2008-10-10T08:33:06.900 回答