首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C# LockBits perfomance (int[,] to byte[])

C# LockBits perfomance (int[,] to byte[])
EN

Stack Overflow用户
提问于 2011-09-24 07:21:42
回答 5查看 3.3K关注 0票数 3
代码语言:javascript
复制
Graphics g;
using (var bmp = new Bitmap(_frame, _height, PixelFormat.Format24bppRgb))
{
    var data = bmp.LockBits(new Rectangle(0, 0, _frame, _height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
    var bmpWidth = data.Stride;
    var bytes = bmpWidth * _height;
    var rgb = new byte[bytes];
    var ptr = data.Scan0;
    Marshal.Copy(ptr, rgb, 0, bytes);

    for (var i = 0; i < _frame; i++)
    {
        var i3 = (i << 1) + i;
        for (var j = 0; j < _height; j++)
        {
            var ij = j * bmpWidth + i3;
            var val = (byte)(_values[i, j]);
            rgb[ij] = val;
            rgb[ij + 1] = val;
            rgb[ij + 2] = val;
        }
    }

    Marshal.Copy(rgb, 0, ptr, bytes);
    bmp.UnlockBits(data);

    g = _box.CreateGraphics();
    g.InterpolationMode = InterpolationMode.NearestNeighbor;
    g.DrawImage(bmp, 0, 0, _box.Width, _box.Height);
}
g.Dispose();

我使用这段代码在PictureBox中转换RGB值数组​​(灰度),但速度很慢。请告诉我我的错误。目前,一个441,000个项目的数组处理了35毫秒。我需要在同一时间内处理400万的数组。

EN

回答 5

Stack Overflow用户

发布于 2011-09-24 07:42:16

您可以跳过将数据从映像复制到数组的第一个Array.Copy,因为无论如何您都将覆盖数组中的所有数据。

这将减少大约25%的时间,但如果你想更快,你将不得不使用不安全的代码块,以便您可以使用指针。这样,您可以在访问数组时绕过范围检查,并且可以直接将数据写入图像数据,而不是复制它。

票数 5
EN

Stack Overflow用户

发布于 2011-09-25 05:10:37

我完全同意Guffa的回答。使用不安全的代码块会加快速度。要进一步提高性能,可以使用.Net框架中的Parallel类并行执行for循环。对于较大的位图,这会提高性能。下面是一个小的代码示例:

代码语言:javascript
复制
using (Bitmap bmp = (Bitmap)Image.FromFile(@"mybitmap.bmp"))
{
  int width = bmp.Width;
  int height = bmp.Height;

  BitmapData bd = bmp.LockBits(new Rectangle(0, 0, width, height),
    System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

  byte* s0 = (byte*)bd.Scan0.ToPointer();
  int stride = bd.Stride;

  Parallel.For(0, height, (y1) =>
  {
    int posY = y1*stride;
    byte* cpp = s0 + posY;

    for (int x = 0; x < width; x++)
    {              
      // Set your pixel values here.
      cpp[0] = 255;
      cpp[1] = 255;
      cpp[2] = 255;
      cpp += 3;
    }
  });

  bmp.UnlockBits(bd);
}

为了保持示例简单,我将像素值设置为常量值。注意,要编译上面的例子,你必须允许不安全的代码。

霍普,这有帮助。

票数 3
EN

Stack Overflow用户

发布于 2011-09-24 07:55:54

除了Guffa的优秀建议之外,我还建议您分析一下您的代码,看看它花费了哪些时间。请确保在对此进行计时时,在未附加调试器的情况下以发布模式运行。

如果对DrawImage的调用占用了大部分时间,我也不会感到惊讶。您在那里缩放图像,这可能是相当昂贵的。您要将图像绘制到的框有多大?

最后,尽管这不会影响性能,但您应该将代码更改为:

代码语言:javascript
复制
using (Graphics g = _box.CreateGraphics())
{
    g.InterpolationMode = InterpolationMode.NearestNeighbor;
    g.DrawImage(bmp, 0, 0, _box.Width, _box.Height);
}

并去掉示例中的第一行和最后一行。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7535812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档