Solved QCursor from 32-bit ARGB pixmap
-
Is there a way to set a 32-bit ARGB Pixmap as the mouse cursor? The QCursor constructor that takes a Pixmap converts the Pixmap image to the
QImage::Format_Indexed8
format (code snippet fromqcursor.cpp
):QCursor::QCursor(const QPixmap &pixmap, int hotX, int hotY) : d(0) { QImage img = pixmap.toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither); QBitmap bm = QBitmap::fromImage(img, Qt::ThresholdDither|Qt::AvoidDither); QBitmap bmm = pixmap.mask(); if (!bmm.isNull()) { QBitmap nullBm; bm.setMask(nullBm); } else if (!pixmap.mask().isNull()) { QImage mimg = pixmap.mask().toImage().convertToFormat(QImage::Format_Indexed8, Qt::ThresholdDither|Qt::AvoidDither); bmm = QBitmap::fromImage(mimg, Qt::ThresholdDither|Qt::AvoidDither); } else { bmm = QBitmap(bm.size()); bmm.fill(Qt::color1); } d = QCursorData::setBitmap(bm, bmm, hotX, hotY, pixmap.devicePixelRatio()); d->pixmap = pixmap; }
Is this format conversion necessary, or is it possible to use a 32-bit image as a cursor? If possible, is there some way of doing so without having to modify qcursor.cpp and compiling QT myself?
-
@Dericoun said in QCursor from 32-bit ARGB pixmap:
Pixmap converts the Pixmap image to the QImage::Format_Indexed8 format
Please take another look - the pixmap is not converted. There are only some temporary conversions to retrieve the alpha mask.
-
Thank you for the quick reply!
I see... My bad! Then something else must be causing my pixmap to render in slightly different colors. The color difference only happens when I render the pixmap using a QCursor. The pixmap renders in correct colors when I render it normally using
void QPainter::drawPixmap(int x, int y, const QPixmap &pm)
or through QML as
Image { ... source : "image://test" ... }
I tried taking a screenshot to show the color difference, but the QCursor pixmap strangely has the correct color in the resulting screenshot. The same thing happens when I try to record a video: When recording, the QCursor pixmap has the wrong color. But in the resulting video, the QCursor pixmap has the correct color.
Visually, it looks like the saturation of the colors in the pixmap decreases by around 15%.
Also forgot to mention that I'm running this on Windows 10, if that makes a difference. I have not tested any other operating systems.
-
Maybe some kind of opacity which is not added when taking a screenshot/video? Don't know. Check the alpha channel or remove it for testing purposes.
-
Thanks! I gave it a go. I converted the pixmap to RGB32:
QPixmap rgbPixmap = QPixmap::fromImage(pixmap.toImage().convertToFormat(QImage::Format::Format_RGB32)); QApplication::setOverrideCursor(rgbPixmap);
This did not resolve the color difference. The only difference was that the image now has a black background instead of a transparent one.
However, I noticed another peculiar thing: If I press on the title bar and move my application window around, the cursor is rendered in the correct color. It switches to the correct color as soon as the mouse moves while the title bar is pressed. The cursor remains rendered in the correct color (even when the mouse is not moving) until I release the press. This happens regardless of whether or not I convert to RGB32.
Do you have any other suggestions for debugging?
-
No, I'm out of ideas. Do you have a chance to check it on Win8.1, 7 or any other Win10 version to see if it makes a difference?
-
Okay. No, unfortunately not :(
I also tried adding the
QApplication::setOverrideCursor(pixmap)
to one of the example projects that come with QT (Qt-5.15.0\widgets\draganddrop\draggableicons
). The same color difference (and behavior when pressing the title bar) happens there too. Can you (or someone else) check this too, to find out whether this issue is related to my setup? At this point I'm guessing it is caused by something on my end, but it would be nice to make sure.I added
QApplication::setOverrideCursor(QPixmap(":/images/boat.png"));
to the draggableicons example project inmain.cpp
, right beforemainWidget.setWindowTitle(QObject::tr("Draggable Icons"));
Thank you again for your help, I really appreciate it!
-
Update: The cursor colors are correct now. Both in my application and in the example application. I changed the following:
- Updated my NVIDIA GeForce Game Drivers to the latest version.
- For my screen: Disabled the built-in blue light filter and maxed out the built-in brightness setting.
I believe one of these two changes fixed the issue (guessing it was the screen's built-in light filters that somehow messed with the cursor color). Tomorrow I'll try re-enabling the blue light filter and reducing brightness to the previous levels to see if that was the cause of the issue.
I'll report back tomorrow and mark the topic as resolved once I've tested that.
Update 2: I can't seem to reproduce the issue now. Maybe the NVIDIA drivers were the issue after all. Marking this as resolved for now. Thank you for the help Christian!