How to Resize Images in Ren’Py

How to Resize Images in Ren’Py

Have you ever wanted to resize images in Ren’Py while maintaining the aspect ratio? Luckily, there is a built-in property to help you do that, called fit. In this article, we’ll go over how to use fit and how different fit values work.

Difficulty Level: Beginner

If you haven’t already, you should be sure to read up on Ren’Py Size Properties – xysize, maximum, and minimum at minimum, and I recommend reading the follow-up Ren’Py Size Properties – fill, fit, size_group, and area as well.

While xfit and yfit are used for fixed containers, there is a special fit property which can be used with Transform or as part of ATL. Since ATL deals with displayables, not “elements”, I’ll be using “displayable” to refer to the thing you’re applying fit to.

fit causes the displayable to be sized in a particular way, typically preserving its original dimensions in some form. It is used in combination with xsize and ysize.

By default, fit begins as None. It can be one of several values, which I’ll explain in turn. For each of these examples, we will discuss an 800x400 pixel displayable called “feniks.png” which will have the fit property applied in various ways.

“contain”

If you use fit "contain", the displayable will try to be as large as possible without exceeding any provided dimensions (provided via xsize and/or ysize). It maintains the original aspect ratio of the displayable.

So, for our 800x400 pixel “feniks.png” displayable, if we applied the fit property with "contain", here’s what would happen:

add "feniks.png":
    fit "contain"
    xsize 400

Result: the width can be at most 400px, aka half the original width, so the height is scaled down to match. The resulting displayable is 400×200.

add "feniks.png":
    fit "contain"
    ysize 600

Result: The height can be at most 600px, aka 1.5x the current height. The width is scaled up to match. The resulting displayable is 1200×600.

add "feniks.png":
    fit "contain"
    xysize (900, 900)

Result: the displayable can be at most 900px in either dimension. The displayable is wider than it is tall, so the width will be 900px. The height will then be 450px to maintain the aspect ratio. The resulting displayable is 900×450.

“cover”

If you use fit "cover", the displayable will try to be as small as possible, while matching or exceeding any provided dimensions. It maintains the original aspect ratio.

add "feniks.png":
    fit "cover"
    xsize 400

Result: The width is at minimum 400px. To maintain the aspect ratio, the height is set to 800px. The resulting displayable is 400×800 (same as with “contain”).

add "feniks.png":
    fit "cover"
    ysize 600

Result: The height is at minimum 600px. To maintain the aspect ratio, the width is set to 1200. The resulting displayable is 1200×600 (again, same as “contain”).

add "feniks.png":
    fit "cover"
    xysize (900, 900)

This is where contain and cover differ. The minimum dimension we have is 900. Since “cover” will exceed or match the provided dimensions, we take the smallest dimension – the height – and set that as the baseline. So the height will be 900px, and thus the width will be 1800px to match. This results in a displayable that is 1800×900.

“fill” or None

If you have fit None or fit "fill", then the xysize are taken as exact dimensions which should squash/stretch the displayable to match. It does NOT maintain the original aspect ratio. This is the default behaviour. So:

add "feniks.png":
    fit "fill"
    xsize 400

Result: The xsize is set to 400. The height remains 400px. The resulting displayable is 400×400 (making it squished narrower than the original).

add "feniks.png":
    fit "fill"
    ysize 600

Result: The ysize is set to 600. The width remains 800px. The resulting displayable is 800×600 (making it stretched taller than the original).

add "feniks.png":
    fit "fill"
    xysize (900, 900)

Result: The width and height are set to 900px. The resulting displayable is 900×900, making it slightly wider and over twice as tall.

“scale-down”

“scale-down” is nearly the same as “contain”, but it will never increase the size of the displayable. So, for our example displayable, the width will never be more than 800px, and the height will never be more than 400px.

add "feniks.png":
    fit "scale-down"
    xsize 400

Result: The width is smaller than 400px, so it is selected and the height scaled to match the aspect ratio. The resulting displayable is 800×400 (same as “contain”).

add "feniks.png":
    fit "scale-down"
    ysize 600

Result: The provided height of 600px is larger than 400px. The displayable can’t exceed 800×400, so it remains 800×400.

add "feniks.png":
    fit "scale-down"
    xysize (900, 900)

Result: The width can’t exceed 800 and the height can’t exceed 400, so the resulting displayable remains 800×400.

“scale-up”

“scale-up” is nearly the same as “cover”, but it will never decrease the size of the displayable. So, for our example displayable the width will never be less than 800px, and the height will never be less than 400px.

add "feniks.png":
    fit "scale-up"
    xsize 400

Result: The width is smaller than 800px, but the displayable can’t get any smaller. The resulting displayable is 800×400.

add "feniks.png":
    fit "scale-up"
    ysize 600

Result: The height is larger than 400px. The height is set to 600 and the width scaled to match. The resulting displayable is 1200×600 (same as “cover”).

add "feniks.png":
    fit "scale-up"
    xysize (900, 900)

Result: The height is selected as the largest dimension and the width scaled to match. The resulting displayable is 1800×900 (same as “cover”).

Summary

ValueDescription
“contain”As large as possible, without exceeding any dimensions. Maintains aspect ratio.
“cover”As small as possible, without exceeding any dimensions. Maintains aspect ratio.
None or “fill”Exactly the size of the provided dimensions. Does not maintain aspect ratio.
“scale-down”As large as possible, while not exceeding any dimensions including the original dimensions of the displayable. Maintains aspect ratio.
“scale-up”As small as possible, while not being smaller than the original displayable. Maintains aspect ratio.

The ATL fit property is incredibly powerful for sizing and scaling displayables without losing their original dimensions. For example, maybe your character sprites are all slightly different sizes, and you want to be able to display them in a Character Bio screen. You can use fit "contain" with xysize to ensure all sprites fit inside the area designated to display their character sprites without worrying about what exact size they need to be scaled down to.

Next Steps

The next tutorial in this series will be on incompatible size and position properties from the last several tutorials so you can tell them apart, and then after that we will begin to look at other containers like frame.

You can also check out my recent tool releases on itch.io, which add Gradients and Circular Bars to Ren’Py!

And lastly, I also put out an article format of my recent talk at Visual;Conference. You can find it here: Character Customization 101 Talk

Leave a Reply