Comment out the 'loadtest' backend in the 'counter' backend sample so that it does...
[gae-samples.git] / images-demo / image_transformer.py
blob4a307c0b3dca040e9d51f5b8ff6bb2ae793e69c6
1 #!/usr/bin/python2.5
3 # Copyright 2008 Google Inc.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Map CGI argument 'commands' to Image class method calls."""
19 import re
21 from google.appengine.api import images
24 # VALID_TRANSFORMS lists valid parameters and simple regexes to test them.
25 # The regexes only do very basic sanity checking, not full API validation.
26 # The match groups are later used to pass the results on to the functions.
27 VALID_TRANSFORMS = {
28 u'crop': re.compile(','.join(['([01]\.[0-9]+)'] * 4)),
29 u'horizontal_flip': re.compile('.*$'),
30 u'im_feeling_lucky': re.compile('.*$'),
31 u'resize': re.compile('([0-9]+),([0-9]+)$'),
32 u'rotate': re.compile('(-?[0-9]+0)$'),
33 u'vertical_flip': re.compile('.*$')
36 # _CONVERSION_INFO lists functions to convert the string captured by the
37 # regex into some other format which the API may require.
38 _CONVERSION_INFO = {
39 u'crop': float,
40 u'resize': int,
41 u'rotate': int
45 class ImageTransformer(object):
46 """ImageTransformer: A wrapper for google.appengine.api.images.
48 In a sense, this is an inverse of google.appengine.api.images: it is
49 intialized with image data to which multiple transforms are applied. This is
50 initialized with a serialized list of transforms with can then be run on
51 multiple images.
52 """
54 def __init__(self, params, format):
55 """Load and transform image data in a specified manner.
57 Args:
58 params: UnicodeMultiDict of possible tranformations.
59 Typically request.params from a web request.
60 Unknown and invalid items will be mostly ignored.
61 format: images.JPEG or images.PNG
62 """
64 self.format = format
65 self.transforms = []
66 self.unknown_params = []
67 self.invalid_params = []
68 for (param, value) in params.iteritems():
69 if param in VALID_TRANSFORMS:
70 if VALID_TRANSFORMS[param].match(value):
71 self.transforms.append((param, value))
72 else:
73 self.invalid_params.append(param)
74 else:
75 self.unknown_params.append(param)
77 def transform_image(self, image_data):
78 """Applies this object's list of transforms to an image.
80 Args:
81 image_data: binary image data in JPEG, PNG, or another format which the
82 images.image class can interpret.
84 Returns:
85 Image data transformed using the transforms and formatting specified at
86 ImageTransformer initialization time.
88 Raises:
89 Any of the exceptions which images.Image.execute_transforms can raise.
91 images.BadRequestError when there is something wrong with the request
92 specifications.
93 images.NotImageError when the image data given is not an image.
94 images.BadImageError when the image data given is corrupt.
95 images.LargeImageError when the image data given is too large to process.
96 images.TransformtionError when something errors during image manipulation.
97 images.Error when something unknown, but bad, happens.
98 """
100 image = images.Image(image_data)
101 seen_transforms = set()
102 for (transform, param) in self.transforms:
103 if transform in seen_transforms:
104 # we need to execture all transforms before continuing.
105 image_data = image.execute_transforms(self.format)
106 image = images.Image(image_data)
107 seen_transforms.clear()
109 args = VALID_TRANSFORMS[transform].match(param).groups()
110 if transform in _CONVERSION_INFO:
111 args = [_CONVERSION_INFO[transform](arg) for arg in args]
112 getattr(image, transform)(*args)
113 seen_transforms.add(transform)
115 if seen_transforms:
116 image_data = image.execute_transforms(self.format)
117 return image_data