QML Image smooth property not working

Robbert picture Robbert · Apr 25, 2014 · Viewed 8.5k times · Source

In QML I've created a Rectangle view with a set of Image elements in it. I can't seem to get the smooth property to work, which is set to true for both the view and the images. I've tried scaling the images themselves and scaling the view. No matter what I do, I get a jagged scaled image. Am I missing something?

I'm working with Qt 5.2 and am using a QtQuick2ApplicationViewer (subclass of QQuickView) as my main view.

I've found solutions where smoothing is applied by replacing the image handler in the engine, but I feel like the smooth property should just work out of the box.

Code:

Image {
    source: "image_400x400.png"
    width:  400
    height: 400
    smooth: true

    transform {
        Scale {xScale: 0.25; yScale: 0.25}
    }
}

Second attempt:

Image {
    source: "image_400x400.png"
    width:  100
    height: 100
    smooth: true
}

Third attempt:

Rectangle {
    width:  400
    height: 400
    smooth: true

    Image {
        source: "image_400x400.png"
        width:  400
        height: 400
        smooth: true
    }

    transform {
        Scale {xScale: 0.25; yScale: 0.25}
    }
}

I get the same result every time.

Update: as suggested by Nejat, I tried the new Qt 5 antialiasing property. The result does improve, but when scaling below 0.5x edges still get a bit jagged. Is there any way to change the antialiasing quality?

From left to right:

  • expected output (scaled with Photoshop, unedited)
  • antialiasing and smooth enabled
  • only smooth enabled

Three antialiasing results with zoom

I'm also still wondering why smooth doesn't do anything.

Answer

Kay Sarraute picture Kay Sarraute · May 3, 2014

For smooth downsampling you need mipmaps!

With Qt 5.3 (which will be released very soon) this will work:

Image {
    source: "image_400x400.png"
    width: 100
    height: 100
    mipmap: true
}

For Qt 5.2 you can try the following as an higher-quality alternative to your multisampling approach:

ShaderEffectSource {
    id: src
    sourceItem: Image { source: "image_400x400.png" }
    mipmap: true
}

ShaderEffect {
    width: 100
    height: 100
    property var source: src
}

If you don't need to change the scale of the image dynamically, the optimal approach (for all relevant Qt versions) is this:

Image {
    source: "image_400x400.png"
    sourceSize.width: 100
    sourceSize.height: 100
}

The image will be high-quality downscaled on the CPU and then uploaded to the GPU. Be aware that, because image information is lost, it will look worse when shown at the scale of the original image.

Regarding the smooth property:

The smooth property of an Image enables linear interpolation. It's on by default and it's an improvement over nearest-neighbor interpolation, which is used when smooth = false; but it doesn't help much for downscaling.

Regarding the antialising property:

Setting antialiasing = true doesn't change the quality of the image scaling at all. It just smoothes the edges, which might be important when the image is rotated.