如何解决从输入数组创建位图的更快方法,而不是使用for循环和SetPixel
我具有以下工作代码,可以根据源 pixels 数组创建Bitmap。 源数组的类型为 byte [] ,它是库函数的输出,它是 flatten 数组3D => 1D。
我创建位图的代码:
var bmp = new Bitmap(width,height,PixelFormat.Format24bppRgb);
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
// unflattening 1D array using 3D coordinates
// index = z * yMax * xMax + y * xMax + x
var rv = pixels[0 * height * width + j * width + i];
var gv = pixels[1 * height * width + j * width + i];
var bv = pixels[2 * height * width + j * width + i];
bmp.SetPixel(i,j,Color.FromArgb(rv,gv,bv));
}
}
上面的代码有效,但是慢。对于2048 x 1364位图,创建大约需要2秒钟。 我检查了stackoverflow的类似情况,有使用BitmapData和Marshal.Copy的解决方案,但是当源数组不是3D => 1D扁平化数组时就是这种情况。当然,我尝试使用BitmapData并将其从像素复制到BitmapData.Scan0,但是得到了错误的位图。 有什么窍门,如何加快位图的创建速度?
更新: 根据下面的评论,我最终得到了这段代码,它的运行速度更快:
var bytes = new byte[pixels.Length];
var idx = 0L;
var area = height * width;
var area2 = 2 * area;
var bmp = new Bitmap(width,PixelFormat.Format24bppRgb);
var bmd = bmp.LockBits(new Rectangle(0,bmp.Width,bmp.Height),ImageLockMode.ReadWrite,bmp.PixelFormat);
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
var Unflatten1D = j * width + i;
bytes[idx] = pixels[Unflatten1D];
bytes[idx + 1] = pixels[Unflatten1D + area];
bytes[idx + 2] = pixels[Unflatten1D + area2];
idx += 3;
}
}
Marshal.Copy(bytes,bmd.Scan0,bytes.Length);
bmp.UnlockBits(bmd);
解决方法
您可以使用/ unsafe标志编译应用程序(在Visual Studio中,右键单击项目,然后在属性中允许使用不安全的代码)
接下来使方法代码不安全。例如:
public unsafe void CreateImage()
然后按如下所示更改代码。
var bmp = new Bitmap(width,height,PixelFormat.Format24bppRgb);
var bitmapData = bmp.LockBits(new Rectangle(0,width,height),ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb);
byte* bits = (byte*)bitmapData.Scan0;
fixed (byte* p = pixels)
{
// Avoid having those 2 multiplications in the loop
int wtimesh1 = height * width * 1;
int wtimesh2 = height * width * 2;
for (int j = 0; j < height; j++)
{
// Avoid multiplication in the loop
int jtimesw = j * width;
for (int i = 0; i < width; i++)
{
// unflattening 1D array using 3D coordinates
// index = z * yMax * xMax + y * xMax + x
int pixel = j * bitmapData.Stride + i * 3;
// Avoid recalculation
int jtimeswplusi = jtimesw + i;
bits[pixel + 2] = p[jtimeswplusi];
bits[pixel + 1] = p[wtimesh1 + jtimeswplusi];
bits[pixel] = p[wtimesh2 + jtimeswplusi];
}
}
}
在我的PC上,此优化使创建时间从2.1s减少到0.05s
当然这里需要说明的是,代码是不安全的(如编译器标志所暗示的),因此必须格外小心代码的正确性,以避免崩溃,不确定的行为和/或安全性问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。