【问题标题】:Convert GDI Plus Bitmap to QPixmap将 GDI Plus 位图转换为 QPixmap
【发布时间】:2017-03-22 16:52:55
【问题描述】:
我有一个 GdiPlus::Bitmap 对象,我需要构建一个将其转换为 QPixmap 的函数。我正在使用 Qt 5.8.0,性能是我关心的问题。我在网上找不到任何关于此的内容,甚至在 QImages 中搜索 GDI+ 图像。我不需要访问像素数据,所以我所要做的就是将 GDI+ 位图转换为可以在 QWidget 中显示的东西。
到目前为止,我发现的最有希望的解决方案是在 QtWin 中使用 fromHBitMap():http://doc.qt.io/qt-5/qtwin.html#fromHBITMAP,但我没有能够理解位图句柄所需的知识/经验。
【问题讨论】:
标签:
c++
qt
gdi+
qimage
qpixmap
【解决方案1】:
我假设您手中有“位图”对象。
另外我假设您的开发环境同时支持“Windows 编程”和“Qt”。
基于以上假设,您可以从“位图”中获取HICON,并将其传递给“QPixmap QtWin::fromHICON(HICON icon)”。
步骤:
首先您必须包含“Gdiplus.h”。
还包括“QtWin”。
HICON hIcon;
Status st = <<Your Bitmap Object>>.GetHICON(&hIcon);
QPixmap pixM = QtWin::fromHICON(hIcon);
试试这个。
上面的代码未经测试。
它提供了一个想法。
【解决方案2】:
我不需要访问像素数据
你不知道,但 Qt 肯定会。 Qt 不使用 GDI 来呈现小部件 - 相反,它使用在 QImage 上运行的光栅后端。在底层,QPixmap 只是 QImage 的包装,在两者之间进行转换很便宜,因为它不会复制任何图像数据。
因此,无论您选择何种路线,都会在某个时候涉及QImage,即使它是以QPixmap 的形式出现的。
【解决方案3】:
我有一种方法可以翻转红色和蓝色字节,然后使用以下代码将其从 Gdiplus::Bitmap 转换为 QPixmap:
QPixmap getAsQPixmap(Gdiplus::Bitmap bitmap)
{
// One of my functions to flip blue and red bytes of the image
_flipBlueWithRed();
// m_pBytes is a pointer to an unsigned char that marks the start of the image
// It was retrieved from locking the Gdiplus::Bitmap
auto result = QPixmap::fromImage(QImage(m_pBytes, getWidth(), getHeight(), QImage::Format_RGB888));
// Restore data back to original state
_flipBlueWithRed();
return result;
}
但是,这种方法很慢,需要 60 毫秒才能执行。所以我的新方法是将 Gdiplus::Bitmap 保存到文件中,并使用该文件的路径从 QPixmap 的构造函数中读取。 这种方法要快得多,大约 5 毫秒。
QPixmap getAsQPixmap(GdiPlus::Bitmap bitmap)
{
std::string path = "C:/path_to_img.....png";
// One of my functions to unlock the Gdi+ bitmap
_unlockGdiPlusBitmap();
// Get Clsid
CLSID pngClsid;
getEncoderClsid(format_mime, &pngClsid);
// Save bitmap
// stringToWString() was a function that I wrote to convert a standard string to be a wide string
bitmap->Save(stringToWString(path).c_str(), static_cast<const CLSID*>(&pngClsid));
// Lock bitmap
_lockGdiPlusBitmap();
// Create the QPixmap
QPixmap new_img(path);
return new_img;
}