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. Dynamic image in QML
QtWS25 Last Chance

Dynamic image in QML

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

    I'm developing an app where user should erase image by eraser, it is similar to clear image by eraser in microsoft paint app. When the user drag a mouse with pressed button I need to clear appropriate point on an image.
    It is pretty simple to do by subclassing from QQuickPainted item, redefine paint event and just draw original image, connect mouse move signal with coordinates and replace image pixel color to transparent at each point produced by user. But I'm stuck with a performance, since update() call takes too much time on mobile device.

    Another idea I have is to write fragment shader, but in this case I need a way to put to shader space a data array with cleared points produced by user. Have no idea how to do it.

    Could you please help me to find a way to solve my task in QtQuick with good performance on mobile platform?

    1 Reply Last reply
    0
    • p3c0P Offline
      p3c0P Offline
      p3c0
      Moderators
      wrote on last edited by
      #2

      Hi @Dmitiy-Tyugin
      There are some options to improve its performance namely setting RenderTarget-enum as RenderTarget-enum and setting PerformanceHint too.

      157

      Dmitiy TyuginD 1 Reply Last reply
      2
      • p3c0P p3c0

        Hi @Dmitiy-Tyugin
        There are some options to improve its performance namely setting RenderTarget-enum as RenderTarget-enum and setting PerformanceHint too.

        Dmitiy TyuginD Offline
        Dmitiy TyuginD Offline
        Dmitiy Tyugin
        wrote on last edited by
        #3

        Hi, @p3c0
        thanks for hints, but no luck. Tried to set in painted item constructor separately and both

        setRenderTarget(QQuickPaintedItem::FramebufferObject);
        setPerformanceHint(QQuickPaintedItem::FastFBOResizing);
        

        The difference: with flags paint event performs much faster, but until I do not change QImage object. When I change QImage object in mouse change slot called from qml, performance became the same: too slow.

        
        void Surface::mouseChanged(int x, int y)
        {
            qDebug()<<"Surface::mouseChanged: "<<x<<y;
            m_img.setPixelColor(x,y,QColor(0,0,0,0));
            update();
        }
        

        And paint event

        
        void Surface::paint(QPainter *painter)
        {
            qDebug()<<"Surface::Paint";
            painter->drawImage(0,0,m_img);
        }
        

        Performance highly depends on image size, for small images painting works much faster.

        Any other ideas?

        1 Reply Last reply
        0
        • p3c0P Offline
          p3c0P Offline
          p3c0
          Moderators
          wrote on last edited by
          #4

          @Dmitiy-Tyugin According to the setPixelColor documentation.

          Warning: This function is expensive due to the call of the internal detach() function called within; if performance is a concern, we recommend the use of scanLine() or bits() to access pixel data directly.

          Can you try these ?

          157

          Dmitiy TyuginD 1 Reply Last reply
          0
          • p3c0P p3c0

            @Dmitiy-Tyugin According to the setPixelColor documentation.

            Warning: This function is expensive due to the call of the internal detach() function called within; if performance is a concern, we recommend the use of scanLine() or bits() to access pixel data directly.

            Can you try these ?

            Dmitiy TyuginD Offline
            Dmitiy TyuginD Offline
            Dmitiy Tyugin
            wrote on last edited by
            #5

            Hi @p3c0,
            thanks for suggestion. Tried, but no changes in performance

            QRgb *rowData = (QRgb*)m_img.scanLine(j);
            rowData[i] = qRgba(0,0,0,0);
            

            Looks like performance degradation happens on paint->drawImage.
            Since small images work enough fast I decided to split my big image into a set of small images. Because user will not change the whole image simoultaneously in my scenario. It works with almost enough performance I need. So currently I'm stop digging for solutions.
            By the way, it works only with render hint, so thanks a lot to @p3c0! I very appreciate your support.

            setRenderTarget(QQuickPaintedItem::FramebufferObject);
            

            Here is an idea if somebody need it (it may have some bugs because this is quick dirty solution)

            
            const int ImgSize = 100;
            int Surface::getImgId(int x, int y)
            {
                int col = x/ImgSize;
                int row = y/ImgSize;
                return col*1000 + row;
            }
            
            void Surface::paint(QPainter *painter)
            {
                for(const auto& it:m_imgs){
                    QImage* img = it.img;
                    int x = it.x;
                    int y = it.y;
                    if(img!=nullptr)
                        painter->drawImage(x,y,*img);
                }
            }
            
            void Surface::splitImages()
            {
                m_cols = m_img.width()/ImgSize;
            
                if(m_img.width()>ImgSize*m_cols)
                    m_cols++;
            
                m_rows = m_img.height()/ImgSize;
                if(m_img.height()>ImgSize*m_rows)
                    m_rows++;
            
                m_imgs.clear();//memory leak here, delete objects before clear
                for(int i=0;i<m_cols;i++)
                    for(int j=0;j<m_rows;j++)
                    {
                        int startX = i*ImgSize;
                        int startY = j*ImgSize;
                        int endX = startX + ImgSize >= m_img.width() ? m_img.width()-1  : startX + ImgSize;
                        int endY = startY + ImgSize >= m_img.height() ? m_img.height()-1  : startY + ImgSize;
                        SubImage subImage;
            
                        subImage.img = new QImage;
                        *(subImage.img) = m_img.copy(startX,startY, endX - startX, endY-startY);
                        subImage.x = startX;
                        subImage.y = startY;
                        m_imgs[getImgId(startX, startY)] = subImage;
                    }
            }
            
            void Surface::mouseChanged(int x, int y)
            {
                const int BrushWidth = 50;
                const int BrushHeight = 50;
            
                int id = getImgId(x,y);
                SubImage subImg = m_imgs[id];
            
                x = x-subImg.x;
                y = y-subImg.y;
                QImage* img = subImg.img;
                for(int i=x-BrushWidth/2;i<x+BrushWidth/2;i++)
                    for(int j=y-BrushHeight/2;j<y+BrushHeight/2;j++)
                    {
                        if(i>=0 && i<img->width()
                                && j>=0 && j<img->height())
                        {
                            img->setPixelColor(i,j,QColor(0,0,0,0));
                        }
                    }
                update();
            }
            

            And some code from header

                 struct SubImage{
                    int x,y;
                    QImage* img;
                };
                typedef QMap<int, SubImage> ImgMap;
                ImgMap m_imgs;
            
            1 Reply Last reply
            1
            • p3c0P Offline
              p3c0P Offline
              p3c0
              Moderators
              wrote on last edited by
              #6

              @Dmitiy-Tyugin Thanks for sharing. Perhaps you also try posting this question on Qt Interest Mailing List.

              157

              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