Created
March 20, 2013 17:24
-
-
Save jawache/5206573 to your computer and use it in GitHub Desktop.
Using PIL on Google App Engine to manipulate images and store inthe blobstore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-gb" lang="en-gb"> | |
<head> | |
<title>Hello World</title> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | |
</head> | |
<body> | |
{% block content %} | |
{% endblock %} | |
</body> | |
</html> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
__author__ = "Asim Hussain" | |
__copyright__ = "Copyright 2012, RT Sports Ltd. All Rights Reserved" | |
""" | |
import logging | |
LOGGER = logging.getLogger(__name__) | |
from django import forms | |
class PhotoForm(forms.Form): | |
name = forms.CharField(required=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from google.appengine.ext import blobstore | |
from google.appengine.ext import db | |
class LogoItem(db.Model): | |
name = db.StringProperty() | |
original = blobstore.BlobReferenceProperty() | |
enhanced = blobstore.BlobReferenceProperty() | |
transparent = blobstore.BlobReferenceProperty() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends "base.html" %} | |
{% block content %} | |
<style type="text/css"> | |
h1 { | |
font-family: "Helvetica Neue Light", sans-serif; | |
} | |
body { | |
background-color: black; | |
color: white;; | |
} | |
</style> | |
<h1>Original Logo</h1> | |
<img src="{{ original }}"/> | |
<h1>Transparent Logo</h1> | |
<img src="{{ trans }}"/> | |
<h1>Enhanced Transparent Logo</h1> | |
<img src="{{ enhanced }}"/> | |
<h1>Enhanced Transparent Thumbnail Logo</h1> | |
<img src="{{ thumbnail }}"/> | |
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% extends "base.html" %} | |
{% block content %} | |
<h1>Upload Photo</h1> | |
{% if upload_error %} | |
<div class="error">{{ upload_error }}</div> | |
{% endif %} | |
<form action="{{ upload_url }}" method="post" | |
enctype="multipart/form-data"> | |
{% csrf_token %} | |
<ul> | |
{{ form.as_ul }} | |
<li><input type="file" name="photo"/></li> | |
<li><input type="submit"/></li> | |
</ul> | |
</form> | |
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import cStringIO | |
from django.core.urlresolvers import reverse | |
from django.http import HttpResponseRedirect | |
from django.shortcuts import render_to_response, redirect | |
from django.template import RequestContext | |
from google.appengine.api import files, images | |
from google.appengine.api.images import get_serving_url, Image | |
from google.appengine.ext import blobstore, db | |
from PIL import Image as PILImage | |
from core.models import LogoItem | |
from core.forms import PhotoForm | |
from core.utils import get_uploads | |
def success(request): | |
key_name = request.GET.get("key_name") | |
key = db.Key.from_path('LogoItem', key_name) | |
logoitem = db.get(key) | |
context = dict( | |
original = get_serving_url(logoitem.original), | |
enhanced = get_serving_url(logoitem.enhanced), | |
thumbnail = get_serving_url(logoitem.enhanced, crop=True, size=32), | |
trans = get_serving_url(logoitem.enhanced) | |
) | |
return render_to_response("success.html", | |
context, | |
RequestContext(request)) | |
def upload_photo(request): | |
if request.method == 'POST': | |
photo_blobs = get_uploads(request, field_name="photo", populate_post=True) | |
form = PhotoForm(request.POST) | |
if form.is_valid() and len(photo_blobs) == 1: | |
name = form.cleaned_data['name'] | |
logo = photo_blobs[0] | |
im = PILImage.open(logo.open()) | |
im = im.convert("RGBA") | |
pixdata = im.load() | |
for y in xrange(im.size[1]): | |
for x in xrange(im.size[0]): | |
if pixdata[x, y] == (255, 255, 255, 255): | |
pixdata[x, y] = (255, 255, 255, 0) | |
buf = cStringIO.StringIO() | |
im.save(buf, "PNG") | |
data = buf.getvalue() | |
# Save transparent image back to blobstore | |
transparent_file = files.blobstore.create(mime_type='image/png') | |
with files.open(transparent_file, 'a') as f: | |
f.write(data) | |
files.finalize(transparent_file) | |
# Enhance Transparent Logo | |
img = Image(blob_key=files.blobstore.get_blob_key(transparent_file)) | |
img.im_feeling_lucky() | |
enhanced = img.execute_transforms(output_encoding=images.PNG) | |
# Save enhanced image back to blob store | |
enhanced_file = files.blobstore.create(mime_type='image/png') | |
with files.open(enhanced_file, 'a') as f: | |
f.write(enhanced) | |
files.finalize(enhanced_file) | |
photo_item = LogoItem(key_name=name, | |
name=name, | |
original=logo, | |
enhanced=files.blobstore.get_blob_key(enhanced_file), | |
transparent=files.blobstore.get_blob_key(transparent_file)) | |
photo_item.put() | |
return redirect("success/?key_name=%s" % name) | |
#ok, not valid | |
if len(photo_blobs) == 0: | |
#the file input is missing | |
request.session['upload_error'] = "Photo is required" | |
#save the post data in the session to be able to present errors after redirect | |
request.session['upload_form_post'] = request.POST | |
return HttpResponseRedirect(reverse("core.views.upload_photo")) | |
elif request.session.has_key('upload_form_post'): | |
form = PhotoForm(request.session['upload_form_post']) | |
del request.session['upload_form_post'] | |
else: | |
form = PhotoForm() | |
params = { | |
'upload_url': blobstore.create_upload_url(reverse("core.views.upload_photo")), | |
'form': form, | |
'upload_error': request.session.pop('upload_error', None) | |
} | |
return render_to_response("upload_photo.html", | |
params, | |
RequestContext(request)) | |
def exception_test(request): | |
logging.debug('Debug log') | |
logging.warn('Warn log') | |
logging.error('Error log') | |
raise Exception() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment