Sometimes I need to draw a few lines or some text on an image or a blank canvas. Just recently I needed to include a simple image of a pixel ruler in a developerWorks article. I wanted the image to be 572 pixels wide, to match the current recommended maximum for developerWorks article images as described in "Illustrating your article or tutorial for developerWorks." Lots of on-screen pixel rulers are available for Linux and for Windows (see Resources), but I just wanted a simple GIF, JPEG or PNG image. This tip shows you how to use Bash scripting, shell arithmetic, and ImageMagick to create a pixel ruler.
The first thing any artist needs is a canvas, so let's create one using
the XC pseudo image type in ImageMagick. We also need a color, either one of
the many named colors in ImageMagick, or a custom color. (See
Resources for a link to the ImageMagick
documentation, where you can find a full list of pseudo image types as
well as color names.) Listing 1 shows how to make a light blue 572x100
canvas using the convert command.
(The convert command is customarily used
to convert to a different image format or otherwise alter an image.)
Listing 1. Creating a canvas
convert -size 572x100 xc:lightblue ruler1.gif
|
Figure 1 shows our new canvas.
Figure 1. A light blue 572x100 pixel canvas for our ruler
Now that we have a canvas, let's draw marks to show the various points along the ruler. 72 ppi (pixels per inch) is standard for Web-based graphics, so let's put our first mark at 72 pixels and make it extend 30 pixels from the bottom of the image. Let's also make the fill color for the line black and specify the two end points of the line.
Listing 2. Adding a line to the canvas
convert -fill black -draw "line 72,70 72,100" ruler1.gif ruler2.gif
|
Figure 2 shows our new image with a single line drawn on it.
Figure 2. The canvas with a single vertical line 72 pixels from the left
Doing this individually for each line we want on the ruler isn't too
appealing. So let's use the seq command to
generate a list of horizontal offsets 72 pixels apart and a
for loop to draw our main lines on the ruler as
shown in Listing 3.
Listing 3. Adding lines to the canvas every 72 pixels
convert -fill black -draw "$(for n in $(seq 0 72 572) ;\
do echo line $n,70 $n,100 ; done)" ruler1.gif ruler3.gif
|
Notice that we use two command substitutions to generate the individual line specifications for the draw operation. We also put a mark at 0, the left edge. Figure 3 is now starting to look more like a ruler.
Figure 3. The canvas with vertical lines every 72 pixels from the left
At this point, our command line is getting a little complex, and we still
have only the major marks on our ruler. Time to start scripting. In
Listing 4, we use shell arithmetic and
for loops to place a 20-pixel mark half way
between the marks we already have, and to place 10-pixel marks every 6
pixels between the longer marks. We'll call the script
buildruler.sh and put it in our working
directory for the purposes of this article.
Listing 4. Adding a full set of marks to the ruler
#!/bin/bash
# Take user parameters or set defaults
rulername="$1"
rulerlength="$2"
rulername="${rulername:=ruler.gif}"
rulerlength="${rulerlength:=572}"
drawstring=""
#Build the line definitions for the ruler marks
for x1 in `seq 0 72 $rulerlength`; do
drawstring="$drawstring line $x1,70 $x1,100"
for x2 in 0 36; do
(( offset = $x1 + $x2 ))
drawstring="$drawstring line $offset,80 $offset,100"
for x3 in `seq 6 6 30`; do
(( offset2 = $offset + $x3 ))
drawstring="$drawstring line $offset2,90 $offset2,100"
done
done
done
#Create the ruler
convert -size "${rulerlength}x100" xc:lightblue -fill black \
-draw "$drawstring" "$rulername"
|
Notice that we added a couple of parameters to allow a user
to change the name of the ruler and to specify the length. Our ruler now
looks like Figure 4. We used the command
./buildruler.sh ruler4.gif to generate
this ruler.
Figure 4. Our ruler with a full set of marks 6 pixels apart
Now let's label the larger marks on our ruler with the numbers 0, 72, 144, and so on. We need to tell ImageMagick what font to use and what size and color it should be. Obviously, the 0 should be at the left edge of the ruler, but if we place the two- and three-digit numbers at the 72-pixel points, they will appear unbalanced. To correct this, we'll shift them slightly to the left, to make them appear more centered over the mark. Our enlarged script is shown in Listing 5.
Listing 5. Adding labels to the ruler
#!/bin/bash
# Take user parameters or set defaults
rulername="$1"
rulerlength="$2"
rulername="${rulername:=ruler.gif}"
rulerlength="${rulerlength:=572}"
drawstring=""
#Build the line definitions for the ruler marks
for x1 in `seq 0 72 $rulerlength`; do
drawstring="$drawstring line $x1,70 $x1,100"
for x2 in 0 36; do
(( offset = $x1 + $x2 ))
drawstring="$drawstring line $offset,80 $offset,100"
for x3 in `seq 6 6 30`; do
(( offset2 = $offset + $x3 ))
drawstring="$drawstring line $offset2,90 $offset2,100"
done
done
done
#Add the labels
labelfont="-fill black -font helvetica -pointsize 24 -draw"
labelstring="text 0,60 \"0\" "
for x1 in 72; do
(( offset = $x1 - 12 ))
labelstring="$labelstring text $offset,60 \"$x1\" "
done
for x1 in `seq 144 72 $rulerlength`; do
(( offset = $x1 - 18 ))
labelstring="$labelstring text $offset,60 \"$x1\" "
done
#Create the ruler
convert -size "${rulerlength}x100" xc:lightblue -fill black \
-draw "$drawstring" $labelfont "$labelstring" "$rulername"
|
Now our ruler looks like Figure 5.
Figure 5. Our ruler with labels a full set of marks
So how did we know how much to offset the text or how far down from the top to place it? The short answer is that I experimented and guessed! Not an ideal solution.
To do a better job on placing text, we need to know how big the
rectangle containing the text will be. But that depends on the font and
whether the font is proportional and other things that aren't so easy to
calculate. Fortunately, in the same way that we can create a canvas with
ImageMagick, we can also create a label. We'll create a title
of Pixel Ruler and make it a 36-point font. The label is
created as an image, and we can use the identify
command to determine its size, as shown in Listing 6.
Listing 6. Creating a title and measuring its size
$ convert -fill NavyBlue -background Lavender -font helvetica -pointsize 36 \ label:"Pixel Ruler" label.gif $ identify "label.gif" label.gif GIF 175x36 175x36+0+0 8-bit PseudoClass 256c 1.98kb |
We've made the text navy blue and added a lavender background color to help the image stand out from this page background, but you get the same size image with or without the background color. The resulting label image is shown in Figure 6.
Figure 6. The label as an image
Even better than writing a file, we can use the ImageMagick INFO class to determine even more information about the text, including where the baseline is. We'll write the text onto a large enough canvas and then trim the canvas to the edge of the text as shown in Listing 7.
Listing 7. Using the INFO image class to determine font information
$ convert -size 572x100 xc:lightblue -font helvetica -pointsize 36 \ -fill black -undercolor lavender -annotate +40+50 'Pixel Ruler' -trim info: xc:lightblue XC 174x36 572x100+40+23 16-bit DirectClass |
Annotated text starts at a point whose y coordinate represents the baseline of the text. The above output shows that the text fits in a box that is 174x36 pixels in size. The 1-pixel discrepancy between this and our earlier result is not significant. The top of the box is positioned 23 pixels below the top of our original canvas. Since the baseline was 50 pixels below the top of the original canvas, this means the baseline is actually 27 pixels (50 minus 23) below the top of the text, leaving 9 pixels for descenders. Figure 7 illustrates the relationship using an image placed on the untrimmed canvas.
Figure 7. The label metrics
So now that we have the label dimensions, let's place the baseline 40 pixels from the top of the image and center it horizontally. Our final script is shown in Listing 8 and is also available for download.
Listing 8. Our final script
#!/bin/bash
# Take user parameters or set defaults
rulername="$1"
rulerlength="$2"
rulername="${rulername:=ruler.gif}"
rulerlength="${rulerlength:=572}"
drawstring=""
#Build the line definitions for the ruler marks
for x1 in `seq 0 72 $rulerlength`; do
drawstring="$drawstring line $x1,70 $x1,100"
for x2 in 0 36; do
(( offset = $x1 + $x2 ))
drawstring="$drawstring line $offset,80 $offset,100"
for x3 in `seq 6 6 30`; do
(( offset2 = $offset + $x3 ))
drawstring="$drawstring line $offset2,90 $offset2,100"
done
done
done
#Add the labels
labelfont="-fill black -font helvetica -pointsize 24 -draw"
labelstring="text 0,60 '0' "
for x3 in 72; do
offset3=$(($x3 - 12 ))
labelstring="$labelstring text $offset3,60 '$x3' "
done
for x4 in `seq 144 72 $rulerlength`; do
offset4=$(( $x4 - 18 ))
labelstring="$labelstring text $offset4,60 '$x4' "
done
#Add a title
titledimension=$(convert -size 572x100 xc:lightblue -font helvetica \
-pointsize 36 -fill black -undercolor lavender\
-annotate +40+50 'Pixel Ruler' -trim info: | awk ' {print $3 } ')
titlewidth=${titledimension%x*}
titlefont="-fill NavyBlue -font helvetica -pointsize 36"
titlepos=$(( (($rulerlength - $titlewidth)) / 2 ))
titletext="text $titlepos,30 'Pixel Ruler' "
#Create the ruler
convert -size "${rulerlength}x100" xc:lightblue \
-fill black -draw "$drawstring" $labelfont "$labelstring" \
$titlefont -draw "$titletext" "$rulername"
|
The final ruler is shown in Figure 8.
Figure 8. The final ruler, complete with title
Not too bad for someone with no artistic skills!
When images are indented—as in lists, for example—the maximum width allowed on developerWorks is reduced accordingly. So you can use these handy rulers as a check for any images you submit with an article.
- This is a short ruler in an unordered list that was created with the
command
./buildruler.sh ruler9.gif 400.
Figure 9. A 400-pixel ruler
- And this is an even shorter ruler that is further indented. It
was created with the command
./buildruler.sh ruler10.gif 300.
Figure 10. A 300-pixel ruler
- And this is an even shorter ruler that is further indented. It
was created with the command
In this short exercise, you've seen some basic techniques for scripting images containing lines and text using ImageMagick. You'll find more techniques in our articles "Graphics from the command line" and "More graphics from the command line." You'll also find a host of other examples at the ImageMagick home page. See Resources for links.
The scripts here are not bullet-proof. For example, we do not validate that length is a positive number big enough for a meaningful ruler or that the file specified is a valid image file type for ImageMagick. You will find other issues as well. For example, the ruler labels may be truncated as in Figure 10 above, a possibility our script did not consider.
You can also parameterize as many aspects as you wish. Try adding color or ruler height as parameters, for example.
While this tip has focused on using ImageMagick with Linux, ImageMagick is available for other platforms including Windows. Try using these techniques with your favorite scripting tools on your favorite platform.
| Description | Name | Size | Download method |
|---|---|---|---|
| Script to build your own pixel ruler | buildruler.zip | 1KB | HTTP |
Information about download methods
Learn
-
"Illustrating your article or tutorial for developerWorks"
(developerWorks, July 2008) shows how to develop and submit technical
graphics for developerWorks articles and tutorials.
-
"Graphics from the command
line" (developerWorks, July 2003)
and
"More graphics
from the command line" (developerWorks, March 2004) demonstrate
other techniques for using ImageMagick
from the command line.
- At the
ImageMagick Web site,
find man pages and lots of examples of
ImageMagick usage.
-
In the
developerWorks Linux zone,
find more resources for Linux developers, and scan our
most popular articles and
tutorials.
-
See all
Linux tips and
Linux tutorials on developerWorks.
-
Stay current with
developerWorks technical events and Webcasts.
Get products and technologies
- Some screen rulers
are available for different operating systems:
- Gnome Screen Ruler (Linux Gnome) may be included in your Linux distribution.
- KRuler (Linux KDE) is part of the KDE graphics package and may be included in your Linux distribution.
- Free ruler (Mac OS X) is a free screen ruler for the Mac.
- JR Screen Ruler (Windows) is a free virtual ruler for Windows.
-
With
IBM trial software,
available for download directly from developerWorks, build your next development
project on Linux.
Discuss
-
Get involved in the
My developerWorks community; with your personal profile and custom home page, you
can tailor developerWorks to your interests and interact with other developerWorks users.

Ian Shields works on a multitude of Linux projects for the developerWorks Linux zone. He is a Senior Programmer at IBM at the Research Triangle Park, NC. He joined IBM in Canberra, Australia, as a Systems Engineer in 1973, and has since worked on communications systems and pervasive computing in Montreal, Canada, and RTP, NC. He has several patents. His undergraduate degree is in pure mathematics and philosophy from the Australian National University. He has an M.S. and Ph.D. in computer science from North Carolina State University.





