指定ディレクトリ以下のすべての画像ファイルの形式を変更して保存する

指定ディレクトリ以下に存在するファイルのファイルパスを列挙するには glob を使うと簡単に取得できます。下記の記事で紹介しています。

ディレクトリ内のファイルパス一覧を取得する

いろいろな取得方法がありますが glob モジュールを使うのが簡単です。

ここでは指定ディレクトリ以下のすべてのPNG画像ファイルを JPEG 形式に変更して保存する方法を紹介します。

皆さんご存知のとおり、Pillow の open() は、ポピュラーな画像ファイル形式であれば、そのデータ内容を簡単に Image オブジェクトに読み込んでくれます。

同じく Pillow の save() というメソッドは、引数に示すファイルパスの拡張子を判断して、保存する画像ファイル形式を選択してくれます。

これを活用すると2行書くだけで、別形式のファイル保存が可能です。

from PIL import Image

im = Image.open( "test.png" )
im.save( "test.jpg" )

これを glob のファイルパスリスト列挙と組み合わせたのが下記のコードです。

import os
import glob
from PIL import Image

# リカーシブにファイルを検索しPNGファイルパスをリストアップする.
dir_target_png = "c:/tmp/my_data_256_256/**/*.png"
list_filepath_src = glob.glob( dir_target_png, recursive=True )

# ファイルの個数を表示する.
num_file = len( list_filepath_src )
print( "file num is {0}".format( num_file ) )

# 変更後のファイル拡張子.
EXT_NEW = ".jpg"

# 変更後のファイルパスのリストを初期化宣言する.
list_filepath_dst = []

# --------------------------------------------------------------------
# 変更前のファイルパスから変更後のファイルパスを作成する.
for filepath_src in list_filepath_src:

    # ファイルパスを、ディレクトリパスとファイル名に分割する.
    the_dir, filename = os.path.split( filepath_src )

    # ファイル名を、ファイルタイトルと拡張子に分割する.
    filetitle, ext = os.path.splitext( filename )

    # 拡張子を変更して新しいファイル名を作成する.
    filename_new = filetitle + EXT_NEW

    # ディレクトリパスと新しいファイル名から、新しいファイルパスを作成する.
    filepath_dst = os.path.join( the_dir, filename_new )

    # 新しいファイルパスをリストに追加する.
    list_filepath_dst.append( filepath_dst )


# --------------------------------------------------------------------
# 変更前のファイルパスと変更後のファイルパスを交互に表示する.
# counter = 0
# for filepath_src in list_filepath_src:
#     print( filepath_src )
#     print( list_filepath_dst[counter] )
#     print( "" )
#     counter += 1

# --------------------------------------------------------------------
# Pillow の open/save で画像形式を変更して保存する.
counter = 0
for filepath_src in list_filepath_src:
    # 画像ファイルを開く.
    im = Image.open( filepath_src )

    # 画像ファイルを保存する.
    im.save( list_filepath_dst[counter] )
    counter += 1

# --------------------------------------------------------------------

# リカーシブにファイルを検索し、すべてのファイルパスをリストアップする.
dir_target_all = "c:/tmp/my_data_256_256/**/*.*"
list_filepath_all = glob.glob( dir_target_all, recursive=True )

# ファイルの個数を表示する.
num_file = len( list_filepath_all )
print( "file num is {0}".format( num_file ) )


print( "finished." )

下記がコンソール実行結果です。ファイルの個数を確認すると2倍になっているはずです。

PS C:\tmp> python test.py
file num is 100
file num is 200
finished.