/ programming

Creating thumbnails

Some time ago during next "refactoring" on http://lastlog.it i wanted to change something with creating images thumbnails. Originally i was using Pillow. I can't say anything bad except problems with GIF animations
(http://stackoverflow.com/questions/9988517/resize-gif-animation-pil-imagemagick-python). I was curious how imagemagick
will work. I have made some small tests. On lastlog.it i want only resizing images and adding logo at the bottom
so my tests are based only on those operations.

Images.

[email protected]:~/Downloads/images$ du -b {1,2,3,4,5,6,7,8}*
1470219 1.jpg
1784484 2.jpg
637483  3.jpeg
4601465 4.jpeg
2574772 5.jpeg
3125064 6.png
369206  7.gif # Animated GIF
1378203 8.gif # Animated GIF

[email protected]:~/Downloads/images$ du -sh {1,2,3,4,5,6,7,8}*
1.5M    1.jpg
1.8M    2.jpg
624K    3.jpeg
4.4M    4.jpeg
2.5M    5.jpeg
3.0M    6.png
364K    7.gif # Animated GIF
1.4M    8.gif # Animated GIF

I have created two small scripts for creating thumbnails.

Script 1.

import argparse
from PIL import Image


parser = argparse.ArgumentParser()
parser.add_argument('-i', type=str, dest='input')
args = parser.parse_args()

size = 800, 600

image = Image.open(args.input)
image.thumbnail(size, Image.ANTIALIAS)
image.save('pil_' + args.input, format=image.format, quality=85)

Script 2.

import argparse
from subprocess import Popen, PIPE


parser = argparse.ArgumentParser()
parser.add_argument('-i', type=str, dest='input')
args = parser.parse_args()

size = 800, 600

Popen([
    '/usr/bin/convert',
    args.input,
    '-resize',
    "800x>",
    '-quality',
    '85%',
    'im_' + args.input
], stdout=PIPE, stderr=PIPE)

Times.

Image  | Pillow   | Imagemagick
------ | -------- | ------
1.jpeg | 0m0.172s | 0m0.031s
2.jpg  | 0m0.163s | 0m0.035s
3.jpeg | 0m0.153s | 0m0.025s
4.jpeg | 0m0.399s | 0m0.025s
5.jpeg | 0m0.185s | 0m0.053s
6.png  | 0m0.631s | 0m0.025s
7.gif  | 0m0.045s | 0m0.025s
8.gif  | 0m0.052s | 0m0.027s

Sizes.

[email protected]:~/Downloads/images$ du -b pil*
62514   pil_1.jpg
109483  pil_2.jpg
72873   pil_3.jpeg
28738   pil_4.jpeg
66020   pil_5.jpeg
827467  pil_6.png
286485  pil_7.gif # Does not work
321766  pil_8.gif # Does not work

[email protected]:~/Downloads/images$ du -b im*
61400   im_1.jpg
107962  im_2.jpg
72091   im_3.jpeg
54545   im_4.jpeg
67292   im_5.jpeg
742881  im_6.png
360580  im_7.gif # Works correctly
1361856 im_8.gif # Works correctly

Next test. Resize and add logo at the bottom of image.

Script 1.

import argparse
from PIL import Image


parser = argparse.ArgumentParser()
parser.add_argument('-i', type=str, dest='input')
args = parser.parse_args()

size = 800, 600

image = Image.open(args.input)
logo_image = Image.open('logo.jpg')

background = '#F9F9F9'

image_width, image_height = image.size
logo_width, logo_height = logo_image.size
image_new = Image.new(
    "RGB",
    (image_width, image_height + logo_height),
    background
)
image_new.paste(image, (0, 0, image_width, image_height))
image_new.paste(
    logo_image, (image_width - logo_width, image_height)
)
image_new.save(
    'pil_logo_' + args.input,
    format=image.format,
    quality=85
)

Script 2.

import argparse
from subprocess import Popen, PIPE


parser = argparse.ArgumentParser()
parser.add_argument('-i', type=str, dest='input')
args = parser.parse_args()

size = 800, 600
background = '#F9F9F9'

Popen([
    '/usr/bin/convert',
    args.input,
    'logo.jpg',
    '-resize',
    "800x>",
    '-background',
    background,
    '-gravity',
    'SouthEast',
    '-quality',
    '85%',
    '-append',
    'im_logo_' + args.input
], stdout=PIPE, stderr=PIPE)

Times.

| Image  | Pillow   | Imagemagick|
| ------ | ------   | ---------- |
| 1.jpeg | 0m0.267s | 0m0.043s   |
| 2.jpg  | 0m0.267s | 0m0.041s   |
| 3.jpeg | 0m0.267s | 0m0.028s   |
| 4.jpeg | 0m3.386s | 0m0.039s   |
| 5.jpeg | 0m1.401s | 0m0.104s   |
| 6.png  | 0m0.662s | 0m0.042s   |
| 7.gif  | 0m0.095s | 0m0.041s   |
| 8.gif  | 0m0.170s | 0m0.043s   |

In the second test Pillow is better that Imagemagick only for processing GIF animations. Imagemagick broke images but i think
that it is caused by missing options in my commands.

I didn't test more cases because i don't need them now. Conclusions from my tests?

Pillow pros:

  • python (Imagemagick also has python api but i don't had time and willing for testing it)

Pillow cons:

  • need more code
  • slower
  • problems with GIF animations

Imagemagick cons:

  • subprocess (as I mentioned - I can use api python, maybe in the future i will test it)

Imagemagick pros:

  • faster
  • less code
  • can change size of GIF animations
  • images looks better after resizing and adding logo (with current options)

At the moment I will stay with Imagemagick.