Image APIを利用する
http://code.google.com/appengine/docs/images/usingimages.html
はじめに
Image APIを使うとリサイズや回転、色やコントラストの調節など標準的な変換を行うことができる。これらの変換は通常はユーザーがアップロードした画像や写真に対して行われることだろう。このドキュメントでは画像を動的にアップロードしたり変換したり保存したりする手順について説明する。Getting Started Guideにある例題Guestbookを利用して、挨拶と共にアバターをアップロードできるように改造してみよう。
画像プロパティ作成
初めにやるべきことは、ゲストブックサンプルのモデルを修正して、アップロードされる画像をBlobで保存できるようにすることだ。
class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) avatar = db.BlobProperty() date = db.DateTimeProperty(auto_now_add=True)
ユーザー画像をアップロード
次にやるのは、フォームを修正してユーザーがファイルを選択してアップロードするためのフィールドを追加することだ。また、フォームタグにenctype属性を追加して、マルチパートフォームデータであることを忘れずに指定しておくこと。
self.response.out.write(""" <form action="/sign" enctype="multipart/form-data" method="post"> <div><label>Message:</label></div> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><label>Avatar:</label></div> <div><input type="file" name="img"/><</div> <div><input type="submit" value="Sign Guestbook"></div> </form> </body> </html>""")
これでフィールドを二つ持つ簡単なフォームができた。
ここまで来たらGuestbookハンドラを変更して、フォームから画像データを受け取り、データストアにBlobとして保存できる。
class Guestbook(webapp.RequestHandler): def post(self): greeting = Greeting() if users.get_current_user(): greeting.author = users.get_current_user() greeting.content = self.request.get("content") avatar = self.request.get("img") greeting.avatar = db.Blob(avatar) greeting.put() self.redirect('/')
I'm Feeling Lucky
この「I'm Feeling Lucky」変換は暗さや明るさを強調し、色を調節してコントラストを最適なレベルにしてくれる。
Guestbookアプリケーションでは32x32のアバターを作りたい。まず初めにgoogle.appengine.api.imagesモジュールをインポートし、それからresize関数を呼んで画像データを渡してやる必要がある。
from google.appengine.api import images class Guestbook(webapp.RequestHandler): def post(self): greeting = Greeting() if users.get_current_user(): greeting.author = users.get_current_user() greeting.content = self.request.get("content") avatar = images.resize(self.request.get("img"), 32, 32) greeting.avatar = db.Blob(avatar) greeting.put() self.redirect('/')
動的画像表示(servingってどう訳せばいいんだろう・・・)
最後に/imgパスにアクセスがあったときに動的にそれらの画像を表示するImageハンドラを作成しなければいけない。またそれらの動的な画像を呼び出すようにHTMLも変更する。
class Image (webapp.RequestHandler): def get(self): greeting = db.get(self.request.get("img_id")) if greeting.avatar: self.response.headers['Content-Type'] = "image/png" self.response.out.write(greeting.avatar) else: self.error(404)
Imageハンドラではimg_idをリクエストから取得する。つまりGuestbookのHTMLを修正して、Imageハンドラにgreetingのkeyを渡す必要がある。
self.response.out.write("<div><img src='img?img_id=%s'></img>" % greeting.key()) self.response.out.write(' %s</div>' % cgi.escape(greeting.content))
これでGuestbookアプリケーションの修正は完了だ:
import cgi import datetime import wsgiref.handlers import logging from google.appengine.ext import db from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.api import images logging.getLogger().setLevel(logging.DEBUG) class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) avatar = db.BlobProperty() date = db.DateTimeProperty(auto_now_add=True) class MainPage(webapp.RequestHandler): def get(self): self.response.out.write('<html><body>') query_str = "SELECT * FROM Greeting ORDER BY date DESC LIMIT 10" greetings = db.GqlQuery (query_str) for greeting in greetings: if greeting.author: self.response.out.write('<b>%s</b> wrote:' % greeting.author.nickname()) else: self.response.out.write('An anonymous person wrote:') self.response.out.write("<div><img src='img?img_id=%s'></img>" % greeting.key()) self.response.out.write(' %s</div>' % cgi.escape(greeting.content)) self.response.out.write(""" <form action="/sign" enctype="multipart/form-data" method="post"> <div><label>Message:</label></div> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><label>Avatar:</label></div> <div><input type="file" name="img"/></div> <div><input type="submit" value="Sign Guestbook"></div> </form> </body> </html>""") class Image (webapp.RequestHandler): def get(self): greeting = db.get(self.request.get("img_id")) if greeting.avatar: self.response.headers['Content-Type'] = "image/png" self.response.out.write(greeting.avatar) else: self.response.out.write("No image") class Guestbook(webapp.RequestHandler): def post(self): greeting = Greeting() if users.get_current_user(): greeting.author = users.get_current_user() greeting.content = self.request.get("content") avatar = images.resize(self.request.get("img"), 32, 32) greeting.avatar = db.Blob(avatar) greeting.put() self.redirect('/') application = webapp.WSGIApplication([ ('/', MainPage), ('/img', Image), ('/sign', Guestbook) ], debug=True) def main(): wsgiref.handlers.CGIHandler().run(application) if __name__ == '__main__': main()