Article

rkalfane's picture
article
Reads:

5302

Score:
4
4
7
 
Comments:

0

Scripting Images

(View Disclaimer)

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.

IDM Icon Generator

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:

Sample 1 Sample 2 Sample 3

Sample 4 Sample 5 Sample 6

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

Example 1

Example 2

Here are some sample images you can easily generate:

Banner 1 Banner 2 Banner 3 Banner 4


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 PIL
  • generate_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 colors
  • test_driverimage_samples.sh: Creates sixiver image samples
  • clear_banner_samples.sh: Deletes the banner samples
  • clear_driverimage_samples.sh: Deletes the driver image samples
  • fonts/*.ttf: Sale fonts for the driver script and the banner script
  • img/system/*.png: Sstem images used to create the driver image
  • img/backgrounds/*: Sample images for backgrounds
  • img/icons/*: Sample images for icons
  • docs/scriptingimages.txt: Wiki source of this article
  • docs/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:

default_banner.png

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:

default_driver.png

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.

Banner Script Details

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 )

 

banner_step02.png

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 )

banner_step03.png

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

banner_step04.png

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

Driver Image Script Details

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

driver-icon.png

driver-icon-mask.png

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 )

step01.png

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 )

step02.png

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 )

step03.png

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 )

 

step05.png

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 )

 

step06.png

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

 

step07.png

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 )

 

step08.png

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 )

 

step09.png

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

step10.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!

AttachmentSize
ScriptingImages.zip1.03 MB
default_banner.png583 bytes
default_driver.png11.94 KB

Disclaimer: As with everything else at Cool Solutions, this content is definitely not supported by Novell (so don't even think of calling Support if you try something and it blows up).

It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.




User Comments

© 2013 Novell