-2

I am trying to make a pixel-art 2d platformer in Pygame-CE. When I use a standard pygame display, the pixels come out as blurry: Image upscaled to remove any filtering

Minimal Reproducible Example:

#Import everything
import pygame, sys
from pygame.locals import QUIT
#Pygame display setup
pygame.init()
screen = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
#Load the image
grid_border = pygame.transform.scale(pygame.image.load('IMAGE.png'), (48, 48)).convert_alpha() #You will need to add your own 24x24 or 48x48 image or you can change the transform dimensions for other images.
#Main loop
while True:
 #Quit if you press the x
 for event in pygame.event.get():
 if event.type == QUIT:
 pygame.quit()
 sys.exit()
 #Fills the screen and then prints the image
 screen.fill("white")
 screen.blit(grid_border, (100, 100))
 #Updates the screen and finishes the loop
 pygame.display.flip()
 clock.tick(60)

When I add this code after the pygame display setup to enable high DPI rendering on windows, the image is no longer blurry on the screen and loads at it's original resolution:

if sys.platform == 'win32':
 # On Windows, the monitor scaling can be set to something besides normal 100%.
 # PyScreeze and Pillow needs to account for this to make accurate screenshots.
 # TODO - How does macOS and Linux handle monitor scaling?
 import ctypes
 try:
 ctypes.windll.user32.SetProcessDPIAware()
 except AttributeError:
 pass # Windows XP doesn't support monitor scaling, so just do nothing.

This is what the screen looks like now: Image upscaled to remove filtering

However, this solution only works on Windows.

I looked at other pages to see if there were any existing solutions for this.

1. (https://github.com/pygame-community/pygame-ce/issues/1456) This page had the same issue as me and found the same solution as me - there is no way to enable high DPI rendering for pygame-ce on MacOS/Linux. However, this page was outdated by a few years so I am deciding to post the question again to see if there are any solutions now. Using the pygame.window class does not work in my situation due to a lack of vsync causing major screen tearing.

2. I looked at the official pygame docs. I could not find anything about high DPI rendering.

These are the only pages I could find that related to my question.

I am fine with any solution that removes the blurry rendering, not just solutions that enable high-DPI rendering on other platforms. I do, however, want the solution to work on all three major platforms (Windows, MacOS, Linux).

bruno
34.3k8 gold badges31 silver badges48 bronze badges
asked Jul 24 at 3:41
3
  • I am not sure any solution really exists. Upsampling has always had this issue. IDK if there is a way to add HQX to pygame — it is a good choice for small assets. But the best option for large displays is twofold: ❶ Use larger assets for larger displays AND ❷ resample to a (fractional) power of two (with as few steps as possible). Commented Jul 24 at 4:40
  • Though, as per docs, your best bet might be to ask the developers at the Pygame Discord Commented Jul 24 at 4:45
  • 1
    I cannot reproduce your problem, I made a 48x48 image and even I use (600,600) in pygame.transform.scale(..) there is no blurry rendering at all. I am under Debian bookworm ona Pi5 Commented Jul 24 at 7:17

1 Answer 1

1

The problem there is in the asset. If you want a pixel-perfect display, you have to provide a pixel-perfect asset. Even for power of 2 scaling, it won't be able to "guess" if you want the scaled up version to retain the jagged pixel outline - it will assume you want interpolation to avoid sharp edges. That said, I believe the 'rotozoom" method (in contrast with scale) uses a different algorithm for scaling - try it instead, and see if you get satisfactory results - otherwise, go to an image editor, and handcraft your assets so you have different versions for the sizes you will use.

(In GIMP, for example, you can select no filter for scaling, preserving the pixels, and retouch what you need with the pencil tool, with a pixel-sized brush for pixel perfect images)

answered Jul 24 at 17:33
Sign up to request clarification or add additional context in comments.

1 Comment

Rotozoom seems to use a method that automatically filters the image even if used at 1x scale. I did try just using pygame.image.load on a 48x48 version of the image, but that turned out with the exact same results as pygame.transform.scale.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.