Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

You should set the “antialiasing” property to true. It can be set on any item, including the Canvas. From the documentation:

Primarily used in Rectangle and image based elements to decide if the item should use antialiasing or not. Items with antialiasing enabled require more memory and are potentially slower to render.

The default is false

So it can be like:

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

Update: as of Qt 5.3, the mipmap property solves the issue. The answer below only applies to Qt 5.2 or older.

Adding the antialiasing property (since Qt 5) did what you would expect the smooth property to do. Thanks for that, Nejat. However, as posed in the updated question, the antialiasing quality is still bad. To solve this, define a custom surface format to set a custom antialiasing sampling rate (excerpt from main.cpp):

QtQuick2ApplicationViewer view;

QSurfaceFormat format;
format.setSamples(16);
view.setFormat(format);

See the docs: QSurfaceFormat::setSamples.

Many suggest using SVG instead of PNG. In my experience, at least with the default Qt Quick setup, SVGs get sampled at a certain size and are thus treated the exact same as PNGs.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top