【问题标题】:Creating a Bitmap from an IntPtr从 IntPtr 创建位图
【发布时间】:2014-08-16 14:56:47
【问题描述】:

我试图弄清楚如何使用 USB Video Camera API,这有点不太清楚(至少它似乎依赖于开发人员以前的知识,我不认为我理解“全貌” ,双关语)。

我有以下成功接收数据的事件处理程序,我目前只能打印到控制台:

    void  _camera_OnPreviewBitmap(IntPtr pbyteBitmap, uint dwBufferSize,
                                  uint dwWidth, uint dwHeight,
                                  uint dwFrameNo, uint dwPreviewPixelFormat) {

        Console.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}, {5}", pbyteBitmap, dwBufferSize, dwWidth, dwHeight, dwFrameNo, dwPreviewPixelFormat));

        //The callback function gets the image data as “IntPtr” type. 
        //When using “System.Runtime.InteropServices.Marshal.Copy”, the image data can copy to the array. 
        //When using “System.Runtime.InteropServices.Marchal.ReadByte”, the image data can get thedirectory. 
        //Sometimes the process speed is fast when receiving the image data after the image data copy to the array with 
        //“System.Runtime.InteropServices.Marchal.Copy”. 

    } 

这给了我这些结果:

259129344, 1228800, 1280, 960, 195051, 1
250281984, 1228800, 1280, 960, 195052, 1
259129344, 1228800, 1280, 960, 195053, 1
250281984, 1228800, 1280, 960, 195054, 1
259129344, 1228800, 1280, 960, 195055, 1
250281984, 1228800, 1280, 960, 195056, 1
259129344, 1228800, 1280, 960, 195057, 1
250281984, 1228800, 1280, 960, 195058, 1
259129344, 1228800, 1280, 960, 195059, 1
250281984, 1228800, 1280, 960, 195060, 1
259129344, 1228800, 1280, 960, 195061, 1
250281984, 1228800, 1280, 960, 195062, 1

因此,这与图像尺寸 (1280 x 960) 一致,并且 1228800 是像素数(缓冲区大小),像素格式的 1 表示 PIXEL_FORMAT_08_MONO_OR_RAW 根据相机 API 像素格式枚举(其中也和这个BW相机一致)。

我的问题是:

如何获取这些信息并使用它创建一个System.Drawing.Bitmap 对象?

我已经尝试过了,但没有成功(显然灰度图像实际上没有被索引...):

        var bmp = new System.Drawing.Bitmap((int)dwWidth, (int)dwHeight, (int)dwBufferSize,
                                            PixelFormat.Format8bppIndexed, pbyteBitmap);

这最终会产生“通用 GDI+ 错误”。

【问题讨论】:

标签: c# marshalling system.drawing interopservices


【解决方案1】:

您正在指定一种索引格式,但没有为其提供调色板。

如果图像是灰度图像,而不是直接使用指针,您可以使用 32bpp 创建位图,锁定位,然后将 RGB 字节值设置为像素字节数据,这里是一个示例(使用不安全代码以方便和快速):

Bitmap bmp = new Bitmap(1280, 960, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
var data = bmp.LockBits(new Rectangle(0, 0, 1280, 960), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

byte* srcBmpData = (byte*)pbyteBitmap.ToPointer();
byte* dstBmpData = (byte*)data.Scan0.ToPointer();

for (int buc = 0; buc < 1280 * 960; buc++)
{
    int currentDestPos = buc * 4;
    dstBmpData[currentDestPos] = dstBmpData[currentDestPos + 1] = dstBmpData[currentDestPos + 2] = srcBmpData[buc];
}

bmp.UnlockBits(data);

【讨论】:

  • 当然,只需将其添加到函数的声明中(不安全的 void ...),并在项目的属性中,在构建选项下选中“允许不安全代码”,这样您就可以像在传统 c 中一样使用指针。
  • 还有一个问题:我连续四次将图像“平铺”。这似乎是一个“跨步”问题或类似问题。你有什么修复它的建议吗?
  • 嗯,四次?你能把图片上传到某个地方让我看到吗?如果存在步幅问题,则图像应该非常扭曲(每条线位移 X 像素)而不是“平铺”。
  • 知道了。你从未使用过currentDestPos。如果你不介意,我会纠正它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多