Automated GIMP Processing of Web Site Images

Take advantage of The GIMP to perform mundane but needed image processing for Web sites.
Images with a 1-Bit Alpha Channel

As a first example, suppose we have an image file that has full 8-bit transparency and we want to export that image as a GIF with only one bit of alpha mask. To make this image look best, we first should perform some processing on pixels that are not either fully opaque or fully transparent. Such semi-transparent pixels should be mixed with a desired background color in order not to appear jagged on the Web site.

The image is a button (Figure 3) with the soft shadow blended to a gray background. If this button is exported to an image with a single-bit alpha mask without any special treatment, it may look poor. Aliasing with the gray background will be merged into the exported image itself, and if the Web site has a different colored background, it will not give a pleasing appearance, as shown in Figure 4. Ignoring the bad choice of bright green as a background, the edges are extremely jagged, and the soft shadow effect is lost.

Figure 3. Button with a Gray Background behind a Soft Shadow

Figure 4. Button intended to have a gray background behind a soft shadow, exported with a single-bit alpha mask and overlayed on a different color background.

The code shown in Listing 2 takes any image file supported by The GIMP, an output file path and an expected background color, and creates an output image that is suitable for using with a 1-bit alpha mask. Both the input and output images can be anything The GIMP can read or write. For this script, it is most likely reading an xcf file and writing a PNG file. The PNG image is processed later with an export to the webgif script to obtain the final image.

Let's walk through the code in Listing 2. First, The GIMP API is imported, and then the main function of the script is declared with its arguments clearly stated as variables. Skipping the function itself for now, there is a register call at the bottom of the script giving some metadata for The GIMP as to where this script should appear in menus and the number and types of arguments it expects along with a reference to the above function that actually does the work. There is a tiny bit of argument checking before handing control over to The GIMP.

With the metadata-handling code out of the way, let's go back to the monkeyiq_gimp_convert function. The nominated image file is loaded and a new layer, $layer, is created with the same dimensions as the image itself, and it will be filled with the nominated background color. This new layer is then put to the bottom, and visible layers are merged. This makes all the transparency in the image be evaluated against the new background layer's color. In the case of our button on a gray background, assuming the input xcf file has the gray background layer hidden, if the script is run with the bright green background color nominated, the soft drop shadow is blended with the green in accordance with each pixel's old alpha values. Next, a selection is performed using the nominated background color, and that selection is inverted. So, the selection should contain everything in the image and effectively be defining a single-bit alpha mask for what pixels should be fully transparent in the image.

The next block adds another new layer to the image, $newlayer, with a transparent color, and then it copies and pastes the selection from the above merged layer (everything other than the background color) into the new layer. We don't need the old merged image layer anymore, so it is set to hidden and only the new layer is shown.

The result is that the new layer contains the old image data that has had any partially transparent pixels merged with the nominated background color. There is a only a single color that is transparent, and the rest are fully opaque.

The imageOutput function is a little utility function in the MonkeyIQGIMP module that handles saving to native GIMP xcf files, but it also does something sane if a non-xcf file is desired. Parts of MonkeyIQGimp are shown in Listing 3. The imageOutput function simply dispatches to one of the gimp_*_save() functions with the only difference being that for non-native formats, first getMergedLayer() is called to get a single layer to export. In getMergedLayer(), if there is only a single layer, we are done; otherwise, we merge the visible ones and return that. If there is more than one layer, but none of them are visible, the code creates a single layer to return to avoid runtime errors from calling code. If nothing is visible, it's the same as saving a fully transparent layer.