为什么Bitmap.LockBits在VM上失败

Ric*_*oss 2 c# graphics gdi+ bitmap lockbits

在部署之前,我使用XP VM和Vista VM对我的应用程序进行烟雾测试.这两款VM都使用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;
}
Run Code Online (Sandbox Code Playgroud)

这段代码在我的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)
Run Code Online (Sandbox Code Playgroud)

根据文档,这是因为PixelFormat值不是特定的每像素位值或者传递了不正确的PixelFormat用于位图.

我没有在这些VM上安装VS但是我确实放了一个测试程序,打开了一个图像并打印了它的格式......这是预期的PixelFormat.Format32bppArgb.我在所有3个系统上使用相同的测试图像集.

我的下一个假设是它对VM的视频硬件的限制,但在一天结束时它是一个位图而不是3D场景......我很确定我应该能够使用它.

任何人都可以对这个问题有所了解吗?我真的希望能够正确地测试这些代码,而不仅仅依赖于"它在我的机器上工作"而且我宁愿不必在VM上安装VS(不是我甚至不确定它)将在XP上安装(我更喜欢在Vista上使用它,因为它的使用速度明显更快)).

希望其他人遇到过这个问题,并有一个解决方案 - 谷歌搜索让我失望.

Ric*_*oss 6

叹了口气......好吧,我现在可以回答这个问题,用户错误.

我曾经玩过VMMap,但它并没有真正起作用,所以我决定尝试在代码中添加一些额外的检查作为在VM上安装VS进行全面调试的前提.我添加了ArgumentException检查传递的图像是否不是32位ARGB.事实证明,我的开发机器上抛出了异常,这有些出乎意料.显然我用于测试的图像之一不是32位ARGB,但很高兴被锁定到32位ARGB.就像显然正确的像素数据被返回一样,我想甚至在操作位之后我会注意到一个乱码的图像!

似乎较新版本的Windows实际上可以将位锁定为完全不同的格式 - 一个快速测试程序,它只是打开一个PNG然后尝试调用每个格式Bitmap.LockBitsPixelFormat工作中的所有值,禁止奇怪的(没有前缀)格式化).好吧,至少它没有抛出异常,在我的情况下,一个格式Format8bppIndexed被锁定的图像Format32bppArgb并返回正确的像素数据.而XP和Vista似乎无法做到这一点而只是抛出异常.不确定我是否更喜欢以前的行为或后者,实际上几乎倾向于后者,尽管前者显然更方便.

我陷入了一个丑陋的黑客,如果源图像不是32位ARGB,那么从源生成一个新的临时图像并用它来获取像素.现在我的代码在VM中运行时没有任何明显的问题,条件的速度会受到影响.所以有一个问题解决了,现在我只需要摆脱那个黑客.