Last Updated: February 25, 2016
· troylelandshields

RMagick - Using Layers


The below image is created entirely from code written in Ruby ( with the help of RMagick. RMagick is an awesome Ruby interface to ImageMagick.


RMagick has the ability to write text to an image by creating a 'draw' object and using the annotate method.

In general, it is pretty easy to programmatically place the text where you want, but in my Big A Calendar I needed to place white text exactly in the middle of the black dots. Calculating the exact pixel to lay the text with annotate seemed like it was going to be a bigger headache than I wanted to deal with (especially since I might want to change the text size, etc).

Create a Sub Image

My solution was really simple: create a small image in which I could center the circle and date, then added this to the correct place on the calendar.

The below method creates a small image with the circle graphic I want to place the date on.

def createDateLabelBg 
    @date_lbl_bg =, @size){
        self.background_color = 'transparent'

    #This is the bigger, all-black circle that makes the black stroke
    cir = 
    cir.fill = @date_lbl_bg_color.to_s, @date_lbl_bg.columns/2,
                    2, @date_lbl_bg.columns/2)

    cir =
    cir.stroke_width(12)., @date_lbl_bg.columns/2,
                    24, @date_lbl_bg.columns/2)        


Later I can write the date exactly in the middle of this circle with no need to calculate any tricky positioning (notice the long list of 0s in the annotate method call):

date_lbl_bg = createDateLabelBg

date_lbl =
date_lbl.gravity = CenterGravity
date_lbl.pointsize = @lbl_size - 90
date_lbl.fill = @date_color.to_s

#Just use 0's and it's centered perfectly!
date_lbl.annotate(date_lbl_bg, 0, 0, 0, 0, date.to_s) 

This also comes with the advantage that my circle and date are now tied perfectly together, and I am free to place them wherever I want as one unit.

I use a similar method to place the letters that label the days of the week because I want it to be easy to keep that letter centered over the columns in the calendar rather than keep it placed in one specific place on the page.

Create a Base Image

Once you have your sub images designed the way you like, you can place them on top of a base image wherever you want.

Create a base image that is the size of the final image you want and add it to a new ImageList object.

baseImg =, 10800){self.background_color = 'white'}
imgList =

Combine the Images

Add all of your other images to your new ImageList. Each image in this is on its own layer and has a position somewhere on the base image. Specify where you want the image placed with the 'page' attribute of the image. =, height, xPos, yPos) #x & y are relative to upper left corner

Finally, flatten and write the image to get one nice image with everything in the position you wanted it.

final = imgList.flatten_images