My favorites | 中文(简体) | Sign in

使用图像 API

简介

图像 API 使您能够对图像执行一些常见的变换操作,比如调整大小、旋转以及调整颜色和对比度。通常,是对用户上传的图像或照片执行这些变换。本文档介绍了上传、变换、存储以及动态提供图像的过程。我们将使用《使用入门指南》中的留言簿示例并对其进行修改以使用户可上传带有自己问候语的头像。

创建图像属性

我们需要做的第一件事情就是更新留言簿示例中的模型,以将上传的图像存储为二进制大对象。

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>""")

这应当提供给我们一个包含两个字段的简单表单。

此时,我们还希望更新留言簿处理程序,以从表单帖子中获取图像数据,并将其作为 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('/')

变换图像

图像 API 可让您用几种不同的方式变换图像。

缩放

您可在保持纵横比不变的同时缩放图像。

  

旋转

您每次可以旋转图像 90 度。

  

水平翻转

您可以水平翻转图像。

  

垂直翻转

您可以垂直翻转图像。

  

裁剪

您可以使用指定的边框裁剪图像。

  

手气不错

[手气不错] 变换功能可增强图像的暗度和亮度,并可将颜色和对比度调整到最佳水平。

  

对于留言簿应用程序,我们将创建 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('/')

动态提供图像

最后,我们需要创建一个图像处理程序,该程序将在 /img 路径之外动态提供这些图像。我们还将更新 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)

在图像处理程序中,我们从请求中获取 img_id。我们将需要更新留言簿的 HTML 以将问候语的键传递到该图像处理程序

self.response.out.write("<div><img src='img?img_id=%s'></img>" %
                              greeting.key())
self.response.out.write(' %s</div>' %
                              cgi.escape(greeting.content))

现在我们已完成修改的留言簿应用程序:

import cgi
import datetime
import logging

from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
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():
  run_wsgi_app(application)


if __name__ == '__main__':
  main()