Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Properly scaling SVG Images



  • I try to instantiate an SVG image scaled by factor 2 like this:

    Image {
        scale: 2.0
        source: "myImage.svg"
    }
    

    The issue with this version is that it looks like the image is first rendered and then scaled. Even using

    smooth: true
    

    or

    antialiasing: true
    

    didn't solve the problem at all. The only way I found for generically scalling my SVG files was the following work around:

    Image {
        // the following line causes a binding loop
        sourceSize.width: 2*width
        source: "myImage.svg"
    }
    

    This really produces the expected result but of course also prints a warning about a binding loop for sourceSize. I would prefer not to use a previously scaled image since I use the same image in different scalings in various places of the application. Also I would prefer if needn't give an explicit sourceSize.width since at that place in the QML the actual source is dynamic and the images can have different dimensions.

    Is there a nicer way to solve this problem?



  • Hi swegmann!

    The following code is more an ugly trick than a solution, but at least it does what it's supposed to do and you get rid of the binding loop:

        Image {
            source: "file:///home/pw/Downloads/SVG_logo.svg"
            sourceSize: Qt.size( img.sourceSize.width*2, img.sourceSize.height*2 )
            Image {
                id: img
                source: parent.source
                width: 0
                height: 0
            }
        }
    


  • Hi Wieland

    Well, it's not beautiful, but it does the job ;-) Thanks for your help!



  • See here: https://bugreports.qt.io/browse/QTBUG-44863

    SVG scaling is quite confusing and hackish in QML.
    Basically what you need to set is the "target" size and not the "source" size...hence the confusion.



  • @mcallegari79 I'm a little confused by your remark. Do you mean there actually is a property called 'targetSize'? Because I couldn't find such a property neither in Image nor in Item. Or do you mean the property 'sourceSize' should be called 'targetSize'? Because I thought, I understood how that part worked. But I didn't know how to properly get the "original" size of the SVG, multipling this by my scaling factor and applying this to sourceSize. And as it currently looks there is no nicer way than what @Wieland has shown.



  • @A-Former-User said in Properly scaling SVG Images:

    Hi swegmann!

    The following code is more an ugly trick than a solution, but at least it does what it's supposed to do and you get rid of the binding loop:

        Image {
            source: "file:///home/pw/Downloads/SVG_logo.svg"
            sourceSize: Qt.size( img.sourceSize.width*2, img.sourceSize.height*2 )
            Image {
                id: img
                source: parent.source
                width: 0
                height: 0
            }
        }
    

    (Funny. When I clicked "reply" the forum wanted to caution me that this thread is quite old. And yet... I arrived here because I still needed to learn the sourceSize hack this many years later.)

    The code snippet above demonstrating how to fix SVG blur using sourceSize is great.

    I'm surely not the first to notice, but you can also then go "one small step further" and make a reusable custom element that will be well-behaved for scaling factors other than "2". Indeed, it should be generalized/reusable for an SVG of any size (any "native" or "starting" size) and any target size or any stretch-due-to-anchoring.

    It would look like this:

    import QtQuick 2.12
    import QtQuick.Controls 2.12
    
    Image {
      // Thanks to this hack, qml can now only DOWN-SCALE/SHRINK the SVG, which won't cause blurriness/pixelation
      sourceSize: Qt.size(
                    // first "trick" qml that the SVG is larger than we EVER NEED
                    Math.max(hiddenImg.sourceSize.width, 250),
                    // change 250 to a per-project "biggest icon in project" value
                    Math.max(hiddenImg.sourceSize.height, 250))
    
      Image {
        id: hiddenImg
        source: parent.source
        width: 0
        height: 0
      }
    }
    
    

    You can build-and-run a full working sample here. (It can also be launched simply with qmlscene).


Log in to reply