Bildquelle: USGS on Unsplash (modified)

Scaling and Cropping images using Python

By Max Dietrich | Geospatial specialist, Web-Developer.

Since I used a lot of pictures (and also very large ones in the beginning), this had a huge impact on the speed of the page. Since PageSpeed ​​is a not unimportant ranking factor for search engines like Google and Co, you should of course make a page as fast as possible.

The images used here are mainly satellite images from ESA, which are licensed under the CC BY-SA 3.0 IGO IGO) and may therefore also be used for your own purposes under certain conditions.

These pictures are often ~ 30MB, which is a bit too big for a website. Since I didn't want to crop all pictures manually, I decided to solve this problem with Python or Pillow.

Pillow library

Pillow is a Python library for image processing that can be installed on with (assuming you have Python already installed)

pip install Pillow

Finally you can import the library with

from PIL import Image

into your Python script.

All images for posts are in a separate "images /" folder in the root directory of the project.

First, all ".jpg" files in a certain directory are opened with Pillow and all file names are saved in an array. In addition, a variable is required and can later access any name in the array.

count = 0
image_list = []

for file in glob.iglob('path/to/images/*.jpg'):
    im=Image.open(file)
    image_list.append(os.path.basename(file))

Define sizes and calculate aspect ratio

Now you should know to which sizes the pictures should be cut and whether, for example, the proportions should be retained. For all "PostCover" (pictures in posts) the aspect ratio is ignored and the picture is simply cut to a certain size, which is declared in a global variable.

size = (1903,453) #(width,height)

With all "PostThumbnails" (picture preview) the aspect ratio should be retained and only scaled smaller. A global standard width is defined for this.

basewidth = 500

Then the original width and height of the images are determined, as we need them to be able to calculate and maintain the aspect ratio. Only the new height is needed here, as the standard width has already been predefined.

    width, height = im.size
    wpercent = (basewidth / float(im.size[0]))
    hsize = int((float(im.size[1]) * float(wpercent)))

Cropping and Rescaling

Now you can cut the images with Image.crop or scale them with Image.resize. The new width "basewidth" and the calculated height "hsize" are now used as parameters for scaling.

    imThumbnail = im.resize((basewidth, hsize), Image.LANCZOS)
    imCover = im.crop(((width-size[0])//2, (height-size[1])//2, (width+size[0])//2, (height+size[1])//2))

Then I renamed the thumbnail and saved both new files under static/assets with a quality of "85" . With the additional parameter "optimize = True" a few KB can be saved.

    newCover = 'static/assets/{}'.format(image_list[count])
    newThumbnail = 'static/assets/{}_thumbnail.jpg'.format(image_list[count].replace(".jpg", ""))
    imCover.save(newCover,optimize=True,quality=85)
    imThumbnail.save(newThumbnail,optimize=True,quality=90)
    count +=1 

Complete script:

from PIL import Image
import glob, os

count = 0
image_list = []
basewidth = 500
size = (1903,453)
 

for file in glob.iglob('path/to/images/*.jpg'):
    im=Image.open(file)
    image_list.append(os.path.basename(file))
    width, height = im.size
    wpercent = (basewidth / float(im.size[0]))
    hsize = int((float(im.size[1]) * float(wpercent)))
    imThumbnail = im.resize((basewidth, hsize), Image.LANCZOS)
    imCover = im.crop(((width-size[0])//2, (height-size[1])//2, (width+size[0])//2, (height+size[1])//2))
    newCover = 'static/assets/{}'.format(image_list[count])
    newThumbnail = 'static/assets/{}_thumbnail.jpg'.format(image_list[count].replace(".jpg", ""))
    imCover.save(newCover,optimize=True,quality=85)
    imThumbnail.save(newThumbnail,optimize=True,quality=90)
    count +=1 

Run script automatically

In order not to have to run the script manually every time, you can add the following to "package.json".

    "img-optimize": "py ./src/utils/resize_images.py"

So you can optimize all images automatically with npm run img-optimize.

More Articles:

Hosting NextJS on a private server using PM2 and Github webhooks as CI/CD

This article shows you how can host your Next.js site on a server with a CI/CD pipeline via PM2 and Github Webhooks.

Syntax Highlighting with Prism and Next.js

Prism is a compact, expandable syntax highlighter that was developed with modern web standards in mind.

How to create a Mailchimp newsletter sign-up-form for your Gatsby Site

Managing your own newsletter is crucial for creating a sustainable online-business. With E-Mails you can build a relationsship with your audience and engage with them so they will drive some nice traffic to your new post or whatever you just have published and want to promote.

I am Max Dietrich.

I am currently working as Geodata-Manager at RIWA.
I love to experiment with web-applications which i am documenting on this site.

Recent Articles

    Good Links

    • All Articles
    • Site Stats
    • About this site
    • Disclaimer & Imprint

    Connect

    You can connect with me on:
    Copyright Β© 2020 Max Dietrich. All Rights Reserved.
    Made with ❀️ by MXD.