Year of the Earth Rooster

Hey look! Code samples!

Earlier today I was reminded of the importance of looking at error codes when your program doesn’t work. I was trying to convert a PNG file into a JPEG using Pillow. I read their sample code then put it in a file called pil_test.py in a virtual environment inside a directory that had a single PNG file, screenshot.png.

import os, sys
from PIL import Image

# Takes the arguments after the file name in the command below
# and "does something" with each of them...based on
# what's in the loop. "infile" isn't a great variable name,
# but I was too lazy to change it. Sorry.
# [1:] Ignores the FIRST argument.
# See https://docs.python.org/3.5/library/sys.html#sys.argv
for infile in sys.argv[1:]:
    f, e = os.path.splitext(infile) # splits file name into name and extension
    outfile = f + ".jpg" # name for new JPG file
    if infile != outfile: # If I haven't already converted this PNG...
        try:
            Image.open(infile).save(outfile)
        except IOError:
            print("cannot convert", infile)

Then I ran python pil_test.py screenshot.png and got cannot convert screenshot.png. SIDENOTE: if anyone wants me to explain what’s going on in this code, just ask me on Twitter. I threw in some quick comments

From reading another part of the docs, this told me I would need to install libjpeg to go any further. Pillow as able to read the file and manipulate it in other ways, just not convert it into a JPEG without that library. I added these lines right after the outfile line in the code above, to test that:

img = Image.open(infile)
img = img.rotate(45) # rotates image 45 degrees
img.show() # opens the image in a viewer

So, I knew I could read and manipulate the file. I used Homebrew to install libjpeg, simplified my code (commented out the try/except part) and tried again.

This time I got OSERROR: cannot write mode RGBA as JPEG. Just to be clear, there was some wailing and gnashing of teeth going on, but I’m leaving that out to streamline the story. But don’t think I’m some ultra-calm, logical coder.

Once I regained my focus, I put that error code into Google. That led me to this issue in the Pillow Github site which reminded me that the A in RGBA is the alpha channel which handles levels of transparency (RGB are for Red, Green and Blue, the colors) AND that JPEGS can’t handle the A. I knew Alpha channels were a thing, but I hadn’t realized (or had forgotten?) that JPEGs couldn’t use them. Simple solution: convert the RGBA image into an RGB image, THEN save it to a JPEG. So, adding these two lines of code after img.show() solved the problem.

img = img.convert("RGB")
img.save(outfile)

See docs on Image.convert and it’s different Mode options for more detail.

Moral of the story? Don’t panic when your code doesn’t work. Look at the error messages you get and try to understand them. If you don’t understand them fully, ask Google. 😀