Open OlaKenji opened 1 year ago
Hello and thanks for the bug report.
Can you provide a minimal reproducer and the png of the original image with transparancy (if there are no licensing restrictions)
Of course. I have attached the original png file (does this work?). For reference, I am using 'pygame-ce 2.2.0 (SDL 2.0.22, Python 3.9.12)'
And here is the code I used:
import pygame
display = pygame.display.set_mode((1000,1000))
screen = pygame.Surface((300,300))
clock=pygame.time.Clock()
surface = pygame.image.load('test.png').convert_alpha()
surface = pygame.transform.gaussian_blur(surface, 2)
while True:
screen.fill((255,255,255))
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(surface,(50,100))
display.blit(pygame.transform.scale(screen,(1000,1000)),(0,0))
pygame.display.update()
clock.tick(60)
@yunline I believe you were the implementer of the blur functions. Thoughts?
@yunline I believe you were the implementer of the blur functions. Thoughts?
This problem exists in box_blur()
too. I'll try to fix it.
I think this is not a bug of gaussian blur, since premultiply should not be a part of blur algorithm.
You can solve this by blitting the transformed surface with pygame.BLEND_PREMULTIPLIED
flag.
This is the modified code:
import pygame
import sys
display = pygame.display.set_mode((1000,1000))
screen = pygame.Surface((300,300))
clock=pygame.time.Clock()
surface = pygame.image.load('alpha_test.png').convert_alpha()
surface = pygame.transform.gaussian_blur(surface, 2)
while True:
screen.fill((255,255,255))
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()
# Add pygame.BLEND_PREMULTIPLIED here ↓
screen.blit(surface,(50,100), special_flags=pygame.BLEND_PREMULTIPLIED)
display.blit(pygame.transform.scale(screen,(1000,1000)),(0,0))
pygame.display.update()
clock.tick(60)
@OlaKenji Does this solve your problem?
I tried your solutions in my project. It was indeed solved for that particular png. However, I noticed now that I instead got a white outline on some of the png files. Here is an example of the png file that is affected:
I reproduced the white outline artifact using your revised code (I made the BG black to highlight the white artifact). The colour of the outline seem to depend on the png file (maybe it depends on the edge colour of the png file?). Do you (@yunline) get the same problem?
It still feels like each pixel RBG value should be weighted by its alpha value (weight = alpha/255), meaning transparent pixels will not contribute (since weight = 0) while none transparent pixels will not be affected (since weight = 1). Or maybe having a flag in the function to enable this kind of weighting? Just a thought. :)
display = pygame.display.set_mode((1000,1000))
screen = pygame.Surface((300,300))
clock=pygame.time.Clock()
surface = pygame.image.load('stone.png').convert_alpha()
surface = pygame.transform.gaussian_blur(surface, 2)
while True:
screen.fill((0,0,0))
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(surface,(50,75), special_flags=pygame.BLEND_PREMULTIPLIED)
display.blit(pygame.transform.scale(screen,(1000,1000)),(0,0))
pygame.display.update()
clock.tick(60)#limmit FPS
However, I noticed now that I instead got a white outline on some of the png files.
This may be caused by the global alpha of the png file. I'll try to figure out why. For now you can try to fix like this.
surface = pygame.image.load('stone.png').premul_alpha()
@yunline maybe this will help you (old pr): https://github.com/pygame/pygame/pull/2968
Especially the link to the stackoverflow entry:
In essence if alpha is involved the calculation has to consider it and the weights are different.
Hi
Using pygame.transform.gaussian_blur() works nicely but in case there is a transparent edge, it induces a black outline on the blurred surface. This is because the transparent pixels are black (but alpha = 0). See for example:
A way to fix it is to manually "weight" each pixel based on their alpha value. If so, you can get the desired effect:
Perhaps it is a good idea to have the alpha weighting implemented in pygame.transform.gaussian_blur()?