Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Why does QPainter.fillRect with transparency leave artifacts?

Why does QPainter.fillRect with transparency leave artifacts?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
6 Posts 2 Posters 1.9k Views 1 Watching
  • 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.
  • fcarneyF Offline
    fcarneyF Offline
    fcarney
    wrote on last edited by
    #1

    main.cpp:

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    
    #include <QBuffer>
    #include <QImage>
    #include <QPainter>
    #include <QQmlContext>
    
    class ImageSource : public QObject
    {
        Q_OBJECT
    
    public:
        ImageSource(QObject* parent=nullptr)
            : QObject(parent)
        {
    
        }
    
        Q_INVOKABLE QString genImageString(QString text){
            QImage textimage(64,64, QImage::Format_RGBA8888);
    
            // create image
            QPainter painter(&textimage);
            //painter.setPen(QColor(255,0,0,255));
            //painter.fillRect(0,0,64,64, QColor(0,0,0,255));
            painter.fillRect(0,0,64,64, QColor(0,0,0,0));
            //painter.fillRect(0,0,64,64, QBrush(Qt::transparent, Qt::BrushStyle::SolidPattern));
            painter.setPen(Qt::blue);
            painter.setFont(QFont("Arial", 20));
            painter.drawText(QRect(0,0,64,64), Qt::AlignCenter, text);
    
            QByteArray bArray;
            QBuffer buffer(&bArray);
            buffer.open(QIODevice::WriteOnly);
    
            textimage.save(&buffer, "PNG");
    
            QString image("data:image/png;base64,");
            image.append(QString::fromLatin1(bArray.toBase64().data()));
    
            return image;
        }
    };
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        ImageSource is;
        auto context = engine.rootContext();
        context->setContextObject(&is);
    
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        engine.load(url);
    
        return app.exec();
    }
    
    #include "main.moc"
    

    main.qml:

    import QtQuick 2.12
    import QtQuick.Window 2.12
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("QML Image from Source String")
    
    
        GridView {
            id: gridview
    
            anchors.fill: imagetester
    
            model: 9
            cellWidth: imagetester.width/3
            cellHeight: imagetester.height/3
    
            delegate: Rectangle {
                width: gridview.cellWidth
                height: gridview.cellHeight
                color: !(index % 2) ? "lightgrey" : "grey"
                opacity: 0.75
            }
        }
    
        Image {
            id: imagetester
    
            width: 64
            height: 64
            source: genImageString("Hello")
        }
    }
    

    I tried doing a fill with black with alpha set to 255. Then a fill with transparency and it just shows black. Is this an issue with conversion to PNG or the QImage itself?

    C++ is a perfectly valid school of magic.

    1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      Woah woah woah!!! This is crazy! If I change the image size then it goes away!
      main.cpp:

      #include <QGuiApplication>
      #include <QQmlApplicationEngine>
      
      #include <QBuffer>
      #include <QImage>
      #include <QPainter>
      #include <QQmlContext>
      
      class ImageSource : public QObject
      {
          Q_OBJECT
      
      public:
          ImageSource(QObject* parent=nullptr)
              : QObject(parent)
          {
      
          }
      
          Q_INVOKABLE QString genImageString(QString text, int width, int height){
              QImage textimage(width,height, QImage::Format_RGBA8888);
      
              // create image
              QPainter painter(&textimage);
              //painter.setPen(QColor(255,0,0,255));
              //painter.fillRect(0,0,width,height, QColor(0,0,0,255));
              painter.fillRect(0,0,width,height, QColor(0,0,0,0));
              //painter.fillRect(0,0,width,height, QBrush(Qt::transparent, Qt::BrushStyle::SolidPattern));
              painter.setPen(Qt::blue);
              painter.setFont(QFont("Arial", 20));
              painter.drawText(QRect(0,0,width,height), Qt::AlignCenter, text);
      
              QByteArray bArray;
              QBuffer buffer(&bArray);
              buffer.open(QIODevice::WriteOnly);
      
              textimage.save(&buffer, "PNG");
      
              QString image("data:image/png;base64,");
              image.append(QString::fromLatin1(bArray.toBase64().data()));
      
              return image;
          }
      };
      
      int main(int argc, char *argv[])
      {
          QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
      
          QGuiApplication app(argc, argv);
      
          QQmlApplicationEngine engine;
      
          ImageSource is;
          auto context = engine.rootContext();
          context->setContextObject(&is);
      
          const QUrl url(QStringLiteral("qrc:/main.qml"));
          QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                           &app, [url](QObject *obj, const QUrl &objUrl) {
              if (!obj && url == objUrl)
                  QCoreApplication::exit(-1);
          }, Qt::QueuedConnection);
          engine.load(url);
      
          return app.exec();
      }
      
      #include "main.moc"
      

      main.qml:

      import QtQuick 2.12
      import QtQuick.Window 2.12
      
      Window {
          visible: true
          width: iw
          height: ih
          title: qsTr("QML Image from Source String")
      
      
          property int iw: 256
          property int ih: iw
      
          GridView {
              id: gridview
      
              anchors.fill: imagetester
      
              model: 9
              cellWidth: imagetester.width/3
              cellHeight: imagetester.height/3
      
              delegate: Rectangle {
                  width: gridview.cellWidth
                  height: gridview.cellHeight
                  color: !(index % 2) ? "lightgrey" : "grey"
                  opacity: 0.75
              }
          }
      
          Image {
              id: imagetester
      
              width: iw
              height: ih
              source: genImageString("Hello", width, height)
          }
      }
      

      64x64:
      artifacts64.png
      128x128:
      noartifacts128.png

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • MarkkyboyM Offline
        MarkkyboyM Offline
        Markkyboy
        wrote on last edited by
        #3

        I can reduce to 32px and there are not any artefacts. Possibly an issue with your graphics driver?

        My machine specs;
        Windows 64bit Ultimate
        16GB RAM
        Intel i7 ~ 2.2gHz
        nVidia 1GB ~ GT555M

        Don't just sit there standing around, pick up a shovel and sweep up!

        I live by the sea, not in it.

        1 Reply Last reply
        1
        • fcarneyF Offline
          fcarneyF Offline
          fcarney
          wrote on last edited by
          #4

          I have Qt apps that display icons from other sources that don't do that. I should see if dumping it directly to file will have images with artifacts. Then I know if its in the qml render side, or in the output of the function that does the drawing.

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          0
          • fcarneyF Offline
            fcarneyF Offline
            fcarney
            wrote on last edited by
            #5

            Interesting, the png file that gets written has the same artifacts. So that limits the issue to the painting/image conversion code:

            Q_INVOKABLE QString genImageString(QString text, int width, int height){
                    QImage textimage(width,height, QImage::Format_RGBA8888);
            
                    // create image
                    QPainter painter(&textimage);
                    //painter.setPen(QColor(255,0,0,255));
                    //painter.fillRect(0,0,width,height, QColor(0,0,0,255));
                    painter.fillRect(0,0,width,height, QColor(0,0,0,0));
                    //painter.fillRect(0,0,width,height, QBrush(Qt::transparent, Qt::BrushStyle::SolidPattern));
                    painter.setPen(Qt::blue);
                    painter.setFont(QFont("Arial", 20));
                    painter.drawText(QRect(0,0,width,height), Qt::AlignCenter, text);
            
                    QByteArray bArray;
                    QBuffer buffer(&bArray);
                    buffer.open(QIODevice::WriteOnly);
            
                    textimage.save(&buffer, "PNG");
            
                    QFile pngfile(QString("image%1%2.png").number(width).number(height));
                    if(pngfile.open(QIODevice::WriteOnly)){
                        textimage.save(&pngfile, "PNG");
                    }
                    pngfile.close();
            
                    QString image("data:image/png;base64,");
                    image.append(QString::fromLatin1(bArray.toBase64().data()));
            
                    return image;
                }
            

            C++ is a perfectly valid school of magic.

            1 Reply Last reply
            0
            • fcarneyF Offline
              fcarneyF Offline
              fcarney
              wrote on last edited by
              #6

              Okay, found something related:
              https://bugreports.qt.io/browse/QTBUG-16264?focusedCommentId=201740&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-201740

              I most likely need to spend some time learning about the different modes.

              Q_INVOKABLE QString genImageString(QString text, int width, int height){
                      QImage textimage(width,height, QImage::Format_RGBA8888);
              
                      // create image
                      QPainter painter(&textimage);
                      //painter.setPen(QColor(255,0,0,255));
                      //painter.fillRect(0,0,width,height, QColor(0,0,0,255));
                      painter.setCompositionMode(QPainter::CompositionMode_Clear);
                      painter.fillRect(0,0,width,height, QColor(0,0,0,0));
                      //painter.fillRect(0,0,width,height, QBrush(Qt::transparent, Qt::BrushStyle::SolidPattern));
                      painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
                      painter.setPen(Qt::blue);
                      painter.setFont(QFont("Arial", 20));
                      painter.drawText(QRect(0,0,width,height), Qt::AlignCenter, text);
              
                      QByteArray bArray;
                      QBuffer buffer(&bArray);
                      buffer.open(QIODevice::WriteOnly);
              
                      textimage.save(&buffer, "PNG");
              
                      QFile pngfile(QString("image%1%2.png").number(width).number(height));
                      if(pngfile.open(QIODevice::WriteOnly)){
                          textimage.save(&pngfile, "PNG");
                      }
                      pngfile.close();
              
                      QString image("data:image/png;base64,");
                      image.append(QString::fromLatin1(bArray.toBase64().data()));
              
                      return image;
                  }
              

              C++ is a perfectly valid school of magic.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved