【发布时间】:2014-01-16 16:12:48
【问题描述】:
在部署应用程序之前,我使用 XP VM 和 Vista VM 进行冒烟测试。这两个 VM 都使用 32 位颜色。不确定它是否有任何区别,但我正在使用 VirtualBox。每台机器还分配了 2GB 的内存,2 个处理器。 XP 有 128MB 的视频内存,Vista 256(在每种情况下我都可以设置它们的最大值)。运行这些机器的桌面有 6 核和 16GB 内存。同样,不确定此信息是否相关,但谁知道。
以下是我用来将Bitmap 转换为我可以直接使用的一堆像素的扩展方法。因为,毕竟我们需要速度。我们需要的是速度。油腻,速度快!而 Bitmap.GetPixel 正好相反。
public static ArgbColor[] GetPixels(this Bitmap bitmap)
{
ArgbColor[] results;
int width;
int height;
BitmapData bitmapData;
width = bitmap.Width;
height = bitmap.Height;
results = new ArgbColor[width * height];
bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
unsafe
{
ArgbColor* pixelPtr;
pixelPtr = (ArgbColor*)(void*)bitmapData.Scan0;
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++)
{
results[row * width + col] = *pixelPtr;
pixelPtr++;
}
}
}
bitmap.UnlockBits(bitmapData);
return results;
}
此代码在我的 Windows 8.1“真实”机器上完美运行,就像我之前使用 Windows 8 和 Windows 7 时一样。
但在 VM 上,它会失败并显示“参数无效”。 ArgumentException:
System.Drawing.Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
System.Drawing.Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)
Cyotek.Drawing.ImageExtensions.GetPixels(Bitmap bitmap)
根据docs,这是因为PixelFormat 值不是特定的每像素位数,或者为位图传递了不正确的PixelFormat。
我没有在这些虚拟机上安装 VS,但我确实在其上放置了一个测试程序,它打开了一个图像并打印了它的格式...这是预期的PixelFormat.Format32bppArgb。我在所有 3 个系统上使用相同的一组测试图像。
我的下一个假设是 VM 的视频硬件受到限制,但归根结底,它是位图而不是 3D 场景......我很确定我应该能够使用它。
谁能解释一下这个问题?我真的很希望能够正确测试其中的一些代码,而不是仅仅依靠“它在我的机器上工作”,而且我宁愿不必在 VM 上安装 VS(我什至不确定它'将安装在 XP 上(我更喜欢 Vista 上的那个,因为它使用起来明显更快))。
希望其他人遇到过这个问题并有解决方案 - Google 搜索让我失望了。
【问题讨论】:
-
视频硬件不起作用。查看进程使用的私有字节,最好使用 SysInternals 的 VMMap,当您使用大位图时,使用此代码可能会耗尽 VM 地址空间。当 GDI+ 无法在地址空间中找到足以容纳像素数据的空洞时,可能会引发“参数无效”。如果您确定在应该处理位图时,除了使用较小的位图或切换到 64 位代码之外,没有简单的解决方法。
-
感谢您的评论。我用来测试的位图已经很小了——最大大约 100x100 像素。我认为我很擅长释放资源,所以我不会认为这是内存问题。不过,我会看看你所说的这个 VMMap 工具。仅仅因为两个虚拟机都安装了 32 位操作系统,所以不能选择 64 位。再次感谢您的评论!
标签: c# graphics bitmap gdi+ lockbits