通过触摸兼容 PixelSense 的 PC 捕获图像并将其保存为 .bmp

Capture image from touch of PixelSense-compatible PC and save it as .bmp

我在 SUR40 PixelSense 兼容计算机上使用 Microsoft Surface 2.0 SDK。我需要从它的触摸中捕获图像并将其保存为 .bmp。由于 Surface SDK 自带 RawImageVisualizer 示例,它在屏幕上显示来自触摸的图片,因此我尝试修改用于将图片写入硬盘的程序。问题是,我在构建 Image 期间从触摸捕获的字节数组中得到 ArgumentException: Parameter is invalid

这就是我在 FrameReceived 事件中从 FrameReceivedEventArgs 检索带有图像数据的字节数组的方式:

event.UpdateRawImage(
                ImageType.Normalized,
                normalizedImage,
                0, 0,
                InteractiveSurface.PrimarySurfaceDevice.WorkingAreaWidth,
                InteractiveSurface.PrimarySurfaceDevice.WorkingAreaHeight);

这就是我尝试将字节 .bmp 写入磁盘的方式:

System.Drawing.Image img;
using (System.Drawing.Image raw = System.Drawing.Image.FromStream(new MemoryStream(normalizedImage)))
{
    img = raw.Clone() as System.Drawing.Bitmap;
}
img.Save("C:/img.bmp", System.Drawing.Imaging.ImageFormat.Bmp);

所以我在尝试从流中创建 Image 时遇到异常。尽管如此,这个字节数组与显示它的 Texture2DSpriteBatch 一起工作得很好。我该如何修复 ArgumentException

我刚刚意识到,UpdateRawImage 不是 return PNG 文件的字节表示,而只是像素数组。因此,要从中构建图像,必须将文件结构的所有其他部分写入数组:header 和颜色 table(如果需要)。在许多情况下,这可以简单地使用 System.Drawing.Bitmap 构造函数之一来完成:

public Bitmap(
    int width,
    int height,
    int stride,
    PixelFormat format,
    IntPtr scan0
)

但我没那么幸运,因为UpdateRawImage returns 8bpp灰度像素,而PixelFormat枚举不支持它们(最接近的是Format16bppGrayScale ,但它使用 2 个字节作为像素,而不是一个)。因此,在这种特殊情况下,有两个明显的解决方案。第一个是制作一个新的像素阵列,它符合 PixelFormat 标准之一(这是我的选择,因为我需要 24 位 RGB 图像,尽管它实际上 black-white 只有 256 种色调)。第二种是手动编写 BMP headers(由于开放规范,这不是很困难)。