Python image library magic

Python's standard library is full of useful utilities. One of which is the Python Image library called Pil for short. There's also a fork of this called Pillow for Python 3 which has lots of capabilities.

So lets say we have a bunch of photos on a webserver and they're all pretty big. About 7Mb would be a typical size for a hi-resolution Jpeg file. Usually you'd want to make thumbnails of those files to have a superfast user browsing experience while loading the pics. There's lots of ways to do this of course , you can use image editing software at the time of the picture generation, you could use a javascript library and force that process onto the browser or you can generate them at build time. ` In my usecase the webserver in question is an object store, a Caringo based one in fact. I've uploaded an image to a bucket and its about 7MB.

This duck

The original is a resolution of 6000x1000 which is 7.5 mb in size. A big image to push through a browser. On this page i'm using the gatsby image plugin to resize and refactor the image so its pretty small but if you had a live site generating those static assets in place can be useful.

Here's a method to do that on a caringo object store without downloading every image to disk. I've comments inline to explain step by step.

# this is our import of the python image library the bit that understands what we're looking at.
from PIL import Image

# This is the BytesIO library, we're going to read the raw body of the file into a bytestream for the image library to understand
from io import BytesIO

# The humble requests library, this will to the heavy lifting of reading a weburl and posting to the same location. 
import requests


#For this example i'm just pointing to a single file and we're not going to 
#confuse things by adding authentication or session handle, super simple.
url = "https://tlokko.cloud.caringo.com/imagetest/duck.jpg"
#this is the url for the bucket path. Will use this when posting the new thumbnail image.
url2 = "https://tlokko.cloud.caringo.com/imagetest"


#Inital request to get the file as a stream directly 
#https://pillow.readthedocs.io/en/4.2.x/releasenotes/2.8.0.html
response = requests.get(url, stream=True)
response.raw.decode_content = True

#Then we can open the file-like object and the print is to show the details.
img = Image.open(response.raw)
print(img)

#here we create a new variable for our image and create a copy.
new_img = img.copy()
#the img.thumbnail operation modifies the object in place (thats why we made a copy)
new_img.thumbnail((300,300), Image.ANTIALIAS)
#now we create a filelike object in memory and stream the contents of our 'new_img' to it.
byte_io = BytesIO()
new_img.save(byte_io, 'jpeg')
byte_io.seek(0)

#then we post the request to Swarm using our filelike byte_io object.

x = requests.post(url2, files={'files': ('smallerduck.jpg', byte_io,'image/jpeg')})
#to finish off we print out the return code for the post. 
print(x.status_code)

So this little script shows a method to read an image into memory then copy and resize it using the thumbnail option in pythons PIL library. You could expand it by say getting a list of all items in a bucket and creating a thumbnail for each. Or create a small , medium and large version of each file and store them in different paths.

The from the storage side that path was wide open zero authentication so the simplest addition would be to add some token or basic authentication to the requests which is easily done and will be covered in another post.


By Tony Lokko