I've set up this window where I blit
an ellipse to the screen. I would like to have the ellipse fully white with a smooth border. It looks acceptable, but when I add the ellipse to a white background, the border of the ellipse shows up.
import pygame
import cv2
import numpy as np
pygame.init()
# Set up the Pygame window
screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))
def drawAACircle(surf, color, center, radius, width, angle):
circle_image = np.zeros((radius*2, radius*2, 4), dtype = np.uint8)
circle_image = cv2.ellipse(circle_image, (radius, radius), (radius-width, radius-width), (angle*-.5)-90 , 0, angle, (*color, 255), width, lineType=cv2.LINE_AA)
#draw it on the surface
surf.blit(pygame.image.frombuffer(circle_image.tobytes(), circle_image.shape[1::-1], "RGBA").convert_alpha(), (center[0]-radius, center[1]-radius))
# Wait for the user to close the window
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
screen.fill((255,255,255))
drawAACircle(screen, (255,255,255), (screen_width/2,screen_height/2), 200, 20, 360)
# Update the display
pygame.display.flip()
I noticed the border when I changed the background to fully white:
I'm currently developing a decal tool where I can stack multiple ellipses on top of each other. I refresh the background screen with a copy()
like this:
def takeSnapshot():
global snapshot
snapshot = screen.copy()
def clearSnapshot():
global snapshot
snapshot = None
----
# Run the main loop
running = True
while running:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
running = False
# Clear the screen
if snapshot is None:
screen.fill((0,0,0))
else:
screen.blit(snapshot, (0,0))
I've tried gfx.aapolygon icm with a filled polygon. But I just can't get it as crisp and clean as the opencv ellipse.
If someone knows an alternative I'll be happy to hear, or I might be overlooking something where I could just get the opencv ellipse fully white.
EDIT: just to make it clear, I've chosen the opencv ellipse for the thickness option, be able to make an arc shape, and the smooth looks.
The problem is that antialiasing is applied not only to the alpha channel, but also to the color channels (RGB channels). Basically, this means that the color channels are already multiplied by the alpha channel. You have to use the mode "BLEND_PREMULTIPLIED" to blend this texture correctly (see blit
):
def drawAACircle(surf, color, center, radius, width, angle):
circle_image = np.zeros((radius*2, radius*2, 4), dtype = np.uint8)
circle_image = cv2.ellipse(circle_image, (radius, radius), (radius-width, radius-width), (angle*-.5)-90 , 0, angle, (*color, 255), width, lineType=cv2.LINE_AA)
circle_surf = pygame.image.frombuffer(circle_image.tobytes(), circle_image.shape[1::-1], "RGBA")
pos = (center[0]-radius, center[1]-radius)
surf.blit(circle_surf, pos, special_flags=pygame.BLEND_PREMULTIPLIED)
(I'm not showing the result here because it's just all white.)