QImage \ QPixmal loses alpha color when drawing
-
Qt 5.7, Clang, OSX
I have png image with QImage::Format_ARGB32 filled with color ARGB(0, 255, 255, 255).
When I draw the image to another image with same format, color of alpha pixels loses. All ARGB(0, 255, 255, 255) pixels converts to ARGB(0, 0, 0, 0).
Following code loses color of alpha-pixels:
QImage sourceImage("image.png"); QImage destImage(sourceImage.width(), sourceImage.height(), sourceImage.format()); QPainter painter(&destImage); painter.setCompositionMode(QPainter::CompositionMode_Source); painter.drawImage(0, 0, sourceImage); painter.end();
Scaling image loses color of alpha-pixels too:
QImage destImage = sourceImage:scaled(sourceImage.width() / 2, sourceImage.height() / 2);
But following code save pixels color:
QImage sourceImage("image.png"); QImage destImage(sourceImage.width(), sourceImage.height(), sourceImage.format()); for(int x = 0; x < sourceImage.width(); x++) { for(int y = 0; y < sourceImage.height(); y++) { destImage.setPixelColor(x, y, sourceImage.pixelColor(x, y)); } }
So, it's synthetic example. In real task I have image with white text rendering in OpenGL application. In that case I get black pixels artifacts around my white text because GL can mix color of pixel with neighbor pixels.
Summary:
I need two things: smooth scale image and draw it to another image without losing rgb color of transparent pixels. -
This post is deleted!
-
Works normally on my machine (Debian). Here's the code I used:
#include <QApplication> #include <QPainter> #include <QImage> #include <QTimer> #include <QLabel> int main(int argc, char ** argv) { QApplication app(argc, argv); QLabel view; QTimer::singleShot(0, [&view] () -> void { QImage sourceImage("butterfly2.png"); QImage destImage(sourceImage.width(), sourceImage.height(), sourceImage.format()); QPainter painter(&destImage); painter.fillRect(destImage.rect(), Qt::magenta); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.drawImage(0, 0, sourceImage); view.setPixmap(QPixmap::fromImage(destImage)); view.show(); }); return QApplication::exec(); }
I also fetched this image for my test run. (
QPainter::CompositionMode_Source
also works as expected for me) -
Thank your for answer, but I means different case.
Please try this image. Just load it to QImage and draw to another QImage with same format(ARGB32). Next, render it without blending. (Best way is render it using OpenGL with glDisable(GL_BLEND) ).
This is correct result
White butterfly on white background. Pixels of transparent area of source image were white but with zero alpha and after splitting alpha channel pixels become opaque white. It's correct.This is incorrect result
White butterfly on black background. Pixels of transparent area of source image were white with zero alpha channel. But after QPainter::drawImage pixels become black with zero alpha channel. So, after splitting alpha channel pixels become opaque black. It's incorrect. -
Hi,
Image-drawing and also scaling is always done by some kind of alpha-blending, so if you use full transparent pixels in drawing they will always end in qRgba(0,0,0,0).What you can do:
If you need a copy of the source.image, use image.copy() instead of drawing the src-image into a new one of the same size and format,If you need to scale such an image you have to invert the pixels before and after the scaling. The scaled Image will be in QImage::Format_ARGB32_Premultiplied, so it has to be converted to QImage::Format_ARGB32.
If you want to draw such an Image into an exsiting image both, the src and the destination image, needs to be in QImage::Format_ARGB32 and both needs to be inverted.
Example for scaling:QImage sourceImage("butterfly3.png"); QImage destImage; sourceImage.invertPixels(QImage::InvertRgba); destImage = sourceImage.scaled(sourceImage.width()/2, sourceImage.height()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).convertToFormat(QImage::Format_ARGB32); sourceImage.invertPixels(QImage::InvertRgba); destImage.invertPixels(QImage::InvertRgba); destImage.save("out.png", "PNG");
Hope that helps
Regards
Gerd -
Thank your for answer, but I means different case.
Please try this image. Just load it to QImage and draw to another QImage with same format(ARGB32). Next, render it without blending. (Best way is render it using OpenGL with glDisable(GL_BLEND) ).
This is correct result
White butterfly on white background. Pixels of transparent area of source image were white but with zero alpha and after splitting alpha channel pixels become opaque white. It's correct.This is incorrect result
White butterfly on black background. Pixels of transparent area of source image were white with zero alpha channel. But after QPainter::drawImage pixels become black with zero alpha channel. So, after splitting alpha channel pixels become opaque black. It's incorrect.@Pisyandry said in QImage \ QPixmal loses alpha color when drawing:
Please try this image. Just load it to QImage and draw to another QImage with same format(ARGB32). Next, render it without blending. (Best way is render it using OpenGL with glDisable(GL_BLEND) ).
This is what I do in my example. One image is drawn to another and is then rendered to the screen. With the suggested image I still get correct behavior.
Best way is render it using OpenGL with glDisable(GL_BLEND)
I don't understand what raw GL calls are doing here, or how they relate to the issue at all.
White butterfly on black background. Pixels of transparent area of source image were white with zero alpha channel. But after QPainter::drawImage pixels become black with zero alpha channel.
???!?
So, after splitting alpha channel pixels become opaque black. It's incorrect.
What is this splitting you're talking about, I don't get what you're trying to accomplish and I don't understand how are you obtaining these images.
-
Hi,
according to your description and your example i thought you where talking about black/white images.
However, even if i think it's not a good idea to deal with "the color of transparent pixels" you can try this:QImage sourceImage("butterfly3.png"); QImage destImage; destImage = sourceImage.scaled(sourceImage.width()/2, sourceImage.height()/2, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).convertToFormat(QImage::Format_ARGB32); quint32 *dst = (quint32*)destImage.bits(); for (int i = 0; i < destImage.byteCount() / 4; i++, dst++) if (*dst == 0x00000000) *dst = 0x00ffffff; destImage.save("out.png", "PNG");
Regards
Gerd