SVG Rendering and Source Size:



  • Hi I have troubles rendering SVG file correctely when scale is set in parent items.
    I saw maybe I should use sourcesize property but coud not figure how to use it.
    Here a sample of code that illustrat the issu. Any svg file can be used. I do not want to set "smooth:true" because of performance issue (I am rendering interface on 11 full HD screens...

    is there any leads ?

    @Rectangle
    {

    width: 800
    height: 800
    Rectangle
    {
        width: 100
        height: 100
        //Graphic
        Image {
            id: iImageFrame
            x: 16; y: 42
            source: "##.svg"
        }
    }
    Rectangle
    {
        x:150
        width: 100
        height: 100
        scale: 1.2
        //Graphic
        Image {
            x: 16; y: 42
            source: "##.svg"
            sourceSize.width: width
            sourceSize.height: height
        }
    }
    Rectangle
    {
        x:300
        width: 100
        height: 100
        scale: 0.8
        //Graphic
        Image {
            x: 16; y: 42
            source: "###.svg"
            sourceSize.width: width
            sourceSize.height: height
        }
    }
    

    }@



  • Hey,

    what exactly is the issue? Does it even display the .svg? If yes; does it scale it wrong?



  • The scale is correct, But juste like mentionned in other posts, it is ugly, Big pixels, or aliasing issues.
    Even is scale is lower than 1 there are big aliasing issues.

    The svg is a vectorial format so I guess Qt is rendering a bitmap matrix and then apply the scale on it,

    Maybe there is a way to render the SVG correctely?



  • I tried this :

    • it changes the scale differently in x and in Y
    • it moves the svg picture, I would expecte no modification in size not position of the svg file

    @ Rectangle
    {
    x:181
    y: 18
    width: 100
    height: 100
    border.color: "#ca1f1f"
    scale: 1.2
    //Graphic
    Image {
    x: 16; y: 42
    source: "##.svg"
    sourceSize.height:height/scale
    sourceSize.width: width/scale
    scale:1/parent.scale
    }
    }@



  • I would say just don't scale the image then!?
    I used some custom SVG files in my latest QML app and it works great, just scale the sourceSize and don't use the scale property, that will of course re-render the SVG but unless it is a very complex SVG it should be fine even for animations.
    I think the default scale property is applied after the SVG is rasterized so it will ge "messy" even with antialiasing enabled (you know thee is an antialiasing property int he Item object, right?).

    In your last post you scale the parent rectangle of the Image, that will off course also scale the Image itself. in a real app i would just never use scale unless for some animations which end with scale:1 ... in most cases at least :)



  • Hi,
    The thing is my Application must render real size object, on *any screen *configuration:
    10cm square must be 10cm.

    So according to the screen hardware I must scale every thing.
    And I have ~2000 objet to render, so I cannot manage this for every instance of images

    The example above is to illustrate my situation in a simplified way.

    So I thought of several leads:

    • Trigger a re-rasterisation, but how ?
    • find a way in the image instantiation using sourcesize, but how ?

    Does any one hase some advice?
    It is realla a shame that vectorial picture format can only be used as Bitmap...



  • I found somethind interesting, in the following coe dpiratio is a global scale factor.
    Putting the following code inside EVERY instance of Image QML item seems to work.
    But This should be available inside the QT C++ code; It would be really more effectiv.

    THow I do not see yet how to do this and manage the global scale factor automaticcaly. Maybe by multiplying all parent object scale factor together or something alike.

    @onSourceChanged: recomputesmoothness();
    onStatusChanged: recomputesmoothness();
    function recomputesmoothness()
    {
    if (status == Image.Ready)
    {
    if(typeof(dpiRatio)==='undefined'){return;}
    var lw=width
    var lh=height
    sourceSize.width=widthdpiRatio
    sourceSize.height=height
    dpiRatio
    width=lw
    height=lh
    }
    }@

    Here is the complete Example code easy to test and see the results. A svg file is required
    @Rectangle
    {
    property real dpiRatio:1.2
    property real sourcesizeratio:1.2
    property bool imageswitch:false

    property string imagesource:"Images/"+(imageswitch?"fond_orange_haut.svg":"Base.svg")
    width: 800
    height: 800
    
    
    focus: true
    Keys.onPressed: {
            console.log(event.key)
            switch (event.key)
            {
            case Qt.Key_Return:
                    dpiRatio = 1.0;
                    sourcesizeratio=1.0
                    break;
    
            case Qt.Key_Plus:
                dpiRatio += 0.1;
                break;
            case Qt.Key_Minus:
                dpiRatio -= 0.1;
                break;
            case Qt.Key_PageUp:
                sourcesizeratio += 0.1;
                 break;
            case Qt.Key_PageDown:
                sourcesizeratio -= 0.1;
                break;
            case Qt.Key_End:
                imageswitch=!imageswitch
                break;
    
    
    
            default :
                return;
            }
    }
    Text {
        id: text1
        x: 38
        y: 240
        width: 71
        height: 34
        text: "imagesource: "+imagesource + "\nscale Factor:"+dpiRatio+"\nsourcesizeratio: "+sourcesizeratio
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignLeft
        font.pixelSize: 12
    }
    
    //---------------------------------------------------
    Rectangle
    {
    
        width: 100
        height: 100
        border.color: "#000000"
        Rectangle
        {
            anchors.centerIn: parent
            width: 100
            height: 100
            border.color: "#000000"
            //Graphic
            Image {
                id: iImage1
                x: 16; y: 42
                source: imagesource
            }
        }
    }
    //-----------------------------------------------------------
    Rectangle
    {
        x:181
        y: 0
        width: 100
        height: 100
        border.color: "#ca1f1f"
        transformOrigin: Item.TopLeft
        scale: dpiRatio
    
        Text{
            x: 0
            y: 8
            width: 100
            height: 13
            text: "Imge2 SourceSize:"+image2.sourceSize.width+" "+image2.sourceSize.height+
                   "\nImge2Size:      "+image2.width+""+image2.height
                   z: 2
        }
    
        //Graphic
        Rectangle
        {
            anchors.centerIn: parent
            width: 100
            height: 100
            border.color: "#ca1f1f"
            //Graphic
            Image {
                id:image2
                x: 16; y: 42
                source: imagesource
    
                onSourceChanged: recomputesmoothness();
                onStatusChanged: recomputesmoothness();
                function recomputesmoothness()
                {
                    if (status == Image.Ready)
                    {
                        if(typeof(dpiRatio)==='undefined'){return;}
                        var lw=width
                        var lh=height
                        sourceSize.width=width*dpiRatio
                        sourceSize.height=height*dpiRatio
                        width=lw
                        height=lh
                    }
                }
            }
        }
    }
    
    //-----------------------------------------------------------
    Rectangle
    {
        x:454
        y: 0
        width: 100
        height: 100
        border.color: "#16b70a"
        scale: dpiRatio
        transformOrigin: Item.TopLeft
        Rectangle
        {
            anchors.centerIn: parent
            width: 100
            height: 100
            border.color: "#16b70a"
            //Graphic
            Image {
                x: 16; y: 42
                source: imagesource
            }
        }
    }
    

    }@



  • first Qt has real vector graphics, but if you know the technical aspects every SVG image has to be rasterized at some point because your monitor needs a raster image to display! so every program who wants to display vector images has to rasterize an image before you can see it :)

    second actually I use a similar solution in my QML app, I have global properties to multiply a DPI factor to every size I use in QML Items, no matter if it is a Rectangle or Image or just a spacing in a ListView.. because than I can scale my app as a whole and the user can even zoom in or out the complete view as he wishes.
    I think a feature like this is missing from QML as of now or I just didn't find a better solution but in my opinion that works great for most apps and is perfect for SVG images, text and every default QML view.

    Also if you know android development, the XML layouts used in android use a similar concept with the device independent pixel (DIP or DP) suffix for sizes, e.g. 5dp or 42dp and 12sp for font sizes.. I simply created global properties with a factor to accomplish a very similar effect so that in QML it looks like 5dp or 42dp and 12*sp and because that are real global properties if the value changes every item that uses that factor will be rescaled with the automatic property binding. :)
    So I never (!) use the scale property anywhere other than for animations, I hope that insight helps you a little.

    maybe I write a blog post about it when i get some time, my app is almost finished if you want I could share some screenshots in different resolutions that you see what i mean?

    android references:
    http://developer.android.com/guide/practices/screens_support.html
    http://developer.android.com/training/multiscreen/screendensities.html

    as you may know in QML every size is absolute pixels only, so you have to apply a factor or something to archive the same effect if you want the same size on every device, no matter f desktop computer or a mobile device, because mobiles devices in general have a very high DPI count and if you leave the values in absolute pixels everything will be very small with higher DPI values :/



  • Thanks for the input.
    I know vectorial format must be rasterize, but I would have prefered it was rasterized correctely, or at least easy to configure....

    I will dig into the Declarative image source code, maybe there I could add a "Property real dpiRatio" so just adding this property trigger the mechanisme described above.

    If someone already did such thing it will be appreciated.



  • an easy solution would be if you just use the Screen.pixelDensity property (The number of physical pixels per millimeter), are you aware of that? if you just want your image to be 10cm on any device and not really scaleable that would be the easist way I guess.

    If you also want it scalable you add a custom scale property and multiply that by Screen.pixelDensity!?

    @
    property real zoomFactor: 1.0
    property real zoom: Screen.pixelDensity * zoomFactor

    Image {
    source: "..."
    sourceSize.width: 100*zoom // because 100mm size
    }
    @
    if the image is quadratic it should be fine just to set the width, the height will be scaled by QML automatically, but if you want set both :D
    if you now change the zoomFactor property it will trigger a re-rasterization of the SVG so it should look as best as it gets.

    maybe that is to easy for you or what is the problem with this approach?



  • Hi,
    On the project we are on QtQuick 1.1 and I do not think we have the Screen.pixelDensity feature, but that is interesting.

    Is this available on QtQuick 2.0 ? does this works well?
    How does "Screen.pixelDensity" get the Dpi?



  • hey don't ask me I am no Qt developer. :D
    if you check the doc http://qt-project.org/doc/qt-5/qml-qtquick-window-screen.html#pixelDensity-prop (since Qt 5.2 so that property is pretty new)

    but what I can tell you is how you may be able to use the same value with older versions of Qt, I don't use the pixelDensity property myself, but have a custom C++ class that does the trick with the "QScreen class":http://qt-project.org/doc/qt-5.0/qtgui/qscreen.html (look at all the dots per inch stuff).

    In my project I use it like this:
    @
    QScreen *screen = qApp->primaryScreen(); // global app pointer
    real dipScaleFactor = screen->physicalDotsPerInch() / screen->devicePixelRatio() / m_dipNorm;
    @
    m_dipNorm is the value I use to normalize the scale factor, if you've read the android stuff that is always 160 DPI on android for example, of course you can use whatever value you like (e.g. 72 or 96 DPI for desktop computers).
    I just came up with that, so if you use 96 as the "norm" that means on a screen with 96 DPI 1 pixel is 1 pixel in size and if you have a a screen with highter DPI the pixel size will be larger so that the physical size will be identical on all screens not matter the size or resolution.

    usually you have larger values like 10 pixel so if you write 10*dp it is exactly 10 pixels on my computer (with 96 DPI) but may be 31 pixels on a smartphone with 300 DPI you know what I mean?

    if you want to use the same value as Screen.pixelDensity you can convert the inch to millimeter (that is what the QML Screen object does):
    @
    qreal QQuickScreenAttached::pixelDensity() const
    {
    if (!m_screen)
    return 0.0;
    return m_screen->physicalDotsPerInch() / 25.4;
    }
    @
    that replaces the "logicalPixelDensity" property, see the changelog:
    - Screen type gained a pixelDensity property, deprecating logicalPixelDensity,
    as logicalPixelDensity is less portable across some mobile platforms.



  • So far I am following the lead of making a MyImae component.
    But there is a side effect:

    • When the source image changed
    • The status changed to 0 then to Image.Ready
    • But the width and height are not yet the new ones !!!
    • SO every time I replace an image source using a different size it messes everything up.

    If I set a timer I see that width and height are correct some times after Image.Ready.
    How can I get the NEW dimensions of the loaded source if not using StatusChanged and Image.Ready?

    This is the code to detect the width and height wrong values:
    @
    MyImageTest.qml
    Image{
    onSourceChanged: recomputesmoothness();
    onStatusChanged: recomputesmoothness();
    function recomputesmoothness()
    {
    if (status == Image.Ready)
    {
    console.log(width,height)
    }
    }
    }@

    This is the code I would like to use:
    @MyImage.qml
    Image{
    onSourceChanged: recomputesmoothness();
    onStatusChanged: recomputesmoothness();
    function recomputesmoothness()
    {
    if (status == Image.Ready)
    {
    if(typeof(dpiRatio)==='undefined'){return;}
    var lw=width
    var lh=height
    sourceSize.width=widthdpiRatio
    sourceSize.height=height
    dpiRatio
    width=lw
    height=lh
    }
    }
    }@



  • if you just want the size if the Item you might just use onHeightChanged and onWidthChanged signals, or maybe onSourceSizeChanged your have to play around a little maybe.



  • Yes I thaught of that but so far I did not find anythingelse than the "recomputesmoothness" function and it modify the properties sourceSize.W&H and he width end eight propertie. so it is likely to engender loops...

    • Modifiyng sourceSize.width automatically modify width :(
    • Modifiyng sourceSize.height automatically modify height :(
    • That is why I reset width and height to their original values in this function...

    But you are right, I will try to dig into onSourceSizeChanged....


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.