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. Qt6 color SVG using MultiEffect
QtWS25 Last Chance

Qt6 color SVG using MultiEffect

Scheduled Pinned Locked Moved Solved QML and Qt Quick
13 Posts 9 Posters 3.1k 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.
  • C Offline
    C Offline
    christofer
    wrote on 2 Apr 2023, 19:25 last edited by christofer 4 Feb 2023, 19:54
    #1

    Can we colorize and SVG (or PNG) using MultiEffect in Qt 6.5?

    I created a sample project that just has a puppy who should be blue but doesn't get colorized: https://gitlab.com/christoferjennings/qt-6-5-colorize-svg

    The code follows the examples in the MultiEffect documentation. But, alas, the puppy doesn't appear blue.

    import QtQuick
    import QtQuick.Effects
    
    Window {
        id: window
        width: 500
        height: 300
        visible: true
        title: "Puppy should be blue"
    
        Image {
            id: theImage
            source: "image.svg"
            sourceSize.height: window.height - 20
            fillMode: Image.PreserveAspectFit
            anchors.centerIn: parent
        }
        MultiEffect {
            source: theImage
            anchors.fill: theImage
            colorization: 1.0
            colorizationColor: "blue"
        }
    }
    

    In the past, I've used ColorOverlay. But I'd like to use MultiEffect. This old related thread ends with a comment that MultiEffect is expected in Qt 6.5. Everything compiles fine but it doesn't seem to work.

    I'm trying this on macOS Monterey and Ubuntu 22.

    M 1 Reply Last reply 4 Apr 2023, 00:19
    0
    • C christofer
      2 Apr 2023, 19:25

      Can we colorize and SVG (or PNG) using MultiEffect in Qt 6.5?

      I created a sample project that just has a puppy who should be blue but doesn't get colorized: https://gitlab.com/christoferjennings/qt-6-5-colorize-svg

      The code follows the examples in the MultiEffect documentation. But, alas, the puppy doesn't appear blue.

      import QtQuick
      import QtQuick.Effects
      
      Window {
          id: window
          width: 500
          height: 300
          visible: true
          title: "Puppy should be blue"
      
          Image {
              id: theImage
              source: "image.svg"
              sourceSize.height: window.height - 20
              fillMode: Image.PreserveAspectFit
              anchors.centerIn: parent
          }
          MultiEffect {
              source: theImage
              anchors.fill: theImage
              colorization: 1.0
              colorizationColor: "blue"
          }
      }
      

      In the past, I've used ColorOverlay. But I'd like to use MultiEffect. This old related thread ends with a comment that MultiEffect is expected in Qt 6.5. Everything compiles fine but it doesn't seem to work.

      I'm trying this on macOS Monterey and Ubuntu 22.

      M Offline
      M Offline
      mzimmers
      wrote on 4 Apr 2023, 00:19 last edited by
      #2

      @christofer I've experienced this as well. I think the problem is in how the .svg file is composed, specifically (but not only) the use of the "fill=" field. I snagged a circle.svg file with this content:

      <svg fill="#0000ff" height="200px" width="200px" version="1.1" id="Layer_1" viewBox="0 0 222.334 222.334" xml:space="preserve">
      <g>
      	<g>
      		<g>
      			<path d="M111.167,0C49.87,0,0,49.87,0,111.167s49.87,111.167,111.167,111.167s111.167-49.87,111.167-111.167S172.464,0,111.167,0
      				z M111.167,214.1c-56.758,0-102.933-46.175-102.933-102.933S54.409,8.235,111.167,8.235S214.1,54.409,214.1,111.167
      				S167.925,214.1,111.167,214.1z"/>
      		</g>
      	</g>
      </g>
      </svg>
      

      which produces this:
      blue.PNG
      Replacing the fill value from "#0000ff" to "none" produces a black circle.

      I tried a similar experiment with the puppy file and couldn't even get that to change color at all.

      So...I think the svg file has to be composed in a particular way in order to support fills, but I can't speak with any authority on this. Hopefully someone else with some .svg file knowledge can chime in.

      M 1 Reply Last reply 4 Apr 2023, 00:26
      0
      • M mzimmers
        4 Apr 2023, 00:19

        @christofer I've experienced this as well. I think the problem is in how the .svg file is composed, specifically (but not only) the use of the "fill=" field. I snagged a circle.svg file with this content:

        <svg fill="#0000ff" height="200px" width="200px" version="1.1" id="Layer_1" viewBox="0 0 222.334 222.334" xml:space="preserve">
        <g>
        	<g>
        		<g>
        			<path d="M111.167,0C49.87,0,0,49.87,0,111.167s49.87,111.167,111.167,111.167s111.167-49.87,111.167-111.167S172.464,0,111.167,0
        				z M111.167,214.1c-56.758,0-102.933-46.175-102.933-102.933S54.409,8.235,111.167,8.235S214.1,54.409,214.1,111.167
        				S167.925,214.1,111.167,214.1z"/>
        		</g>
        	</g>
        </g>
        </svg>
        

        which produces this:
        blue.PNG
        Replacing the fill value from "#0000ff" to "none" produces a black circle.

        I tried a similar experiment with the puppy file and couldn't even get that to change color at all.

        So...I think the svg file has to be composed in a particular way in order to support fills, but I can't speak with any authority on this. Hopefully someone else with some .svg file knowledge can chime in.

        M Offline
        M Offline
        mzimmers
        wrote on 4 Apr 2023, 00:26 last edited by
        #3

        Update: I tried a much simpler circle file:

        <svg width="300" height="550" xmlns="http://www.w3.org/2000/svg">
            <circle cx="150" cy="100" r="60" style="fill:red; stroke-width:3; stroke:rgb(0,0,0); fill-opacity:0.7"  />
        </svg>
        

        (note the fill:red)

        And this code:

            Image {
                id: image
                Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
                source: "qrc:/circle2.svg"
                visible: false // <== DON'T FORGET THIS LINE
            }
            MultiEffect {
                source: image
                anchors.fill: image
                colorization: 1.0
                colorizationColor: "blue"
            }
        

        And it works. So it's not a Qt problem; it's the way the .svg files are constructed.

        M 1 Reply Last reply 4 Apr 2023, 00:51
        0
        • M mzimmers
          4 Apr 2023, 00:26

          Update: I tried a much simpler circle file:

          <svg width="300" height="550" xmlns="http://www.w3.org/2000/svg">
              <circle cx="150" cy="100" r="60" style="fill:red; stroke-width:3; stroke:rgb(0,0,0); fill-opacity:0.7"  />
          </svg>
          

          (note the fill:red)

          And this code:

              Image {
                  id: image
                  Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
                  source: "qrc:/circle2.svg"
                  visible: false // <== DON'T FORGET THIS LINE
              }
              MultiEffect {
                  source: image
                  anchors.fill: image
                  colorization: 1.0
                  colorizationColor: "blue"
              }
          

          And it works. So it's not a Qt problem; it's the way the .svg files are constructed.

          M Offline
          M Offline
          mzimmers
          wrote on 4 Apr 2023, 00:51 last edited by mzimmers 4 Apr 2023, 01:18
          #4

          another update: further testing revealed that you can't just put a fill= in the path; it has to be:

          <path style="fill:#00ff00" ...
          

          and the fill value can't be "none;" it must be a color (either by name or by RGB value).

          This works on my original circle (though it's only filling the outline; I think I need to remove part of the path for it to fill the entire circle.

          It worked on the puppy too (though there are 3 paths in the puppy; you'd have to add it to all of them).

          So...I think we have our answer.

          1 Reply Last reply
          0
          • C Offline
            C Offline
            christofer
            wrote on 4 Apr 2023, 13:02 last edited by christofer 4 Apr 2023, 13:14
            #5

            Thanks for the replies @mzimmers !

            You inspired me to experiment more. It turns out all I have to do is change the existing SVG fill from black to white.

            I changed...

            <g transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
            fill="#000000" stroke="none">
            

            to...

            <g transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
            fill="white" stroke="none">
            

            Result...
            Screen Shot 2023-04-04 at 6.00.26 AM.png

            The changes are in the GitLab project, tag qt-forum-post-02

            M 1 Reply Last reply 4 Apr 2023, 15:37
            0
            • C christofer has marked this topic as solved on 4 Apr 2023, 13:03
            • C christofer
              4 Apr 2023, 13:02

              Thanks for the replies @mzimmers !

              You inspired me to experiment more. It turns out all I have to do is change the existing SVG fill from black to white.

              I changed...

              <g transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
              fill="#000000" stroke="none">
              

              to...

              <g transform="translate(0.000000,1280.000000) scale(0.100000,-0.100000)"
              fill="white" stroke="none">
              

              Result...
              Screen Shot 2023-04-04 at 6.00.26 AM.png

              The changes are in the GitLab project, tag qt-forum-post-02

              M Offline
              M Offline
              mzimmers
              wrote on 4 Apr 2023, 15:37 last edited by mzimmers 4 Apr 2023, 16:00
              #6

              @christofer interesting. I did some experimentation of my own on the puppy file, and it appears that the problem wasn't the use of the RGB format for specifying the color, but rather the fill of black, or indeed any color other than white (or #ffffff).

              EDIT: scratch the comment below -- I forgot my own advice of hiding the original image.

              As a side note, I also noticed that when using the Image inside a Layout, you can't use the anchors property, so the MultiEffect appear below (in the case of a ColumnLayout) the original image. My workaround was to put the Image and the MultiEffect in an Item, so I could use anchors, but there might be a more elegant way to accomplish this.

              ekkescornerE 1 Reply Last reply 24 Jul 2023, 18:58
              0
              • M mzimmers referenced this topic on 11 Jul 2023, 18:52
              • M mzimmers
                4 Apr 2023, 15:37

                @christofer interesting. I did some experimentation of my own on the puppy file, and it appears that the problem wasn't the use of the RGB format for specifying the color, but rather the fill of black, or indeed any color other than white (or #ffffff).

                EDIT: scratch the comment below -- I forgot my own advice of hiding the original image.

                As a side note, I also noticed that when using the Image inside a Layout, you can't use the anchors property, so the MultiEffect appear below (in the case of a ColumnLayout) the original image. My workaround was to put the Image and the MultiEffect in an Item, so I could use anchors, but there might be a more elegant way to accomplish this.

                ekkescornerE Offline
                ekkescornerE Offline
                ekkescorner
                Qt Champions 2016
                wrote on 24 Jul 2023, 18:58 last edited by ekkescorner
                #7

                @mzimmers tried to colorize a png
                my old code:

                Image {
                    id: image
                    ....
                    ColorOverlay {
                        id: colorOverlay
                        anchors.fill: image
                        source: image
                        color: primaryColor
                    }
                

                new code:

                Image {
                        id: image
                        ....    
                MultiEffect {
                        id: colorOverlay
                            source: image
                            anchors.fill: image
                            colorization: 1.0
                            colorizationColor: primaryColor
                        }
                

                But the Image isn't colorized.
                -----------edit: foundSolution

                1. separated Image and MultiEffect and placed both inside an Item
                2. then set visible false at Image
                  result: not colorized, but found the reason
                  the png was a black icon - changed this and used a white icon and now colorizing works.
                  So this is different to QtQuickEffects and Qt 5.15

                ekke ... Qt Champion 2016 | 2024 ... mobile business apps
                5.15 --> 6.8 https://t1p.de/ekkeChecklist
                QMake --> CMake https://t1p.de/ekkeCMakeMobileApps

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  alvarosaes
                  wrote on 20 Mar 2024, 09:47 last edited by alvarosaes
                  #8

                  Hello, I also had this question so i asked directly via Qt support. I got this response:

                  > Thank you for you response. So, ColorOverlayEffect from import
                  > QtQuick.Studio.Effects 1.0 is not equivalent to this? I didnt have this
                  > problem while using that effect
                  
                  Yeah, different effect:
                  
                  fragColor = vec4(mix(pixelColor.rgb/max(pixelColor.a, 0.00390625), color.rgb/max(color.a, 0.00390625), color.a) * pixelColor.a, pixelColor.a) * qt_Opacity;
                  
                  Compared to this for colorization:
                  
                  color.rgb = (color.rgb - 0.5 * color.a) * (1.0 + contrast) + 0.5 * color.a;
                  color.rgb += brightness * color.a;
                  float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
                  float colorizationAlpha = colorization * colorizationColor.a;
                  color.rgb = mix(color.rgb, gray * colorizationColor.rgb, colorizationAlpha);
                  color.rgb = mix(vec3(gray), color.rgb, 1.0 + saturation);
                  

                  So i only see 2 solutions:

                  • Convert all your svgs to fill white
                  • Rollback to use ColorOverlayEffect

                  @mzimmers @christofer @ekkescorner

                  1 Reply Last reply
                  1
                  • S Offline
                    S Offline
                    srce
                    wrote on 13 May 2024, 10:54 last edited by srce
                    #9

                    Rather than converting pngs from black to white, setting brightness to 1 (in addition to colorize) should have a similar effect.

                    M 1 Reply Last reply 22 Aug 2024, 15:43
                    3
                    • Q Offline
                      Q Offline
                      QKelteseth
                      wrote on 16 Jul 2024, 12:07 last edited by
                      #10

                      @srce thank you!!

                      1 Reply Last reply
                      0
                      • S srce
                        13 May 2024, 10:54

                        Rather than converting pngs from black to white, setting brightness to 1 (in addition to colorize) should have a similar effect.

                        M Offline
                        M Offline
                        MattP2
                        wrote on 22 Aug 2024, 15:43 last edited by MattP2
                        #11

                        @srce said in Qt6 color SVG using MultiEffect:

                        Rather than converting pngs from black to white, setting brightness to 1 (in addition to colorize) should have a similar effect.

                        This is the answer, a big thank you.

                        So, visible: false, parent Item and color in svg are not required.
                        This is working with any svg:

                        Image {
                            // image properties
                            layer.enabled: true
                            layer.effect: MultiEffect {
                                brightness: 1.0
                                colorization: 1.0
                                colorizationColor: enabled ? Material.primaryTextColor : Material.secondaryTextColor
                            }
                        }
                        
                        P A 2 Replies Last reply 4 Apr 2025, 08:54
                        1
                        • nicwainwrightN nicwainwright referenced this topic on 20 Nov 2024, 15:01
                        • M MattP2
                          22 Aug 2024, 15:43

                          @srce said in Qt6 color SVG using MultiEffect:

                          Rather than converting pngs from black to white, setting brightness to 1 (in addition to colorize) should have a similar effect.

                          This is the answer, a big thank you.

                          So, visible: false, parent Item and color in svg are not required.
                          This is working with any svg:

                          Image {
                              // image properties
                              layer.enabled: true
                              layer.effect: MultiEffect {
                                  brightness: 1.0
                                  colorization: 1.0
                                  colorizationColor: enabled ? Material.primaryTextColor : Material.secondaryTextColor
                              }
                          }
                          
                          P Offline
                          P Offline
                          PeterG76
                          wrote on 4 Apr 2025, 08:54 last edited by
                          #12

                          @MattP2 Thanks.

                          Setting "brightness: 1.0" worked for me too. I can now successfully colorize a black PGN Image using MultiEffect.

                          1 Reply Last reply
                          0
                          • M MattP2
                            22 Aug 2024, 15:43

                            @srce said in Qt6 color SVG using MultiEffect:

                            Rather than converting pngs from black to white, setting brightness to 1 (in addition to colorize) should have a similar effect.

                            This is the answer, a big thank you.

                            So, visible: false, parent Item and color in svg are not required.
                            This is working with any svg:

                            Image {
                                // image properties
                                layer.enabled: true
                                layer.effect: MultiEffect {
                                    brightness: 1.0
                                    colorization: 1.0
                                    colorizationColor: enabled ? Material.primaryTextColor : Material.secondaryTextColor
                                }
                            }
                            
                            A Offline
                            A Offline
                            Aleksey Asensus
                            wrote 23 days ago last edited by Aleksey Asensus
                            #13

                            @srce said in Qt6 color SVG using MultiEffect:

                            Rather than converting pngs from black to white, setting brightness to 1 (in addition to colorize) should have a similar effect.

                            Yep, this works for me, thanks, however Qt 5 solution more flexible: with ColorOverlay I can set color: "transparent" to fully keep original icon where necessary, here icon becomes white for some reason, even if MultiEffect item or layer is not visible/enabled. So still forced to stay on ColorOverlay.

                            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