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?
Forum Updated to NodeBB v4.3 + New Features

Why does QPainter.fillRect with transparency leave artifacts?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
6 Posts 2 Posters 1.8k 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