(104) 「PILで写真に日付を入れる」をWEBサービス化

(104) 「PILで写真に日付を入れる」をWEBサービス化

1. やりたいこと

Pythonは WEBとの親和性が高い。

よって…
先に書いた (102) PILで写真に日付を入れる をWEBブラウザから実行できるようにする。

それだけ…

2. 仕様

1) WEBブラウザから画像ファイルをアップロードする。
2) CGIで Pythonプログラムを起動する。
3) アップロードされた画像ファイルの EXIF情報から撮影日を抽出する。
4) アップロードされた画像ファイルを幅 640pxにリサイズする。
5) アップロードされた画像ファイルの右下に日付を埋め込む。
6) 処理後の画像を WEBブラウザに表示する。
7) 今回は排他制御は考えない。

3. やってみる

出来上がった物はこちら。
https://www.dogrow.net/python/sample/0104/

処理の詳細は (102) PILで写真に日付を入れる に記してある。

index.cgi
サーバーにアップロード後、当該ファイルに実行属性を付与すること。
出力ファイル名はなるべく散らばるように時刻値とプロセスIDを使用している。(※不完全な排他)

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
print 'Content-type: text/html'

import os
import cgi
from datetime import datetime
import mylib

print """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>サンプル No.104</title>
</head>
<body>
"""

form = cgi.FieldStorage()
if form.has_key('upfile'):     # formから投稿された情報 upfile あり?
    item = form['upfile']
    if item.file:              # upfile はアップロードされたファイル?
        img_path = './%s_%d_%s' % (datetime.now().strftime("%s"), os.getpid(), item.filename)
        mylib.save_img(item, img_path)       # 投稿ファイルを保存
        if True == mylib.exec_put_date(img_path) :   # 投稿画像ファイルに日付を書く
            print('<img src="' + img_path + '">')    # 出来上がった画像を表示
        else:
            os.remove(img_path)   # 失敗したならばアップロードファイルを削除

# 投稿フォームを表示
print """
<form enctype="multipart/form-data" action="./index.cgi" method="post">
  <input type="file" name="upfile">
  <input type="submit" value="実行">
</form>
</body>
</html>
"""

mylib.py

from PIL import Image, ImageDraw, ImageFont

########################################################################
class MyError(Exception):
    pass

########################################################################
def save_img( item, save_path ):
    fout = file(save_path, 'wb')
    while True:
        chunk = item.file.read(1000000)
        if not chunk:
            break
        fout.write(chunk)
    fout.close()

########################################################################
def resize_img( img ):
    w,h = img.size
    w_new = 640
    h_new = h * w_new / w
    imgR = img.resize((w_new, h_new), resample=Image.ANTIALIAS)
    return imgR

########################################################################
def exec_put_date( filepath ):
    ret = False
    try:
        img = Image.open(filepath)
        exif = img._getexif()
        if None == exif :
            raise MyError('No exif')

        if False == 36867 in exif :
            raise MyError('No DateTimeOriginal in exif')

        text_datetime = exif[36867]
        text_date = text_datetime.split()[0]
        text_date = text_date.replace(':','-')

        img = resize_img(img)
        pos_x = img.size[0] - 150
        pos_y = img.size[1] - 30

        obj_draw = ImageDraw.Draw(img)
        obj_font = ImageFont.truetype("./ipagp.ttf", 24)
        obj_draw.text((pos_x+1, pos_y+1), text_date, fill=(0, 0, 0),     font=obj_font)
        obj_draw.text((pos_x,   pos_y),   text_date, fill=(255, 160, 0), font=obj_font)

        img.save(filepath)
        ret = True

    except MyError as e:
        print('<p style="color:#f00">%s</p>' % e.message)

    except IOError:
        print('<p style="color:#f00">Invalid file</p>')

    return ret

できた!


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*