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>
This commit is contained in:
parent
b4aee30692
commit
f06dfb60b9
@ -298,6 +298,11 @@ public:
|
|||||||
// Platform specific conversion functions
|
// Platform specific conversion functions
|
||||||
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
|
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
|
||||||
CGImageRef toCGImage() const Q_DECL_CF_RETURNS_RETAINED;
|
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
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -228,9 +228,9 @@ enum HBitmapFormat
|
|||||||
HBitmapAlpha
|
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 w = bm.width();
|
||||||
const int h = bm.height();
|
const int h = bm.height();
|
||||||
const int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment
|
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;
|
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)
|
static inline QImage::Format format32(int hbitmapFormat)
|
||||||
{
|
{
|
||||||
switch (hbitmapFormat) {
|
switch (hbitmapFormat) {
|
||||||
@ -344,6 +349,40 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm
|
|||||||
return bitmap;
|
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)
|
Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0)
|
||||||
{
|
{
|
||||||
if (p.isNull())
|
if (p.isNull())
|
||||||
@ -451,26 +490,64 @@ Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0
|
|||||||
return result;
|
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)
|
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat = 0)
|
||||||
{
|
{
|
||||||
return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap, /* forceQuads */ true, hbitmapFormat));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNull())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
QBitmap maskBitmap = p.mask();
|
auto effectiveMask = mask;
|
||||||
if (maskBitmap.isNull()) {
|
if (effectiveMask.isNull()) {
|
||||||
maskBitmap = QBitmap(p.size());
|
effectiveMask = QImage(size(), QImage::Format_Mono);
|
||||||
maskBitmap.fill(Qt::color1);
|
effectiveMask.fill(Qt::color1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ICONINFO ii;
|
ICONINFO ii;
|
||||||
ii.fIcon = true;
|
ii.fIcon = true;
|
||||||
ii.hbmMask = qt_createIconMask(maskBitmap);
|
ii.hbmMask = qt_createIconMask(effectiveMask);
|
||||||
ii.hbmColor = qt_pixmapToWinHBITMAP(p, HBitmapAlpha);
|
ii.hbmColor = qt_imageToWinHBITMAP(*this, HBitmapAlpha);
|
||||||
ii.xHotspot = 0;
|
ii.xHotspot = 0;
|
||||||
ii.yHotspot = 0;
|
ii.yHotspot = 0;
|
||||||
|
|
||||||
@ -482,6 +559,15 @@ Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
|
|||||||
return hIcon;
|
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)
|
Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
|
||||||
{
|
{
|
||||||
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
|
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
|
||||||
@ -520,7 +606,14 @@ static inline bool hasAlpha(const QImage &image)
|
|||||||
return false;
|
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 screenDevice = GetDC(nullptr);
|
||||||
HDC hdc = CreateCompatibleDC(screenDevice);
|
HDC hdc = CreateCompatibleDC(screenDevice);
|
||||||
@ -531,7 +624,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
|
|||||||
if (!result) {
|
if (!result) {
|
||||||
qErrnoWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()");
|
qErrnoWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()");
|
||||||
DeleteDC(hdc);
|
DeleteDC(hdc);
|
||||||
return QPixmap();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const int w = int(iconinfo.xHotspot) * 2;
|
const int w = int(iconinfo.xHotspot) * 2;
|
||||||
@ -570,7 +663,12 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
|
|||||||
SelectObject(hdc, oldhdc); //restore state
|
SelectObject(hdc, oldhdc); //restore state
|
||||||
DeleteObject(winBitmap);
|
DeleteObject(winBitmap);
|
||||||
DeleteDC(hdc);
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -3777,10 +3777,6 @@ void tst_QImage::wideImage()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#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)
|
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(QImage::Format_RGB32, width, height, color, bottomRightColor).convertToFormat(format)
|
||||||
: createTestImage(format, width, height, color, bottomRightColor);
|
: createTestImage(format, width, height, color, bottomRightColor);
|
||||||
|
|
||||||
const HBITMAP bitmap = qt_imageToWinHBITMAP(image);
|
const HBITMAP bitmap = image.toHBITMAP();
|
||||||
|
|
||||||
QVERIFY(bitmap != 0);
|
QVERIFY(bitmap != 0);
|
||||||
|
|
||||||
@ -3867,7 +3863,7 @@ void tst_QImage::toWinHBITMAP()
|
|||||||
QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, 3, height - 1)), color);
|
QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, 3, height - 1)), color);
|
||||||
QCOMPARE(COLORREFToQColor(GetPixel(bitmapDc, width - 1, height - 1)), bottomRightColor);
|
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),
|
QCOMPARE(convertedBack.convertToFormat(QImage::Format_ARGB32_Premultiplied),
|
||||||
image.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];
|
char bitmapData[size];
|
||||||
memset(bitmapData, 0, size);
|
memset(bitmapData, 0, size);
|
||||||
const HBITMAP hbitmap = CreateBitmap(width, height, /* planes */ 1, /* bitcount */ 1, bitmapData);
|
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.size(), QSize(width, height));
|
||||||
QCOMPARE(image.scanLine(0)[0], 0u);
|
QCOMPARE(image.scanLine(0)[0], 0u);
|
||||||
DeleteObject(hbitmap);
|
DeleteObject(hbitmap);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user