Article
2803
Automatic 80x15 banner and driver image generation
Table of Contents
Introduction
Content of the attached archive
Using the scripts
The generate_80x15banner Script
The generate_driverimage Script
Technical Details
Easy parsing of command-line options
The Python Imaging Library (PIL)
Banner Script Details
Driver Image Script Details
Summary
Introduction
In IDM projects, it is always nice to customize the nice graphics in the different web applications. A couple of years ago, I wrote an Icon Generator tool in Java using ImageMagick, but it was not very easy to port on different platforms.
![]()
This article shows you how to generate an iManager driver image using Python scripting. It could be interesting to script the creation of your iManager icons, as you can embed version numbers, environment types (DEV, TEST, PROD), and other dynamic useful information in the image. In the attached archive, you will also find a pack of free backgrounds and icons you can use to create your driver icons.
Here are a couple of driver images you can immediately generate, using the generate_driverimage script:


As a bonus, you will also find a script that generates famous 80x15 pixels banners, like these:


Here are some sample images you can easily generate:

Content of the attached archive
Here is the content of the file scriptingimages.zip:
\__ ./ScriptingImages
|__ generate_80x15banner
|__ generate_driverimage
|__ test_banner_samples.sh
|__ test_driverimage_samples.sh
|__ clean_banner_samples.sh
|__ clean_driverimage_samples.sh
|__ docs
| |__ images_scriptingimages
| | \__ *.png, *.gif
| |__ scriptingimages.html
| \__ scriptingimages.txt
|__ img
| |__ system
| | |__ default-back.png
| | |__ default-icon.png
| | |__ driver-icon-mask.png
| | \__ driver-icon.png
| |__ backgrounds
| | \__ *.png, *.gif, *.jpg
| \__ icons
| \__ *.png, *.gif
\__ fonts
|__ font_bold.ttf
|__ slkscrb.ttf
|__ slkscre.ttf
|__ font_normal.ttf
|__ slkscreb.ttf
\__ slkscr.ttf
Details:
generate_80x15banner: Example script on how to create a new image using the Python Imaging Library (PIL), GIF, PNG, JPG and all other formats supported by PILgenerate_driverimage: Creates a Driver Image to be used in iManager with background, icon and text (transparent GIF output format)test_banner_samples.sh: Creates fourple 80x15 banners with different colorstest_driverimage_samples.sh: Creates sixiver image samplesclear_banner_samples.sh: Deletes the banner samplesclear_driverimage_samples.sh: Deletes the driver image samplesfonts/*.ttf: Sale fonts for the driver script and the banner scriptimg/system/*.png: Sstem images used to create the driver imageimg/backgrounds/*: Sample images for backgroundsimg/icons/*: Sample images for iconsdocs/scriptingimages.txt: Wiki source of this articledocs/scriptingimages.html: Result of the conversion from Wiki to HTML (see Wiki to CoolSolutions Converter)docs//communities/files/u3740/ScriptingImages_*: All pictures used in this article
Using the Scripts
The generate_80x15banner Script
You can call the script using a number of options from the command line. You can get the list of options anytime using the -h or --help option:
/ScriptingImages> ./generate_80x15banner -h
usage: generate_80x15banner [options] output.ext
generate 80x15 banner in various format (PNG, GIF, JPEG)
-h or --help for help
options:
--version show program's version number and exit
-h, --help show this help message and exit
-c, --changelog display changelog
--width=WIDTH width of block 1 [default: 18]
--font1=FONT1 font for block 1 [default: fonts/slkscr.ttf]
--font2=FONT2 font for block 2 [default: fonts/slkscr.ttf]
--size1=SIZE1 font size for block 1 [default: 8]
--size2=SIZE2 font size for block 2 [default: 8]
--text1=TEXT1 text for block 1 [default: MY]
--text2=TEXT2 text for block 2 [default: SOLUTIONS]
--color1=COLOR color for text 1 [default: #ffffff]
--color2=COLOR color for text 2 [default: #ffffff]
--back-color1=COLOR background color for block 1 [default: #8fd5f3]
--back-color2=COLOR background color for block 2 [default: #209ce8]
--border-color=COLOR border color [default: #000000]
You can generate a simple default banner using the following command:
./generate_80x15banner mybanner.png
Here is the result of the command:

Here are some sample commands to generate different kind of images:
./generate_80x15banner banner1.png ./generate_80x15banner --back-color1=#68b838 --back-color2=#bce5a3 banner2.png ./generate_80x15banner --back-color1=#f28523 --back-color2=#f3d0b1 banner3.png ./generate_80x15banner --back-color1=#ec2028 --back-color2=#fbc6c8 banner4.png
The generate_driverimage Script
You can call the script using a number of options from the commandbline. You can get the list of options anytime using the -h or --help option:
/ScriptingImages> ./generate_drivericon -h
usage: generate_drivericon [options] output.gif
generate drivericon in GIF format
-h or --help for help
options:
--version show program's version number and exit
-h, --help show this help message and exit
-c, --changelog display changelog
--font1=FONT1 font for line 1 [default: fonts/font_bold.ttf]
--font2=FONT2 font for line 2 [default: fonts/font_bold.ttf]
--font3=FONT3 font for line 3 [default: fonts/font_normal.ttf]
--font4=FONT4 font for line 4 [default: fonts/font_normal.ttf]
--size1=SIZE1 font size for line 1 [default: 8]
--size2=SIZE2 font size for line 2 [default: 8]
--size3=SIZE3 font size for line 3 [default: 8]
--size4=SIZE4 font size for line 4 [default: 8]
--text1=TEXT1 text for line 1 [default: Customer]
--text2=TEXT2 text for line 2 [default: IDM Project]
--text3=TEXT3 text for line 3 [default: eDir-TEST-SYS_A]
--text4=TEXT4 text for line 4 [default: Identity Provider]
--color1=COLOR1 color for line 1 [default: #000000]
--color2=COLOR2 color for line 2 [default: #000000]
--color3=COLOR3 color for line 3 [default: #000000]
--color4=COLOR4 color for line 4 [default: #000000]
--icon=ICON icon image [default: img/system/default-icon.png]
--icon-size=SIZE icon image max height and width [default: 24]
--no-icon no icon image
--back-image=IMAGE background image [default: img/system/default-back.jpg]
--brightness=FACTOR background brightness [default: 1.5]
--contrast=FACTOR background contrast [default: 0.95]
You can generate a default simple driver image using the following command:
./generate_driverimage mydriver.png
Here is the result of the command:

Here are some sample commands to generate different kind of images:
./generate_drivericon --text1=Company1 --text2="IDM Project" --text3="SAP Driver" --text4="TEST 2008.02.28" --icon=img/icons/Globe1.png --back=img/backgrounds/saphr.png --brightness=1.5 --contrast=1.2 sample1.png ./generate_drivericon --text1=Company2 --text2="IDM Project" --text3="ID Server" --text4="DEV 2008.02.28" --icon=img/icons/Utilknife.png --back=img/backgrounds/novell.png --brightness=1.5 --contrast=1.2 sample2.png ./generate_drivericon --text1=Company2 --text2="IDM Project" --text3="Auth Driver" --text4="PROD 2008.02.28" --icon=img/icons/Autorization.png --back=img/backgrounds/pics.jpg --brightness=1.4 --contrast=1.1 sample3.png ./generate_drivericon --text1=Company2 --text2="IDM Project" --text3="LOOPBACK" --text4="PROD 2008.02.28" --icon=img/icons/Gear.png --back=img/backgrounds/novell.png --brightness=1.5 --contrast=1.2 sample4.png ./generate_drivericon --text1=Company3 --text2="IDM Project" --text3="PKI Integration" --text4="PROD 2008.02.28" --icon=img/icons/GPG-Signature-OK-Alt.png --back=img/backgrounds/pics.jpg --brightness=1.4 --contrast=1.1 sample5.png ./generate_drivericon --text1=Company3 --text2="IDM Project" --text3="Valentine's Day" --text4="PROD 2008.02.14" --icon=img/icons/Rose.png --back=img/backgrounds/pics.jpg --brightness=1.4 --contrast=1.1 sample6.png
Technical Details
Easy parsing of command-line options
Python offers a very easy and powerfull way to handle command-line arguments and options using the OptParser module. This feature has already been discussed in the Automatic Role Matrix article. Have a look at it!
The Python Imaging Library (PIL)
The Python Imaging Library offers a variety of utility classes to manipulate your images. You can load, create new, crop, merge, apply filters, etc. on images from a wide range of formats (GIF, PNG, JPG, etc.).
Here are some interesting modules you can use:
- The Image module lets you do basic operations on images such as loading, saving, creating, resizing, combining, and get information.
- The ImageChops module lets you do operations on images such as adding, substracting, multiplying, and blending images, like you can do on Gimp or Photoshop layers.
- The ImageDraw module lets you draw on your images, adding text, lines, and shapes.
- The ImageEnhance module lets you adjust the brightness, contrast, and sharpness of your images.
- The ImageFont module lets you use PIL fonts or TrueType fonts.
- The ImageOps module offers you pre-defined filters, such as equalize, colorize, deform, crop, mirror, and posterize.
- The ImageFilter module offers filters such as blur, contour, emboss, find edges, smooth, and sharpen.
The different parts of the generate_banner80x15 script are explained in this section.
1. The first part specifies the modules to import. The Image, ImageDraw and ImageFont modules from PIL are used here. The OptionParser class lets you handle command-line options and arguments, and the sys module offers a few useful functions:
#!/usr/bin/python import Image, ImageDraw, ImageFont from optparse import OptionParser import sys
2. The next part handles command-line options and arguments using the OptionParser class:
changelog = [ "28/02/2008 - v0.1 - 80x15 simple banner generation" ]
usage = """%prog [options] output.ext
generate 80x15 banner in various format (PNG, GIF, JPEG)
-h or --help for help"""
# Handle command-line options and arguments
parser = OptionParser(usage=usage, version="%prog - 28/02/2008 - v0.1 - Reza Kalfane")
parser.add_option( "-c", "--changelog", action="store_true", dest="changelog", help="display changelog" )
parser.add_option( "--width", type="int", dest="width", default=18, help="width of block 1 [default: %default]" )
parser.add_option( "--font1", dest="font1", default="fonts/slkscr.ttf", help="font for block 1 [default: %default]" )
parser.add_option( "--font2", dest="font2", default="fonts/slkscr.ttf", help="font for block 2 [default: %default]" )
parser.add_option( "--size1", type="int", dest="size1", default=8, help="font size for block 1 [default: %default]" )
parser.add_option( "--size2", type="int", dest="size2", default=8, help="font size for block 2 [default: %default]" )
parser.add_option( "--text1", dest="text1", default="MY", help="text for block 1 [default: %default]" )
parser.add_option( "--text2", dest="text2", default="SOLUTIONS", help="text for block 2 [default: %default]" )
parser.add_option( "--color1", dest="color1", metavar="COLOR", default="#ffffff", help="color for text 1 [default: %default]" )
parser.add_option( "--color2", dest="color2", metavar="COLOR", default="#ffffff", help="color for text 2 [default: %default]" )
parser.add_option( "--back-color1", dest="back_color1", metavar="COLOR", default="#8fd5f3", help="background color for block 1 [default: %default]" )
parser.add_option( "--back-color2", dest="back_color2", metavar="COLOR", default="#209ce8", help="background color for block 2 [default: %default]" )
parser.add_option( "--border-color", dest="border_color", metavar="COLOR", default="#000000", help="border color [default: %default]" )
(options, args) = parser.parse_args()
3. Once the options and arguments are parsed, you need to verify that everything is valid. Here, you need to handle the changelog option and to verify that an output file is specified:
# Display changelog if options.changelog: print "\n".join( changelog ) sys.exit() if len(args) != 1: parser.error( "output filename not provided" )
4. To begin manipulating images, you can create a new 80x15 blank image:
# Create new image banner = Image.new( "RGB", ( 80, 15 ), "#ffffff" ) draw = ImageDraw.Draw( banner )
5. From there, draw a 1-pixel border with the color specified by options:
# Create a black border draw.rectangle( [ ( 0, 0 ), ( 79, 14 ) ], outline=options.border_color )

6. The next step is to build the two colored blocks:
# Create blocks draw.rectangle( [ ( 2, 2 ), ( 2 + options.width, 12 ) ], fill=options.back_color1 ) draw.rectangle( [ ( 2 + 2 + options.width, 2 ), ( 77, 12 ) ], fill=options.back_color2 )

7. Then add the two texts for the diffferent blocks and save the result:
# Add texts font1 = ImageFont.truetype( options.font1, 8) font2 = ImageFont.truetype( options.font2, 8) draw.text( ( 5, 3 ), options.text1, font=font1, fill=options.color1 ) draw.text( ( 5 + 2 + options.width, 3 ), options.text2, font=font2, fill=options.color2 ) # Save banner try: banner.save( args[0] ) except: print "could not save image (invalid format or path)"

This script is very simple and will help you get started with the Python Imaging Library. Now let's see what we can do with more advanced features ...
The different parts of the generate_driverimage script are explained here.
1. The first part specifies the modules to import. From the PIL library we are using Image, ImageOps, ImageChops, ImageDraw, ImageFont and ImageEnhance!
#!/usr/bin/python import Image, ImageOps, ImageChops, ImageDraw, ImageFont, ImageEnhance from optparse import OptionParser import sys
2. The next part handles command-line options and arguments:
changelog = [ "27/02/2008 - v0.1 - driver icon generation" ]
usage = """%prog [options] output.gif
generate drivericon in GIF format
-h or --help for help"""
# Handle command-line options and arguments
parser = OptionParser(usage=usage, version="%prog - 27/02/2008 - v0.1 - Reza Kalfane")
parser.add_option( "-c", "--changelog", action="store_true", dest="changelog", help="display changelog" )
parser.add_option( "--font1", dest="font1", default="fonts/font_bold.ttf", help="font for line 1 [default: %default]" )
parser.add_option( "--font2", dest="font2", default="fonts/font_bold.ttf", help="font for line 2 [default: %default]" )
parser.add_option( "--font3", dest="font3", default="fonts/font_normal.ttf", help="font for line 3 [default: %default]" )
parser.add_option( "--font4", dest="font4", default="fonts/font_normal.ttf", help="font for line 4 [default: %default]" )
parser.add_option( "--size1", type="int", dest="size1", default=8, help="font size for line 1 [default: %default]" )
parser.add_option( "--size2", type="int", dest="size2", default=8, help="font size for line 2 [default: %default]" )
parser.add_option( "--size3", type="int", dest="size3", default=8, help="font size for line 3 [default: %default]" )
parser.add_option( "--size4", type="int", dest="size4", default=8, help="font size for line 4 [default: %default]" )
parser.add_option( "--text1", dest="text1", default="Customer", help="text for line 1 [default: %default]" )
parser.add_option( "--text2", dest="text2", default="IDM Project", help="text for line 2 [default: %default]" )
parser.add_option( "--text3", dest="text3", default="eDir-TEST-SYS_A", help="text for line 3 [default: %default]" )
parser.add_option( "--text4", dest="text4", default="Identity Provider", help="text for line 4 [default: %default]" )
parser.add_option( "--color1", dest="color1", default="#000000", help="color for line 1 [default: %default]" )
parser.add_option( "--color2", dest="color2", default="#000000", help="color for line 2 [default: %default]" )
parser.add_option( "--color3", dest="color3", default="#000000", help="color for line 3 [default: %default]" )
parser.add_option( "--color4", dest="color4", default="#000000", help="color for line 4 [default: %default]" )
parser.add_option( "--icon", dest="icon_image", metavar="ICON", default="img/system/default-icon.png", help="icon image [default: %default]" )
parser.add_option( "--icon-size", type="int", dest="icon_size", metavar="SIZE", default=24, help="icon image max height and width [default: %default]" )
parser.add_option( "--no-icon", action="store_true", default=False, dest="no_icon", help="no icon image" )
parser.add_option( "--back-image", dest="background_image", metavar="IMAGE", default="img/system/default-back.png", help="background image [default: %default]" )
parser.add_option( "--brightness", type="float", dest="brightness", metavar="FACTOR", default=1.5, help="background brightness [default: %default]" )
parser.add_option( "--contrast", type="float", dest="contrast", metavar="FACTOR", default=0.95, help="background contrast [default: %default]" )
(options, args) = parser.parse_args()
3. When the options and arguments are parsed, you can verify that everything is valid:
# Display changelog if options.changelog: print "\n".join( changelog ) sys.exit() if len(args) != 1: parser.error( "output filename not provided" )
4. Define in the script the information about the Driver Image such as sizes, offsets, etc.
# Driver image configuration image_width = 98 image_height = 79 inside_width = 67 inside_height = 53 offset_x = 12 offset_y = 16 icon_box = 32
5. Load the system images used to build the final driver image:
# Load all system images mask_image = Image.open( "img/system/driver-icon-mask.png" ) driver_image = Image.open( "img/system/driver-icon.png" ) blank_image = Image.new( "RGBA", ( image_width, image_height ) )
![]()
![]()
6. Open the icon and background images:
# Icon and background images icon_image = Image.open( options.icon_image ) background_image = Image.open( options.background_image )
7. Prepare the background, starting with the background image. The following code resizes the background image so it can fit inside the driver image:
# Prepare background prepared_background = ImageChops.duplicate( blank_image ) resized_background_image = background_image.resize( ( inside_width, inside_height ), Image.ANTIALIAS )

8. Use the ImageEnhance module to adjust the brightness:
# Makes the image lighter enhancer = ImageEnhance.Brightness( resized_background_image ) resized_background_image = enhancer.enhance( options.brightness )

9. Again with the ImageEnhance module, you can adjust the contrast of the background:
enhancer = ImageEnhance.Contrast( resized_background_image ) resized_background_image = enhancer.enhance( options.contrast )

10. Paste the prepared background on a new image, using a mask to fit the result inside the driver image:
# Cut out the background prepared_background.paste( resized_background_image, ( offset_x, offset_y ) ) prepared_background2 = ImageChops.duplicate( blank_image ) prepared_background2.paste( prepared_background, ( 0, 0 ), mask_image )

11. Add texts using the different fonts and colors chosen through the options:
# Add text on the background draw = ImageDraw.Draw( prepared_background2 ) font1 = ImageFont.truetype( options.font1, options.size1 ) font2 = ImageFont.truetype( options.font2, options.size2 ) font3 = ImageFont.truetype( options.font3, options.size3 ) font4 = ImageFont.truetype( options.font4, options.size4 ) draw.text( ( 17, 20 ), options.text1, font=font1, fill=options.color1 ) draw.text( ( 17, 30 ), options.text2, font=font2, fill=options.color2 ) draw.text( ( 17, 42 ), options.text3, font=font3, fill=options.color3 ) draw.text( ( 17, 52 ), options.text4, font=font4, fill=options.color4 )

12. Using the driver image template, you can multiply the result and obtain the inside of the driver image:
# Merge prepared background with driver image final_driver_image = ImageChops.multiply( prepared_background2, driver_image.convert( "RGBA" ) )

13. You now have a composite image with the inside and the driver image:
final_driver_image = ImageChops.composite( final_driver_image, driver_image, mask_image )

14. If an icon is specified, you can resize it to fit in a small box:
# Add icon on the top left if options.no_icon == False: ( iconw, iconh ) = icon_image.size maxborder = max( iconw, iconh ) width = iconw * options.icon_size / maxborder height = iconh * options.icon_size / maxborder icon_image_resized = icon_image.resize( ( width, height ), Image.ANTIALIAS )

15. Finally, paste the icon onto the driver image:
final_driver_image.paste( icon_image_resized.convert( "RGB" ), ( 0, 0 ), icon_image_resized.convert( "RGBA" ) ) # Save final image in PNG format final_driver_image.save( args[0], "PNG" )

In this script, you can see how to use more advanced features such as multiplying and combining images using masks, which can be very useful. The resulting image is in .PNG format. It works fine on my iManager accessed with Firefox, but it might be a problem with Internet Explorer, which does not always handle .PNG files properly. You can always convert the result to .GIF format using Gimp or Photoshop. For the moment, I couldn't find an easy way to handle .GIF transparency using PIL, but I am sure you will find a solution!
Summary
Using the Python Imaging Library, you can generate specific images such as banners, buttons, or driver images, as explained in this article. You can also generate background images and logos for mobile phones. The library looks almost as powerfull as ImageMagick, so have a look at it! Now you can use your creativity to create interesting imaging scripts.
If you create scripts to customize iManager or UserApp, keep me posted!
| Attachment | Size |
|---|---|
| ScriptingImages.zip | 1.03 MB |
| default_banner.png | 583 bytes |
| default_driver.png | 11.94 KB |





0