🖼️

画像に枠線をつけてくれるWEBアプリを作る

2023/08/07に公開

はじめに

昨日はpythonのpillowを使って画像に外枠を追加しました。
https://zenn.dev/not75743/articles/718e72a20453ff

今回はこれをWebアプリにして使いやすくしてみました。
環境はDocker(compose)、フレームワークはFlaskです。

どんなアプリ?

このようなアクセスして枠線をつけたい画像をアップロードすると

枠線をつけたものをダウンロードすることができます。

環境

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS"

$ docker --version
Docker version 24.0.5, build ced0996

$ docker compose version
Docker Compose version v2.20.2

コード

ディレクトリ構成

.
├── app
│   ├── app.py
│   └── templates
│       └── index.html
├── docker-compose.yaml
├── Dockerfile
└── requirements.txt

Dockerfile(略)

Dockerfile
Dockerfile
FROM python:3.11.4-slim-bookworm

ENV FLASK_APP=app
ENV FLASK_RUN_HOST=0.0.0.0

WORKDIR /app

COPY requirements.txt requirements.txt
RUN pip install --upgrade pip && \
    pip install -r requirements.txt

requirements.txt

Flask==2.3.2
Pillow==10.0.0

docker-compose.yaml(略)

docker-compose.yaml
docker-compose.yaml
version: '3'

services:
  web:
    build: .
    command: flask run
    ports:
      - "5000:5000"
    volumes:
      - ./app:/app

app.py

app.py
from flask import Flask, render_template, request, send_file
from PIL import Image, ImageOps
import os

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/process_image', methods=['POST'])
def process_image():
  image_file = request.files['image']
  if image_file:

    image = Image.open(image_file.stream)
    bordered_image = ImageOps.expand(image, border=1, fill='black')
    
    temp_file = "temp_image.png"
    bordered_image.save(temp_file)

    response = send_file(temp_file, as_attachment=True, download_name=f"bordered_{image_file.filename}")
    os.remove(temp_file)

    return response

if __name__ == '__main__':
    app.run(debug=True)

index.html

index.html
<!DOCTYPE html>
<html>
<head>
    <title>Wakusen App</title>
</head>
<body>
    <h1>Wakusen App</h1>
    <form action="/process_image" method="post" enctype="multipart/form-data">
        <input type="file" name="image" accept="image/*" required>
        <input type="submit" value="Upload and Process Image">
    </form>
</body>
</html>

立ち上げ

Dockerfile,composeファイルのあるディレクトリで

docker compose up -d --build

を実行

処理の流れ

  1. フォーム送信
  2. process_image関数呼び出し
  3. フォームから画像ファイルの取得
    • request.files['image']でname属性imageのファイルを取得
  4. 取得した画像ファイルに枠線追加
  5. 画像の一時保存
    • 後続のsend_fileでクライアントにファイルを送るため
  6. 一時ファイルの削除
    • os.remove(temp_file)箇所です。これを行わないと一時ファイルがたまり続けます。
  7. 画像のダウンロード
    • send_fileで加工したファイルをクライアントに送付する
    • ダウンロードしたファイルの名前はbordered_<元のファイル名>となる。

おわりに

最低限webアプリとして立ち上げることが出来たのではないでしょうか。
さっそく使ってZennの添付画像をわかりやすくしたいです。

参考

request.filesでの画像取得
https://flask.palletsprojects.com/en/2.3.x/patterns/fileuploads/
https://qiita.com/fghyuhi/items/d42ce8cb1f5de5280ac5

send_fileでのファイルダウンロード
https://tedboy.github.io/flask/generated/flask.send_file.html
https://www.tsubock-lab.xyz/entry/2021/01/31/235326

ImageOps.expandでの枠線追加
https://zenn.dev/not75743/articles/718e72a20453ff

Discussion