Search code examples
pythonimagepygametransformscale

pyGame image scale does not work as expected


I am new into Python and pyGame and i have a problem with scaling an image. I want to zoom an image in pygame. The pygame documentation claims that

pygame.transform.scale()

should scale to a new resolution. But in my example below it does not work - it crops the image instead of resizing it!? What am i doing wrong?

#!/usr/bin/env python3
# coding: utf-8

import pygame
from pygame.locals import *

# Define some colors
BLACK = (0, 0, 0)

pygame.init()

# Set the width and height of the screen [width, height]
screen = pygame.display.set_mode((1920, 1080))

pic = pygame.image.load('test.jpg').convert()
pic_position_and_size = pic.get_rect()

# Loop until the user clicks the close button.
done = False

# Clear event queue
pygame.event.clear()

# -------- Main Program Loop -----------
while not done:
    for event in pygame.event.get():
        if event.type == QUIT:
            done = True
        elif event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                done = True

    # background in black
    screen.fill(BLACK)

    # Copy image to screen:
    screen.blit(pic, pic_position_and_size)

    # Update the screen with what we've drawn.
    pygame.display.flip()
    pygame.display.update()

    pygame.time.delay(10)    # stop the program for 1/100 second

    # decreases size by 1 pixel in x and y axis
    pic_position_and_size = pic_position_and_size.inflate(-1, -1)

    # scales the image
    pic = pygame.transform.scale(pic, pic_position_and_size.size)

# Close the window and quit.
pygame.quit()

Solution

  • pygame.transform.scale() does not work very well for your case. If you shrink a Surface by such a small amount, the algorithm just crops the last column and row of pixels. If you now repeat this process over and over again with the same Surface, you get the strange behaviour you see.

    A better approach would be to keep a copy of your original Surface around, and use that for creating the scaled image. Also, using smoothscale instead of scale may also lead to a better effect; it's up to you if you want to use it.

    Here's a "fixed" version of your code:

    #!/usr/bin/env python3
    # coding: utf-8
    
    import pygame
    from pygame.locals import *
    
    # Define some colors
    BLACK = (0, 0, 0)
    
    pygame.init()
    
    # Set the width and height of the screen [width, height]
    screen = pygame.display.set_mode((1920, 1080))
    
    org_pic = pygame.image.load('test.jpg').convert()
    pic_position_and_size = org_pic.get_rect()
    pic = pygame.transform.scale(org_pic, pic_position_and_size.size)
    # Loop until the user clicks the close button.
    done = False
    
    # Clear event queue
    pygame.event.clear()
    
    # -------- Main Program Loop -----------
    while not done:
        for event in pygame.event.get():
            if event.type == QUIT:
                done = True
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    done = True
    
        # background in black
        screen.fill(BLACK)
    
        # Copy image to screen:
        screen.blit(pic, (0,0))
    
        # Update the screen with what we've drawn.
        pygame.display.flip()
        pygame.display.update()
    
        pygame.time.delay(10)    # stop the program for 1/100 second
    
        # decreases size by 1 pixel in x and y axis
        pic_position_and_size = pic_position_and_size.inflate(-1, -1)
    
        # scales the image
        pic = pygame.transform.smoothscale(org_pic, pic_position_and_size.size)
    
    # Close the window and quit.
    pygame.quit()