Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Call for Presentations - Qt World Summit

    QImage \ QPixmal loses alpha color when drawing

    General and Desktop
    4
    8
    3664
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • P
      Pisyandry last edited by Pisyandry

      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.

      1 Reply Last reply Reply Quote 0
      • Hamed.Masafi
        Hamed.Masafi last edited by

        This post is deleted!
        1 Reply Last reply Reply Quote 0
        • kshegunov
          kshegunov Moderators last edited by

          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)

          Read and abide by the Qt Code of Conduct

          1 Reply Last reply Reply Quote 1
          • P
            Pisyandry last edited by Pisyandry

            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.

            kshegunov 1 Reply Last reply Reply Quote 0
            • G
              Gerd last edited by

              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

              1 Reply Last reply Reply Quote 2
              • P
                Pisyandry last edited by

                Hi, thank you for answer, but it work only for white images. Now drawing loses color of full opaque pixels instead of transparent pixels (I.e. all image areas with opaque pixels become white)

                1 Reply Last reply Reply Quote 0
                • kshegunov
                  kshegunov Moderators @Pisyandry last edited by

                  @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.

                  Read and abide by the Qt Code of Conduct

                  1 Reply Last reply Reply Quote 0
                  • G
                    Gerd last edited by

                    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

                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post