How to scale image while keeping aspect ratio in Pygame?

4.1k Views Asked by At

How can I rescale an image using pygame.transform.scale but keeping the same aspect ratio? Like if I have a 16:9 image and I want to scale it while keeping the same ratio. My main goal is to make an image viewer because Windows 10's takes forever to load, here's my current code:

import pygame
from sys import argv
from win32api import GetSystemMetrics
pygame.init()
pygame.display.init()

width=GetSystemMetrics(0)*0.9   #Window size a bit smaller than monoitor size
height=GetSystemMetrics(1)*0.8
img=pygame.image.load(argv[-1]) #Get image file opened with it

img=pygame.transform.scale(img, (int(width), int(height)))  #Scales image to window size
Main=pygame.display.set_mode((int(width), int(height)))
pygame.display.set_caption(str(argv[-1].split("\\")[-1]))   #Set window title as filename
imgrect=img.get_rect()

Main.blit(img, imgrect)
pygame.display.update()
while True:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            exit()

I guess the problem is that I can resize it but the image is distorted, or I can display it as the image's width and height, but I can't scale the image as big as it gets in the window's dimensions while keeping the aspect ratio, there's always blank space. Sorry for the vague question I don't know how to explain it well.

Edit: Fixed it. If anyone else has the same problem, I had to normalize the ratio, get it to 1:something by dividing both sides by the width. Then, I multiplied the 1:something ratio by the width of the window, and in a while loop, decreased the scale if the image's width was larger than the window's. Source:

import pygame
from sys import argv
from win32api import GetSystemMetrics
pygame.init()
pygame.display.init()

windowwidth=GetSystemMetrics(0)*0.9
windowheight=GetSystemMetrics(1)*0.8
Main=pygame.display.set_mode((int(windowwidth), int(windowheight)))
img=pygame.image.load(argv[-1])

imgratiox=int(1)
imgratioy=int(img.get_height()/img.get_width())

imgwindowwidth=int(windowwidth)
imgwindowheight=int(round(img.get_height()/img.get_width(), 2)*windowwidth)
scale=1
while imgwindowheight>windowheight:
    imgwindowheight*=scale
    imgwindowwidth*=scale
    scale-=0.05

img=pygame.transform.scale(img, (int(imgwindowwidth), int(imgwindowheight)))
pygame.display.set_caption(str(argv[-1].split("\\")[-1])+ "    Img width:"+str(img.get_width())+"    Img height:"+str(img.get_height()))
imgrect=img.get_rect()

Main.blit(img, imgrect)
pygame.display.update()
while True:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            exit()
1

There are 1 best solutions below

2
On BEST ANSWER

When you load the image, adjust the window to match the image ratio.

In this code, the width is set then the height is adjusted according to the image ratio. If the height is to large, the width is reduced to allow a smaller height.

import pygame
from sys import argv
from win32api import GetSystemMetrics
pygame.init()
pygame.display.init()

img=pygame.image.load(argv[-1]) #Get image file opened with it

width=GetSystemMetrics(0)*0.9   #Window size a bit smaller than monoitor size
height=width*img.get_height()/img.get_width()  # keep ratio

if height > GetSystemMetrics(1)*0.8:  # too tall for screen
    width = width * (GetSystemMetrics(1)*0.8)/height  # reduce width to keep ratio 
    height = GetSystemMetrics(1)*0.8  # max height

img=pygame.transform.scale(img, (int(width), int(height)))  #Scales image to window size
Main=pygame.display.set_mode((int(width), int(height)))
pygame.display.set_caption(str(argv[-1].split("\\")[-1]))   #Set window title as filename
imgrect=img.get_rect()

Main.blit(img, imgrect)
pygame.display.update()
while True:
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            pygame.quit()
            exit()

Test output

  • Original

Original

  • Script

Pygame