7#include <private/qpixmap_win_p.h>
8#include <qpa/qplatformpixmap.h>
12#include <QScopedArrayPointer>
13#include <qt_windows.h>
20template <
typename Int>
21static inline Int pad4(Int v)
23 return (v + Int(3)) & ~Int(3);
26#ifndef QT_NO_DEBUG_STREAM
29 QDebugStateSaver saver(d);
31 d <<
"BITMAPINFOHEADER(" << bih.biWidth <<
'x' << qAbs(bih.biHeight)
32 << (bih.biHeight < 0 ?
", top-down" :
", bottom-up")
33 <<
", planes=" << bih.biPlanes <<
", bitCount=" << bih.biBitCount
34 <<
", compression=" << bih.biCompression <<
", size="
35 << bih.biSizeImage <<
')';
41 DWORD compression, DWORD bitCount,
42 BITMAPINFOHEADER *bih)
44 memset(bih, 0,
sizeof(BITMAPINFOHEADER));
45 bih->biSize =
sizeof(BITMAPINFOHEADER);
47 bih->biHeight = topToBottom ? -height : height;
49 bih->biBitCount = WORD(bitCount);
50 bih->biCompression = compression;
52 const DWORD bytesPerLine = bitCount == 1 ? pad4(DWORD(qCeil(width / 8.0)))
53 : pad4(DWORD(width) * bitCount / 8);
54 bih->biSizeImage = bytesPerLine * DWORD(height);
64template <
class BITMAPINFO_T>
66 DWORD compression, DWORD bitCount,
69 initBitMapInfoHeader(width, height, topToBottom, compression, bitCount, &bmi->bmiHeader);
70 memset(bmi->bmiColors, 0,
sizeof(bmi->bmiColors));
73static inline uchar *
getDiBits(HDC hdc, HBITMAP bitmap,
int width,
int height,
bool topToBottom =
true)
76 initBitMapInfo(width, height, topToBottom, BI_RGB, 32u, &bmi);
77 uchar *result =
new uchar[bmi.bmiHeader.biSizeImage];
78 if (!GetDIBits(hdc, bitmap, 0, UINT(height), result, &bmi, DIB_RGB_COLORS)) {
80 qErrnoWarning(
"%s: GetDIBits() failed to get bitmap bits.",
__FUNCTION__);
88 const uint mask = target->format() == QImage::Format_RGB32 ? 0xff000000 : 0;
89 const int height = target->height();
90 const int width = target->width();
91 const qsizetype bytesPerLine = width *
sizeof(QRgb);
92 for (
int y = 0; y < height; ++y) {
93 QRgb *dest =
reinterpret_cast<QRgb *>(target->scanLine(y));
94 const QRgb *src =
reinterpret_cast<
const QRgb *>(data + y * bytesPerLine);
95 for (
int x = 0; x < width; ++x) {
96 const uint pixel = src[x];
97 if ((pixel & 0xff000000) == 0 && (pixel & 0x00ffffff) != 0)
98 dest[x] = pixel | 0xff000000;
100 dest[x] = pixel | mask;
107static inline void flipRgb3(uchar *p,
int width,
int height)
109 const int lineSize = 3 * width;
110 const int linePad = pad4(lineSize) - lineSize;
111 for (
int y = 0; y < height; ++y) {
112 uchar *end = p + lineSize;
113 for ( ; p < end; p += 3)
114 std::swap(*p, *(p + 2));
121 RGBQUAD result = {BYTE(qBlue(qrgb)), BYTE(qGreen(qrgb)), BYTE(qRed(qrgb)), 0};
127 return QRgb(quad.rgbBlue) + (QRgb(quad.rgbGreen) << 8) + (QRgb(quad.rgbRed) << 16)
133 const void *data, QImage::Format format)
135 const QSize size = QSize(header.biWidth, qAbs(header.biHeight));
136 QImage image(size, format);
138 int colorTableSize = 0;
140 case QImage::Format_Mono:
143 case QImage::Format_Indexed8:
149 if (colorTableSize) {
150 Q_ASSERT(colorTableIn);
151 QList<QRgb> colorTable;
152 colorTable.reserve(colorTableSize);
153 std::transform(colorTableIn, colorTableIn + colorTableSize,
154 std::back_inserter(colorTable), rgbQuadToQRgb);
155 image.setColorTable(colorTable);
158 switch (header.biBitCount) {
160 copyImageDataCreateAlpha(
static_cast<
const uchar *>(data), &image);
166 Q_ASSERT(DWORD(image.sizeInBytes()) == header.biSizeImage);
167 memcpy(image.bits(), data, header.biSizeImage);
168 if (format == QImage::Format_RGB888)
169 image =
std::move(image).rgbSwapped();
200 Q_ASSERT(bm.format() == QImage::Format_Mono);
201 const int w = bm.width();
202 const int h = bm.height();
203 const int bpl = ((w+15)/16)*2;
204 QScopedArrayPointer<uchar> bits(
new uchar[size_t(bpl * h)]);
206 for (
int y = 0; y < h; ++y)
207 memcpy(bits.data() + y * bpl, bm.constScanLine(y), size_t(bpl));
208 HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits.data());
214 return qt_createIconMask(bitmap.toImage().convertToFormat(QImage::Format_Mono));
219 switch (hbitmapFormat) {
221 return QImage::Format_RGB32;
223 return QImage::Format_ARGB32;
227 return QImage::Format_ARGB32_Premultiplied;
232 if (imageIn.isNull())
236 DWORD compression = 0;
240 QImage image = imageIn;
241 switch (image.format()) {
242 case QImage::Format_Mono:
245 case QImage::Format_RGB32:
246 case QImage::Format_ARGB32:
247 case QImage::Format_ARGB32_Premultiplied: {
248 compression = BI_RGB;
250 const QImage::Format targetFormat = format32(hbitmapFormat);
251 if (targetFormat != image.format())
252 image = image.convertToFormat(targetFormat);
255 case QImage::Format_RGB888:
256 case QImage::Format_BGR888:
257 compression = BI_RGB;
260 case QImage::Format_Indexed8:
263 case QImage::Format_RGB555:
267 QImage::Format fallbackFormat = QImage::Format_ARGB32_Premultiplied;
268 switch (image.format()) {
269 case QImage::Format_MonoLSB:
270 fallbackFormat = QImage::Format_Mono;
272 case QImage::Format_RGB16:
273 fallbackFormat = QImage::Format_RGB555;
275 case QImage::Format_Grayscale8:
276 fallbackFormat = QImage::Format_Indexed8;
281 return qt_imageToWinHBITMAP(imageIn.convertToFormat(fallbackFormat), hbitmapFormat);
285 const int w = image.width();
286 const int h = image.height();
289 initBitMapInfo(w, h,
true, compression, bitCount, &bmiColorTable256);
290 BITMAPINFO &bmi =
reinterpret_cast<BITMAPINFO &>(bmiColorTable256);
291 switch (image.format()) {
292 case QImage::Format_Mono:
293 case QImage::Format_Indexed8:
294 std::transform(image.colorTable().constBegin(), image.colorTable().constEnd(),
295 bmiColorTable256.bmiColors, qRgbToRgbQuad);
302 uchar *pixels =
nullptr;
303 const HBITMAP bitmap = CreateDIBSection(
nullptr, &bmi, DIB_RGB_COLORS,
304 reinterpret_cast<
void **>(&pixels),
nullptr, 0);
306 qErrnoWarning(
"%s, failed to create dibsection",
__FUNCTION__);
310 DeleteObject(bitmap);
311 qErrnoWarning(
"%s, did not allocate pixel data",
__FUNCTION__);
314 memcpy(pixels, image.constBits(), bmi.bmiHeader.biSizeImage);
315 if (image.format() == QImage::Format_RGB888)
316 flipRgb3(pixels, w, h);
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344HBITMAP QImage::toHBITMAP()
const
347 case QImage::Format_ARGB32:
348 return qt_imageToWinHBITMAP(*
this, HBitmapAlpha);
349 case QImage::Format_ARGB32_Premultiplied:
350 return qt_imageToWinHBITMAP(*
this, HBitmapPremultipliedAlpha);
354 return qt_imageToWinHBITMAP(*
this);
362 QPlatformPixmap *platformPixmap = p.handle();
363 if (platformPixmap->classId() != QPlatformPixmap::RasterClass) {
364 QRasterPlatformPixmap *data =
new QRasterPlatformPixmap(p.depth() == 1 ?
365 QRasterPlatformPixmap::BitmapType : QRasterPlatformPixmap::PixmapType);
366 data->fromImage(p.toImage(), Qt::AutoColor);
367 return qt_pixmapToWinHBITMAP(QPixmap(data), hbitmapFormat);
370 return qt_imageToWinHBITMAP(*
static_cast<QRasterPlatformPixmap*>(platformPixmap)->buffer(), hbitmapFormat);
375 QImage::Format result = QImage::Format_Invalid;
376 switch (header.biBitCount) {
378 result = hbitmapFormat == HBitmapNoAlpha
379 ? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied;
382 result = QImage::Format_BGR888;
385 result = QImage::Format_RGB555;
388 result = QImage::Format_Indexed8;
391 result = QImage::Format_Mono;
401 DIBSECTION dibSection;
402 memset(&dibSection, 0,
sizeof(dibSection));
403 dibSection.dsBmih.biSize =
sizeof(dibSection.dsBmih);
405 if (!GetObject(bitmap,
sizeof(dibSection), &dibSection)
406 || !dibSection.dsBm.bmBits
407 || dibSection.dsBmih.biBitCount <= 8
408 || dibSection.dsBmih.biCompression != BI_RGB) {
412 const QImage::Format imageFormat = imageFromWinHBITMAP_Format(dibSection.dsBmih, hbitmapFormat);
413 if (imageFormat == QImage::Format_Invalid)
416 return copyImageData(dibSection.dsBmih,
nullptr, dibSection.dsBm.bmBits, imageFormat);
423 BITMAPINFO &info =
reinterpret_cast<BITMAPINFO &>(bmiColorTable256);
424 memset(&info, 0,
sizeof(info));
425 info.bmiHeader.biSize =
sizeof(info.bmiHeader);
428 if (!GetDIBits(displayDc, bitmap, 0, 1, 0, &info, DIB_RGB_COLORS)) {
429 qErrnoWarning(
"%s: GetDIBits() failed to query data.",
__FUNCTION__);
433 if (info.bmiHeader.biHeight > 0)
434 info.bmiHeader.biHeight = -info.bmiHeader.biHeight;
435 info.bmiHeader.biCompression = BI_RGB;
436 size_t allocSize = info.bmiHeader.biSizeImage;
438 info.bmiHeader.biBitCount = 32;
439 allocSize = info.bmiHeader.biWidth * qAbs(info.bmiHeader.biHeight) * 4;
442 const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat);
443 if (imageFormat == QImage::Format_Invalid) {
444 qWarning().nospace() <<
__FUNCTION__ <<
": unsupported image format:" << info.bmiHeader;
448 QScopedArrayPointer<uchar> data(
new uchar[allocSize]);
449 if (!GetDIBits(displayDc, bitmap, 0, qAbs(info.bmiHeader.biHeight), data.data(), &info, DIB_RGB_COLORS)) {
450 qErrnoWarning(
"%s: GetDIBits() failed to get data.",
__FUNCTION__);
453 return copyImageData(info.bmiHeader, bmiColorTable256.bmiColors, data.data(), imageFormat);
458 QImage result = imageFromWinHBITMAP_DibSection(bitmap, hbitmapFormat);
460 result = imageFromWinHBITMAP_GetDiBits(bitmap,
false, hbitmapFormat);
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483QImage QImage::fromHBITMAP(HBITMAP hbitmap)
485 return qt_imageFromWinHBITMAP(hbitmap);
490 return QPixmap::fromImage(imageFromWinHBITMAP_GetDiBits(bitmap,
true, hbitmapFormat));
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508HICON QImage::toHICON(
const QImage &mask)
const
510 if (!mask.isNull() && mask.format() != QImage::Format_Mono) {
511 qWarning(
"QImage::toHICON(): Mask must be empty or have format Format_Mono");
518 auto effectiveMask = mask;
519 if (effectiveMask.isNull()) {
520 effectiveMask = QImage(size(), QImage::Format_Mono);
521 effectiveMask.fill(Qt::color1);
526 ii.hbmMask = qt_createIconMask(effectiveMask);
527 ii.hbmColor = qt_imageToWinHBITMAP(*
this, HBitmapAlpha);
531 HICON hIcon = CreateIconIndirect(&ii);
533 DeleteObject(ii.hbmColor);
534 DeleteObject(ii.hbmMask);
543 if (!maskBitmap.isNull())
544 mask = maskBitmap.toImage().convertToFormat(QImage::Format_Mono);
545 return p.toImage().toHICON(mask);
550 QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
553 QScopedArrayPointer<uchar> data(getDiBits(hdc, bitmap, w, h,
true));
556 copyImageDataCreateAlpha(data.data(), &image);
562 QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
565 QScopedArrayPointer<uchar> data(getDiBits(hdc, bitmap, w, h,
true));
568 memcpy(image.bits(), data.data(), size_t(image.sizeInBytes()));
574 const int w = image.width();
575 const int h = image.height();
576 for (
int y = 0; y < h; ++y) {
577 const QRgb *scanLine =
reinterpret_cast<
const QRgb *>(image.scanLine(y));
578 for (
int x = 0; x < w; ++x) {
579 if (qAlpha(scanLine[x]) != 0)
587
588
589
590
591
592
593
594
595QImage QImage::fromHICON(HICON icon)
597 HDC screenDevice = GetDC(
nullptr);
598 HDC hdc = CreateCompatibleDC(screenDevice);
599 ReleaseDC(
nullptr, screenDevice);
602 const bool result = GetIconInfo(icon, &iconinfo);
604 qErrnoWarning(
"QPixmap::fromWinHICON(), failed to GetIconInfo()");
609 const int w =
int(iconinfo.xHotspot) * 2;
610 const int h =
int(iconinfo.yHotspot) * 2;
612 BITMAPINFOHEADER bitmapInfo;
613 initBitMapInfoHeader(w, h,
false, BI_RGB, 32u, &bitmapInfo);
616 HBITMAP winBitmap = CreateDIBSection(hdc,
reinterpret_cast<BITMAPINFO *>(&bitmapInfo),
617 DIB_RGB_COLORS,
reinterpret_cast<VOID **>(&bits),
619 HGDIOBJ oldhdc =
static_cast<HBITMAP>(SelectObject(hdc, winBitmap));
620 DrawIconEx(hdc, 0, 0, icon, w, h, 0,
nullptr, DI_NORMAL);
621 QImage image = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h);
623 if (!image.isNull() && !hasAlpha(image)) {
624 DrawIconEx( hdc, 0, 0, icon, w, h, 0,
nullptr, DI_MASK);
625 const QImage mask = qt_imageFromWinIconHBITMAP(hdc, winBitmap, w, h);
627 for (
int y = 0 ; y < h ; y++){
628 QRgb *scanlineImage =
reinterpret_cast<QRgb *>(image.scanLine(y));
629 const QRgb *scanlineMask = mask.isNull() ?
nullptr :
reinterpret_cast<
const QRgb *>(mask.scanLine(y));
630 for (
int x = 0; x < w ; x++){
631 if (scanlineMask && qRed(scanlineMask[x]) != 0)
632 scanlineImage[x] = 0;
634 scanlineImage[x] |= 0xff000000;
639 DeleteObject(iconinfo.hbmMask);
640 DeleteObject(iconinfo.hbmColor);
642 SelectObject(hdc, oldhdc);
643 DeleteObject(winBitmap);
650 return QPixmap::fromImage(QImage::fromHICON(icon));
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapFormat)
static void flipRgb3(uchar *p, int width, int height)
static bool hasAlpha(const QImage &image)
static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int hbitmapFormat)
static QImage qt_imageFromWinIconHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
static void initBitMapInfoHeader(int width, int height, bool topToBottom, DWORD compression, DWORD bitCount, BITMAPINFOHEADER *bih)
QPixmap qt_pixmapFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat)
static HBITMAP qt_createIconMask(QImage bm)
static RGBQUAD qRgbToRgbQuad(QRgb qrgb)
static QImage::Format format32(int hbitmapFormat)
@ HBitmapPremultipliedAlpha
static QImage copyImageData(const BITMAPINFOHEADER &header, const RGBQUAD *colorTableIn, const void *data, QImage::Format format)
static QImage::Format imageFromWinHBITMAP_Format(const BITMAPINFOHEADER &header, int hbitmapFormat)
QImage qt_imageFromWinHBITMAP(HBITMAP bitmap, int hbitmapFormat)
QPixmap qt_pixmapFromWinHICON(HICON icon)
HBITMAP qt_createIconMask(const QBitmap &bitmap)
static QImage imageFromWinHBITMAP_DibSection(HBITMAP bitmap, int hbitmapFormat)
HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat)
HICON qt_pixmapToWinHICON(const QPixmap &p)
static uchar * getDiBits(HDC hdc, HBITMAP bitmap, int width, int height, bool topToBottom=true)
static void copyImageDataCreateAlpha(const uchar *data, QImage *target)
static QRgb rgbQuadToQRgb(RGBQUAD quad)
static void initBitMapInfo(int width, int height, bool topToBottom, DWORD compression, DWORD bitCount, BITMAPINFO_T *bmi)
QImage qt_imageFromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
BITMAPINFOHEADER bmiHeader
RGBQUAD bmiColors[Indexed8ColorTableSize]