【发布时间】:2020-12-05 08:39:16
【问题描述】:
我有以下 工作 代码从源 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,但得到了错误的位图。 有没有什么技巧,如何加快位图的创建速度?
更新: 根据下面的 cmets,我最终得到了这个代码,它的运行速度要快得多:
var bytes = new byte[pixels.Length];
var idx = 0L;
var area = height * width;
var area2 = 2 * area;
var bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
var bmd = bmp.LockBits(new Rectangle(0, 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, 0, bmd.Scan0, bytes.Length);
bmp.UnlockBits(bmd);
【问题讨论】:
-
如果你先“解压”数组,但不为每个像素调用
SetPixel()- 将其存储在临时数组中;然后使用BitmapData/Marshal.Copy方法?基本上,我认为是SetPixel()调用很慢,而不是计算。临时数组将采用正确的格式,因此您最终会得到正确的位图。 -
Of course I tried to use BitmapData and copy from pixels to BitmapData.Scan0 but got a wrong bitmap.你应该问一个关于如何解决这个问题的问题。 LockBits 是正确的方法。向我们展示您尝试使用它的代码,我们可以帮助您解决此问题。 -
使用不安全代码(如下)或 LockBits
-
谢谢@CoolBots,你的想法很完美! SetPixel() 方法在代码中很慢——很明显。打算用一个有效且快速的解决方案更新我的帖子。
-
几年前我在一个相关问题上发布了一个完整的解决方案,用于将字节数组转储到图像中:stackoverflow.com/a/43967594/395685 扁平化当然可以简单地提前完成,在字节数组中。
标签: c# arrays performance bitmap flatten