在部署应用程序之前,我使用XP虚拟机和Vista虚拟机对应用程序进行烟雾测试。这两个虚拟机都使用32位颜色。不确定它是否有任何不同,但我正在使用VirtualBox。每台机器还分配了2GB的内存和2个处理器。XP有128MB的视频ram,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时一样。
但在虚拟机上,它会以"参数无效"失败。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)
根据文档,这是因为PixelFormat值不是特定的每像素位数或位图传递了不正确的PixelFormat。
我还没有在这些虚拟机上安装VS,但我确实删除了一个测试程序,打开了一个图像并打印了它的格式。。。即预期的CCD_ 3。我在所有3个系统上使用相同的测试图像集。
我的下一个假设是,这是虚拟机视频硬件的限制,但归根结底,这是一个位图,而不是3D场景。。。我很确定我应该能够使用它。
有人能阐明这个问题吗?我真的很想能够正确地测试其中的一些代码,而不是仅仅依赖于"它在我的机器上工作",而且我也不想在虚拟机上安装VS(我甚至不确定它会安装在XP上(我更喜欢它而不是Vista,因为它明显更快)。
希望其他人也遇到了这个问题,并找到了解决方案——谷歌搜索让我失望了。
叹息。。。好吧,我现在可以回答这个问题了,用户错误。
我曾经尝试过VMMap,但它并没有真正的帮助,所以我决定尝试在代码中添加一些额外的检查,作为在VM上安装VS进行全面调试的前兆。我添加了一个ArgumentException
检查,检查通过的图像是否不是32位ARGB。然而,事实证明,我的开发机器出现了异常,这有点出乎意料。显然,我用来测试的图像之一不是32位ARGB,但很高兴被锁定到32位ARBB。同样明显的是,正确的像素数据被返回了,因为我想即使是我也会在操作比特后注意到一个混乱的图像!
似乎新版本的Windows实际上可以将比特锁定为一种完全不同的格式——一个快速测试程序只需打开一个PNG,然后尝试对PixelFormat
中的所有值调用Bitmap.LockBits
,它适用于每一种格式,除了奇怪的格式(没有加format前缀)。好吧,至少它没有抛出异常,在我的情况下,格式为Format8bppIndexed
的图像被锁定为Format32bppArgb
,并返回正确的像素数据。而XP和Vista似乎不能做到这一点,只是抛出了一个例外。实际上,我不确定我是喜欢前者还是后者,几乎倾向于后者,尽管显然前者更方便。
我陷入了一个丑陋的破解,如果源图像不是32位ARGB,那么就会从源生成一个新的临时图像,并用它来获取像素。现在我的代码在虚拟机中工作,没有任何明显的问题,方法的速度会受到影响。所以有一个问题解决了,现在我只需要摆脱那个黑客。