Module: AppEngine::Images

Defined in:
lib/appengine-apis/images.rb

Overview

Image Manipulation on Google app Engine

Usage

Use it like this:

require 'appengine-apis/images'
image = AppEngine::Images.open('public/clown.jpg')
image.resize(100,100)
image.to_s   #or @image.data
# => "data string"

You can also make a new Image object by simply passing a data string

@image = AppEngine::Images.load("data string")

Currently all of Google’s image manipulation methods except for composite images. This means you can rotate, resize, crop and flip your images. The syntax for this is really straigthforward

image = AppEngine::Images.load("data string")
image.resize(width,height)
image.resize!(width,height)

image.rotate(angle)
image.rotate!(angle)

image.flip   #flips horizontal
image.flip(:horizontal) #default
image.flip(:vertical)

image.flip!(direction)

image.crop(leftX,topY,rightX,bottomY)
image.crop!(leftX,topY,rightX,bottomY)

#Bonus method from google that tries to enhance colour
image.i_feel_lucky
image.i_feel_lucky!

The power lies in chaining the methods:

AppEngine::Images.open('public/clown.jpg').resize(100, 100).rotate(90).flip.to_s

Legacy

Maby you feel that learning yet another image manipulation syntax is cumbersome. I can hardly imagine that because syntax is really simple. Anyway, people have numerous reasons to stick to old syntaxes. The most compelling argument is not having to rewrite code for something like GAE. The easier it is for people to port their app to GAE the more usefull it will be. That is why I also included a simple drop-in interface for ImageScience

require 'imagescience.rb'

ImageScience.with_image('public/clown.jpg') do |img|
  img.cropped_thumbnail(100) do |thumb|
    return thumb.to_s
  end
end

All the methods of ImageScience are supported. It should behave exactly like ImageScience does. There is however one slight problem. Google App Engine apps cannot write files to the filesytem. This means that the following will never work.

ImageScience.with_image('public/clown.jpg') do |img|
  img.cropped_thumbnail(100) do |thumb|
    thumb.save('public/clown_thumb.jpg')
  end
end

To overcome this I simply added a .to_s method that returns the image data as a String. You can then either directly return this data, memcache it or store it through google DataStore.

I understand that this still means you have to modify code. If you still want minimal effort porting your code I suggest you monkeypatch the class and add save yourself. Then you can store it the way you want(probably DataStore).

But both of these approaches leave you with a problem if you want manipulate an image that you didn’t include with your deploy. For example a user uploaded image or a previously modified image. You cannot simply write it to a tempfile and then open them with ImageScience.with_image. To overcome this problem I added a simple with_image variation called with_image_data. You just use it like this:

ImageScience.with_image('public/clown.jpg') do |img|
  @datastring = img.to_s
end
#Or get your @datastring from DataStore, Memcache or post/put params
ImageScience.with_image_data(@datastring) do |img|
  img.cropped_thumbnail(100) do |thumb|
    thumb.to_s
    # => Jeeh, another datastring let's store it safely!
  end
end

I realize this still means you need you sometimes have to do quite a lot of work to make it work. I personally think this is not a big problem as it gives your app quite some advantages. For example it becomes much easier to scale to app(That is the actual reason why you cannot write to filesystem). If you wanted to scale your app with amazon for example you also need to modify your code cause you probably want to send your images to S3.

If you still feel that modifying your code is to much of a trouble perhaps the google app engine is just nothing for you. But ofcourse you can also MonkeyPatch ruby File class and use Datastore as a virtual filesystem. That would be quite a cool project, you can let File.open search the datastore first and then the read-only harddisk (to simulate file overwriting) You can Cache things with memcache(If that makes it faster). When you are done drop me a note will you?

Meta

Created by Bas Wilbers

Defined Under Namespace

Modules: IS Classes: Image

Class Method Summary collapse

Class Method Details

.load(data) ⇒ Object



151
152
153
# File 'lib/appengine-apis/images.rb', line 151

def self.load(data)
  Image.new(data)
end

.open(filename) ⇒ Object



147
148
149
# File 'lib/appengine-apis/images.rb', line 147

def self.open(filename)
  Image.open(filename)
end