Building Python Webp Convertor CLI

Published on and updated on
by

This article tutorial demonstrates how to easily build a Python-based WebP image converter CLI tool. How to convert a image into WebP using Python with Pillow.

Python is a programming language with many libraries and tools that allow you to do almost anything you can think of. In this article, we'll show you how to convert a image to webp using Python. Now, there are a few ways to convert an image to webp using Python. One way is to use the Python Image Library (PIL). PIL can be used to create webp images from other image formats and in this guide we're going to use Python's Pillow or PIL library to do so.

Before getting started let’s start working on a Jupyter notebook file instead of directly creating a file or program to better and ease the work. Once, we're done we will be creating a terminal based program to convert our images. So, without any further a due let's get into this.

Prerequisites

We're going to use VS code and will installing Python and Jupyter notebook extension directly inside of our code editor instead of installing it separately and running code in the browser. However, you can use whatever you want it won't make any difference.

  1. Open VS code.
  2. Install two extensions named “Python” and “Jupyter Notebook”

Converting images to webp with Python using PIL Library

1. Create an .ipynb file and Install necessary packages

Firstly, create directory to store all the code files (in our case it's going to be one or two.) Then create file named main.ipynb. Now, VS studio code will automatically convert that file into Jupyter notebook's cell format.

Then create virtual environment:

On Windows:

python -m vene python-webp-convertor-env

On Unix:

python3 -m vene python-webp-convertor-env

Activate the virtual environment

On Windows:

python-webp-convertor-env\Scripts\activate

On Unix:

source python-webp-convertor-venv/activate

Install Pillow (PIL)

Now, we're directly installing them in notebook itself for now. So, open the main.py file and run the following code:

%pip install Pillow

# output
Collecting Pillow
  Using cached Pillow-9.2.0-cp310-cp310-win_amd64.whl (3.3 MB)
Installing collected packages: Pillow
Successfully installed Pillow-9.2.0

[notice] A new release of pip available: 22.2.1 -> 22.2.2
[notice] To update, run: python.exe -m pip install --upgrade pip

2. Import packages and add sample image

We need to import Image from Pillow and we also need to import Python's os package.

import os
from PIL import Image

Now, let's add a sample image in the project directory python-webp-convertor/sample.jpg. You can use this image from Unsplash or any image just name it sample.png.

To make sure we're on the page, my project directory looks like this:

python-webp-convertor/
---- main.ipynb
---- sample.jpg

Right now, the image size is 1.82MB and we are also going to optimize using Pillow's quality feature.

3. Load and open the image programmatically

Add this code in your main.py file and run this code of cell and I will explain further.

im = Image.open("sample.jpg")
im.show()

So, in the first line we're creating a variable named, im assign the Image imported class and opening the image from sample.jpg path.

And in the next line using the show() method. We're calling it to show the image using computer's default image viewer program. And on top we the actual image in window's default picture viewer program.

4. Converting image to webp

To convert and image into webp, set the image path with WEBP parameter, and save it.

im = Image.open("sample.jpg")
im.save("sample.webp", "WEBP")

Once you run this cell of code. A new image will be saved in your project directory. For more context about this save method, basically the “sample.webp” is our new file path. You use a variable instead of hardcoding to make it dynamic. In the last part, we are passing the file format in our case it's WEBP but it could be anything like PNG, JPEG, etc.

Let's talk about the image we have just generated. Let compare the size of images.

Our original image was about 1.82MB and our new WEBP image is about 1.07MB. Sure, we have optimized it and the size is reduced by 0.75 but still 1.07MB image is not best for the web. So, now we're going to resize the image.

5. Resizing the image

To resize the image we're going to use thumbnail method from Image class itself. So, we don't have to care about aspect ratio or image stretching issue.

im = Image.open("sample.jpg")
size = (500, 800)
im.thumbnail(size)
im.save("sample_resized.webp", "WEBP")

Now, this code a new image by the name of sample_resized.webp will be saved the project directory and checkout the size. It's 106.09KB and size 500x750, I guess it useable for the web now?

Actually, yes but what if you have 10 images on a single it's going to be more than 1MB worth of data from just images. So, now we're going to look at another feature of this amazing package called quality.

6. Manipulating image quality

To change quality of image we just have to pass another parameter as you would guess by the name of quality while saving the image. So, run the following and let's see the results then.

im = Image.open("sample.jpg")
size = (500, 800)
im.thumbnail(size)
im.save("sample_resized_75.webp", "WEBP", quality=50)

Now, if you run this code a new image will be saved by the name of sample_resized_75.webp in the project directory. If you compare it's size with the last image (sample_resized.webp) it's almost 50% less around 63.33KB. Now, it's pretty useful great for web. We can do a lot things with this library. Checkout the official docs from Pillow. They straight forward and easy to use.

7. Converting it into a function or method

All code will remain the same, I'm going to wrap it in a Python function.

def webp_conv(in_file, out_file, quality=75, size=(500, 500)):
    im = Image.open(in_file)
    im.thumbnail(size)
    return im.save(out_file, "WEBP", quality=quality)

Now, we can invoke our function webp_conv anywhere we in the project. It requires two parameter which is the in_file, path of the image that you want to convert and out_file, the new image path. quality and size both parameters are not required because we have assigned a default value but we can do and override it.

Let's test it:

webp_conv("sample.jpg", "t1.webp")

We're doing this only required parameters, the new image t1.webp has 333x500 size and it's about 40.51KB.

Now, let's pass all parameters.

webp_conv("sample.jpg", "t2.webp", quality=50, size=(500, 500))

The new t2.webp is about 29.05KB and the same size as t1.webp.

8. Making it into a command line tool (CLI tool)

Now, create a new Python file and let's name it main.py. Put the following code, there's nothing new apart from using __main__ and __name__ function. Please the Python's official docs for this.

import os
from PIL import Image

def webp_conv(in_file, out_file, quality=75, size=(500, 500)):
    im = Image.open(in_file)
    im.thumbnail(size)
    return im.save(out_file, "WEBP", quality=quality)


def main():
    webp_conv(
        input("Enter the image file path: "),
        input("Enter the output file name: "),
        quality = int(input("Enter the quality (0-100): ")),
        size=(int(input("Enter the width: ")), int(input("Enter the height: ")))
    )

    print("Done!!!")
    print(".\n.\n.\n")
    rerun = input("Do you want to run again? (y/n): ")
    if rerun == "y":
        main()
    else:
        print("\n")
        print("Goodbye!")
        print("\n")
        exit()


if __name__ == "__main__":
    main()
    exit()

Now, if you run this code, it will ask you step by step for output file path and input file path, for size, quality, and after saving it if you want it to rerun otherwise exit the program.

Now, we can run this file from terminal using python main.py.

Both files including main.ipynb and main.py is saved under a GitHub repository called Python Webp CLI you can download, test and modify as your needs.