将opencv图像转换为gdi位图不起作用取决于图像大小

时间:2013-12-23 12:02:02

标签: c++ image opencv bitmap

我有这个代码将opencv图像转换为位图:

  void processimage(MAT imageData)
  {
      Gdiplus::Bitmap bitmap(imageData.cols,imageData.rows,stride, PixelFormat24bppRGB,imageData.data);

   // do some work with bitmap
  }

当图像尺寸为2748 X 3664时效果很好。但是我想要处理尺寸为1374 X 1832的图像,它不起作用。

错误是无效的参数(2)。

我检查过并确认:

in 2748 * 3664:

  • cols = 2748
  • rows = 3664
  • stride = 8244
  • 图片继续。

in 1374 X 1832

  • cols = 1374
  • rows = 1832
  • stride = 4122
  • 图片继续。

所以一切对我来说都是正确的,但它会产生错误。

问题是什么,我该如何解决?

修改

根据答案解释了为什么我无法创建位图。我终于以这种方式实现了它:

   Mat newImage;
   cvtColor(imageData, newImage, CV_BGR2BGRA);
   Gdiplus::Bitmap bitmap(newImage.cols,newImage.rows,newImage.step1(), PixelFormat32bppRGB,newImage.data);

如此有效,我将输入图像转换为每像素4个字节,然后使用将其转换为位图。

所有归功于 Roger Rowland 的回答。

2 个答案:

答案 0 :(得分:6)

我认为问题是BMP格式的步幅必须是4的倍数。

你的大图像有8244的步幅,有效(8244/4 = 2061),但你的小图像有一个4122的步幅,不是(4122/4 = 1030.5)。

作为 stride 参数的it says on MSDN(我的重点):

  

整数,指定一个开头之间的字节偏移量   扫描线和下一个。这通常是(但不一定)   像素格式的字节数(例如,每个16位的2个字节)   像素)乘以位图的宽度。传递给它的值   参数必须是四的倍数

假设你的步伐是正确的,我认为你唯一的选择就是逐行复制。所以,像:

  1. 非常Gdiplus::Bitmap所需的尺寸和格式
  2. 使用LockBits获取位图像素数据。
  3. 一次复制一行OpenCV图像。
  4. 调用UnlockBits以释放位图数据。

答案 1 :(得分:0)

您可以使用我的CGdiPlus类,它实现了从cv :: Mat转换为Gdiplus :: Bitmap所需的一切,反之亦然:

OpenCV / Tesseract: How to replace libpng, libtiff etc with GDI+ Bitmap (Load into cv::Mat via GDI+)