Monday, May 22, 2017

Creating images for legacy PC VGA display

Recently I came across the problem of creating bitmap images for VGA color display: the famous int 10h - 13h mode. Don't ask me why I needed it - I have used DOSBox for emulation. The question was how do I create images for this display more in a way that the pixels can be easily copied directly from the file into the display memory. This means two things:

  1. No image compression
  2. Image needs to be fit to VGA 256 palette 
  3. Maybe resizing
Since I haven't found resources I took the "challenge" and write you how I did it. Though it is not rocket-science it might help you save some precious time.

You are going to need GIMP. I'm sure it can be done with PS, but GIMP is open source ;-)

Step one

Take any image you want. Of course, you need to keep in mind the limitations of VGA mode. Most likely you will need to downscale the image and most of the colors will be lost.

Step two

Install VGA palette to GIMP. It is not included in GIMP by default. I took the palette definition file from here. Thanks to icebreaker (Szabolcs Mihali).

You need to download the "VGA.gpl" file from the link above and import it to GIMP. I have just copied it to the palette folder of your GIMP installation. On my Windows installation it was "c:\Program Files\GIMP 2\share\gimp\2.0\palettes". But it is just me and I tend to do shortcuts when talking about GUI. 

The proper way to import the palette is to open palettes dialog by going to Windows -> Dockable Dialogs -> Palettes. When the dialog is open right click in the list of palettes and select Import from the context menu. Then navigate to the gpl file and select it. Voila!

Step 3

Convert image to VGA mode. Select Image -> Mode -> Indexed... in the menu. It will open the Indexed Color Conversion dialog in GIMP. You have to select the custom palette option from the colormap radio buttons. 

Important not to use the "Remove unused colors from colormap" feature. It will break the original goal of being able to copy the contents directly to the VGA memory because if remaps the color values.

Hit Convert. After this your image might seem less nice because of the downgrading of colors.

Step 4

Here we might need to resize the image. Open Image -> Scale image...

I have chosen to fit the image to the 320x200 pixels of the VGA display but you can resize the image as you please. 

You can hit "Scale" and your image will probably look smaller :)

Step 5

Exporting to BMP format. BMP raw is a very simple image format where the pixels are kept "as is" in the file. We are exporting the image to this format by clicking File -> Export As...

Here you have to give the file ".bmp" extension like "ibm_at.bmp". After it hit "Export" and you will get the following dialog. I select "Do not write color space information" because it is not needed for this application and it saves memory.

Now you have a BMP image whose pixel data can directly copied into the VGA memory. It looks like this in DOSBox:

The following post had helped me implementing the parsing of the BMP file.

Caveat: I do see that in some cases GIMP writes the last pixel of a line in four bytes instead of one. This can cause problems in some image parsers. You can try to resize the image to another size an the problem disappears for me. 


  1. Another alternate option is to export to PCX format, which Gimp also supports. It has a much more straightforward header layout and supports uncompressed pixels as well. It was a very common format back in the DOS era, since most image programs of the time supported it.