PILで画像の変換

PIL(python imaging library)を使って画像の変換をやってみる。
http://www.pythonware.com/library/index.htm
ここにチュートリアルやリファレンスがあるので、たいへん学びやすい。

画像ファイルの形式をjpegに変換する

まず、画像ファイルの形式をjpegに変換する。以下のスクリプトconv.pyを作成しておく。

import os, sys
import Image

for infile in sys.argv[1:]:
    f, e = os.path.splitext(infile)  # ファイルの拡張子を取り出す。
  outfile = f + ".jpg"
    if infile != outfile:
        try:
            Image.open(infile).save(outfile)
        except IOError:
            print "cannot convert", infile

最初にpngファイルとbmpファイルを用意しておく。これらを上のスクリプトjpegファイルに変換する。実行方法は、

$ python conv.py sun1.png sun2.bmp

とする。これで、sun1.jpgファイルが作成される。sun2.jpgファイルは作成されない。なぜ?
詳細に見ていくと、bmpファイルのオープンはできるが、jpgファイルにセーブするところでエラーになる。

>>> im = Image.open("sun.bmp")
>>> im
<BmpImagePlugin.BmpImageFile instance at 0x7f4feaae0f38>
>>> im.save("sgks.jpg")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.5/site-packages/PIL/Image.py", line 1406, in save
    save_handler(self, fp, filename)
  File "/usr/lib/python2.5/site-packages/PIL/JpegImagePlugin.py", line 390, in _save
    raise IOError("cannot write mode %s as JPEG" % im.mode)
IOError: cannot write mode P as JPEG

原因は、このへんの話(http://d.hatena.ne.jp/perezvon/20090421/1240307348)ですね。カラーモードがPモードなので、いけないらしい。Pモードなんてあるのだな。そこで、修正した完全版のconv.pyは、

import os, sys
import Image

for infile in sys.argv[1:]:
    f, e = os.path.splitext(infile)
    outfile = f + ".jpg"
    im = Image.open(infile)

    if infile != outfile:
        try:
            if im.mode != "RGB":
                im = im.convert("RGB") # RGBモードに変換する
            im.save(outfile)
        except IOError:
            print "cannot convert", infile

となる。jpeg以外の形式で保存する場合は、拡張子jpgのところを変えればいい。

画像ファイルのサムネイルを作成する

画像ファイルの縮小版を作成する。以下のスクリプトthumbnail.pyでできる。

import os, sys
import Image

size = 64, 64

for infile in sys.argv[1:]:
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    if infile != outfile:
        try:
            im = Image.open(infile)
      if im.mode != "RGB":
                im = im.convert("RGB")
            im.thumbnail(size)
            im.save(outfile, "JPEG")
        except IOError:
            print "cannot create thumbnail for ", infile

実行方法は、

$ python thumbnail.py sun.png
$ \ls
sun.png sun.thumbnail

とする。単にresizeで縮小した場合と何が違うのだろうか。

  • thumbnail(64, 64)とすると、64x64で画像が保存される。
  • resize(64, 64)としても、保存される画像は、280x280になる。

なぜ?