diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-07-24 09:22:16 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-07-24 22:51:46 +0200 |
commit | f06dfb60b96004971917a27559713314b7f60de6 (patch) | |
tree | 269572c9e5a564851d410b871fe0d78cfadeb567 | |
parent | b4aee30692c166025b4e2283c19dbc1247bcce54 (diff) |
QtGui: Add Windows conversion functions for to QImage
Add conversions from/to HBITMAP, HICON to QImage. Split the pixmap
conversion functions apart to use them.
Task-number: QTBUG-81876
Change-Id: Ic0c41a402a1f6e9bec572fc4d691357bd48e6423
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r-- | src/gui/image/qimage.h | 5 | ||||
-rw-r--r-- | src/gui/image/qpixmap_win.cpp | 124 | ||||
-rw-r--r-- | tests/auto/gui/image/qimage/tst_qimage.cpp | 10 |
3 files changed, 119 insertions, 20 deletions
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index b8f2dd8faf..2743ed285a 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -298,6 +298,11 @@ public: // Platform specific conversion functions #if defined(Q_OS_DARWIN) || defined(Q_QDOC) CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED; +#elif defined(Q_OS_WIN) || defined(Q_QDOC) + HBITMAP toHBITMAP() const; + HICON toHICON(const QImage &mask = {}) const; + static QImage fromHBITMAP(HBITMAP hbitmap); + static QImage fromHICON(HICON icon); #endif protected: diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index a5565479e3..f9b4f600e2 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -228,9 +228,9 @@ enum HBitmapFormat HBitmapAlpha }; -Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap) +static HBITMAP qt_createIconMask(QImage bm) { - QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); + Q_ASSERT(bm.format() == QImage::Format_Mono); const int w = bm.width(); const int h = bm.height(); const int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment @@ -242,6 +242,11 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap) return hbm; } +Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap) +{ + return qt_createIconMask(bitmap.toImage().convertToFormat(QImage::Format_Mono)); +} + static inline QImage::Format format32(int hbitmapFormat) { switch (hbitmapFormat) { @@ -344,6 +349,40 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm return bitmap; } +/*! + \since 6.0 + + Creates a \c HBITMAP equivalent of the QImage. Returns the \c HBITMAP + handle. + + It is the caller's responsibility to free the \c HBITMAP data + after use. + + For usage with with standard GDI calls, such as \c BitBlt(), the image + should have the format QImage::Format_RGB32. + + When using the resulting HBITMAP for the \c AlphaBlend() GDI function, + the image should have the format QImage::Format_ARGB32_Premultiplied + (use convertToFormat()). + + When using the resulting HBITMAP as application icon or a systray icon, + the image should have the format QImage::Format_ARGB32. + + \sa fromHBITMAP(), convertToFormat() +*/ +HBITMAP QImage::toHBITMAP() const +{ + switch (format()) { + case QImage::Format_ARGB32: + return qt_imageToWinHBITMAP(*this, HBitmapAlpha); + case QImage::Format_ARGB32_Premultiplied: + return qt_imageToWinHBITMAP(*this, HBitmapPremultipliedAlpha); + default: + break; + } + return qt_imageToWinHBITMAP(*this); +} + Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0) { if (p.isNull()) @@ -451,26 +490,64 @@ Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0 return result; } +/*! + \since 6.0 + + Returns a QImage that is equivalent to the given \a bitmap. + + HBITMAP does not store information about the alpha channel. + + In the standard case, the alpha channel is ignored and a fully + opaque image is created (typically of format QImage::Format_RGB32). + + There are cases where the alpha channel is used, though, for example + for application icon or systray icons. In that case, + \c reinterpretAsFormat(QImage::Format_ARGB32) should be called + on the returned image to ensure the format is correct. + + \sa toHBITMAP(), reinterpretAsFormat() +*/ +QImage QImage::fromHBITMAP(HBITMAP hbitmap) +{ + return qt_imageFromWinHBITMAP(hbitmap); +} + Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0) { return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat)); } -Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p) +/*! + \since 6.0 + + Creates a \c HICON equivalent of the QPixmap, applying the mask + \a mask. If \a mask is not null, it needs to be of format QImage::Format_Mono. + Returns the \c HICON handle. + + It is the caller's responsibility to free the \c HICON data after use. + + \sa fromHICON() +*/ +HICON QImage::toHICON(const QImage &mask) const { - if (p.isNull()) + if (!mask.isNull() && mask.format() != QImage::Format_Mono) { + qWarning("QImage::toHICON(): Mask must be empty or have format Format_Mono"); return nullptr; + } - QBitmap maskBitmap = p.mask(); - if (maskBitmap.isNull()) { - maskBitmap = QBitmap(p.size()); - maskBitmap.fill(Qt::color1); + if (isNull()) + return nullptr; + + auto effectiveMask = mask; + if (effectiveMask.isNull()) { + effectiveMask = QImage(size(), QImage::Format_Mono); + effectiveMask.fill(Qt::color1); } ICONINFO ii; ii.fIcon = true; - ii.hbmMask = qt_createIconMask(maskBitmap); - ii.hbmColor = qt_pixmapToWinHBITMAP(p, HBitmapAlpha); + ii.hbmMask = qt_createIconMask(effectiveMask); + ii.hbmColor = qt_imageToWinHBITMAP(*this, HBitmapAlpha); ii.xHotspot = 0; ii.yHotspot = 0; @@ -482,6 +559,15 @@ Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p) return hIcon; } +Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p) +{ + QImage mask; + QBitmap maskBitmap = p.mask(); + if (!maskBitmap.isNull()) + mask = maskBitmap.toImage().convertToFormat(QImage::Format_Mono); + return p.toImage().toHICON(mask); +} + Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h) { QImage image(w, h, QImage::Format_ARGB32_Premultiplied); @@ -520,7 +606,14 @@ static inline bool hasAlpha(const QImage &image) return false; } -Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) +/*! + \since 6.0 + + Returns a QImage that is equivalent to the given \a icon. + + \sa toHICON() +*/ +QImage QImage::fromHICON(HICON icon) { HDC screenDevice = GetDC(nullptr); HDC hdc = CreateCompatibleDC(screenDevice); @@ -531,7 +624,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) if (!result) { qErrnoWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()"); DeleteDC(hdc); - return QPixmap(); + return {}; } const int w = int(iconinfo.xHotspot) * 2; @@ -570,7 +663,12 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) SelectObject(hdc, oldhdc); //restore state DeleteObject(winBitmap); DeleteDC(hdc); - return QPixmap::fromImage(std::move(image)); + return image; +} + +Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon) +{ + return QPixmap::fromImage(QImage::fromHICON(icon)); } QT_END_NAMESPACE diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index c9c5b5b201..7fcbabd532 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -3777,10 +3777,6 @@ void tst_QImage::wideImage() } #if defined(Q_OS_WIN) -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &p, int hbitmapFormat = 0); -Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0); -QT_END_NAMESPACE static inline QColor COLORREFToQColor(COLORREF cr) { @@ -3844,7 +3840,7 @@ void tst_QImage::toWinHBITMAP() ? createTestImage(QImage::Format_RGB32, width, height, color, bottomRightColor).convertToFormat(format) : createTestImage(format, width, height, color, bottomRightColor); - const HBITMAP bitmap = qt_imageToWinHBITMAP(image); + const HBITMAP bitmap = image.toHBITMAP(); QVERIFY(bitmap != 0); @@ -3867,7 +3863,7 @@ void tst_QImage::toWinHBITMAP() QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, 3, height - 1)), color); QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, width - 1, height - 1)), bottomRightColor); - const QImage convertedBack = qt_imageFromWinHBITMAP(bitmap); + const QImage convertedBack = QImage::fromHBITMAP(bitmap); QCOMPARE(convertedBack.convertToFormat(QImage::Format_ARGB32_Premultiplied), image.convertToFormat(QImage::Format_ARGB32_Premultiplied)); @@ -3884,7 +3880,7 @@ void tst_QImage::fromMonoHBITMAP() // QTBUG-72343, corruption for mono bitmaps char bitmapData[size]; memset(bitmapData, 0, size); const HBITMAP hbitmap = CreateBitmap(width, height, /* planes */ 1, /* bitcount */ 1, bitmapData); - const QImage image = qt_imageFromWinHBITMAP(hbitmap); + const QImage image = QImage::fromHBITMAP(hbitmap); QCOMPARE(image.size(), QSize(width, height)); QCOMPARE(image.scanLine(0)[0], 0u); DeleteObject(hbitmap); |