Skip to page content Skip to main navigation
English | Site Directory

e.g. "templates" or "datastore"

# Using the Images Python API

## Introduction

The Images API enables you perform common transforms on images like resizing, rotating and adjusting their color and contrast. These tranforms generally happen in the context of a user uploaded image or photo. This document describes the process of uploading, transforming, storing and serving images dynamically. We'll use the Guesbook example from the getting started guide and modify it to let a user upload an avatar with their greeting.

- Creating a image property
- Uploading User Images
- Transforming Images
- Dynamically serving images

## Creating a image property

The first thing we need to do is update the model from the guestbook sample to store the uploaded image as a blob.

    class Greeting(db.Model):
      author = db.UserProperty()
      content = db.StringProperty(multiline=True)
      avatar = db.BlobProperty()
      date = db.DateTimeProperty(auto_now_add=True)

## Uploading User Images

Next we'll modify the form to add another field that enables the user to select a file from their computer to upload. We'll also have to add a the `enctype` attribute to the form tag to specify that we want this to be a multi-part form post.

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

This should give us a simple form with two fields.

At this point we are also going to want to update the Guestbook handler to get the image data from the form post and store it as a Blob in the datastore.

    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('/')

## Transforming Images

The Images API enables you to transform your images in a few different ways.

#### Resize

You can resize the image while maintaining the same aspect ratio.

#### Rotate

You can rotate the image in 90 degree increments.

#### Flip Horizontally

You can flip the image horizontally.

#### Flip Vertically

You can flip the image vertically.

#### Crop

You can crop the image with a given bounding box.

#### I'm Feeling Lucky

The "I'm Feeling Lucky" transform enhances dark and bright colors in an image and adjusts both color and contrast to optimal levels.

For the Guestbook application we are going to create 32x32 avatars. First we have to import the `google.appengine.api.images` module. Then all we have to do is call the `resize` function and pass in the image data.

    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('/')

## Dynamically serving images

Finally we have to create a Image handler that will dynamically serve these images off the `/img` path. We'll also update the HTML to pull in these dynamically served images.

    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)

In the Image Handler we get the `img_id` from the request. We'll need to update the HTML of the Guestbook to pass the key of the greeting to the Image handler

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

We now have completed our modified Guestbook application:

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