summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/image/qimage.h5
-rw-r--r--src/gui/image/qpixmap_win.cpp124
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp10
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);