App Engine provides the ability to manipulate image data using a dedicated Images service. The Images service can resize, rotate, flip, and crop images; it can composite multiple images into a single image; and it can convert image data between several formats. It can also enhance photographs using a predefined algorithm. The API can also provide information about an image, such as its format, width, height, and a histogram of color values.
The Images service can accept image data directly from the app, or it can use a Google Cloud Storage value. (The Images service can also use a Blobstore value, but we recommend the use of Cloud Storage instead.) When the source is Cloud Storage (or Blobstore), the size of the image to transform can be up to the maximum size of a Cloud Storage (or Blobstore) value. However, the transformed image is returned directly to the app, and so must be no larger than 32 megabytes. This is potentially useful for making thumbnail images of photographs uploaded to the Blobstore or Cloud Storage by users.
Transforming images in Java
The Image service API lets you apply transformations to images, using a service
instead of performing image processing on the application server. The app
Image object with the image data to transform, and a
object with instructions on how to transform the image. The app gets an
ImagesService object, then calls its
applyTransform() method with the
Image and the
Transform objects. The method returns an
Image object of the
The app gets
Transform instances using the
// Get an instance of the imagesService we can use to transform images. ImagesService imagesService = ImagesServiceFactory.getImagesService(); // Make an image directly from a byte array, and transform it. Image image = ImagesServiceFactory.makeImage(imageBytes); Transform resize = ImagesServiceFactory.makeResize(100, 50); Image resizedImage = imagesService.applyTransform(resize, image); // Write the transformed image back to a Cloud Storage object. gcsService.createOrReplace( new GcsFilename(bucket, "resizedImage.jpeg"), new GcsFileOptions.Builder().mimeType("image/jpeg").build(), ByteBuffer.wrap(resizedImage.getImageData()));
Multiple transforms can be combined into a single action using a
CompositeTransform instance. See the images API reference.
Available image transformations
The Images service can resize, rotate, flip, and crop images, and enhance photographs. It can also composite multiple images into a single image.
You can resize the image while maintaining the same aspect ratio. Neither the width nor the height of the resized image can exceed 4000 pixels.
You can rotate the image in 90 degree increments.
You can flip the image horizontally.
You can flip the image vertically.
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.
The service accepts image data in the JPEG, PNG, WEBP, GIF (including animated GIF), BMP, TIFF and ICO formats.
It can return transformed images in the JPEG, WEBP and PNG formats. If the input format and the output format are different, the service converts the input data to the output format before performing the transformation.
Transforming images from the Blobstore
The Images service can use a value from the Blobstore as the source for a transformation. You have two ways to transform images from the Blobstore:
- Using the ImageServiceFactory() class allows you to perform simple image transformations, such as crop, flip, and rotate.
- Using getServingUrl() allows you to dynamically resize and crop images, so you don't need to store different image sizes on the server. This method returns a URL that serves the image, and transformations to the image are encoded in this URL.
Using the ImageServiceFactory() Class
You can transform images from the Blobstore as long as the image size is smaller than the maximum Blobstore value size. Note, however, that the result of the transformation is returned directly to the app, and must therefore not exceed the API response limit of 32 megabytes. You can use this to make thumbnail images of photographs uploaded by users.
To transform an image from the Blobstore in Java, you create the
Image object by calling the static method
ImageServiceFactory.makeImageFromBlob(), passing it a
blobstore.BlobKey value. The rest of the API behaves as expected. The
applyTransform() method returns the result of the transforms, or throws an
ImageServiceFailureException if the result is larger than the maximum size of 32 megabytes.
// Make an image from a Cloud Storage object, and transform it. BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService(); BlobKey blobKey = blobstoreService.createGsBlobKey("/gs/" + bucket + "/image.jpeg"); Image blobImage = ImagesServiceFactory.makeImageFromBlob(blobKey); Transform rotate = ImagesServiceFactory.makeRotate(90); Image rotatedImage = imagesService.applyTransform(rotate, blobImage); // Write the transformed image back to a Cloud Storage object. gcsService.createOrReplace( new GcsFilename(bucket, "rotatedImage.jpeg"), new GcsFileOptions.Builder().mimeType("image/jpeg").build(), ByteBuffer.wrap(rotatedImage.getImageData()));
In addition to the Images API, you can also use the transforms provided in the Python Imaging Library (PIL) in your Python 2.7 app. To do this, declare the library in the libraries section of the
app.yaml file. However, if you wish to use PIL in your local environment (using the development
server) you must also download and install PIL or pillow locally.
The getServingUrl() method allows you to generate a fixed, dedicated URL for an image that is stored in Blobstore.
The generated URL uses highly-optimized image serving infrastructure that is separate from your application. Because it's served separately the serving URL does not incur any dynamic load on your application which can be very cost effective. The URL returned by this method is always publicly accessable but not guessable.
If you wish to stop serving the URL, delete it using the deleteServingUrl() method.
The method returns a URL encoded with the specified size and crop arguments. If you do not specify any arguments, the method returns the default URL for the image, for example:
You can resize and crop the image dynamically by specifying the arguments in the URL. The available arguments are:
xxis an integer from 0–1600 representing the length, in pixels, of the image's longest side. For example, adding
=s32resizes the image so its longest dimension is 32 pixels.
=sxx-cwhere xx is an integer from 0–1600 representing the cropped image size in pixels, and
-ctells the system to crop the image.
# Resize the image to 32 pixels (aspect-ratio preserved) http://lhx.ggpht.com/randomStringImageId=s32 # Crop the image to 32 pixels http://lhx.ggpht.com/randomStringImageId=s32-c
Images and the development server
The development server uses your local machine to perform the capabilities of the Images service.
The Java development server uses the ImageIO framework to simulate the Image service. The "I'm Feeling Lucky" photo enhancement feature is not supported. The WEBP image format is only supported if a suitable decoder plugin has been installed. The Java VP8 decoder plugin can be used, for example.
A note about deletion
Whether you store your images in Cloud Storage or Blobstore, the right way to stop an image from being publicly accessible through the serving URL is to call the deleteServingUrl() method.
If you merely delete the underlying stored image from Cloud Storage or Blobstore, under some circumstances the image may remain accessible through the serving URL.
Serving URLs will stop working if the application that created them is disabled or deleted, even if the underlying image remains available.
Quotas, limits, and pricing
There is currently no additional charge incurred by using the Images API. See the App Engine pricing page.
Each Images service request counts toward the Image Manipulation API Calls quota. An app can perform multiple transformations of an image in a single API call.
Data sent to the Images service counts toward the Data Sent to (Images) API quota. Data received from the Images service counts toward the Data Received from (Images) API quota.
Each transformation of an image counts toward the Transformations Executed quota.
In addition to qu