【问题标题】:How to manipulate images at the pixel level in C#如何在 C# 中以像素级别操作图像
【发布时间】:2010-09-16 11:09:31
【问题描述】:

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

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

我们将不胜感激。

【问题讨论】:

    标签: c# image-processing image-manipulation


    【解决方案1】:

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

    【讨论】:

    • 不错。我从来没有费心研究超越设置/获取像素。感谢您的链接。
    • Bob Powell 没有告诉您的是,您实际上不需要在 C# 中处理指针。看看 MSDN 库中的 LockBits,有一个示例将内存复制到托管数组,其中方法未标记为不安全,因此应用程序不必是不安全的 :)
    • XNA 用户请注意,XBox360 .NET CF 不支持 System.Drawing 库,LockBits 所在的库。所以托管 DirectX 可能是您唯一的选择(感谢 Ash)。
    • 链接到“这里”的站点已关闭。
    • “这里”链接的网站现在是消息框弹出病毒骗局。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 托管 DirectX 现已弃用。
    【解决方案3】:

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

        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's post 注意到 LockBits 并使用它直接在内存中修改图像。如果性能是一个问题,我建议查看它而不是我发布的内容。谢谢马克!

    【讨论】:

    • 正如可能已经多次提到的那样,GetPixelSetPixel 是出了名的慢。 Bitmap.LockBitsMarshal.Copy 结合可以实现相同的效果,但以批量方式而不是逐像素方式获取数据,这使其加载速度更快。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-12-08
      • 2012-10-11
      • 1970-01-01
      • 2016-06-18
      • 2014-05-18
      • 1970-01-01
      • 1970-01-01
      • 2014-07-06
      相关资源
      最近更新 更多