Bug 471871

Summary: Image gets white outline on certain transparent parts in some image viewing programs and other software
Product: [Applications] krita Reporter: redmattis
Component: File formatsAssignee: Dmitry Kazakov <dimula73>
Status: RESOLVED FIXED    
Severity: normal CC: dimula73, ginoba, halla, tomtomtomreportingin
Priority: NOR    
Version First Reported In: 5.1.4   
Target Milestone: ---   
Platform: Microsoft Windows   
OS: Microsoft Windows   
Latest Commit: Version Fixed/Implemented In:
Sentry Crash Report:
Attachments: Example file. The white border will show up in some programs, f.ex. Discord around the platform only. Windows does _not_ show it.
White outline

Description redmattis 2023-07-02 12:35:12 UTC
Created attachment 160045 [details]
Example file. The white border will show up in some programs, f.ex. Discord around the platform only. Windows does _not_ show it.

SUMMARY
Image looks fine in Krita, but when exported as png there is a subtle white outline around icons and models I export.

I would expect it to fade to whatever color was in the area, not to... white. This seems to always happen when using the outline effect, but randomly with other areas too. Probably the png has white color in the almost fully alpha region for some reason?

The white line makes the textures unsuitable for use in some programs.

STEPS TO REPRODUCE
1. Start new scene.
2. Clear scene so it become transparent
3: Draw something in part of the image.
4. Add a stroke with 100% transparency.
5. Export as PNG with default settings.

OBSERVED RESULT
Image looks okay in some programs, but others such as Discord, Rimworld, etc. produce a white outline around the border.

This makes the exported image unsuitable for importing into f.ex. Rimworld, and possibly other Unity programs since Rimworld is Unity-powered.

Importing the image into GIMP and resaving it fixes the image.

EXPECTED RESULT
No white outline regardless of image program used to open it; png behaving as when reexported from GIMP.

SOFTWARE/OS VERSIONS
Windows: 10
Krita 5.1.4

ADDITIONAL INFORMATION
Additional info in this Krita thread on the official discord:
https://discord.com/channels/435123295550046218/1124341944055775373/1124341944055775373
Some OS:es doesn't seem to see the white outline. The thread shows an image of how it renders on windows 10 using a 4090. That image is not attached since there seems to be a max of two files on these reports.
Comment 1 redmattis 2023-07-02 12:36:05 UTC
Created attachment 160046 [details]
White outline

White outline, as it renders in discord.
Comment 2 Dmitry Kazakov 2023-07-19 16:23:09 UTC
Okay, I see the problem. Krita has an optimization that keeps the colors under the fully transparent pixels "undefined". This behavior is half-intentional, because a lot of game engines user rgb-alpha vectors separately. Though in this particular case, it is a bug. I will check what can be done with that :)
Comment 3 Dmitry Kazakov 2023-07-20 07:47:42 UTC
Hi, redmattis!

Until I think up a better solution, here is a workaround:

1) Right Click (RC) on the layer -> Split Alpha -> Aplit Alpha into Mask
2) Select the mask and press Ctrl+J to duplicate it
3) RC on the mask's clone and press Convert -> Selection Mask
4) Select -> Invert
5) Select the layer, select black color in the color selector
6) Edit->Fill with FG color
7) RC on transparency mask -> Split Alpha -> Write Alpha into Layer

Now your layer doesn't have anything in the color channels of the fully transparent pixels
Comment 4 Bug Janitor Service 2023-07-21 08:57:15 UTC
A possibly relevant merge request was started @ https://invent.kde.org/graphics/krita/-/merge_requests/1860
Comment 5 redmattis 2023-07-24 09:17:04 UTC
(In reply to Dmitry Kazakov from comment #3)
> Hi, redmattis!
> 
> Until I think up a better solution, here is a workaround:
> 
> 1) Right Click (RC) on the layer -> Split Alpha -> Aplit Alpha into Mask
> 2) Select the mask and press Ctrl+J to duplicate it
> 3) RC on the mask's clone and press Convert -> Selection Mask
> 4) Select -> Invert
> 5) Select the layer, select black color in the color selector
> 6) Edit->Fill with FG color
> 7) RC on transparency mask -> Split Alpha -> Write Alpha into Layer
> 
> Now your layer doesn't have anything in the color channels of the fully
> transparent pixels

From the sounds of it this will need to be done for every layer and will require collapsing f.ex. the stroke FX effect. I can't really see many artists wanting to go through this many steps when exporting assets for games and places like Discord.
Comment 6 tomtomtomreportingin 2023-07-24 17:44:23 UTC
I would think ideally that this would be an export option instead of a filter.
Comment 7 Deif Lou 2023-07-28 09:02:05 UTC
Hi redmattis. Can you tell us other programs that have the issue other than discord so that we can test the images?
Comment 8 Dmitry Kazakov 2023-08-09 10:58:53 UTC
> From the sounds of it this will need to be done for every layer and will require collapsing f.ex. the stroke FX effect. I can't really see many artists wanting to go through this many steps when exporting assets for games and places like Discord.

That is just a workaround that can be used in the released versions of Krita until we invent some better fix. And that shouldn't be performed for every layer, instead, you should flatten the image before doing this.
Comment 9 redmattis 2023-08-31 06:32:10 UTC
(In reply to Deif Lou from comment #7)
> Hi redmattis. Can you tell us other programs that have the issue other than
> discord so that we can test the images?

Discord and Rimworld are the obvious ones. Since Rimworld is Unity based it is likely that this issue is present for anything in Unity processing textures in a similar way. The result is most obvious with low-res images where it gives a fairly visible grey "halo" around them.

Sorry for the late response by the way. I only saw this because I looked for the issue to check if it was fixed and I could go back to using krita for icons and textures with alpha.
Comment 10 Dmitry Kazakov 2023-08-31 08:02:40 UTC
Just for the fun sake: here is a bugreport that asks for exactly the opposite behavior (keeping all the transparent pixels intact): bug 473948 :)
Comment 11 Deif Lou 2023-08-31 09:13:42 UTC
It srems to me that those other programs are not premultiplying the color channels when doing bilinear filtering or something. In the case of unity I guess you should convert the images to premiltiplied images and work with those when rendering.
Even if one sets the transparent color components to 0, if the opaque pixels near the edge are, say, white, then the black will spill in. So it won't work in all cases. The real solution is being aware of it as being non premultiplied and premultiply if the operation needs it.
One solution that would work better in my opinion is to kind of extend the color of the edge pixels to the fully transparent area. In the case of bilinear sampling 1px extension would be enough.
Comment 12 Dmitry Kazakov 2023-08-31 10:13:54 UTC
> One solution that would work better in my opinion is to kind of extend the color of the edge pixels to the fully transparent area

As far as I can tell the example image is some kind of a sticker or something like that. I'm not sure that such extreme precision is necessary for these cases :)
Comment 13 Deif Lou 2023-08-31 14:21:33 UTC
The thing is that if the border of the "sticker" was white, then setting the neighbor fully transparent pixels to 0, could end up in a dark halo in those areas (all of that if my hypothesis is correct, that is, that the real issue is not pre-multiplying when doing the filtering).
Comment 14 redmattis 2023-09-09 08:45:50 UTC
You know better than I about the exact operations here, I don't even know what pre-multiplying means in this context.

I do know that people using the likes of Affinity Designer and Inkscape (and probably Photoshop) don't seem to be getting this issue when they export .PNG files.
Comment 15 Dmitry Kazakov 2023-10-23 15:23:04 UTC
Git commit a0db80d17af34454bb3244a91d9c9a47449454c2 by Dmitry Kazakov.
Committed on 23/10/2023 at 17:15.
Pushed by dkazakov into branch 'master'.

Implement Other->Reset Transparent filter

In Krita we have an optimization, which causes pixels under zero alpha
to have undefined color channel values. It may cause some issues with
software that expects the values under fully transparent pixels to have
exactly zero values.

To overcome this issue the user can just apply Reset Transparent
filter over his/her image and it will guarantee that all the fully
transparent pixels are zeroed.
CC:kimageshop@kde.org

M  +1    -0    plugins/filters/CMakeLists.txt
A  +4    -0    plugins/filters/resettransparent/CMakeLists.txt
A  +69   -0    plugins/filters/resettransparent/KisResetTransparentFilter.cpp     [License: GPL(v2.0+)]
A  +42   -0    plugins/filters/resettransparent/KisResetTransparentFilter.h     [License: GPL(v2.0+)]
A  +9    -0    plugins/filters/resettransparent/kritaresettransparent.json

https://invent.kde.org/graphics/krita/-/commit/a0db80d17af34454bb3244a91d9c9a47449454c2
Comment 16 Dmitry Kazakov 2023-10-24 07:48:14 UTC
Git commit a4c4e7f2515b5ff01ea2b8cda2f958096e0b8939 by Dmitry Kazakov.
Committed on 24/10/2023 at 09:48.
Pushed by dkazakov into branch 'krita/5.2'.

Implement Other->Reset Transparent filter

In Krita we have an optimization, which causes pixels under zero alpha
to have undefined color channel values. It may cause some issues with
software that expects the values under fully transparent pixels to have
exactly zero values.

To overcome this issue the user can just apply Reset Transparent
filter over his/her image and it will guarantee that all the fully
transparent pixels are zeroed.
CC:kimageshop@kde.org


(cherry picked from commit a0db80d17af34454bb3244a91d9c9a47449454c2)

M  +1    -0    plugins/filters/CMakeLists.txt
A  +4    -0    plugins/filters/resettransparent/CMakeLists.txt
A  +69   -0    plugins/filters/resettransparent/KisResetTransparentFilter.cpp     [License: GPL(v2.0+)]
A  +42   -0    plugins/filters/resettransparent/KisResetTransparentFilter.h     [License: GPL(v2.0+)]
A  +9    -0    plugins/filters/resettransparent/kritaresettransparent.json

https://invent.kde.org/graphics/krita/-/commit/a4c4e7f2515b5ff01ea2b8cda2f958096e0b8939