How not to lose the alpha channel when converting between QRgb/QColor/QString

Working on color imagery for QiTissue recently, I realized we were accidentally losing the alpha channel in multiple places. For efficiency reasons, we keep colors in memory using the QRgb type, and convert that to/from QString for serialization purposes via QColor as needed. Here’s what I discovered about why that doesn’t work, and some ways I fixed it.

Firstly, be aware there is no QRgba in the Qt API . There is only QRgb , for 8bit color channels. It can hold an alpha value too, despite the lack of a trailing a in the type name. Then there is QRgba64 which uses 16bit per color channel. For our purposes, 8bit per channel is sufficient. So where do we lose the alpha channel, when QRgb can store it in principle?

The first pitfall is QColor(QRgb) , which calls QColor::fromRgb internally. Both of these functions silently ignore the alpha channel of the passed QRgb value and assume the color is fully opaque. To get around this, you have to use QColor::fromRgba instead.

QColor toColor(QRgb colorWithAlpha) { // all bad: input alpha ignored, set to fully opaque return QColor(colorWithAlpha); return colorWithAlpha; return QColor::fromRgb(colorWithAlpha); // good: return QColor::fromRgba(colorWithAlpha); }

Then you’ll find that QColor::name() also ignores the alpha channel. Here, you have to use QColor::name(QColor::HexArgb) instead.

QString toString(const QColor &colorWithAlpha) { // bad: input alpha ignored, output is e.g. #112233 return colorWithAlpha.name(); // good: output is e.g. #00112233 return colorWithAlpha.name(QColor::HexArgb); }

Thankfully, the QColor constructors and QColor::setName function, which parse a string color name, won’t ignore the alpha channel when you pass an ‘#AARRGGBB’ string.

However, there is one more pitfall: When you have a QColorDialog with QColorDialog::ShowAlphaChannel , and listen to its currentColorChanged signal and set a color with an alpha channel on it, a stray change signal notification will be emitted with a fully opaque color. The reason is that, internally, the color dialog will first set the RGB color components, and then in a second step will set the alpha component. But both will trigger a change notification, where the first step holds a fully opaque color. This should be fixed upstream, but thankfully for now it is easy to workaround by ignoring the signal while setting a color from the outside.

About KDAB If you like this blog and want to read similar articles, consider subscribing via our RSS feed. Subscribe to KDAB TV for similar informative short video content. KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.