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

Converting opencv image to gdi bitmap doesn't work depends on image size

本文关键字:图像 不起作用 取决于 位图 gdi opencv 转换      更新时间:2023-10-16

我有这样的代码,可以将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)。

我检查了一下,可以确认:

2748*3664:

  • cols=2748
  • 行=3664
  • 步幅=8244
  • 图像继续

在1374 X 1832 中

  • cols=1374
  • 行=1832
  • 步幅=4122
  • 图像继续

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

问题出在哪里?我该如何解决?

编辑

基于解释为什么我不能创建位图的答案。我最终以这种方式实现了它:

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

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

感谢罗杰·罗兰的回答。

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

较大图像的步幅为8244,这是有效的(8244/4=2061),但较小图像的步距为4122,这不是(4122/4=1030.5)。

正如MSDN上对步幅参数所说(我强调):

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

假设您的步幅是正确的,我认为您唯一的选择就是逐行复制。所以,类似于:

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

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

OpenCV/Tesseract:如何用GDI+位图替换libpng、libtiff等(通过GDI+加载到cv::Mat)