Qt 4.8
qpixmap_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qpixmap.h"
43 #include "qpixmap_raster_p.h"
44 
45 #include "qbitmap.h"
46 #include "qimage.h"
47 #include "qwidget.h"
48 #include "qpainter.h"
49 #include "qdatastream.h"
50 #include "qbuffer.h"
51 #include "qapplication.h"
52 #include "qevent.h"
53 #include "qfile.h"
54 #include "qfileinfo.h"
55 #include "qdatetime.h"
56 #include "qpixmapcache.h"
57 #include "qimagereader.h"
58 #include "qimagewriter.h"
59 #include "qdebug.h"
60 #include "qt_windows.h"
61 
62 #if defined(Q_WS_WINCE)
63 #include <winbase.h>
64 #include "qguifunctions_wince.h"
65 extern bool qt_wince_is_high_dpi();
66 extern bool qt_wince_is_pocket_pc();
67 #endif
68 
69 #ifndef CAPTUREBLT
70 #define CAPTUREBLT ((DWORD)0x40000000)
71 #endif
72 
74 
75 QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
76 {
77  RECT r;
78  GetClientRect(winId, &r);
79 
80  if (w < 0) w = r.right - r.left;
81  if (h < 0) h = r.bottom - r.top;
82 
83 #ifdef Q_WS_WINCE_WM
84  if (qt_wince_is_pocket_pc()) {
85  QWidget *widget = QWidget::find(winId);
86  if (qobject_cast<QDesktopWidget *>(widget)) {
87  RECT rect = {0,0,0,0};
88  AdjustWindowRectEx(&rect, WS_BORDER | WS_CAPTION, FALSE, 0);
89  int magicNumber = qt_wince_is_high_dpi() ? 4 : 2;
90  y += rect.top - magicNumber;
91  }
92  }
93 #endif
94 
95  // Create and setup bitmap
96  HDC display_dc = GetDC(0);
97  HDC bitmap_dc = CreateCompatibleDC(display_dc);
98  HBITMAP bitmap = CreateCompatibleBitmap(display_dc, w, h);
99  HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap);
100 
101  // copy data
102  HDC window_dc = GetDC(winId);
103  BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY
104 #ifndef Q_WS_WINCE
105  | CAPTUREBLT
106 #endif
107  );
108 
109  // clean up all but bitmap
110  ReleaseDC(winId, window_dc);
111  SelectObject(bitmap_dc, null_bitmap);
112  DeleteDC(bitmap_dc);
113 
114  QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap);
115 
116  DeleteObject(bitmap);
117  ReleaseDC(0, display_dc);
118 
119  return pixmap;
120 }
121 
123 {
124  if (isNull())
125  return 0;
126 
127  HBITMAP bitmap = 0;
129  QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data.data());
130  int w = d->image.width();
131  int h = d->image.height();
132 
133  HDC display_dc = GetDC(0);
134 
135  // Define the header
136  BITMAPINFO bmi;
137  memset(&bmi, 0, sizeof(bmi));
138  bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
139  bmi.bmiHeader.biWidth = w;
140  bmi.bmiHeader.biHeight = -h;
141  bmi.bmiHeader.biPlanes = 1;
142  bmi.bmiHeader.biBitCount = 32;
143  bmi.bmiHeader.biCompression = BI_RGB;
144  bmi.bmiHeader.biSizeImage = w * h * 4;
145 
146  // Create the pixmap
147  uchar *pixels = 0;
148  bitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, (void **) &pixels, 0, 0);
149  ReleaseDC(0, display_dc);
150  if (!bitmap) {
151  qErrnoWarning("QPixmap::toWinHBITMAP(), failed to create dibsection");
152  return 0;
153  }
154  if (!pixels) {
155  qErrnoWarning("QPixmap::toWinHBITMAP(), did not allocate pixel data");
156  return 0;
157  }
158 
159  // Copy over the data
161  if (format == NoAlpha)
162  imageFormat = QImage::Format_RGB32;
163  else if (format == PremultipliedAlpha)
165  const QImage image = d->image.convertToFormat(imageFormat);
166  int bytes_per_line = w * 4;
167  for (int y=0; y<h; ++y)
168  memcpy(pixels + y * bytes_per_line, image.scanLine(y), bytes_per_line);
169 
170  } else {
171  QPixmapData *data = new QRasterPixmapData(depth() == 1 ?
173  data->fromImage(toImage(), Qt::AutoColor);
174  return QPixmap(data).toWinHBITMAP(format);
175  }
176  return bitmap;
177 }
178 
180 {
181  // Verify size
182  BITMAP bitmap_info;
183  memset(&bitmap_info, 0, sizeof(BITMAP));
184 
185  int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info);
186  if (!res) {
187  qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info");
188  return QPixmap();
189  }
190  int w = bitmap_info.bmWidth;
191  int h = bitmap_info.bmHeight;
192 
193  BITMAPINFO bmi;
194  memset(&bmi, 0, sizeof(bmi));
195  bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
196  bmi.bmiHeader.biWidth = w;
197  bmi.bmiHeader.biHeight = -h;
198  bmi.bmiHeader.biPlanes = 1;
199  bmi.bmiHeader.biBitCount = 32;
200  bmi.bmiHeader.biCompression = BI_RGB;
201  bmi.bmiHeader.biSizeImage = w * h * 4;
202 
203  QImage result;
204  // Get bitmap bits
205  uchar *data = (uchar *) qMalloc(bmi.bmiHeader.biSizeImage);
206 
207  HDC display_dc = GetDC(0);
208  if (GetDIBits(display_dc, bitmap, 0, h, data, &bmi, DIB_RGB_COLORS)) {
209 
211  uint mask = 0;
212  if (format == NoAlpha) {
213  imageFormat = QImage::Format_RGB32;
214  mask = 0xff000000;
215  }
216 
217  // Create image and copy data into image.
218  QImage image(w, h, imageFormat);
219  if (!image.isNull()) { // failed to alloc?
220  int bytes_per_line = w * sizeof(QRgb);
221  for (int y=0; y<h; ++y) {
222  QRgb *dest = (QRgb *) image.scanLine(y);
223  const QRgb *src = (const QRgb *) (data + y * bytes_per_line);
224  for (int x=0; x<w; ++x) {
225  const uint pixel = src[x];
226  if ((pixel & 0xff000000) == 0 && (pixel & 0x00ffffff) != 0)
227  dest[x] = pixel | 0xff000000;
228  else
229  dest[x] = pixel | mask;
230  }
231  }
232  }
233  result = image;
234  } else {
235  qWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap bits");
236  }
237  ReleaseDC(0, display_dc);
238  qFree(data);
239  return fromImage(result);
240 }
241 
242 HBITMAP qt_createIconMask(const QBitmap &bitmap)
243 {
245  int w = bm.width();
246  int h = bm.height();
247  int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment
248  uchar *bits = new uchar[bpl*h];
249  bm.invertPixels();
250  for (int y=0; y<h; y++)
251  memcpy(bits+y*bpl, bm.scanLine(y), bpl);
252  HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits);
253  delete [] bits;
254  return hbm;
255 }
256 
257 HICON QPixmap::toWinHICON() const
258 {
259  QBitmap maskBitmap = mask();
260  if (maskBitmap.isNull()) {
261  maskBitmap= QBitmap(size());
262  maskBitmap.fill(Qt::color1);
263  }
264 
265  ICONINFO ii;
266  ii.fIcon = true;
267  ii.hbmMask = qt_createIconMask(maskBitmap);
268  ii.hbmColor = toWinHBITMAP(QPixmap::Alpha);
269  ii.xHotspot = 0;
270  ii.yHotspot = 0;
271 
272  HICON hIcon = CreateIconIndirect(&ii);
273 
274  DeleteObject(ii.hbmColor);
275  DeleteObject(ii.hbmMask);
276 
277  return hIcon;
278 }
279 
280 #ifdef Q_WS_WIN
281 #ifndef Q_WS_WINCE
282 
283 static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
284 {
285  BITMAPINFO bmi;
286  memset(&bmi, 0, sizeof(bmi));
287  bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
288  bmi.bmiHeader.biWidth = w;
289  bmi.bmiHeader.biHeight = -h;
290  bmi.bmiHeader.biPlanes = 1;
291  bmi.bmiHeader.biBitCount = 32;
292  bmi.bmiHeader.biCompression = BI_RGB;
293  bmi.bmiHeader.biSizeImage = w * h * 4;
294 
296  if (image.isNull())
297  return image;
298 
299  // Get bitmap bits
300  uchar *data = (uchar *) qMalloc(bmi.bmiHeader.biSizeImage);
301 
302  if (GetDIBits(hdc, bitmap, 0, h, data, &bmi, DIB_RGB_COLORS)) {
303  // Create image and copy data into image.
304  for (int y=0; y<h; ++y) {
305  void *dest = (void *) image.scanLine(y);
306  void *src = data + y * image.bytesPerLine();
307  memcpy(dest, src, image.bytesPerLine());
308  }
309  } else {
310  qWarning("qt_fromWinHBITMAP(), failed to get bitmap bits");
311  }
312  qFree(data);
313 
314  return image;
315 }
316 
317 QPixmap QPixmap::fromWinHICON(HICON icon)
318 {
319  bool foundAlpha = false;
320  HDC screenDevice = GetDC(0);
321  HDC hdc = CreateCompatibleDC(screenDevice);
322  ReleaseDC(0, screenDevice);
323 
324  ICONINFO iconinfo;
325  bool result = GetIconInfo(icon, &iconinfo); //x and y Hotspot describes the icon center
326  if (!result)
327  qWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()");
328 
329  int w = iconinfo.xHotspot * 2;
330  int h = iconinfo.yHotspot * 2;
331 
332  BITMAPINFOHEADER bitmapInfo;
333  bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
334  bitmapInfo.biWidth = w;
335  bitmapInfo.biHeight = h;
336  bitmapInfo.biPlanes = 1;
337  bitmapInfo.biBitCount = 32;
338  bitmapInfo.biCompression = BI_RGB;
339  bitmapInfo.biSizeImage = 0;
340  bitmapInfo.biXPelsPerMeter = 0;
341  bitmapInfo.biYPelsPerMeter = 0;
342  bitmapInfo.biClrUsed = 0;
343  bitmapInfo.biClrImportant = 0;
344  DWORD* bits;
345 
346  HBITMAP winBitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0);
347  HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap);
348  DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL);
349  QImage image = qt_fromWinHBITMAP(hdc, winBitmap, w, h);
350 
351  for (int y = 0 ; y < h && !foundAlpha ; y++) {
352  QRgb *scanLine= reinterpret_cast<QRgb *>(image.scanLine(y));
353  for (int x = 0; x < w ; x++) {
354  if (qAlpha(scanLine[x]) != 0) {
355  foundAlpha = true;
356  break;
357  }
358  }
359  }
360  if (!foundAlpha) {
361  //If no alpha was found, we use the mask to set alpha values
362  DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK);
363  QImage mask = qt_fromWinHBITMAP(hdc, winBitmap, w, h);
364 
365  for (int y = 0 ; y < h ; y++){
366  QRgb *scanlineImage = reinterpret_cast<QRgb *>(image.scanLine(y));
367  QRgb *scanlineMask = mask.isNull() ? 0 : reinterpret_cast<QRgb *>(mask.scanLine(y));
368  for (int x = 0; x < w ; x++){
369  if (scanlineMask && qRed(scanlineMask[x]) != 0)
370  scanlineImage[x] = 0; //mask out this pixel
371  else
372  scanlineImage[x] |= 0xff000000; // set the alpha channel to 255
373  }
374  }
375  }
376  //dispose resources created by iconinfo call
377  DeleteObject(iconinfo.hbmMask);
378  DeleteObject(iconinfo.hbmColor);
379 
380  SelectObject(hdc, oldhdc); //restore state
381  DeleteObject(winBitmap);
382  DeleteDC(hdc);
383  return QPixmap::fromImage(image);
384 }
385 #else //ifndef Q_WS_WINCE
387 {
388  HDC screenDevice = GetDC(0);
389  HDC hdc = CreateCompatibleDC(screenDevice);
390  ReleaseDC(0, screenDevice);
391 
392  ICONINFO iconinfo;
393  bool result = GetIconInfo(icon, &iconinfo);
394  if (!result)
395  qWarning("QPixmap::fromWinHICON(), failed to GetIconInfo()");
396 
397  int w = 0;
398  int h = 0;
399  if (!iconinfo.xHotspot || !iconinfo.yHotspot) {
400  // We could not retrieve the icon size via GetIconInfo,
401  // so we try again using the icon bitmap.
402  BITMAP bm;
403  int result = GetObject(iconinfo.hbmColor, sizeof(BITMAP), &bm);
404  if (!result) result = GetObject(iconinfo.hbmMask, sizeof(BITMAP), &bm);
405  if (!result) {
406  qWarning("QPixmap::fromWinHICON(), failed to retrieve icon size");
407  return QPixmap();
408  }
409  w = bm.bmWidth;
410  h = bm.bmHeight;
411  } else {
412  // x and y Hotspot describes the icon center
413  w = iconinfo.xHotspot * 2;
414  h = iconinfo.yHotspot * 2;
415  }
416  const DWORD dwImageSize = w * h * 4;
417 
418  BITMAPINFO bmi;
419  memset(&bmi, 0, sizeof(bmi));
420  bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
421  bmi.bmiHeader.biWidth = w;
422  bmi.bmiHeader.biHeight = -h;
423  bmi.bmiHeader.biPlanes = 1;
424  bmi.bmiHeader.biBitCount = 32;
425  bmi.bmiHeader.biCompression = BI_RGB;
426  bmi.bmiHeader.biSizeImage = dwImageSize;
427 
428  uchar* bits;
429 
430  HBITMAP winBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &bits, 0, 0);
431  if (winBitmap )
432  memset(bits, 0xff, dwImageSize);
433  if (!winBitmap) {
434  qWarning("QPixmap::fromWinHICON(), failed to CreateDIBSection()");
435  return QPixmap();
436  }
437 
438  HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap);
439  if (!DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_NORMAL))
440  qWarning("QPixmap::fromWinHICON(), failed to DrawIcon()");
441 
442  uint mask = 0xff000000;
443  // Create image and copy data into image.
444  QImage image(w, h, QImage::Format_ARGB32);
445 
446  if (!image.isNull()) { // failed to alloc?
447  int bytes_per_line = w * sizeof(QRgb);
448  for (int y=0; y < h; ++y) {
449  QRgb *dest = (QRgb *) image.scanLine(y);
450  const QRgb *src = (const QRgb *) (bits + y * bytes_per_line);
451  for (int x=0; x < w; ++x) {
452  dest[x] = src[x];
453  }
454  }
455  }
456  if (!DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK))
457  qWarning("QPixmap::fromWinHICON(), failed to DrawIcon()");
458  if (!image.isNull()) { // failed to alloc?
459  int bytes_per_line = w * sizeof(QRgb);
460  for (int y=0; y < h; ++y) {
461  QRgb *dest = (QRgb *) image.scanLine(y);
462  const QRgb *src = (const QRgb *) (bits + y * bytes_per_line);
463  for (int x=0; x < w; ++x) {
464  if (!src[x])
465  dest[x] = dest[x] | mask;
466  }
467  }
468  }
469  SelectObject(hdc, oldhdc); //restore state
470  DeleteObject(winBitmap);
471  DeleteDC(hdc);
472  return QPixmap::fromImage(image);
473 }
474 #endif //ifndef Q_WS_WINCE
475 #endif //ifdef Q_WS_WIN
476 
double d
Definition: qnumeric_p.h:62
QImage toImage() const
Converts the pixmap to a QImage.
Definition: qpixmap.cpp:542
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition: qpixmap.cpp:2197
Format
The following image formats are available in Qt.
Definition: qimage.h:91
unsigned int QRgb
Definition: qrgb.h:53
unsigned long WId
Definition: qwindowdefs.h:119
HBitmapFormat
HBITMAP and QPixmap is performed.
Definition: qpixmap.h:157
QPixmap()
Constructs a null pixmap.
Definition: qpixmap.cpp:174
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QPixmap fromWinHICON(HICON hicon)
QPointer< QWidget > widget
QSize size() const
Returns the size of the pixmap.
Definition: qpixmap.cpp:661
Q_GUI_EXPORT_INLINE int qAlpha(QRgb rgb)
Definition: qrgb.h:66
QExplicitlySharedDataPointer< QPixmapData > data
Definition: qpixmap.h:252
Q_CORE_EXPORT void qFree(void *ptr)
Definition: qmalloc.cpp:58
bool isNull() const
Returns true if it is a null image, otherwise returns false.
Definition: qimage.cpp:1542
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
#define GetDIBits(a, b, c, d, e, f, g)
static QPixmap fromWinHBITMAP(HBITMAP hbitmap, HBitmapFormat format=NoAlpha)
Win32 only: Returns a QPixmap that is equivalent to the given bitmap.
bool qt_wince_is_pocket_pc()
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
Q_CORE_EXPORT void * qMalloc(size_t size)
Definition: qmalloc.cpp:53
int depth() const
Returns the depth of the pixmap.
Definition: qpixmap.cpp:695
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
unsigned char uchar
Definition: qglobal.h:994
The QBitmap class provides monochrome (1-bit depth) pixmaps.
Definition: qbitmap.h:55
T * data() const
Returns a pointer to the shared data object.
Definition: qshareddata.h:145
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
virtual void fromImage(const QImage &image, Qt::ImageConversionFlags flags)=0
static QWidget * find(WId)
Returns a pointer to the widget with window identifer/handle id.
Definition: qwidget.cpp:2517
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
unsigned int uint
Definition: qglobal.h:996
#define FALSE
Synonym for false.
Definition: qglobal.h:1019
ClassId classId() const
void fill(const QColor &fillColor=Qt::white)
Fills the pixmap with the given color.
Definition: qpixmap.cpp:1080
int width() const
Returns the width of the image.
Definition: qimage.cpp:1557
QImage convertToFormat(Format f, Qt::ImageConversionFlags flags=Qt::AutoColor) const Q_REQUIRED_RESULT
Returns a copy of the image in the given format.
Definition: qimage.cpp:3966
bool qt_wince_is_high_dpi()
HBITMAP toWinHBITMAP(HBitmapFormat format=NoAlpha) const
It is the caller&#39;s responsibility to free the HBITMAP data after use.
QBitmap mask() const
Extracts a bitmap mask from the pixmap&#39;s alpha channel.
Definition: qpixmap.cpp:2077
HICON toWinHICON() const
Returns the HICON handle.
int height() const
Returns the height of the image.
Definition: qimage.cpp:1572
QRect rect() const
Returns the pixmap&#39;s enclosing rectangle.
Definition: qpixmap.cpp:676
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
HBITMAP qt_createIconMask(const QBitmap &bitmap)
static QPixmap grabWindow(WId, int x=0, int y=0, int w=-1, int h=-1)
Creates and returns a pixmap constructed by grabbing the contents of the given window restricted by Q...
void invertPixels(InvertMode=InvertRgb)
Inverts all pixel values in the image.
Definition: qimage.cpp:2179
#define Q_WS_WINCE
Definition: qglobal.h:895
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
friend class QBitmap
Definition: qpixmap.h:279
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
#define CAPTUREBLT
Definition: qpixmap_win.cpp:70
void qErrnoWarning(const char *msg,...)
Definition: qglobal.cpp:2954