ISOLINUX/SYSLINUX splash image mini-HOWTO

By: Frank Rysanek <Frantisek DOT Rysanek AT post DOT cz>

Introduction

Isolinux by H. Peter Anvin is one of a family of nifty gadgety bootloaders - the original ancestor is maybe syslinux, there are brothers called memboot and pxeboot.

Isolinux can load a neat splash-screen image. E.g. in RedHat, it's stored on the CD No.1 in /isolinux/splash.lss.
Its creation is not quite documented and there are some myths in the area. The goal of this mini-HOWTO is to document the creation of this image.

What you need

You'll need a util (it's really a Perl script) called ppmtolss16, from the syslinux package. As of version 2.04 of syslinux, this Perl script had a bug - it didn't set binmode(STDIN) and binmode(STDOUT), as a result of which Perl was doing some text-wise conversions on its input and output... - my patched version of the file can be downloaded from a local copy.
The syslinux package including the source code can be downloaded from www.kernel.org - that's where the Linux kernel sources come from.

Next, you need the giftoppm tool - this is a part of an elderly package called PBM Plus. It is really out of date (updated around 1992 - real archaeology now), it doesn't seem to have a primary download site, its successor is called netpbm - it's just that netpbm doesn't contain giftoppm anymore. So, you really need the original PBM Plus.
Alternatively, you can get any other software capable of PPM export - but then you're on your own with palette processing (see below). Now I have a rather dated version of Gimp - if Gimp can export PPM by now, you can probably skip giftoppm and PBM Plus altogether.

If you decide to go with PBM Plus, know ye, that you'll have a problem compiling it on a reasonably new Linux (mine is a RedHat 8.0). If you understand recent C libraries on Linux and Makefiles, you can probably get out of the gotchas yourselfs - the GCC is surprisingly backwards compatible :)
Namely, you have to replace sys_errlist[errno] with strerror(errno) in pbm/libpbm1.c, in ./libtiff/Makefile you have to toggle two defines to read -DUSE_VARARGS=0 and -DUSE_PROTOTYPES=1 and `make libtiff.a` in this directory explicitly, before anything else will compile (corrupt dependencies in the Makefiles). Perhaps there's more - I don't remember.

Alternatively, you can donwload my corrected source tree of PBM Plus from a local mirror.. Unzip with

tar tvjf pbmplus.tar.bz2

For image processing, I recommend the Gimp.

In the following text, there are also references to giftrans (from the giftrans-* RPM) and mogrify (from the ImageMagick RPM).

The recipe

The .lss format consists of a simple header and a RLE-compressed section with indexed palette. It's capable of 16 colors out of 2^^18 (6 bits per RGB channel per pixel). See the Perl source of ppmtolss16 for details.

The ppm (portable pixmap) seems to be quite a venerable creature. It's got a simple text-based header and an uncompressed (RAW) data section, 24bpp (three bytes per pixel). The recommended converter is giftoppm, to take advantage of the GIF's indexed palette.

For a start, get a bitmap image of your splash screen. Please be aware that the final splash image will be 640 pixels wide (the basic VGA screen width) with 4bpp color depth (16 colors) - we'll be trying to get maximum possible image quality out of that :)
In other words, your master image should not contain too much detail, it will vanish in the downconversions anyway.

Load/prepare that image in Gimp - at this stage you can work in true-color RGB mode. Convert it to 640x[something].
The vertical dimension should be definitely less then 480 pixels and please be aware that you need some space below your image on the splash screen for your welcome text - at least one line for the boot prompt. To sum up, 200 - 300 pixels might be an appropriate height.
To downsample your image in Gimp to the required resolution, press right mouse button on the image to get into the context menu, choose image->image size, enter 640 for the horizontal dimension. If you leave the X/Y lock on, your X/Y ratio should remain OK.

Next, we need to downsample the color depth to 16 colors. This is done in [context menu]->Image->Mode - select "indexed".
Our target number of colors is 16. Hey, wait a moment. Not so fast. Consider setting this to 15 or 14, to save one or two slots in the index table for one or two text colors. Alternatively, you can select suitable text colors from your resulting image and use them in your boot.msg (or whatever your welcome screen text is called).
In this Gimp indexing dialog, you can also select an appropriate palette optimization method. For images originating in photoes, with a large number of color shades, use one of the Floyd-steinberg dithering methods. This produces mellow random noise in the resulting image, greatly reducing the effects of low color depth. If OTOH you have a flat-color company logo, choose "no dithering" - your company colors will be slightly shifted but clean.

Please note that if you're already in indexed mode, e.g. as a result of loading an 8bpp GIF as a master image of your splash screen, you need to swich to RGB mode first and then back to indexed, in order to get to the index generation screen, to get the palette down to 16 colors.
The color palette can be checked using [context menu]->dialogs->indexed palette. Or, using the giftrans tool, by typing `giftrans -l' (text mode numeric output). Or, you can also check it with the hex mode in Midnight Commander viewing the resulting .LSS in raw hex mode (F3,F4).

Some suggest that the color reduction can be done from the command-line using `mogrify -colors 14 <filename.gif>`. Note that its output file is called <filename.mgk> - the original .GIF remains intact.

So we have a .gif with an optimized palette reduced to 16 colors. Next, we need to convert it to .lss, with an intermediate step via .ppm.
The first step is easy:

giftoppm image.gif >image.ppm

Please note that the ppm file is a true-color format (no indexing) - but the index is recovered by ppmtolss16 and using basic statistics you can deduce that the recovered palette in the .lss will exactly match that of the reduced .gif.
Now the second step, using ppmtolss16, is more complicated. We still need to choose an appropriate text color. Please note that normal text on a CRT is not shiny white (#ffffff) but gray (about #d0d0d0). If you need something special, you may choose e.g. pistacchia green: #c0cfc0. Isolinux is using color index number 7 for the basic text color - so we need to make sure that our pistacchia will be at index 7 in the table. The ppmtolss16 can handle this for us - it will reserve the indicated slot in the index table for the color shade indicated by us. If the recovered index table has less than 16 colors, the color table will be shuffled in a lossless way to accomodate our additional color(s) at the desired slot(s).
./ppmtolss16 '#c0cfc0=7' <image.ppm >image.lss

Now if you already ate all the 16 slots in the Gimp indexing dialog, you can choose to occupy one color slot with your desired shade, thus shifting the least frequent color from your optimized palette, setting all pixels in your image referring to that slot to index zero (black), possibly introducing horrible color distortion. Or, you can select one color from the existing palette for your text. Your custom text in boot.msg can be set to any color index, I'm not sure about the boot prompt though.

Someone on the internet has suggested to swap color indices in the .gif image (so that our chosen color is at index 7) using

giftrans -g 11=7

This is IMO a misunderstanding (experimentally proven). This command does not *swap* the two index slots. Rather, it sets the color value of index 7 to the value taken from index 11 (or the other wey around, even?), effectively distorting the palette in a completely unwanted way.

Choice of filename

While I was struggling to get the splash image to load, one of my findings was that isolinux.bin is sensitive to filename. For some reason, I had a problem with CD-LOGO.lss. The original RedHat images are called splash.lss. Then I chose cdlogo.lss and it worked.

H. Peter Anvin, the author of Isolinux, has reminded me of one important detail - thanks again for the quick response.

Isolinux undestands only the original ISO9660 format - without Joliet extensions. The original standard says that names are case-insensitive, internally stored in UPPERCASE form, max. 64 characters long, with up to one dot (period). Joliet extensions translate long or otherwise non-standard names to modified names that are ISO-compliant and yet unique within the file system. There's a visible trace of this shim - the TRANS.TBL file in every directory on a Joliet CD, that is explicitly visible under Linux (and hidden under Windows, AFAIK).

Now I did enable Joliet extensions in mkisofs when mastering my CD - I had some strange filenames that I needed to transfer without damage.
When I chose a name with uppercase letters for the .lss file, even though I was in Linux, the Joliet support in mkisofs has converted my name to some garbled internal ISO9660 name, that finally got burned on the CD. As a result, the true ISO9660 name was different and Isolinux couldn't find the Joliet-compliant name that I was referring to in my boot.msg. Even though I could see my original name on the burned CD - obviously because the Joliet shim layer in the Linux kernel converted it back according to isolinux/TRANS.TBL :)

Therefore my recommendation is: use all lowercase names with exactly one dot, no spaces, perhaps no dashes and underscores. Otherwise be prepared to burn the CD over and over to find out where the gremlins are hiding.

That's all folks :)

Well, almost. There's a small script that can do a lot of the above. Saves typing.

Last update: 12 June 2003