Skip to content

App Engine’s High-Performance Image Serving

Real quick blog post while I eat my lunch….

Google released a SDK 1.3.6 for App Engine yesterday: Google App Engine Blog: Multi-tenancy Support, High Performance Image Serving, Increased Datastore Quotas and More Delivered In New App Engine Release. Of particular interest to me was the High Performance Image Serving.

High-Performance Image Serving This release also includes a new, high-performance image serving system for your applications, based on the same infrastructure we use to serve images for Picasa. This feature allows you to generate a stable, dedicated URL for serving web-suitable image thumbnails … This special URL can serve that image resized and/or cropped automatically, and serving from this URL does not incur any CPU or dynamic serving load on your application (though bandwidth is still charged as usual).

So I store some images in an App Engine blob, pass this to get_serving_url and Google give me back a URL for the ‘high performance’ location. I was just interested to see what the URL would look like, and where it would actually be hosted. So I whipped up something real quick to grab the URL ..and here’s what it looks like:

http://lh5.ggpht.com/FIl4UGix2IbadeLOotXq2CgIF4Wi4xUSaSegSDSrfnIy5YyQlZWWaPcDRhyxkJTGepVkxNHUVcv8o1_1zWazbg=s200

Note this URL has the “=s200” parameter to scale the image down to 200px wide. You can also pass along a crop parameter to crop the image down to a small square, e.g: =s200-c

The code is a hacked up version of the image upload and blob storage examples.

from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.api import images
from google.appengine.api import urlfetch
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

class ImageModel(db.Model):
    image = db.BlobProperty()
		


class MainPage(webapp.RequestHandler):
	def get(self):
		upload_url = blobstore.create_upload_url('/upload')

		self.response.out.write("""<html><head><title>High Performance Image Tester</title></head>""");
		self.response.out.write("""<body>""");
		self.response.out.write("""
				<form action="%s" enctype="multipart/form-data" method="post">
				<div><label>Image:</label></div>
				<div><input type="file" name="file"/></div>
				<div><input type="submit" value="Upload"></div>
				</form>
			</body>
			</html>""" % upload_url)


class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files = self.get_uploads('file')  # 'file' is file upload field in the form
        blob_info = upload_files[0]
        self.redirect('/serve/%s' % blob_info.key())

class ServeHandler(webapp.RequestHandler):
	def get(self,resource):
		self.response.out.write("%s %s %s" % (images.get_serving_url(resource, 32),
		images.get_serving_url(resource, 150),
		images.get_serving_url(resource, 80)))

application = webapp.WSGIApplication(
	[('/', MainPage),
	('/upload', UploadHandler),
	('/serve/([^/]+)?', ServeHandler)],

	debug=True)

def main():
	run_wsgi_app(application)

if __name__ == "__main__":
	main()

{ 1 } Comments

  1. Kyle | August 26, 2010 at 1:00 am | Permalink

    Check out:
    http://www.answercow.com/q/304002/app-engines-high-performance-image-serving-system

    for some performance comparisons of the new high perf image serving vs serving images from the blobstore.

Post a Comment

Your email is never published nor shared. Required fields are marked *