0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Pythonで画像圧縮とwebp画像生成をする

Posted at

経緯

Webサイトを制作していく過程で画像の圧縮、webp画像を作る際に

という手順で作業を行った。

小規模なサイトならいいのですが、大規模なサイトや環境を組んでも共有できない事情があるなどを考えツールを作成してみた。

開発環境

  • Windows10
  • Python 3.9.5

目標

  1. 複数のJPG, PNG画像を圧縮してくれる
  2. 複数のJPG, PNG画像からWebp画像を生成してくれる
  3. エンジニア以外の環境構築ができない人でも作業を行うことができる

3を考えたときにWebブラウザで動作するかGUIを作ってアプリケーションとするか悩ましいが
今回はPythonを勉強中ということもあり、デスクトップで使用できるアプリケーションを作成する。

完成品

/dist/image_controller.exeに完成品が入っている

image.png

  • パスに圧縮・変換する画像が格納されているディレクトリを指定する
  • webp画像に変換したい場合はチェックボックスにチェックをいれる

使用するライブラリ

  • Pillow
    • リサイズや圧縮など画像の処理を行う
  • PySimpleGUI
    • 簡単にGUIを実装する
  • glob
    • Pythonインストール時にデフォルトでインストールされる
  • os
    • Pythonインストール時にデフォルトでインストールされる

事前準備

$ pip install Pillow
$ pip install pysimplegui

実装

必要なライブラリを読み込む

# 画像圧縮のライブラリをImportする
from PIL import Image, ImageFilter

# ファイルを取得するためのライブラリをImportする
import glob
import os

#GUI生成するライブラリをImportする
import PySimpleGUI as sg

画像の圧縮をするソース

# 圧縮のクオリティ
quality = 70

# 画像が格納されているディレクトリを指定する
path = 'path/to/dir'
files = glob.glob(path + '/*')

# ディレクトリ内の画像をループで処理する
for file in files :
  # 画像の情報を取得
  image = Image.open(file)
  
  # 画像を圧縮してセーブする
  image.save(path  + '/' + os.path.split(file)[1], optimize=True, quality=quality)

JPG, PNGをwebp画像として保存する

# 画像が格納されているディレクトリを指定する
path = 'path/to/dir'
files = glob.glob(path + '/*')

# ディレクトリ内の画像をループで処理する
for file in files :
  image.save(path + '/' + os.path.split(file)[1].split('.')[0] + '.webp', 'webp')

これで圧縮、webp画像の生成ができる

GUIを実装する

# GUIのテーマを選択する
sg.theme('Reddit')

# GUIに必要な要素を配列で格納する
layout = [
            [sg.Text('  パス'), sg.InputText(key='path', size=(40,8))],
            [sg.Text('webp画像を生成する'), sg.Checkbox('',key='is_webp', default=False)],
            [sg.Text('実行結果'),sg.MLine(key='output'+sg.WRITE_ONLY_KEY, size=(40,8))],
            [sg.Button('実行')]
          ]

# Windowを生成する
window = sg.Window(title='Image controller', layout=layout)

# Window内の処理を記載する
while True:
    event, values = window.read()

    # Windowが閉じられたときの処理
    if event == sg.WINDOW_CLOSED or event == 'Quit':
        break

    # ここに実行をクリックしたときの処理を記載する
    # syori();

GUIの実装を行っただけでPythonファイルを実行すると完成品のような見た目のGUIができる

組み合わせて一つのPythonファイルにする

# ------------------------------ Settings ------------------------------ #

# 画像圧縮のライブラリ
from PIL import Image, ImageFilter

# ファイルを取得するためのライブラリ
import glob
import os

#GUI
import PySimpleGUI as sg

# ------------------------------ Config ------------------------------ #

# 圧縮のクオリティ
quality = 70

# GUI
sg.theme('Reddit')

layout = [
            [sg.Text('  パス'), sg.InputText(key='path', size=(40,8))],
            [sg.Text('webp画像を生成する'), sg.Checkbox('',key='is_webp', default=False)],
            [sg.Text('実行結果'),sg.MLine(key='output'+sg.WRITE_ONLY_KEY, size=(40,8))],
            [sg.Button('実行')]
          ]
window = sg.Window(title='Image controller', layout=layout)

# テーマの確認
# sg.preview_all_look_and_feel_themes()

# ------------------------------ 画像圧縮の処理 ------------------------------ #

def compression(file) :
  # 画像の情報を取得
  # フォーマット image.format
  # サイズ image.size
  # カラーモード image.mode
  image = Image.open(file)
  
  # 画像を圧縮してセーブする (values['path']でGUIで入力したパスが取得できる)
  image.save(values['path'] + '/' + os.path.split(file)[1],optimize=True,quality=quality)

  # メッセージをGUIに表示する
  window['output'+sg.WRITE_ONLY_KEY].print(os.path.split(file)[1] + ' is compressed.')

def initalizeWebp(file) :
  image = Image.open(file)

  # webpに変換してセーブする  (values['path']でGUIで入力したパスが取得できる)
  image.save(values['path'] + '/' + os.path.split(file)[1].split('.')[0] + '.webp', 'webp')

  # メッセージをGUIに表示する
  window['output'+sg.WRITE_ONLY_KEY].print(os.path.split(file)[1] + ' is initalize webp image.')

# ------------------------------ GUIの処理 ------------------------------ #

# Windowの処理
while True:
    event, values = window.read()

    # See if user wants to quit or window was closed
    if event == sg.WINDOW_CLOSED or event == 'Quit':
        break
    
    files = glob.glob(values['path'] + '/*')

    for file in files :
      compression(file)
      
      # チェックボックスがチェックされていたら実行
      if (values['is_webp'] == True) :
        initalizeWebp(file)

参考サイト

https://note.com/kohaku935/n/n721e5e620839
https://qiita.com/dario_okazaki/items/656de21cab5c81cabe59

PySimpleGUIは公式のドキュメントがわかりやすく書いてあるので参考になります。
https://pysimplegui.readthedocs.io/en/latest/

補足

Pythonファイルのexe化は以下のツールを使用しています。

  • pyinstaller

以下サイトを参考にしています。
https://techacademy.jp/magazine/18963

結構導入~実行まで簡単だったのでおすすめです。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?