Image Manipulation on Google app Engine
Image-GAE is a library that wraps google's ImageService. It is intented for usage on Google App engine with JRuby.
Just copy all the files to your app, make sure warbler includes them and then simply require image-gae.rb
Use it like this:
image = GAE::Image.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 = GAE::Image.new("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 = GAE::Image.new("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:
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 'legacy/imagescience.rb' include GAE::Legacy 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 1 slight problem. Google Engine app's 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?
Created by Bas Wilbers
Released under the ruby licence www.ruby-lang.org/en/LICENSE.txt