Today I was working on automating of preparation of iPhone screen shots for usage on the website. The new eideticsoftware.com website design requires for the images to have drop shadows so instead processing everything in Adobe® Photoshop® I have decided it would be much nicer to just automate the process with rmagick.
If you are impatient and just want the script jump to the bottom of the post and download image_processor.rb but if you want to know how it works then read on.
This script scales the images for the post.

First we take the original image and scale it by 50% –
source = original.scale(0.5)

Next we strip out the status bar with crop method:
source = source.crop(0, 10, 160, 240)

We create a transparent canvas that is 10px wider and 10px longer and another identical canvas that we are going to use for the shadow. On the image_shadow canvas we draw a rectangle with the same dimensions as the original image. In the source file the rectangle is created by the “drop_shadow_rectangle” function.
We use the image_shadow canvas to create two shadows, first is the actual shadow, the second we use as a mask to soften the shadow itself.
We apply the first shadow to the original canvas with “OverCompositeOp” option and then we apply the mask on top of that with “CopyOpacityCompositeOp” option.

We apply the scaled and cropped image on top of the shadow and draw a white border. The white border is only necessary when the screen shot is dark to distinguish the shadow from the image.
Finally we write the image to a file with “canvas.write” method.
Source Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | require 'rubygems' require 'rmagick' include Magick img_filename = "example.png" # Helper function to create new name def new_name(img_filename, modifier = "_shadow") chunks = img_filename.split(".") chunks[0..-2].join(".") + modifier + ".#{chunks[-1]}" end # Creates drop show rectangle def drop_shadow_rectangle(x,y,width,height) gc = Draw.new gc.fill_color("black") gc.rectangle(x,y,width,height) end # creates frame draw object def white_frame(x,y,width, height) frame = Draw.new frame.fill_opacity(0) frame.stroke_color("white") frame.rectangle(x,y,width,height) end def add_shadow(img_filename) original = ImageList.new(img_filename) source = original.scale(0.5) source.write(new_name(source.filename, "_scaled")) source = source.crop(0, 10, 160, 240) canvas = Image.new(source.columns + 10, source.rows + 10) do self.background_color = "transparent" end # Generates intermediate images #source.write(new_name(source.filename, "_stripped")) #canvas.write(new_name(source.filename, "_raw_canvas")) image_shadow = Image.new(canvas.columns, canvas.rows) do self.background_color = "transparent" end drop_shadow_rectangle(0, 0, source.columns, source.rows).draw(image_shadow) blur = 1 x, y = 1, 1 image_shadow = image_shadow.shadow(x, y, blur, 1) shadow_mask = image_shadow.shadow(x, y, blur, 1) # Place the shadow canvas.composite!(image_shadow, 0, 0, OverCompositeOp) # Place the mask to soften the shadow canvas.composite!(shadow_mask, 0, 0, CopyOpacityCompositeOp) # Intermediate image # canvas.write(new_name(source.filename, "_canvas_with_shadow")) # Now place the image on the canvas canvas.composite!(source, 1, 1, OverCompositeOp) # And draw the white border on top of the image white_frame(0, 0, source.columns, source.rows).draw canvas # save the final image canvas.write(new_name(source.filename, "_canvas_with_image")) end add_shadow(img_filename) |
Processor: image_processor.rb
Social Networking