| Level: Intermediate Nathan Harrington (harrington.nathan@gmail.com), Programmer, IBM
24 Jan 2006 Use simple Perl scripts to automate the image manipulation, text creation, and compositing of arbitrary mosaic images. Learn how to use ImageMagick, GD, and The Gimp to create your own mosaic images suitable for static display and dynamic content. Explore the capabilities of ImageMagick and open source graphical editing tools.
Mosaic images are popular in today's print and video media due to their visual appeal and suggestions of technological advancement. This article will cover the methods required to create your own simple mosaic-type images using text and graphical content. The techniques discussed in this article can be used for static and dynamic content creation. As an example, IBM employees can use a tool this article was based on to create mosaic images of their manager's name composed of pictures of that manager's employees.
Using Perl to access and modify the images into mosaic "tile" form, we will then process the images using the GD module in a Perl script. GD is also used in Perl to create textual overlays, and the ImageMagick suite of tools will allow us to composite the final result. With the use of The Gimp image manipulation tool, we will create a modified version of the Linux® mascot, Tux the penguin, and create a mosaic image with a Linux theme.
Requirements
Hardware
The image manipulation and compositing process are very memory and CPU-intensive. This article was developed on a 500-MHz Pentium® III with 512 MB of RAM. Slower systems should still work fine, but I recommend at least 256 MB of RAM, as the image files created are almost 6 megapixels in size.
Software
You need Perl, GD, The Gimp, and ImageMagick, all of which are installed by default in the majority of Linux distributions. See Resources for more information on where to find these tools. feh is an excellent image viewing program that will help in the processing of your mosaic tiles (see Resources).
Mosaic tile images
Acquisition of images
IBM's internal resources include a repository of employee photos linked with job responsibilities. I searched this job responsibilities field and retrieved the photos of everyone responsible for developerWorks. There are plenty of great tools out there to create libraries of images from the Web suitable for developing mosaics. I have included some images in the source code package for this article (see Download).
Processing of tiles
No matter the source of your images, chances are good they will need processing to be ready for use in a mosaic. The list of photos I had were of various sizes, or consisted of "default" images that were undesirable for use in the mosaic. Use the feh image viewer to remove the unwanted images.
- Get an idea of the contents of your image directory with the command
feh -t images/ . This will give you a thumbnail-type image of each picture with its filename underneath.
Figure 1. Feh thumbnail mode
- Use feh to eliminate the pictures you do not want with the command
feh -F -d -A "rm %f" images/ . This will allow you to cycle through the images one at a type in full-screen mode. Press the spacebar to move to the next image, and when you see an image to be removed, press the Enter key and the '-A "rm %f"' option will delete the image. In this example, all of the blue and white default images were removed.
- Now that you have collected acceptable images, we need to make sure they are all the same size. 25 x 25 pixels works well for this demonstration. At that size, they are large enough to discern the contents, but small enough to be a good visual component in the finished image. Use the ImageMagick command
mogrify -geometry 25 x 25 images/* to make all the images the same size. Note that this command will restrict the images' dimensions to 25 x 25 while keeping the aspect ratio the same.
Text overlay mosaic
We will use the text "developerWorks" as the content of our mosaic. We need to create a transparent image with white text to be composited in with the tiles later. Follow these steps:
- Create the overlays directory.
- Create a file called build_text_overlay.pl with the following code:
Listing 1. build_text_overlay.pl
#!/usr/bin/perl -w
# build_text_overlay.pl, creates the transparent image with user specified
# text in the foreground
use strict;
use GD; # graphics library
my $text = $ARGV[0] or die "Please specify text\n"; # text to overlay
my $textlen = length($text); # length of text
# specify your font location here:
# remember that if you change the font, the magic number needs
# to change to give the image the appropriate width
my $font = "./VeraMoBd.ttf";
my $width = 400 * $textlen; # 400 is magic number suitable for VeraMoBd font
# create a new GD image of $width, 600 pixels high so it will fit nicely on
# the screen, and the printed page
my $image = new GD::Image($width,600);
# initialize some colors
my $white = $image->colorAllocate(255,255,255);
$image->transparent($white); # set white as transparent
# write the file to disk
open(PNGOUT,"> overlays/empty_white_$text.png") or die
"can't write to output file overlays/empty_white_$text.png";
print PNGOUT $image->png;
close(PNGOUT);
# setup convert command with font, foreground color, fontsize
# -draw 'text 50,490' gives a nice offset from the top left corner
my $res = qq{ convert -font $font }.
qq{ -fill "#ffffff" -pointsize 601 -draw 'text 50,490 "$text"' }.
qq{ overlays/empty_white_$text.png overlays/done_$text.png};
$res =`$res`; # run the command
|
- Download the attached VeraMoBd.ttf file into your working directory.
- Run the build_text_overlay.pl script
perl build_text_overlay.pl developerWorks .
- Check your overlay image with the command
feh overlays/done_developerWorks.png .
Now that our overlay text is created, we need to create a tiled background image of the same size, then composite the two together.
- Create the backgrounds directory.
- Determine the size of the text overlay with the command
identify overlays/done_developerWorks.png . In this case, we can see that the overlay is 5,600 x 600.
- Create a file called build_background.pl with the following code:
Listing 2. build_background.pl
#!/usr/bin/perl -w
# build_backgroun.pl, creates the tiled background of mosaic images
use strict;
use GD; # image library
use List::Util 'shuffle'; # to randomize the image list
my $im_width = $ARGV[0] or die "specify an image width, height, and filename";
my $im_height = $ARGV[1] or die "specify an image width, height, and filename";
my $filename = $ARGV[2] or die "specify an image width, height, and filename";
my @tilelist = `ls -1 images/`; # create an array of tile images
my @randlist = shuffle(@tilelist); # randomize the array
# create a new image in true color for background only
my $backimage = new GD::Image($im_width,$im_height);
# initialize some colors
my $white = $backimage->colorAllocate(255,255,255);
my $black = $backimage->colorAllocate(0,0,0);
# write the file to disk
open(PNGOUT,"> backgrounds/backimage_$filename.png") or die
"can't write to output file backgrounds/backimage_$filename.png";
print PNGOUT $backimage->png;
close(PNGOUT);
# create a new image in true color
my $image = new GD::Image($im_width,$im_height,1);
my $xpos = 0; # incrementer for x axis
my $ypos = 0; # incrementer for y axis
my $row_total = $im_height / 25; # number of rows for a 600 pixel high image
# for each row
while( $ypos <= $row_total ){
$xpos = 0;
#for each column
while( $xpos <= $im_width ){
# if the random list is all used up, regenerate it
if( @randlist < 1 ){
@randlist = ();
@randlist = shuffle(@tilelist);
}
# remove image from random list so it is not reused in this row
my $currimage = pop @randlist;
# open the image
my $tileimg = newFromJpeg GD::Image( "images/$currimage");
# insert the image into the existing large template
$image->copy($tileimg,$xpos,($ypos*25),0,0,25,25);
# move to next column
$xpos += 25;
}#while xpos < = width
# move to next row
$ypos++;
}#while coutn < $width
# write out the image
open( TILEOUT,"> backgrounds/back_$filename.png") or die
"can't write to backgrounds/back_$filename.png";
print TILEOUT $image->png;
close(TILEOUT);
|
- Run the build_background.pl script with the dimensions determined from the "identify" command:
perl build_background.pl 5600 600 developerWorks .
- Examine the background image with the command
feh backgrounds/back_developerWorks.png .
We have a background image of tiles and white text with transparent background overlay ready to be composited. Create the composite directory, then use the ImageMagick composite command to layer them together:
composite -compose in \
backgrounds/back_developerWorks.png \
overlays/done_developerWorks.png \
composite/step1_developerWorks.png
|
In this case, the -compose in option tells ImageMagick to effectively treat the white layer in the overlay as a pass-through layer, producing a transparent background with the white text filled in with mosaic tiles.
Now apply the white background. This step is necessary because many png readers (such as Internet Explorer), will display the background as black when transparent, instead of white.
composite -compose over \
composite/step1_developerWorks.png \
backgrounds/backimage_developerWorks.png \
composite/complete_developerWorks.png
|
The -compose over option tells ImageMagick to overlay the first image onto the second, creating our final product. View the result by typing feh composite/complete_developerWorks.png . Create a smaller version of the mosaic with convert , like so:
convert -resize 800x600 \
composite/complete_developerWorks.png \
composite/800x600_complete_developerWorks.png
|
Figure 2. developerWorks text overlay ("e" enlarged to show detail)
That's it -- text overlay completed! Repeat the above steps for any text you like and plug in different images for the different text. Add the mosaic to your existing graphical content or print out the image on a large-format printer. You can easily modify the background image-generation code to record the precise coordinate of every tile. Use this information to create a dynamic application to show users where their image is in the mosaic. Read on for the integration of graphics with your mosaics.
Image overlay mosaic
Now that you have created your text overlays, you probably would like to create some graphical overlays. For the purpose of this article, we will use an image of Tux, the Linux penguin. In addition to being litigationally unencumbered, Tux is a great example to use because a large portion of his body is plain white, along with his eyes. This is by no means the only color that can be processed for mosaic creation, but it makes the integration steps easier.
Recall that in the text-overlay example (which is a good candidate for automatic posters for your workplace or organization), you created an image that was a grid of the mosaic pieces, created a white on transparent background of your text of the same size, and overlaid them using the composite -compose -in command (phew!). The same process will apply to the image example, with an additional step at the end. You need to create two masks this time, instead of just one.
- Get a version of the Tux image. There is a nice big (2,400 x 2,796) version available (see Download).
- Open the file in The Gimp, and Isolate Tux from his extra white background. Use the fuzzy select tool, click on the white outside of Tux. Invert the selection, and cut and paste the selection as a new file. Save this file as transparent.tux.png. This will be the default canvas size for the final image.
- Starting from transparent.tux.png, create an exterior for Tux by choosing the fuzzy select tool, clicking on the white of his stomach, then hitting Ctrl+X to remove. Do the same for the white of his eyes and save the file as epi.overlay.tux.png.
Figure 3. Tux exterior
- Starting from transparent.tux.png again, use the select by color tool, and click inside Tux's stomach. This will select all of the white in his stomach and eyes. Use Ctrl+I to invert the selection, and use Ctrl+X to remove all but his white stomach and eyes. Save this as int.overlay.tux.png.
Figure 4. Tux interior
You have just created a white stomach and eyes-only portion of Tux, centered in the image frame. This is equivalent to the white text on transparent background we created in the text overlay example. Now we need to create an image of tiles the size of the Tux frame.
- Determine the size of the Tux background with the command
identify transparent.tux.png . In this case, we can see that the frame is 2,312 x 2,741.
- Build the background with
perl build_background.pl 2312 2741 tux .
- Then we do more composing of the components:
composite -compose in \
backgrounds/back_tux.png \
int.overlay.tux.png step1.png
|
This creates a mosaic tile-filled stomach and eyes of Tux. Then we apply the second mask:
composite -compose over \
step1.png \
epi.overlay.tux.png \
composite/complete_tux.png
|
The -compose over option tells ImageMagick to overlay the first image onto the second, creating our final product. View the result by typing feh composite/complete_tux.png . Create a smaller version of the mosaic with convert , like so:
convert -resize 800x600 \
composite/complete_tux.png \
composite/800x600_complete_tux.png
|
Figure 5. Close-up of Tux head mosaic
Acknowledgement
The Linux Tux images are available at http://www.isc.tamu.edu/~lewing/linux/.
Conclusion
With your current framework and example mosaics, you can build quite a few interesting graphics. I encourage you to experiment with fade percentages, color selections, and all of the other fantastic capabilities of ImageMagick and Perl. You can use this framework, along with open source MPEG software, to extract frames from video and reintegrate them, applying the mask at each frame. Try creating a zoom-in effect with the convert -crop options and make a small movie out of it. Simple mosaic movies of this type are now possible and can make a huge impact in presentations.
Download Description | Name | Size | Download method |
---|
Sample code | os-mosaic_posters.zip | 790KB | HTTP |
---|
Resources Learn
-
Learn all about ImageMagick.
-
Visit Boutell.com to learn what GD is, its API, and see sample code.
-
Find Perl modules that include GD.pm and more at CPAN, the comprehensive Perl archive network.
-
Stay current with developerWorks technical events and webcasts.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
Get products and technologies
-
Download Tom Gilbert's image viewer, feh.
-
If you need the best in image manipulation software, get The Gimp.
-
Download a free trial version of WebSphere Application Server V6.0.
-
Order the SEK for Linux, a two-DVD set containing the latest IBM trial software for Linux from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.
-
Innovate your next open source development project with IBM trial software, available for download or on DVD.
Discuss
-
KernelNewbies.org has lots of resources for people who are new to hacking the kernel: FAQ, IRC channel, mailing list, and wiki.
-
Get involved in the developerWorks community by participating in developerWorks blogs.
About the author | | | Nathan Harrington is the lead programmer on the Resource Locator project within IBM, and has been working with Linux and open source tools to streamline IBM's business for four years. |
Rate this page
| |