Use Google Colab and Python to upload resized images to Wordpress

Nathan John Krupa
8 min readNov 22, 2021

I’m terribly lazy, and one of the things that I don’t like doing is resizing and compressing images before uploading them to WordPress. So I thought, “Why don’t I create a python script that can do it for me automatically?” This calls for Google Colab!

(If you just want to look at the full code, click here to jump to the program at the end of the article.)

I discovered Colab a few months ago when a friend of mine, who is a real programmer, opened my eyes to this wonderful tool. If you haven’t tried Colab, it’s basically a Jupyter Notebook that lives in your Google Cloud account.

The first time you sign into Colab, you’ll get a screen that looks like this:

If you’re signed into a Google account, your Colab workspace will attach itself to your Google drive. This will prove to be very useful.

To open up a new notebook, just click on file and new notebook. A new tab with a notebook named Untitled.ipynb will pop up on your browser. Click on the name to give it a new title like “Colab Python WordPress”. Or whatever you want.

The Colab notebook functions like a Jupyter Notebook, and is actually built on the Jupyter source code. You can add cells of text and cells of runnable code. If you want to experiment with your program, you can chunk your code into smaller cells and then run them one at a time, iterating as necessary.

The Welcome to Colab notebook has more information about how to use the Colab tools, and I’ll be talking about a few of the features later on.

Load your libraries.

Now that you have a fresh notebook, you’ll want to load the necessary libraries.

Here’s what I’ve started with: (I’ll have the full code at the bottom of the article.)

from google.colab import drive drive.mount('/content/drive') 
!CC="cc -mavx2" pip install -U --force-reinstall pillow-simd import PIL
from PIL import Image
import glob
import os

The first two lines are super important and useful. They connect your Colab notebook to your Google Drive. You’ll have to do an oauth2 verification when you run the program to give permission to connect, but you’ll only have to do that once per session. It only takes a moment.

When you first run the program, just click the link, sign into your Google account, copy and paste the token in the dialogue box.

Using the “!” allows you to install libraries in Colab. After doing some research, I decided that I really liked the Pillow-SIMD library for photo manipulation, so I’m installing it here.

Once that’s uploaded, you can import it as PIL, as well as Image. You’ll also need to import glob, which will help you to manage your files, and os which you’ll need the first time if you want to create new directories to hold your files.

import requests import json import base64

Next you’ll need to add the libraries that will enable you to communicate with the WordPress Rest API. Requests will help you build the API calls, JSON will will you structure the data correctly, and base64 will encode it so that the server can read it.

Connecting to WordPress.

To connect to the WordPress Rest API for your site, you need to use this code to configure your credentials.

url = 'https://yoururl.com/wp-json/wp/v2' user = 'yourusername' password = 'your application password' creds = user + ":" + password token = base64.b64encode(creds.encode())

The first thing you need is the API endpoint for your upload. The variable ‘url’ should be modified to replace ‘yoururl.com’ with your domain name. The user is your username for the WordPress instance that you are trying to access.

To get your password, you’ll need to create an application password for the user that will be connecting to WordPress. Go to the User tab in WordPress and click All Users. Open up the user that you will use for API Access. Near the bottom of the page, you should see a button for creating an application password.

Give your application a name and click the generate password button. A screen will pop-up with the new password. Make sure to save it, because you won’t be able to retrieve it if you lose it.

Note: If you don’t see the Applications Passwords field on the User page, it might be disabled by your security plugin. If you’re using a security plugin like WordFence, you might have to go into the plugin settings and enable the Application Passwords feature. WordFence disables it by default, but allows you to reactivate it manually.

The code I’ve given you above puts the password directly into your program. If you’d like an extra layer of safety, you can change that line of code to the following, which will give you an input field each time you run the program.

password = input("Type your password and press enter:")

The next two lines of code use your username and password to create the API credentials that the program will use.

Create your photo buckets.

Your “Colab Python WordPress” program takes all of the photos from one folder, saves an identical copy to another folder, and then saves a resized and compressed image to still another folder so that the program can ship them off to WordPress.

If the folders don’t already exist, you can use the os library to create the folder as shown in this code snippet.

#os.mkdir('Resized')

Please note that the path to the new folder would be “/content/drive/Resized/”. That’s due to the path that you used to mount your Google drive earlier.

If you plan on running this program more than once, you will not need to mkdir every time unless you delete the folder after running the program. So instead, you can just set the paths to three permanent folders like this:

inputFolder = '/content/drive/My Drive/WebPics/Uploads/' archiveFolder = '/content/drive/My Drive/WebPics/Archive/' outputFolder = '/content/drive/My Drive/WebPics/Final/'

If you have trouble tracing the path of your files, Colab has a convenient file system that works in a standard kind of way. Just click on the file icon on the left side of your browser (below it’s highlighted in orange). Clicking on any of the arrows next to the file names will expose the contents of the folder.

Churn through your photos.

Now you’re ready to change all of your photos. I’ve commented the following code to clarify what’s going on.

Basically, I want the images reformatted at 1200 X 800 if they are landscape and 800 X 1200 if they are portrait. The algorithm determines their orientation and calculates the aspect ratio.

i = 0 #Numbers the images starting with this number. 
for img in glob.glob(inputFolder + "/*.JPG"): #iterates through the paths for all images in the Uploads folder
image = Image.open(img)#opens the current image # save a copy of the image in the archive folder)
mage.save('/content/drive/MyDrive/WebPics/Archive/ image11.17.21.%04i.JPG' %i, optimize = True, quality = 100) #Change Date every time so you don't overwrite old files print(image.format, image.size, image.mode)#Unnecessary, but allows you to track the progress of the program through your files. new_image_width = image.size[0] new_image_height = image.size[1]
if new_image_width > new_image_height:
new_image_width = 1200
new_image_height = int((new_image_width * image.size[1]) / image.size[0])
else:
new_image_width = 800
new_image_height = int((new_image_width * image.size[1]) / image.size[0])
imgResized = image.resize((new_image_width, new_image_height), resample = 1)
imgResized.save("/content/drive/MyDrive/WebPics/Final/ image11.17.21.%04i.JPG" %i, optimize = True, quality = 70) #Saves images into Final folder - Make sure to change the date above or you will write over old pictures.
i +=1
#Watch the indents on this section. I had a hard time formatting the code on Medium!

When you’re resizing the image, you have several options for sampling algorithm. The values for the resample paramater translate as follows: Image.NEAREST (0) Image.LANCZOS (1) Image.BILINEAR (2) Image.BICUBIC (3) Image.BOX (4) Image.HAMMING (5). I use Lanczos resampling because I like the way it turns out.

You can also change the quality of the image by changing the quality parameter in imgResized.save() to a different integer between 0 and 100. 100 is full quality and the image gets progressively smaller and more pixelated as the number goes down. At quality of 70 0r 80, I notice no visible change in quality.

I noted in the code a couple of things, but it’s worth pointing them out. The program creates new files, and so you will need to slightly tweak the parameters for the saves each time you run the program so the files don’t all come out with the same name. I recommend manually changing the date of the upload because it’s easy. I’m lazy, remember. You can get more complicated and do it programmatically, if you want.

Sending the images to WordPress.

Now that you have your resized images, the last thing that you need to do is upload them to WordPress. This code will do it for you.

for img in glob.glob(outputFolder + "/*.JPG"): 
header = {'Authorization': 'Basic ' + token.decode('utf-8')}
media = {
'file': open(img, 'rb'),
'caption': 'first API image',
'description': 'First API image'
}
print(media) #Not necessary, but allows you to track the progress image = requests.post(url + '/media', headers = header, files = media)
imageURL = str(json.loads(image.content)['source_url'])
#Again, watch out for the formatting.

This part of the “Colab Python WordPress” program iterates through all of the photos in your output folder, creates the JSON file needed for the API call, and uses the authorization token you created earlier to upload them to your WordPress site.

One thing to notice in the media file: as written, every image in your folder will have the same caption and description. This is not necessarily desirable. If you don’t want a caption, you can set this equal to an empty string: “. For the description, you might put something like your copyright information and the place where the photos were taken. It’s really up to your imagination.

If you have problems with connecting to the API, make sure that you have the right url for your API endpoint.

Putting “Colab Python WordPress” together.

As I promised, here’s the code all put together:

from google.colab import drive 
drive.mount('/content/drive')
!CC="cc -mavx2" pip install -U --force-reinstall pillow-simd
import PIL from PIL
import Image
import glob
import os
#os.mkdir('Resized')
import requests
import json
import base64
url = 'https://yoururl.com/wp-json/wp/v2'
user = 'username'
password = 'Password'
creds = user + ":" + password
token = base64.b64encode(creds.encode())
inputFolder = '/content/drive/My Drive/WebPics/Uploads/' archiveFolder = '/content/drive/My Drive/WebPics/Archive/' outputFolder = '/content/drive/My Drive/WebPics/Final/' #os.mkdir('/content/drive/My Drive/WebPics/Final/')
i = 0
for img in glob.glob(inputFolder + "/*.JPG"): #pulls images from Uploads folder and resizes them
image = Image.open(img)
image.save('/content/drive/My Drive/WebPics/Archive/image11.17.21.%04i.JPG' %i, optimize = True, quality = 100) #Change Date every time
print(image.format, image.size, image.mode)
new_image_width = image.size[0]
new_image_height = image.size[1]
aspect_ratio = new_image_height / new_image_width
if new_image_width > new_image_height:
new_image_width = 1200
new_image_height = int((new_image_width * image.size[1]) / image.size[0])
else:
new_image_width = 800
new_image_height = int((new_image_width * image.size[1]) / image.size[0]) #imgResized = image
imgResized = image.resize((new_image_width, new_image_height), resample = 1)
imgResized.save("/content/drive/My Drive/WebPics/Final/image11.17.21.%04i.JPG" %i, optimize = True, quality = 70) #Saves images into Final folder - Make sure to change the date
i +=1
for img in glob.glob(outputFolder + "/*.JPG"):
header = {'Authorization': 'Basic ' + token.decode('utf-8')}
media = {
'file': open(img, 'rb'),
'caption': 'first API image',
'description': 'First API image'
}
print(media) #Not necessary, but allows you to track the progress
image = requests.post(url + '/media', headers = header, files = media)
imageURL = str(json.loads(image.content)['source_url'])

Originally published at https://nathankrupa.com on November 22, 2021.

--

--

Nathan John Krupa

Nathan raises money to feed the hungry. He's an indie author with two books under his belt and blogs about fundraising and the spiritual life.