[Rod Stephens Books]
Index Books Python Examples About Rod Contact
[Mastodon] [Bluesky] [Facebook]
[Build Your Own Python Action Arcade!]

[Build Your Own Ray Tracer With Python]

[Beginning Database Design Solutions, Second Edition]

[Beginning Software Engineering, Second Edition]

[Essential Algorithms, Second Edition]

[The Modern C# Challenge]

[WPF 3d, Three-Dimensional Graphics with WPF and C#]

[The C# Helper Top 100]

[Interview Puzzles Dissected]

Title: Fit an image to a target rectangle and center it in Python

[A smiley face image fit to three different rectangles in Python]

This is the first in a series of posts leading to a flash card application that you can use to learn about Japanese hiragana characters.

The first step is figuring out how to resize an image to make it fit a target rectangle without distorting it.

Fitting Images

This isn't really very hard. I'm putting the code in a function so it's easy to reuse.

The following fit_image function takes as inputs a PIL image and the bounds of the rectangle where you want to put it. It returns the resized imageand the X and Y coordinates for the image's upper left corner to center it in the rectangle.

def fit_image(image, xmin, ymin, xmax, ymax): '''Resize the image so it fits without distorting it.''' # Get the available and image dimensions. rect_wid = xmax - xmin rect_hgt = ymax - ymin image_wid = image.width image_hgt = image.height # Scale the image to fit. x_scale = rect_wid / image_wid y_scale = rect_hgt / image_hgt scale = min(x_scale, y_scale) # Scale the image dimensions to fit. image_wid = int(scale * image_wid) image_hgt = int(scale * image_hgt) # Resize the image. image = image.resize((image_wid, image_hgt)) # Find the position that centers the image. x = xmin + (rect_wid - image_wid) // 2 y = ymin + (rect_hgt - image_hgt) // 2 # Return the resized image and the location that centers it. return image, x, y

This function first gets the width and height of the rectangle and the image. It then calculates scale factors that would stretch the image to fill the rectangle horizontally and vertically. It sets the scale variable to the smaller of the two scales. That is the largest scale that we can use on the image while keeping it small enough to fit in the rectangle.

Next, the code uses scale to calculate the image's new width and height. It calls the image's resize method to resize the image.

To calculate the X coordinate of the resized image's upper left corner, the code subtracts the rectangle's width from the image's width to see how much extra width is left over unused by the image. Half of that unused space should be to the left of the image, so the code divides it by 2 and adds it to the rectangle's minimum X coordiate.

The function uses similar steps to find the Y coordinate of the image's upper left corner.

(Note that the resized image will fill the rectangle either horizontally, vertically, or both, so at least one of the "unused space" values will be zero.)

The function finishes by returning the resized image and the coordinates of its upper left corner.

Using the Function

The following code shows how the program builds its user interface. The code that calls the fit_image function is highlighted in blue.

def build_ui(self): '''Build the user iterface.''' # Define the rectangles where we will draw the smileys. rects = [ [10, 10, 320, 110], [10, 120, 110, 320], [120, 120, 320, 320], ] # Make the canvas. canvas = tk.Canvas(self.window, background='white', width=rects[-1][2]+5, height=rects[-1][3]+5, borderwidth=2, relief=tk.SUNKEN) canvas.pack(side=tk.TOP, padx=5, pady=(0,5)) # Make a lost to store PhotoImage objects. self.photo_images = [] # Load the smiley face image. image = Image.open('Smiley.png') # Center the smiley in three rectangles. for rect in rects: # Center the smiley in this rectangle. resized_image, x, y = fit_image(image, *rect) photo_image = ImageTk.PhotoImage(resized_image) self.photo_images.append(photo_image) canvas.create_image(x, y, image=photo_image, anchor=tk.NW) # Draw this rectangle. canvas.create_rectangle(*rect, outline='blue')

This method first defines three rectangles where it will draw the smiley face image. It then creates a Canvas widget.

Next, the code creates a list to hold PhotoImage objects. We need to store those images somewhere safe so the garbage collector can't run off with them and tkinter can use them when needed.

The code loads the smiley image file and then loops through the rectangles.

For each rectangle, the program calls fit_image to fit the image to the rectangle. It converts the resized image into a PhotoImage, saves it in the PhotoImage list, and uses the canvas's create_image method to draw the image at the coordinates returned by fit_image. The code then outlines the rectangle so we can see that the image was drawn inside it.

Conclusion

This is a relatively simple application that does something pretty common: it enlarges or shrinks an image to fit in a target area and centers it within that area. The fit_image function makes that easy.

If you want the image to fill a Canvas widget, pass the function the coordinates 0, 0, canvas.winfo_width(), canvas.winfo_height(). Just remember to call canvas.update() first so winfo_width and winfo_height can return the correct results.

Download the example to experiment with it and to see additional details.

© 2025 Rocky Mountain Computer Consulting, Inc. All rights reserved.