将 GDI Plus 位图转换为 QPixmap

Convert GDI Plus Bitmap to QPixmap

本文关键字:QPixmap 转换 位图 GDI Plus      更新时间:2023-10-16

我有一个GdiPlus::Bitmap对象,我需要构建一个函数将其转换为QPixmap。 我使用的是Qt 5.8.0,性能是我关心的问题。 我在网上找不到任何关于这个的信息,甚至搜索GDI+图像到QImages。 我不需要访问像素数据,所以我所要做的就是将GDI+位图转换为可以在QWidget中显示的内容。

到目前为止,我发现的最有希望的解决方案是在QtWin:http://doc.qt.io/qt-5/qtwin.html#fromHBITMAP 中使用fromHBitMap((,但我没有能够理解位图句柄所需的知识/经验。

我假设你手里有"位图"对象。此外,我假设您的开发环境同时支持"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);

试试这个。上面的代码未经测试。它给出了一个想法。

我不需要访问像素数据

你没有,但Qt肯定会。Qt不使用GDI来渲染小部件 - 相反,它使用在QImage上运行的光栅格后端。在引擎盖下,QPixmap只是QImage的包装器,并且在两者之间进行转换很便宜,因为它不会复制任何图像数据。

因此,无论您选择哪种路线,都会在某个时候涉及QImage,即使它是以QPixmap的形式。

我有一个方法来做到这一点,我翻转红色和蓝色字节,然后使用以下代码将其从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;
}