This is an archived cached-text copy of the developerWorks article. Please consider viewing the original article at: IBM developerWorks



IBM®
Skip to main content
    Country/region [select]      Terms of use
 
 
    
     Home      Products      Services & industry solutions      Support & downloads      My IBM     
skip to main content

developerWorks  >  Open source | Linux  >

Create mosaic images with Perl and ImageMagick

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


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).



Back to top


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.

  1. 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
Feh thumbnail mode
  1. 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.
  2. 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.


Back to top


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:

  1. Create the overlays directory.
  2. 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


  1. Download the attached VeraMoBd.ttf file into your working directory.
  2. Run the build_text_overlay.pl script perl build_text_overlay.pl developerWorks.
  3. 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.

  1. Create the backgrounds directory.
  2. 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.
  3. 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);


  1. Run the build_background.pl script with the dimensions determined from the "identify" command: perl build_background.pl 5600 600 developerWorks.
  2. 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)
developerWorks text overlay

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.



Back to top


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.

  1. Get a version of the Tux image. There is a nice big (2,400 x 2,796) version available (see Download).
  2. 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.
  3. 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
Tux exterior
  1. 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
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.

  1. 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.
  2. Build the background with perl build_background.pl 2312 2741 tux.
  3. 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
Close-up of Tux head mosaic


Back to top


Acknowledgement

The Linux Tux images are available at http://www.isc.tamu.edu/~lewing/linux/.



Back to top


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.




Back to top


Download

DescriptionNameSizeDownload method
Sample codeos-mosaic_posters.zip790KBHTTP
Information about download methods


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


Please take a moment to complete this form to help us better serve you.



YesNoDon't know
 


 


12345
Not
useful
Extremely
useful
 


Back to top



    About IBM Privacy Contact