Bug 439156 - Diagonal lines produce aliasing at certain zoom level
Summary: Diagonal lines produce aliasing at certain zoom level
Status: CONFIRMED
Alias: None
Product: krita
Classification: Applications
Component: OpenGL Canvas (show other bugs)
Version: nightly build (please specify the git hash!)
Platform: Microsoft Windows Microsoft Windows
: NOR normal
Target Milestone: ---
Assignee: Krita Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-06-25 14:43 UTC by thequver
Modified: 2021-10-09 23:23 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:
Sentry Crash Report:


Attachments
The scale of example images is original (as on monitor) (18.11 KB, image/png)
2021-06-25 14:43 UTC, thequver
Details
Gimp and Autodesk SketchBook behavior (31.95 KB, image/png)
2021-06-26 09:01 UTC, thequver
Details
0-200% good (73.69 KB, image/png)
2021-06-26 12:09 UTC, thequver
Details
0-50% good (46.08 KB, image/png)
2021-06-26 12:14 UTC, thequver
Details
Blender tex interp test (65.83 KB, image/png)
2021-10-09 23:23 UTC, thequver
Details

Note You need to log in before you can comment on or make changes to this bug.
Description thequver 2021-06-25 14:43:59 UTC
Created attachment 139660 [details]
The scale of example images is original (as on monitor)

SUMMARY
Images display incorrectly at certain zoom levels

The bug persists in Krita 4.4.3, krita-nightly-x64-5.0.0-prealpha-583a1a7a36 nightly build and also other builds that I've tested


STEPS TO REPRODUCE
1. Create a 128x128px image
2. Draw a sharp diagonal line
3. Set zoom to 282% (or 282.8% by default)
4. You can see as line distorts at this zoom level
(My display resolution is 1366x768 if it matters to reproducing)

OBSERVED RESULT
See an attachment


EXPECTED RESULT
The line displayed without aliasing

SOFTWARE/OS VERSIONS
Windows: 10
macOS: 
Linux/KDE Plasma: 
(available in About System)
KDE Plasma Version: 
KDE Frameworks Version: 
Qt Version: 

ADDITIONAL INFORMATION
Sometimes you can see this effect on different zoom levels (for example at 66.7% zoom)
Panning the canvas doesn't change aliasing pattern
Disabling hardware acceleration or switching Angle to OpenGl doesn't affect the bug
Comment 1 thequver 2021-06-26 09:01:27 UTC
Created attachment 139669 [details]
Gimp and Autodesk SketchBook behavior

I also checked Gimp and Autodesk SketchBook on the same image, Gimp have same artifacts at 282% zoom but Sketchbook smooths the image after you zooming so it displayed correctly.
(See the 2 attachment)
Comment 2 Halla Rempt 2021-06-26 10:05:17 UTC
Check your display settings: Krita has several settings that control smoothing when zooming.
Comment 3 thequver 2021-06-26 11:05:43 UTC
(In reply to Halla Rempt from comment #2)
> Check your display settings: Krita has several settings that control
> smoothing when zooming.

Are you referring to Scaling mode settings?
The images I took are using High Quality Filtering method.
Those settings do work however, but differently (or not as intended?)
I don't know how to explain it more clear, but it seems it works only at zoom  levels 0-200% and if you scale more to 200-400% it starting to look as Nearest Neighbor mode.
And second, it still produces artifacts as scale 50-100% at some images.
Live example - Open my first attachment in Krita and zoom to 55%. You'll see wave-like aliasing at the left line and if you switch filtering to nearest neighbor you'll see that those waves became sharp.
Comment 4 thequver 2021-06-26 12:09:55 UTC
Created attachment 139670 [details]
0-200% good

More Examples of how weird it is:
At this image you can see that filtering works at 0-200% and at 202% it's broken.
Do note 55% looks good
Comment 5 thequver 2021-06-26 12:14:16 UTC
Created attachment 139671 [details]
0-50% good

At this example 0-50% zoom looks good but distortions starts at at 50-100%.
I don't understand why in one case it looks good and in other it doesn't. Maybe it depends on the image resolution.
Comment 6 Halla Rempt 2021-09-07 09:36:33 UTC
Yes, Krita switches the scaling mode to nearest neighbour when zooming in at a certain point, because we assume that from that point on, the user wants to see pixels, instead of a smoothly scaled image.
Comment 7 Leonardo 2021-10-07 22:48:45 UTC
The problem is that Krita has weird zoom levels:

100%, 141%, 200%, 283%, 400%, 566%, 800%

Normally, to avoid this exact issue, you'd use mainly integer zoom levels. For reference, zoom levels in other graphics software:

SAI: 100%, 150%, 200%, 300%, 400%, 500%, 600%, 800%.
Fire Alpaca: 100%, 150%, 200%, 300%, 400%, 600%, 800%.
MyPaint: 100%, 150%, 200%, 300%, 400%, 550%, 800%.
Photoshop: 100%, 200%, 300%, 400%, 500%, 600%, 700%, 800%.
Gimp: 100%, 150%, 200%, 300%, 400%, 550%, 800%.

iirc Krita's weird zoom levels come from KDE. They probably aren't an issue in other KDE software, but because Krita is a drawing software it becomes an issue here.

I suggest changing Krita's zoom levels to match MyPaint:

100%, 150%, 200%, 300%, 400%, 550%, 800%, 1100%, 1600%, 2300%, 3200%, 4500%, 6400%.
Comment 8 Halla Rempt 2021-10-08 08:49:03 UTC
It's more complicated than that, because the zoom levels aren't hard-coded, but calculated KoZoomAction::Private::generateSliderZoomLevels().
Comment 9 Leonardo 2021-10-08 12:46:27 UTC
(In reply to Halla Rempt from comment #8)
>It's more complicated than that, because the zoom levels aren't hard-coded, but calculated
>KoZoomAction::Private::generateSliderZoomLevels().

Is this the code for it?

https://invent.kde.org/graphics/krita/-/blob/master/libs/widgets/KoZoomAction.cpp#L63

It seems to be already hard-coded.

    QList<qreal> zoomLevels;

    qreal defaultZoomStep = sqrt(2.0);

    zoomLevels << 0.25 / 2.0;
    zoomLevels << 0.25 / 1.5;
    zoomLevels << 0.25;
    zoomLevels << 1.0 / 3.0;
    zoomLevels << 0.5;
    zoomLevels << 2.0 / 3.0;
    zoomLevels << 1.0;

See, that's 100%, 67% (2/3), 50% (0.5), 33% (1/3), 25% (0.25), 17% (0.25 / 1.5) and 13% (0.25 / 2.0).

For some reason the first zoom levels smaller than 100% are hard-coded, but the ones larger than 100% aren't hard-coded. You could fix this issue by simply adding something like:

    zoomLevels << 1.5;
    zoomLevels << 2.0;
    zoomLevels << 3.0;
    zoomLevels << 4.0;
    zoomLevels << 5.5;
    zoomLevels << 8.0;

I say this is an UX issue because without using whole numbers for zoom levels the size of the pixels on display becomes unequal in unpredictable ways. It isn't much of an issue with high zoom levels like 550%, but with 283%, for example, some pixels are scaled into 3x3 squares, while others become 2x2 squares, and others become 2x3 or 3x2 rectangles. Consequently, if you draw a line, some pixels of the line appear bigger than others randomly, so some parts of the line appear thicker randomly, which gives the jagged appearance. This jagged appearance isn't expected by the user, so they'll think the brush isn't drawing right, or krita isn't anti-aliasing right, etc., until they figure out the zoom is weird in krita.

Probably unnecessary, but for zoom levels higher than 800% one could adjust the calculated levels to round to the nearest 50%, e.g. by changing this:

    zoomLevels.append(zoom);

To something like this:

    zoomLevels.append(whatever_round_to_nearest_integer_is_called_in_cpp(zoom * 2) / 2.0);

In fact if you did this you wouldn't even need to hard code the zoom levels since 141%, 283%, and 566% round to the 150%, 300%, and 550% anyway.
Comment 10 Halla Rempt 2021-10-08 13:26:42 UTC
Well, it's only part it. There is also the ctrl- and + keys, and those use, as far as I can tell a different table.
Comment 11 thequver 2021-10-09 22:10:25 UTC
Oh! Auto switching to nearest neighbor explains drastic change in quality. But there's something more than that, look at the attachment 139671 [details], 56.5% zoom,  high quality filtering smooths pixels out but the line appears "wavey", should it work like that? Can it be improved?
Also you can restrict zoom levels to integers only when nearest neighbor is enabled (if user wants to see pixels at close zoom, user expects them to look sharp anyway?). But it won't work if the canvas is rotated
Comment 12 thequver 2021-10-09 23:23:14 UTC
Created attachment 142285 [details]
Blender tex interp test

Another test from blender's eevee with 1 sample - 1 image uses closest interpolation and 2 is cubic, no waves are visible. Also in blender it's possible to simply add samples to anti aliasing and it fixes everything, even closest interpolation would look good. Is it possible with Krita?