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万的数组。
答案 0 :(得分:5)
您可以跳过将数据从图像复制到数组的第一个Array.Copy
,因为您将覆盖数组中的所有数据。
这样可以减少25%的时间,但是如果你想要它更快,你将不得不使用不安全的代码块,以便你可以使用指针。这样,您可以在访问数组时绕过范围检查,并且可以将数据直接写入图像数据而不是复制它。
答案 1 :(得分:3)
我完全同意Guffa的回答。使用不安全的代码块会加快速度。
为了进一步提高性能,可以使用.Net框架中的Parallel
类并行执行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);
}
为了使示例简单,我将像素值设置为常量值。注意,要编译上面的示例,您必须允许不安全的代码。
希望,这有帮助。
答案 2 :(得分:1)
除了Guffa的出色建议之外,我建议您分析一下代码,看看它花时间在哪里。确保在计时时,您在没有附加调试器的情况下以释放模式运行。
如果DrawImage
的电话占用大部分时间,我不会感到惊讶。你在那里缩放图像,这可能相当昂贵。您要将图像绘制到的框有多大?
最后,虽然这不会影响性能,但您应该将代码更改为:
using (Graphics g = _box.CreateGraphics())
{
g.InterpolationMode = InterpolationMode.NearestNeighbor;
g.DrawImage(bmp, 0, 0, _box.Width, _box.Height);
}
并摆脱示例中的第一行和最后一行。
答案 3 :(得分: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;
});
}
}
对我来说跑得很快
答案 4 :(得分: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;
}
}