summaryrefslogtreecommitdiffstats
path: root/src/gui/image/qpixmap_win.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@digia.com>2014-05-20 14:44:26 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-05-23 22:18:30 +0200
commitd3d8ade87b74c541cc3baa67b9972d6471864c25 (patch)
tree25e8ae4de6114fb729dd5273d9aa3e1e81ffe923 /src/gui/image/qpixmap_win.cpp
parent57d0ed8f1e0b2e98102bd3718abd449d5dd7aa1d (diff)
Windows: Fix qt_imageFromWinHBITMAP().
Factor out common code paths from the QPixmap/QImage conversion code and use the same algorithm for copying the image data with alpha correction as does qt_pixmapFromWinHBITMAP(). Rename the previous version of qt_imageFromWinHBITMAP() to qt_imageFromWinIconHBITMAP() since it is used for HICON conversion. Task-number: QTBUG-39084 Change-Id: Ia4042c33db485c3604461a5eafd6282968b36e3b Reviewed-by: Andy Shaw <andy.shaw@digia.com>
Diffstat (limited to 'src/gui/image/qpixmap_win.cpp')
-rw-r--r--src/gui/image/qpixmap_win.cpp160
1 files changed, 86 insertions, 74 deletions
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index 93efe2e696..6cbb6fdb69 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
@@ -133,6 +133,68 @@ int qt_wince_GetDIBits(HDC /*hdc*/ , HBITMAP hSourceBitmap, uint, uint, LPVOID l
}
#endif
+static inline void initBitMapInfoHeader(int width, int height, bool topToBottom, BITMAPINFOHEADER *bih)
+{
+ memset(bih, 0, sizeof(BITMAPINFOHEADER));
+ bih->biSize = sizeof(BITMAPINFOHEADER);
+ bih->biWidth = width;
+ bih->biHeight = topToBottom ? -height : height;
+ bih->biPlanes = 1;
+ bih->biBitCount = 32;
+ bih->biCompression = BI_RGB;
+ bih->biSizeImage = width * height * 4;
+}
+
+static inline void initBitMapInfo(int width, int height, bool topToBottom, BITMAPINFO *bmi)
+{
+ initBitMapInfoHeader(width, height, topToBottom, &bmi->bmiHeader);
+ memset(bmi->bmiColors, 0, sizeof(RGBQUAD));
+}
+
+static inline uchar *getDiBits(HDC hdc, HBITMAP bitmap, int width, int height, bool topToBottom = true)
+{
+ BITMAPINFO bmi;
+ initBitMapInfo(width, height, topToBottom, &bmi);
+ uchar *result = new uchar[bmi.bmiHeader.biSizeImage];
+ if (!GetDIBits(hdc, bitmap, 0, height, result, &bmi, DIB_RGB_COLORS)) {
+ delete [] result;
+ qErrnoWarning("%s: GetDIBits() failed to get bitmap bits.", __FUNCTION__);
+ return 0;
+ }
+ return result;
+}
+
+static inline void copyImageDataCreateAlpha(const uchar *data, QImage *target)
+{
+ const uint mask = target->format() == QImage::Format_RGB32 ? 0xff000000 : 0;
+ const int height = target->height();
+ const int width = target->width();
+ const int bytesPerLine = width * int(sizeof(QRgb));
+ for (int y = 0; y < height; ++y) {
+ QRgb *dest = reinterpret_cast<QRgb *>(target->scanLine(y));
+ const QRgb *src = reinterpret_cast<const QRgb *>(data + y * bytesPerLine);
+ for (int x = 0; x < width; ++x) {
+ const uint pixel = src[x];
+ if ((pixel & 0xff000000) == 0 && (pixel & 0x00ffffff) != 0)
+ dest[x] = pixel | 0xff000000;
+ else
+ dest[x] = pixel | mask;
+ }
+ }
+}
+
+static inline void copyImageData(const uchar *data, QImage *target)
+{
+ const int height = target->height();
+ const int bytesPerLine = target->bytesPerLine();
+ for (int y = 0; y < height; ++y) {
+ void *dest = static_cast<void *>(target->scanLine(y));
+ const void *src = data + y * bytesPerLine;
+ memcpy(dest, src, bytesPerLine);
+ }
+
+}
+
enum HBitmapFormat
{
HBitmapNoAlpha,
@@ -176,14 +238,7 @@ Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat =
// Define the header
BITMAPINFO bmi;
- memset(&bmi, 0, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = w;
- bmi.bmiHeader.biHeight = -h;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = w * h * 4;
+ initBitMapInfo(w, h, true, &bmi);
// Create the pixmap
uchar *pixels = 0;
@@ -227,31 +282,16 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat =
const int w = bitmap_info.bmWidth;
const int h = bitmap_info.bmHeight;
- BITMAPINFO bmi;
- memset(&bmi, 0, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = w;
- bmi.bmiHeader.biHeight = -h;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = w * h * 4;
-
// Get bitmap bits
- QScopedArrayPointer<uchar> data(new uchar[bmi.bmiHeader.biSizeImage]);
HDC display_dc = GetDC(0);
- if (!GetDIBits(display_dc, bitmap, 0, h, data.data(), &bmi, DIB_RGB_COLORS)) {
+ QScopedArrayPointer<uchar> data(getDiBits(display_dc, bitmap, w, h, true));
+ if (data.isNull()) {
ReleaseDC(0, display_dc);
- qWarning("%s, failed to get bitmap bits", __FUNCTION__);
return QPixmap();
}
- QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied;
- uint mask = 0;
- if (hbitmapFormat == HBitmapNoAlpha) {
- imageFormat = QImage::Format_RGB32;
- mask = 0xff000000;
- }
+ const QImage::Format imageFormat = hbitmapFormat == HBitmapNoAlpha ?
+ QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied;
// Create image and copy data into image.
QImage image(w, h, imageFormat);
@@ -260,18 +300,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat =
qWarning("%s, failed create image of %dx%d", __FUNCTION__, w, h);
return QPixmap();
}
- const int bytes_per_line = w * sizeof(QRgb);
- for (int y = 0; y < h; ++y) {
- QRgb *dest = (QRgb *) image.scanLine(y);
- const QRgb *src = (const QRgb *) (data.data() + y * bytes_per_line);
- for (int x = 0; x < w; ++x) {
- const uint pixel = src[x];
- if ((pixel & 0xff000000) == 0 && (pixel & 0x00ffffff) != 0)
- dest[x] = pixel | 0xff000000;
- else
- dest[x] = pixel | mask;
- }
- }
+ copyImageDataCreateAlpha(data.data(), &image);
ReleaseDC(0, display_dc);
return QPixmap::fromImage(image);
}
@@ -307,32 +336,25 @@ Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &p)
Q_GUI_EXPORT QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
{
- BITMAPINFO bmi;
- memset(&bmi, 0, sizeof(bmi));
- bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = w;
- bmi.bmiHeader.biHeight = -h;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 32;
- bmi.bmiHeader.biCompression = BI_RGB;
- bmi.bmiHeader.biSizeImage = w * h * 4;
-
QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
if (image.isNull())
return image;
+ QScopedArrayPointer<uchar> data(getDiBits(hdc, bitmap, w, h, true));
+ if (data.isNull())
+ return QImage();
+ copyImageDataCreateAlpha(data.data(), &image);
+ return image;
+}
- // Get bitmap bits
- QScopedArrayPointer<uchar> data(new uchar [bmi.bmiHeader.biSizeImage]);
- if (!GetDIBits(hdc, bitmap, 0, h, data.data(), &bmi, DIB_RGB_COLORS)) {
- qErrnoWarning("%s: failed to get bitmap bits", __FUNCTION__);
+static QImage qt_imageFromWinIconHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
+{
+ QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
+ if (image.isNull())
+ return image;
+ QScopedArrayPointer<uchar> data(getDiBits(hdc, bitmap, w, h, true));
+ if (data.isNull())
return QImage();
- }
- // Create image and copy data into image.
- for (int y = 0; y < h; ++y) {
- void *dest = (void *) image.scanLine(y);
- void *src = data.data() + y * image.bytesPerLine();
- memcpy(dest, src, image.bytesPerLine());
- }
+ copyImageData(data.data(), &image);
return image;
}
@@ -354,23 +376,13 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
const int h = iconinfo.yHotspot * 2;
BITMAPINFOHEADER bitmapInfo;
- bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
- bitmapInfo.biWidth = w;
- bitmapInfo.biHeight = h;
- bitmapInfo.biPlanes = 1;
- bitmapInfo.biBitCount = 32;
- bitmapInfo.biCompression = BI_RGB;
- bitmapInfo.biSizeImage = 0;
- bitmapInfo.biXPelsPerMeter = 0;
- bitmapInfo.biYPelsPerMeter = 0;
- bitmapInfo.biClrUsed = 0;
- bitmapInfo.biClrImportant = 0;
+ initBitMapInfoHeader(w, h, false, &bitmapInfo);
DWORD* bits;
HBITMAP winBitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0);
HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap);
DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL);
- QImage image = qt_imageFromWinHBITMAP(hdc, winBitmap, w, h);
+ QImage image = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h);
for (int y = 0 ; y < h && !foundAlpha ; y++) {
const QRgb *scanLine= reinterpret_cast<const QRgb *>(image.scanLine(y));
@@ -384,7 +396,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon)
if (!foundAlpha) {
//If no alpha was found, we use the mask to set alpha values
DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK);
- const QImage mask = qt_imageFromWinHBITMAP(hdc, winBitmap, w, h);
+ const QImage mask = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h);
for (int y = 0 ; y < h ; y++){
QRgb *scanlineImage = reinterpret_cast<QRgb *>(image.scanLine(y));