画像を指定のサイズに切り取る(よきにはからう感じで)

image_key : 画像を指定
w : 欲しい横幅
h : 欲しい縦幅

models.py

from django.utils.translation import ugettext_lazy as _
from google.appengine.ext import db

class Photo(db.Model):
    image_binary    = db.BlobProperty()

views.py

from django.http import HttpResponse
from images.models import Photo
from google.appengine.api import images as gimages
import math

def main(request):
    request_width_min = 5
    request_height_min = 5
    request_width_max = 1000
    request_height_max = 1000
    default_width = 100
    default_height = 100

    req = request.GET
    image_key = req['image_key']
    w = int(req['w']) if req.has_key('w') and request_width_min < int(req['w']) and int(req['w']) <= request_width_max else default_width
    h = int(req['h']) if req.has_key('h') and request_height_min < int(req['h']) and int(req['h']) <= request_height_max else default_height

    img = Photo.get(image_key)
    # 画像生データ
    image_data = img.image_binary
    # 画像縦横長さ取得
    gimg = gimages.Image(img.image_binary)
    image_width = gimg.width
    image_height = gimg.height

    # rate が1より小さい場合は拡大処理。大きい場合は縮小処理。
    width_rate = float(image_width)/float(w)
    height_rate = float(image_height)/float(h)

    # resize
    if height_rate == 1.0 and width_rate == 1.0 :
        resize_h = image_height
        resize_w = image_width
    elif height_rate >= 1.0 and width_rate == 1.0 :
        resize_h = image_height
        resize_w = image_width
    elif height_rate == 1.0 and width_rate >= 1.0 :
        resize_h = image_height
        resize_w = image_width
    elif height_rate == width_rate :
        resize_h = h
        resize_w = w
    elif height_rate > width_rate :
        resize_h = get_best_length(image_height, image_width, w)
        resize_w = w
    else :
        resize_h = h
        resize_w = get_best_length(image_width, image_height, h)

    # crop
    if height_rate == width_rate :
        crop_h = 1.0
        crop_w = 1.0
    elif height_rate > width_rate :
        crop_h = float(h)/float(resize_h)
        crop_w = 1.0
    else :
        crop_h = 1.0
        crop_w = float(w)/float(resize_w)

    base_image = gimages.resize(img.image_binary, resize_w, resize_h, gimages.JPEG)
    gdata = gimages.crop(base_image, 0.0, 0.0, crop_w, crop_h, gimages.JPEG)
    return HttpResponse(gdata, 'image/jpeg')

def get_best_length(base_len, denominator_len, molecule_len, type='int'):
    result = math.ceil( base_len * ( float(molecule_len)/float(denominator_len) ) )
    if type == 'int' :
        return int(result)
    else :
        return result

左上始点で作成したので楽だった。中央が欲しいとか、そもそもリサイズが不要であればまた別途…
もっときれいなコードにしたいなあ。
「get_best_length」とかうける。