3
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 万个数组。

4

5 回答 5

5

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

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

于 2011-09-23T23:42:16.423 回答
3

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

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

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

希望这可以帮助。

于 2011-09-24T21:10:37.350 回答
1

除了 Guffa 的出色建议之外,我建议您对代码进行概要分析,以了解它在哪里花费了时间。确保在计时时,您在没有附加调试器的情况下以发布模式运行。

DrawImage如果电话占用大部分时间,我不会感到惊讶。您正在那里缩放图像,这可能非常昂贵。您要绘制图像的框有多大?

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

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

并摆脱示例中的第一行和最后一行。

于 2011-09-23T23:55:53.580 回答
1

尝试使用不安全的代码:

byte* rp0;
int* vp0;
fixed (byte* rp1 = rgb)
{
    rp0 = rp1;
    fixed (int* vp1 = _values)
    {
        vp0 = vp1;
        Parallel.For(0, _width, (i) =>
        {
            var val = (byte)vp0[i];
            rp0[i] = val;
            rp0[i + 1] = val;
            rp0[i + 2] = val;
        });
    }
}

对我来说跑得很快

于 2011-09-25T08:57:10.493 回答
0

我的理解是.Net 中的多维(方形)数组非常慢。您可以尝试将 _values 数组改为单维数组。这是一个参考,如果你搜索还有更多:http: //odetocode.com/articles/253.aspx

阵列性能示例。

using System;
using System.Diagnostics;

class Program
{
static void Main(string[] args)
{
    int w = 1000;
    int h = 1000;

    int c = 1000;

    TestL(w, h);
    TestM(w, h);


    var swl = Stopwatch.StartNew();
    for (int i = 0; i < c; i++)
    {
        TestL(w, h);
    }
    swl.Stop();

    var swm = Stopwatch.StartNew();
    for (int i = 0; i < c; i++)
    {
        TestM(w, h);
    }
    swm.Stop();

    Console.WriteLine(swl.Elapsed);
    Console.WriteLine(swm.Elapsed);
    Console.ReadLine();
}


static void TestL(int w, int h)
{
    byte[] b = new byte[w * h];
    int q = 0;
    for (int x = 0; x < w; x++)
        for (int y = 0; y < h; y++)
            b[q++] = 1;
}

static void TestM(int w, int h)
{
    byte[,] b = new byte[w, h];

    for (int y = 0; y < h; y++)
        for (int x = 0; x < w; x++)
            b[y, x] = 1;
}
}
于 2011-09-23T23:55:40.680 回答