# Generalised Bitmap Module

## Introduction

The GBM package consists of a number of components :-

- A piece of code capable of loading and saving bitmap files in a variety of popular file formats. Programs may be written to use this code, and thus be able to access a variety of file formats without actually knowing what format the pictures are in, or any details about file format itself.
- Some peices of code that perform common operations on bitmap data. Such as reflection, X-Y transposition, rotation, cropping, scaling, halftoning, error-diffusing, palette mapping, and colour space mapping.
- Some sample command line programs which use the above code.

## Distributed packages

The GBM packages are best obtained via the links on my home page :-

- http://www.nyangau.fsnet.co.uk/.

Packages with names link GBMDOS32, GBMWIN, GBMOS2, GBMAIX, GBMLINUX and others contain the executables for that platform.

The GBMSRC source package contains all the source code, which is 32 bit portable C. Makefiles for OS/2 (VisualAge C++), Win32 (Visual C++ 4.2, 5.0, 6.0), and UNIX (using xlc under AIX, and gcc under Linux) are included.

All the GBM source code is written using Andys Source Code Folding Editor, and this is also accessible via my home page. The source will look funny (have strange comments in it, etc.) when veiwed using a regular 'flat' editor.

There is a GBMOS2PM package, which contains programs specific to OS/2 and to OS/2 with Presentation Manager. These include GBMV, GBMV2, GBMVFSA and GBMLOGO. These used to be a part of the standard packages, but I have recently split them out as most people don't have or use OS/2. See the OS/2 extras documentation.

## JPEG support

The Independant JPEG Group have generously allowed others to use their source code to their JPEG handling library. The only condition of use is that the IJG must be credited for their work. Try looking for this library at :-

- `ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/AFPL/gs851/jpegsr6b.zip`.

Martin Lisowski `<mlisowsk@aixterm1.urz.uni-heidelberg.de>` has generously donated his `gbmjpg.c` to GBM. This file allows GBM to use the IJG 6a/IJG 6b library.

GBM may be compiled up either with or without JPEG support. If you use the JPEG enabled variety of GBM in your project, you must credit the IJG.

This code has been tested on OS/2, AIX, Linux and Windows.

## PNG support

The official Open Source reference libraries Libpng 1.2.8 and Zlib 1.2.3 can be used to build GBM with PNG support. Try looking for these libraries at :-

- `http://www.libpng.org`.
- `http://www.zlib.org`.

Heiko Nitzsche has generously donated his `gbmpng.c` and `gbmmap.c` to GBM. These files allow GBM to use the Libpng 1.2.8 library.

GBM may be compiled up either with or without PNG support. If you use the PNG enabled variety of GBM in your project, you should credit the Open Source projects for Libpng and Zlib.

This code has been tested on OS/2.

## TIF support

The official Open Source reference libraries Libtiff 3.7.4 can be used to build GBM with TIF support. Required are Zlib 1.2.8 and the IJG Group lib IJG 6b that is also used for standard JPEG support. Try looking for these libraries at :-

- `http://www.libtiff.org`.
- `http://www.zlib.org`.
- `ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/AFPL/gs851/jpegsr6b.zip`.

Heiko Nitzsche has generously donated his `gbmtif.c` and `gbmmap.c` to GBM. These files allow GBM to use the Libtiff 3.7.4 library.

GBM may be compiled up either with or without TIF support. If you use the TIF enabled variety of GBM in your project, you should credit the Open Source projects for Libtiff, Zlib and the IJG.

This code has been tested on OS/2.

## PPM support

Heiko Nitzsche has generously donated his `gbmppm.c` to GBM. This file allows GBM to read and write unpalettised RGB PPM files.

This code has been tested on OS/2.

## Formats supported

GBM supports a variety of file formats:

Bitmap Formats | File Extensions | 1 bpp | 2,3 bpp | 4 bpp | 5,6,7 bpp | 8 bpp | 16 bpp | 24 bpp | 32 bpp | 48 bpp | 64 bpp
Bitmap (OS/2, Windows) | BMP, VGA, BGA, RLE, DIB, RL4, RL8 | RW |  | RW |  | RW |  | RW |  |  |
CompuServe Graphics | GIF | RW | R(2,3) | RW | R(5,6,7) | RW |  |  |  |  |
ZSoft PC Paintbrush | PCX, PCC | RW |  | RW |  | RW |  | RW |  |  |
Tagged Image File Format | TIF, TIFF | RW | R(2) | RW |  | RW | R | RW | RW | RW | RW
Truevision Targa/Vista | TGA, VST, AFI |  |  |  |  | RW | W | RW | W |  |
Amiga IFF / ILBM | IFF, ILBM | RW | R(2,3) | RW | R(5,6,7) | RW |  | RW |  |  |
YUV12C M-Motion Frame Buffer | VID |  |  |  |  |  |  | RW |  |  |
Portable Greyscale-map (binary P5) | PGM |  |  |  |  | RW |  |  |  |  |
Portable Network Graphics | PNG | RW | R(2) | RW |  | RW | R | RW | RW | RW | RW
Portable Pixel-map (binary P6) | PPM |  |  |  |  |  |  | RW |  | RW |
IBM KIPS | KPS |  |  |  |  | RW |  |  |  |  |
IBM Image Access eXecutive | IAX |  |  |  |  | RW |  |  |  |  |
X Windows bitmap | XBM | RW |  |  |  |  |  |  |  |  |
Archimedes Sprite (RiscOS) | SPR | RW |  | RW |  | RW |  |  |  |  |
IBM Printer Page Segment | PSE, PSEG, PSEG38PP, PSEG3820 | RW |  |  |  |  |  |  |  |  |
GEM Raster | IMG, XIMG | RW | R(2,3) | RW | R(5,6,7) | RW |  | RW |  |  |
Portrait | CVP |  |  |  |  |  |  | RW |  |  |
JPEG File Interchange Format | JPG, JPEG, JPE |  |  |  |  | R |  | RW |  |  |

Normally, applications using GBM deduce the file format from the file extension. eg: `filename.gif` is a Compu$erve GIF file.

When specifying file names to programs written using GBM, it is usually possible to append a comma seperated list of format specific options. eg: you can say `webpiccy.gif,ilace`. In this case, the `ilace` is a cue to the code in GBM which writes GIF files, to tell it to write an interlaced GIF.

    Short name : Long name : File extensions
      Comments

    Bitmap : OS/2 1.1, 1.2, 2.0 / Windows 3.0 bitmap : .BMP .VGA .BGA .RLE .DIB .RL4 .RL8
      Reads any of the above if uncompressed or run-length compressed.
      Will not read CCITT G3 MH Fax compressed files.
      If input is an OS/2 bitmaparray file then which bitmap can be specified.
        Input options: index=# (default: 0)
      Can be made to write OS/2 1.1 or Windows 3.0 / OS/2 2.0 bitmaps
        Output options: 1.1,win,2.0 (default: 2.0, note win=2.0)
      The handling of 1bpp bitmaps is a little complicated.
      When reading 1bpp bitmaps, the palette is ignored.
      1's are considered foreground, and they are considered black.
      0's are considered background, and they are considered white.
      This agrees with WorkPlace Shell WPFolder background mode, and most PM
      programs, but notably disagrees with Windows PBrush.
      When writing 1bpp bitmaps, the actual 2 colours in the palette are
      ignored, and a fixed palette is written. This is so that the resulting
      bitmap will display 1's in black on 0's in white when displayed by
      WPFolder etc..
      Foreground and background colours in palette can be inverted on input.
        Input options: inv
      Foreground and background colours in palette can be inverted on output.
        Output options: inv
      Foreground and background colours in bits can be inverted on input.
        Input options: invb
      Foreground and background colours in bits can be inverted on output.
        Output options: invb
      The best option for writing 1bpp bitmaps is to write the darkest
      colour as the foreground. The resulting bitmap will have darkest
      colour as 1 bits, and lightest colour as 0 bits. When reloaded
      WPFolders and GBM will give a black 1's on white 0's picture.
        Output option: darkfg
      Also, there is an option for writing 1bpp bitmaps with the lightest
      colour as foreground. As WPFolder and GBM assume the foreground is
      black and the background is white on reloading, this will typically
      cause the image to be inverted.
        Output option: lightfg

    GIF : CompuServe Graphics Interchange Format : .GIF
      Reads 1, bit data files.
      Reads 2, 3 and 4 bit data files and presents them as 4 bit.
      Reads 5, 6, 7 and 8 bit data files and presents them as 8 bit.
      Writes 1, 4 and 8 bit data files.
      Reads "GIF87a" and "GIF89a" style files.
      Writes "GIF87a" style files.
      Will write "GIF89a" file, if the transcol= option is used.
      Should correctly handle deferred clear-code in LZW data stream.
      Will not generate output with deferred clear-code.
      ie: should not break older GIF readers.
      Can specify index of image within file on read.
        Input option: index=# (default 0)
      Can specify to return decoded data so far rather than error if corrupt.
        Input option: errok
      Can specify screen size to write in output screen descriptor.
        Output options: xscreen=#,yscreen=# (defaults: image size).
      Can specify background colour index to write in file BMHD header.
        Output option: background=# (default: 0)
      Can specify position information in output image descriptor.
        Output options: xpos=#,ypos=# (defaults: 0,0).
      Can specify transparent colour index (useful for HTML embedding).
        Output option: transcol=# (default is none).
      Can specify transparent colour index same as first pixel.
        Output option: transcol=edge
      Can write interlaced GIFs (good for HTML <IMG=SRC="x.gif">)
        Output option: ilace
      Extensively test on GIF files from a wide variety of sources.
      Compatibility tested with xloadimage and xv.

    PCX : ZSoft PC Paintbrush Image format : .PCX .PCC
      Reads and writes 1,4,8 and 24 bit colour files.
      Subset of plane/bits-per-plane combinations supported.
      Files are read and written using a run-length coding scheme.
      Tested using Zsoft originated .PCX files.
      Compressed runs of pixels are not supposed to straddle scan lines.
      GBM never does this, but some other applications violate this rule.
      By default, if GBM finds that a run of pixels is longer than the scan
      line, it will use the leftover pixels on the next scan line.
      Some images will not load properly, as they require the loading
      program to discard those pixels in the run that extend beyond the end
      of the scan line. This behaviour can be enabled in GBM.
        Input option: trunc

    TIFF : Microsoft/Aldus Tagged Image File Format support : .TIF .TIFF

    Standard formats (backward compatible):
      Reads  1 bpp black/white and colour palette/gray level files.
      Reads  2 bpp colour palette/gray level files and presents them as  4 bpp.
      Reads  4 bpp colour palette/gray level files and presents them as  4 bpp.
      Reads  8 bpp colour palette/gray level files and presents them as  8 bpp.
      Reads 16 bpp colour palette/gray level files and presents them as 24 bpp.
      Reads 24 bpp colour files and presents them as 24 bpp.
      Reads 32 bpp colour files (RGB + alpha channel) and presents them as 24 bpp.
      Reads 48 bpp colour files and presents them as 24 bpp.
      Reads 64 bpp colour files (RGB + alpha channel) and presents them as 24 bpp.
      Reads CMYK ( 8 bit per channel) files and presents them as 24 bpp RGB (strip encoded only).
      Reads CMYK (16 bit per channel) files and presents them as 24 bpp RGB (strip encoded only).

    Extended formats (not backward compatible, import option ext_bpp required):
      Reads 16 bpp colour palette/gray level files and presents them as 48 bpp (strip encoded only).
      Reads 32 bpp colour files (RGB + alpha channel) and presents them as 32 bpp.
      Reads 48 bpp colour files and presents them as 48 bpp (strip encoded only).
      Reads 64 bpp colour files (RGB + alpha channel) and presents them as 64 bpp (strip encoded only).
      Reads CMYK (16 bit per channel) files and presents them as 48 bpp RGB (strip encoded only).

    Writes 1, 4, 8, 24, 32 (24 bpp + alpha), 48, 64 (48 bpp + alpha) bpp RGB files.

      The depth of the alpha channel must in all cases match with the depth of all RGB channels.

      Supports the following compression schemes:
      - uncompressed
      - LZW
      - PackBits
      - ThunderScan
      - NeXT
      - JPEG
      - CCITT
      - Deflate
      - Adobe Deflate

      Input:

      Handling of alpha channel:
        If the bitmap contains an associated alpha channel (pre-multiplied alpha), the alpha
        channel values are not separately returned. In this case a provided background color
        is ignored.
        If the bitmap contains an unaccociated alpha channel (not pre-multiplied alpha), the
        alpha channel is returned separately unless the client requests that it has to be
        calculated against the provided background color.
        In the case the ext_bpp option is not specified and the bitmap contains an unassociated
        alpha channel, the alpha channel is only calculated against the background color if
        a background color has been specified by the client. Otherwise the alpha channel data
        is ignored.

      Can specify image within TIFF file with many images
        Input option: index=# (default: 0)
      Can specify background color as RGB for alpha channel mixing
      (only interpreted for bitmaps with unassociated alpha channel)
        Input option: back_rgb=#_#_# (red_green_blue, 0..65535)
      Can specify that non-standard GBM color depths are exported (also with alpha channel)
        Input option: ext_bpp (default: bpp is downsampled to 24 bpp)

      Output:

      Handling of alpha channel:
        GBM allows writing of unassociated alpha channel information for 32 and 64 bpp.
        It can also associate separately provided alpha channel information by
        pre-multiplying a specified background color against the RGB channels (option back_rgb).
        If the alpha channel has already been associated (pre-multiplied), color depths
        of 24 and 48 bpp should be used when writing RGB bitmaps.

      Can specify background color as RGB for associating alpha channel
      (the alpha channel is preserved in the bitmap file)
        Output option: back_rgb=#_#_# (red_green_blue, 0..65535)
      Can write 1bpp as non-Baseline file preserving fg/bg cols
      (this can be done to enforce writing a B/W palette bitmap,
       usually non B/W bitmap is automatically detected and a palette image is written)
        Output option: pal1bpp
      Can ask for specific strip size
        Output option: strip_size=# (4,8,16,32,64 kBytes, default=16)
      Can ask for LZW compression.
        Output option: lzw
      Can ask for LZW compression with horizontal prediction
        Output option: lzw_pred_hor
      Can ask for PackBits compression.
        Output option: packbits
      Can ask for Deflate compression (Adobe compatible Deflate).
        Output option: deflate
      Can specify Deflate compression level
        Output option: deflate_comp=# (default=6, 1..9, no compression to max)
      Can ask for JPEG compression (only 24 bpp).
        Output option: jpeg
      Can specify JPEG quality level
        Output option: jpeg_quality=# (default=75, 0..100)
      Can ask for CCITT modified Huffman RLE encoding (only 1 bpp).
        Output option: ccittrle
      Can ask for CCITT Group 3 fax encoding (only 1 bpp).
        Output option: ccittfax3
      Can ask for CCITT Group 4 fax encoding (only 1 bpp).
        Output option: ccittfax4
      Can specify informational tags to append on output.
        Output options: artist=,software=,make=,model=,host=,documentname=,pagename=,imagedescription=

    Targa : Truevision Targa/Vista bitmap : .TGA .VST .AFI
      Reads any uncompressed/run-length-compressed files.
      Reads 8 bit and 24 bit files.
      Can read 8 bit greyscale and 8 bit colour mapped files.
      Reads both yup and ydown files.
      Writes out as uncompressed 8 bit or 16,24,32 bit.
        Output options: 16,24,32 (default 24)
      8 bit data is always written out as a colour mapped file.
      Can be made to write yup and ydown files.
        Output options: ydown,yup (default: yup)

    ILBM : Amiga IFF / ILBM Interleaved bitmap format : .IFF .LBM
      Reads 1 bit palettised files.
      Reads 2,3 and 4 bit palettised files, returning them as 4 bit.
      Reads 5,6,7 and 8 bit palettised files, returning them as 8 bit.
      Reads 24 bit images and returns them as 24 bit.
      Reads HAM6, HAM8, SHAM and Extra-Halfbrite images.
      HAM6, HAM8 and SHAM returned as 24 bit data.
      Writes 1,4 and 8 bit palettised colour files.
      Writes 24 bit files normally, or by converting to HAM6 first.
      This loses quality but results are still better than 8 bit.
      Understands the RLE compression scheme used.
      Uses BMHD, CMAP, CAMG and BODY sections of file only.
      Only writes BMHD, CMAP, CAMG and BODY sections in output files.
      Can specify position information in file BHMD header.
        Output options: xpos=#,ypos=# (defaults: 0,0).
      Can specify transparent colour to write in file BMHD header.
        Output option: transcol=# (default: 0)
      Can specify aspect ratio to write in file BMHD header.
        Output options: xaspect=#,yaspect=# (defaults: 1,1).
      Can specify screen size to write in output BMHD header.
        Output options: xscreen=#,yscreen=# (defaults: image size).
      Can specify to write 24 bpp data in HAM6 format.
        Output option: ham6
      Note that when DeluxePaint etc. try to load an 8 bit IFF file, they
      switch to a 32 colour (5 bit mode) and only read the 5 least
      significant planes of the file - this generally looks yukky!
      Tested using DeluxePaint sample bitmaps.

    YUV12C : YUV12C M-Motion Frame Buffer : .VID
      Reads files and presents data as 24 bit data.
      Writes 24 bit data files by converting them into 12 bit YUV.
      VID files MUST be a multiple of 4 pixels wide.
      When writing a non-multiple of 4, the last 1, 2 or 3 pixels are lost.
      Can specify image origin information in YUV12C header.
        Output options: xpos=#,ypos=# (defaults: 0,0).
      Tested using M-Control Program 2.0, Browser sample application.

    Greymap : Portable Greyscale-map (binary P5 type) : .PGM
      Credit for file format to Jef Poskancer.
      No palette present in file format.
      Reads 8 bit grey scale files.
      Writes red, green, blue plane or greyscale equivelent of 8 bit image.
        Output options: r,g,b,k (default: k)

    PNG : Portable Network Graphics Format : .PNG

    Standard formats (backward compatible):
      Reads  1 bpp black/white and colour palette/gray level files.
      Reads  2 bpp colour palette/gray level files and presents them as  4 bpp.
      Reads  4 bpp colour palette/gray level files and presents them as  4 bpp.
      Reads  8 bpp colour palette/gray level files and presents them as  8 bpp.
      Reads 16 bpp gray level files and presents them as 24 bpp.
      Reads 32 bpp gray level files (16 bit gray + alpha channel) and presents them as 24 bpp.
      Reads 24 bpp colour files and presents them as 24 bpp.
      Reads 32 bpp colour files (RGB + alpha channel) and presents them as 24 bpp.
      Reads 48 bpp colour files and presents them as 24 bpp.
      Reads 64 bpp colour files (RGB + alpha channel) and presents them as 24 bpp.

    Extended formats (not backward compatible, import option ext_bpp required):
      Reads 16 bpp gray level files and presents them as 48 bpp.
      Reads 32 bpp gray level files (16 bit gray + alpha channel) and presents them as 64 bpp.
      Reads 32 bpp colour files (RGB + alpha channel) and presents them as 32 bpp.
      Reads 48 bpp colour files and presents them as 48 bpp.
      Reads 64 bpp colour files (RGB + alpha channel) and presents them as 64 bpp.

    Writes 1, 4, 8, 24, 32 (24 bpp + alpha), 48, 64 (48 bpp + alpha) bpp RGB files.

      The depth of the alpha channel must in all cases match with the depth of all RGB channels.

      Input:

      Handling of alpha channel:
        PNG alpha channel is always unassociated (not pre-multiplied alpha).
        The alpha channel is returned separately unless the client requests that it has
        to be calculated against the provided background color.
        In the case the ext_bpp option is not specified and the bitmap contains an alpha
        channel, the alpha channel is only calculated against the background color if a
        background color has been specified by the client or is provided by the bitmap.
        Otherwise the alpha channel data is ignored.

      Can specify screen gamma
        Input option: gamma=# (default=2.2)
      Can specify a default background color as RGB to be used for all image types
      (if the bitmap has a background associated, it is replaced by the specified color)
        Input option: back_rgb=#_#_# (red_green_blue, 0..65535)
      Can ignore a bitmap provided background
      (helpful if the alpha channel should be preserved and the bitmap rendered by the
       application against a textured background)
        Input option: ignore_back

      Output:

      Handling of alpha channel:
        GBM allows writing of unassociated alpha channel information for 32 and 64 bpp.
        If the alpha channel has already been associated (pre-multiplied), color depths
        of 24 and 48 bpp should be used when writing RGB bitmaps.
        If a full alpha channel is provided, transparency cannot be specified additionally.

      Can write interlaced PNGs (good for HTML)
        Output option: ilace
      Can write user defined image gamma
        Output option: gamma=#
      Can specify background colour index for palette/gray images to write in file PNG header.
      (alpha channel is preserved in the bitmap file)
        Output option: back_index=#
      Can specify background colour as RGB for RGB images to write in file PNG header.
      (alpha channel is preserved in the bitmap file)
        Output option: back_rgb=#_#_# (red_green_blue, 24/32 bpp: 0..255, 48/64 bpp: 0..65535)
      Can specify transparency for palette images to write in file PNG header.
      (only for bitmap without alpha channel)
        Output option: transparency=#  (0..255, opaque..transparent)
      Can specify transparency colour for RGB images to write in file PNG header.
      (only for bitmap without alpha channel)
        Output option: transcol_rgb=#_#_# (red_green_blue, 24/32 bpp: 0..255, 48/64 bpp: 0..65535)
      Can specify compression level
        Output option: compression=# (default=6, 0..9, no compression to max)

    Pixmap : Portable Pixel-map (binary P6 type) : .PPM

    Standard formats (backward compatible):
      Reads 24 bpp unpalettised RGB files.
      Reads 48 bpp unpalettised RGB files and presents them as 24 bpp.

    Extended formats (not backward compatible, import option ext_bpp required):
      Reads 48 bpp unpalettised RGB files and presents them as 48 bpp.

    Writes 24 and 48 bpp unpalettised RGB files.

      Can specify image within PPM file with multiple images
        Input option: index=# (default: 0)
      Can specify that non-standard GBM color depth is exported (48 bpp)
        Input option: ext_bpp (default: bpp is downsampled to 24 bpp)

    KIPS : IBM KIPS : .KPS
      Reads 8 bit palettised files.
      Will look for palette in .PAL file unless .KPL file specified.
        Input options: pal,kpl (default: pal)
      Writes 8 bit palettised files.
      Will write palette in .PAL file unless .KPL file specified.
        Output options: pal,kpl (default: pal)

    IAX : IBM Image Access eXecutive : .IAX
      Reads array as 8 bit greyscale.
      File format does not hold image dimensions.
      Hence code assumes width is 512 pixels unless overridden.
        Input options: width=# (default: 512)
      File format does not include palette.
      Writes red, green, blue plane or greyscale equivelent of 8 bit image.
        Output options: r,g,b,k (default: k)

    XBitmap : X Windows bitmap : .XBM
      Reads 1bpp X bitmaps, presenting 1's as black, 0's as white.
      Writes 1bpp X bitmaps, darkest colours as 1's, brightest colour as 0's.
      Tested upon some sample .XBM files.

    Sprite : Archimedes Sprite format from RiscOS : .SPR .SPRITE
      Technically sprite files have no extension.
      But GBM recognises .SPR and .SPRITE for convenience.
      Reads 1,4 and 8 bit sprites.
      'First bit' value in header must be a multiple of 8 (v.likely).
      Will only read image plane, will ignore any mask plane.
      Will handle case when no palette present in file.
      Will default to the default Wimp palette in this case.
      If input contains more than one sprite then which can be specified.
        Input options: index=# (default: 0)
      Will output 1,4 and 8 bit files.
      Will write a palette in the file.
      Will only write an image plane, ie: no mask plane.
      Will write a 16 entry palette for 8 bit data (not 64 entry).
      Will map to wierd archmedes palette when writing 8 bit data.
      Tested reading 4bpp sprites with no palette.
      Tested reading 8bpp sprites with no palette and with 64 entry palette.
      Sprites generated by GBM have been loaded on RiscOS.
      Remember: Use SetType to change type of file from PC-file to Sprite,
      by SetType option of filer menu or "*SetType <filename> Sprite".

    PSEG : IBM Printer Page Segment : .PSE .PSEG .PSEG38PP .PSEG3820
      This is a file format used by IBM document/printing systems.
      It is used to represent a bi-level image to be used in a document.
      Reads data and presents a 1bpp bitmap.
      Image is presented 1's as black on 0's as white background.
      PSEG files should be downloaded from a VM host in binary mode.
      Some PSEG files have a corrupt record structure.
      This doesn't cause a problem on VM but can confuse a non-VM reader.
      GBM can be made to attempt to handle these files.
        Input option: fixrec
      Will output 1bpp file.
      Will output file with scale factor of 1000
      Can specify new scale for both x and y
        Output options: scalex=#, scaley=#
      Can double the scale factors (option exists for backwards compatibility).
        Output option: double
      WIll output file with pel values of 2400 (dots per 10 inches, ie: 240 dpi).
      Can specify new pel values for both x and y
        Output options: pelx=#, pely=#
      Palette in 1bpp data is lost when written to file.
      The resulting non-VM file has no record structure.
      So when it is uploaded it must be fixed using FIXL3820 EXEC or similar.
      Image width is rounded up to next multiple of 8 when written.

    GemRas : GEM Raster : .IMG .XIMG
      There is a basic level of support, and assorted XIMG extensions.
      One extension is the inclusion of palette info.
      Another allows 24 bpp data to be placed into an .IMG file.
      Reads 1 bpp files (which are B/W) and returns 1 bpp data.
      Reads 2,3 and 4 bpp files (col, grey, XIMG with pal) and returns 4 bpp.
      Reads 5,6,7 and 8 bpp files (grey, XIMG with pal) and returns 8 bpp.
      Reads 24 bpp (which are by definition XIMG) files and returns 24 bpp.
      Writes 1 bpp data as B/W 1 bpp file.
      Writes 4 bpp data mapped to 'standard' 16 colour palette.
      Or writes 4 bpp data greyscale 4 bpp file.
        Output option: grey
      Or writes 4 bpp data to XIMG file with palette.
        Output option: pal
      There is no 'standard' palette for 256 colour files.
      Writes 8 bpp data as greyscale 8 bpp file.
      Or writes 8 bpp to XIMG file with palette.
        Output option: pal
      Writes 24 bpp data as an XIMG file (normal file can't do 24 bpp).
      The pixel dimensions in microns can be specified.
        Output options: pixw=#,pixh=# (defaults: 85,85)

    Portrait : Portrait : .CVP
      In Germany, photographers sometimes supply a floppy with a .CVP on it.
      File holds a single 512x512 24bpp RGB image.
      File is uncompressed, and will therefore always be 3/4Mb.
      You can only write 512x512 images using this format.
      Pixels in the file are not square, the width is approx. 3/4 the height.
      This aspect ratio problem is not adjusted for when reading or writing.

    JPEG : JPEG File Interchange Format : .JPG .JPEG .JPE .JFIF
      Can read 8 bpp (greyscale) and 24 bpp files.
      Can write 24 bpp data to a file.
      Can write with varying degrees of quality.
        Output option: quality=# (range 0 to 100, default 75)
      Can write progressive JPEGs.
        Output option: prog

## Command line programs

All the command line programs are written in portable C, and therefore can be compiled up on a wide variety of platforms.

### GBMHDR - Display header information from bitmap files

      usage: gbmhdr [-g] [-s] [--] {fn.ext{,opt}}
      flags: -g            don't guess bitmap format, try each type
             -s            be silent about errors
             -c            show all contained bitmaps of multipage images
                           (this option discards all user options except ext_bpp)
             fn.ext{,opt}  input filenames (with any format specific options)
                           Bitmap when ext in [BMP VGA BGA RLE DIB RL4 RL8]
                           GIF when ext in [GIF]
                           PCX when ext in [PCX]
                           TIFF when ext in [TIF]
                           Targa when ext in [TGA VST AFI]
                           ILBM when ext in [IFF LBM]
                           YUV12C when ext in [VID]
                           Greymap when ext in [PGM]
                           Pixmap when ext in [PPM]
                           KIPS when ext in [KPS]
                           IAX when ext in [IAX]
                           XBitmap when ext in [XBM]
                           Sprite when ext in [SPR]
                           GemRas when ext in [IMG]
                           Portrait when ext in [CVP]
                           PNG when ext in [PNG]
                           JPEG when ext in [JPG JPEG JPE]
             opt           bitmap format specific option to pass to bitmap reader

Note that the GBM module only ever surfaces the size and bits per pixel of images (regardless of the other information present in the header). All GBM programs have access to the bitmap file formats documented above, although this list is omitted in subsequent documentation.

GBMHDR displays output in the following style :-

       384x768   8bpp    51Kb  17% GIF        aab.gif
       227x254   8bpp    58Kb 102% Bitmap     andy.bmp
       256x256  24bpp    84Kb  43% TIFF       bardot.tif

Listed is the size, bits per pixel, Kb size of the file, a percentage value, the file format, and the file name. The percentage is calculated as (filesize*100/datasize) and effectively gives the compression ratio. For example `aab.gif` is well compressed (to 17% of the theoretical size). `andy.bmp` gives a >100% value because of the file header.

When called with option -c for a single multipage file :-

       Index   0:  640x480   4bpp  2308Kb 1538% Bitmap     DTOPBGND.BMP
       Index   1:  800x600   4bpp  2308Kb  984% Bitmap     DTOPBGND.BMP
       Index   2: 1024x768   4bpp  2308Kb  600% Bitmap     DTOPBGND.BMP
       Index   3:  640x480   8bpp  2308Kb  769% Bitmap     DTOPBGND.BMP
       Index   4:  800x600   8bpp  2308Kb  492% Bitmap     DTOPBGND.BMP
       Index   5: 1024x768   8bpp  2308Kb  300% Bitmap     DTOPBGND.BMP
       Compression ratio: 100%

### GBMCONV - Convert a bitmap file to an other format

      usage: gbmconv fn1.ext{,opt} fn2.ext{,opt}
             fn1.ext{,opt}  input  filename (with any format specific options)
             fn2.ext{,opt}  output filename (with any format specific options)

Instead of having to use gbmsize or other provided utilities to do file format conversions, a separate tool is provided.

### GBMREF - Reflect in horizontal and/or vertical directions

      usage: gbmref [-h] [-v] [-t] [--] fn1.ext{,opt} [fn2.ext{,opt}]
      flags: -h             reflect horizontally
             -v             reflect vertically
             -t             transpose x for y
             fn1.ext{,opt}  input filename (with any format specific options)
             fn2.ext{,opt}  optional output filename (or will use fn1 if not present)
                            bitmap formats and options as before

Certain non-obvious combinations of `-h`, `-v` and `-t` can be very handy :-

None of them
  can be used for just file format translation.
`-h -v`
  reflect both, equivelent to 180 degree turn.
`-h -t`
  equivelent to 90 degree turn clockwise.
`-v -t`
  equivelent to 90 degree turn anti-clockwise.

### GBMSUB - Extract a subrectangle of a bitmap

      usage: gbmsub [-x x] [-y y] [-w w] [-h h] [--] fn1.ext{,opt} [fn2.ext{,opt}]
      flags: -x x           left edge of rectangle (default 0)
             -y y           bottom edge of rectangle (default 0)
             -w w           width of rectangle (default width of image - x)
             -h h           height of rectangle (default height of image - y)
             fn1.ext{,opt}  input filename (with any format specific options)
             fn2.ext{,opt}  optional output filename (or will use fn1 if not present)
                            bitmap formats and options as before

If none of the `-x`, `-y`, `-w` and `-h` options are supplied the defaults cover the whole of the input file. Hence this program will just read one file and write the data as another. Great for format conversion.

### GBMSIZE - Change the size of a bitmap

      usage: gbmsize [-w w] [-h h] [-a] [--] fn1.ext{,opt} [fn2.ext{,opt}]
      flags: -w w           new width of bitmap (default width of bitmap)
             -h h           new height of bitmap (default height of bitmap)
             -a             preserve aspect ratio when only one of -w or -h given
             fn1.ext{,opt}  input filename (with any format specific options)
             fn2.ext{,opt}  optional output filename (or will use fn1 if not present)
                            bitmap formats and options as before

If none of the `-w` or `-h` options are supplied, the defaults will be the input image size. Hence this program will just read one file and write the data as another. Great for format conversion.

The scaling algorithm simply uses pixel skipping and/or replication.

### GBMBPP - Do various bits per pixel conversions

      usage: gbmbpp [-m map] [-e] [-hN] [-p fnp.ext{,opt}]
                    [--] fn1.ext{,opt} [fn2.ext{,opt}]
      flags: -m map            mapping to perform (default 7x8x4)
                               bw           black and white
                               vga          16 colour VGA
                               8            8 colour (in 4 bit file)
                               4g           4 bit greyscale
                               7x8x4        7 levels red, 8 green, 4 blue 8514/A
                               6x6x6        6 levels red, 6 green, 6 blue
                               4x4x4        4 levels red, 4 green, 4 blue
                               8g           8 bit greyscale
                               tripel       64 reds, 64 greens, 64 blues tripel
                               pal1bpp      map to 1bpp, palette specified via -p
                               pal4bpp      map to 4bpp, palette specified via -p
                               pal8bpp      map to 8bpp, palette specified via -p
                               freqR:G:B:N  keep R red, G green, b blue bits, and map
                                            to N most used colours in 8 bit palette
                               mcutN        median cut to N colours
                               R:G:B        keep R red, G green, B blue bits
             -e                enable error-diffusion (default is to truncate)
                               -e only with -m bw, vga, 4g, 7x8x4, 6x6x6 or 4x4x4
             -h                enable halftoning (default is to truncate)
                               -h only with -m 7x8x4, 6x6x6, 8, vga or R:G:B
                               -e and -h may not be used together
                               N is a halftoning algorithm number (default 0)
             -p fnp.ext{,opt}  palette is taken from this bitmap
             fn1.ext{,opt}     input filename (with any format specific options)
             fn2.ext{,opt}     optional output filename (or use fn1 if not present)
                               ext's are used to deduce desired bitmap file formats
                               Bitmap when ext in [BMP VGA BGA RLE DIB RL4 RL8]
                               GIF when ext in [GIF]
                               PCX when ext in [PCX PCC]
                               TIFF when ext in [TIF TIFF]
                               Targa when ext in [TGA VST AFI]
                               ILBM when ext in [IFF LBM]
                               YUV12C when ext in [VID]
                               Greymap when ext in [PGM]
                               Pixmap when ext in [PPM]
                               KIPS when ext in [KPS]
                               IAX when ext in [IAX]
                               XBitmap when ext in [XBM]
                               Sprite when ext in [SPR SPRITE]
                               PSEG when ext in [PSE PSEG PSEG38PP PSEG3820]
                               GemRas when ext in [IMG]
                               Portrait when ext in [CVP]
                               PNG when ext in [PNG]
                               JPEG when ext in [JPG JPEG JPE]
             opt's             bitmap format specific options

This program reads the input bitmap. If it is not 24 bit, then it is expanded to 24 bit per pixel. The data is then processed using the supplied mapping giving a 24,8,4 or 1 bit per pixel image, which is then written to the output bitmap file.

The `bw` mapping produces a 1 bpp output file, `vga` and `4g` gives 4 bit output files, `7x8x4`, `6x6x6`, `4x4x4`, `8g`, `freq` and `tripel` give 8 bit output files. `R:G:B` (where R,G and B are numbers in the range 0 to 8), gives a 24 bit output file where only the top R bits of red are non-zero, the top G of green and B of blue.

The normal way to map is simply to map each colour in the source bitmap to the closest one in the destination bitmap. However if `-e` is supplied, error diffusion is used to get a smoother result. Also, if `-h` is supplied halftoning may be used instead. `-e` and `-h` are not valid together, and are only valid with certain mappings.

### GBMGAMMA - Convert between various colour spaces

      usage: gbmgamma [-m map] [-g gamma] [-s shelf] [--] fn1.ext{,opt} [fn2.ext{,opt}]
      flags: -m map         mapping in the form ?_to_? (default: i_to_l), where ? is
                            i  physical intensitys (eg: raytracer output)
                            p  gamma corrected for a specific monitor
                            l  L* cyclometric linear perceived intensitys (as in PM)
             -g gamma       set monitor gamma (default 2.1)
             -s shelf       set monitor shelf (default 0.0)
                            gamma and shelf only used for mapping to or from p
                            for 8514 monitor gamma=2.3,shelf=0.136
                            for 8515 monitor gamma=2.1,shelf=0.0
             fn1.ext{,opt}  input filename (with any format specific options)
             fn2.ext{,opt}  optional output filename (or will use fn1 if not present)
                            bitmap formats and options as before

This program reads a bitmap and assumes the pixel values in it are in the input colour space.

If the bitmap has a palette it maps each palette entry according to the supplied mapping, otherwise it maps each individual 24 bit pixel.

For example, if you get a 24 bit per pixel image from a Windows video capture program, the odds are in may be in a gamma corrected colour space with a gamma of 2.2. You can convert this to the L* cyclometric colour space used by PM by typing :-

      gbmgamma -m p_to_l -g 2.2 captured.bmp nicepm.bmp

The shelf option is primarily for when converting to a gamma corrected colour space for a specific monitor (when you aren't going to use PM to display the bitmap, and the display program doesn't do any correction). Some monitors don't actually start to light up pixels until the pixel values are a certain value. Normally `-s shelf` will not be used.

### GBMCPAL - Map to Common Palette

      usage: gbmcpal [-m map] [-v] n1 n2 n3 ifspec{,opt} ofspec{,opt}
      flags: -m map         mapping to perform (default freq6:6:6:256)
                            freqR:G:B:N       map all bitmaps to same palette, worked
                                              out using frequency of use histogram
                            mcutN             map all bitmaps to same palette, worked
                                              out using median cut algorithm
                            rofreqR:G:B:N:N2  map each bitmap to frequency palette,
                                              reordered to minimise differences
                                              between successive bitmaps
                            romcutN:N2        map each bitmap to median cut palette,
                                              reordered to minimise differences
                                              between successive bitmaps
                                              R,G,B are bits of red, green and blue
                                              to keep, N is number of unique colours,
                                              N2 is extra palette entries
             -v             verbose mode
             n1 n2 n3       for ( f=n1; f<n2; f+=n3 )
             ifspec           printf(ifspec, f);
             ofspec           printf(ofspec, f);
                            filespecs are of the form fn.ext
                            ext's are used to deduce desired bitmap file formats
                            bitmap formats and options as before

Given a set of bitmaps, it is possible to examine them all and compute a common palette for holding them, and then generate new bitmaps mapped to that palette.

The mappings available are frequency based and median-cut based.

Alternatively, it is possible to generate the most suitable palette for each frame, and then reorder the palettes of each bitmap so as to be as close as possible to its predecessor.

By reordering palettes (using `rofreq`/`romcut`) it is possible to remove almost all flicker on playback. From frame to frame, almost all palette entries in a given frame, have close entries in the previous frame.

However for a few, this is not true, and flicker may be seen. The `N2` parameter is designed to alleviate this. The process will handle the `N2` worst palette changes using `N2` extra palette entries. Thus the `N2` worst causes of flicker can be eliminated. A typical use might be :-

      gbmcpal -m romcut240:16 0 100 1 in%02d.bmp out%02d.bmp

This means map each frame to a palette with 240 unique colours in. Any given frame only uses 240 colours at most. But the palette is actually 240+16 colours in length, and the additional 16 are used to eliminate flicker caused by the 16 worst matches.

## Colour spaces

If a light is physically twice as bright, the eye does not necessarily see it as twice as bright. Also, if a pixel is written onto a monitor screen with twice the value, the physical intensity of the pixel is not necessarily double.

How exactly should numbers inside a bitmap file relate to physical or perceived intensitys when displayed on the screen?

In OS/2 PM perceived intensitys are proportional to the values in the bitmap file. Pixels in such a bitmap are in the 'L* cyclometric' colour space.

Ray Tracers often write pixel values in the bitmap proportional to the physical intensity computed for that ray. Such data is in the 'intensity' colour space.

Finally, if a bitmap holds values computed in such a way as to compensate for the gamma of the monitor (ie: intensitys transformed to cancel out the gamma of the monitor), then the data is in a 'gamma corrected' colour space.

So, if you have some Ray Tracer output, and you wish to display on an 8514 monitor WITHOUT using OS/2 PM, then to get a decent colour rendition, you must map the bitmap from the 'intensity' to a 'gamma corrected' colour space. To do this you must know the gamma of the 8514 monitor (which is about 2.1).

Also, if you have some Ray Tracer output, and you wish to display on OS/2 PM, then to get a decent rendition you must map the bitmap from the 'intensity' to the 'L* cyclometric' colour space.

GBMGAMMA is a colour mapping program capable of performing mappings between any 2 of the 3 colour spaces above.

Mapping of this sort should really be done on 24 bit data, before error-diffusion or halftoning takes place.

## Making bitmap animations

GBM was originally written as the bitmap handling portion of my homebrew Ray Tracer, RT. RT was originally written to allow me to trace snazzy animations. For example, here is what I did to make a spinning globe animation.

First I traced a largish number of individual bitmap frames using RT. I wrote these out under the names `globeNNN.tif` where `NNN` is `000`, `010`, `020`, ... `350` (ie: the angle of rotation in degrees). I used the `,lzw` option to get the files written LZW encoded to reduce the disk space requirements.

Then to map the data to a common palette, I used GBMCPAL :-

      gbmcpal -m freq6:6:6:256 0 360 10 globe%03d.tif globe%03d.bmp

Obviously there are file formats specifically for holding animations, and algorithms for having animations where palette entries vary from frame to frame, but the simple example above is ok for many purposes.

## Examples of use

      gbmhdr *.bmp *.tif
        Displays the headers of all the bitmaps and TIFF files

      gbmref file.bmp file.tga
        Perform no reflection (no -h, -v or -t).
        Hence simply converts file from Bitmap to Targa format!

      gbmref -h larrow.tga rarrow.tga
        Reflects larrow.tga to make rarrow.tga

      gbmref -h -t profit.gif loss.gif
        The combination of a horizontal flip with a transpose gives a 90
        degree rotation clockwise. Thus a graph going up from bottom left
        to top right, ends up going from top left to bottom right!

      gbmref -v uarrow.pcx "darrow.lbm,xaspect=5,yaspect=6,xscreen=320,yscreen=200"
        Reflects uarrow.pcx to make darrow.lbm
        Output options defined for ILBM files used to write to aspect ratio
        and screen size fields in output .lbm file.
        Note: some command processors (such as OS/2 CMD.EXE) will split command
        line arguments at spaces and commas, so we quote second argument.

      gbmsub -x 100 -y 50 page.bmp
        Trims 100 pixels off the left, and 50 off of the bottom
        Note: no second filename given, so output overwrites page.bmp

      gbmsize -w 1024 -h 768 strangesize.bmp screensized.bmp
        Takes any bitmap and scales it to a typical SVGA screen size.

      gbmbpp -m 7x8x4 24bit.tga 8bit.bpp
        Maps a 24 RGB image to the 8514/A PM palette
        Note: Source image format (Targa) not same as output format (Bitmap)

      gbmbpp -m 7x8x4 -h 24bit.bmp nice8bit.bmp
        As above but with halftoning

      gbmbpp -m 7x8x4 -e 24bit.bmp nice8bit.bmp
        As above, but with error diffusion

      gbmbpp -m vga -e 24bit.bmp nice4bit.bmp
        As above, but suitable for VGA display

      gbmbpp -m 5:5:5 -e 8r8g8b.tga "5r5g5b.tga,16"
        Error diffuse from 24 bit RGB to 15 bit RGB
        (bottom 3 bits of each of R,G and B become zero)
        Output option ",16" ensures data written in Targa-16 form
        This reduces wasted disk space.

      gbmbpp -m freq8:8:8:240 24bit.bmp 8bit.bmp
        Finds 240 most frequently used colours.
        For other colours finds closest match in most common 240 colours.
        Maps colours in 24bit.bmp to give 8 bit output file.
        If excessively large number of colours in original, may truncate bits.

      gbmgamma -m i_to_l raytrace.bmp pmsuited.bmp
        raytrace.bmp has pixels values proportional to physical intensity.
        pmsuited.bmp is made with pixels proportional to perceived intensity.

      gbmcpal -m freq6:6:6:256 0 360 10 globe%03d.bmp cpal%03d.bmp
        Read globe000.bmp, globe010.bmp, ... globe350.bmp.
        Compute a common shared palette.
        Map each globeXXX.bmp file to a cpalXXX.bmp file.

## Related code

GBM was originally written as the file handling part of my homebrew ray tracer, RT.

My follow-on Modular Renderer package, MR, uses GBM. It does wire-frame, polygon rendering and raytracing.

Martin Lisowski informs me he is working on something he calls GBMV3, which is like the OS/2 PM GBMV2 viewer, only with extra features.

From time to time I notice people (other than myself) using GBM either in its precompiled DLL form, or by recompiling bits of the source. Sometimes people email me to let me know.

Of course, simply using the code unmodified makes it easier for you to pick up improvements in the code, as and when they happen.

IBM WebExplorer uses the Bitmap, GIF and XBM handling parts of GBM to some degree - in `webexwin.dll`, around byte offset 86924 (in my copy) are a whole load of GBM error strings.

IBM VisualAge C++ 3.0 for OS/2 uses large wedges of GBM source code. I think they're using it in their supplied `class IGBitmap`. This is apparent from the object filenames listed in `\ibmcpp\iocdll\cppoou3.rsp` and the exported function names in `\ibmcpp\iocdll\cppoou3.def`.

The IBM Person to Person personal conferencing system for OS/2 used the PCX and TIFF parts of GBM, and I think the AIX variant used whole loads more.

BITMAP32, a bitmap viewer for OS/2 PM, uses GBM.DLL unmodified. Because the IBM Developer Connection shipped BITMAP32, they ship GBM too.

BluePaint, an OS/2 PM painting program, being developed for Shareware (I think) uses GBM.DLL unmodified.

## Legal stuff

### Public domain declaration

I wrote all this code in my own time on my own equiptment.

I used public non-confidential information to do so.

I hereby place all this code into the public domain.

Feel free to do whatever you like with it.

No copyright / no royalties / no guarantees / no problem.

Caveat Emptor!

Anyone offering ideas/code must be happy with the above.

The above does not apply to the JPEG, PNG and TIFF support.

### JPEG support

This section is applicable if you are using GBM with JPEG support.

The Independent JPEG Group JPEGLIB version 6a/6b may be used provided they are credited, (which I do so here).

This software is based in part on the work of the Independent JPEG Group.

Martin Lisowski has donated `gbmjpg.c` to GBM and it is just as public domain as the rest of GBM.

### Compu$erve GIF Tax

Both Unisys and IBM (and others) have various patents pertaining to the LZW algorithm used in GIF and LZW compressed TIFF files.

For many years Unisys have only licensed their LZW technology in hardware implementations (typically Modems). Now Unisys (through Compu$erve) are looking to license the use of LZW in software applications, such as GIF and TIFF. This is the infamous 'Compu$erve GIF Tax'.

Unisys have stated (in news postings) that non-commercial software need not be licensed.

Assuming this to be true, GBM will continue to support GIF and LZW compressed TIFF.

It is anticipated that this move will mean the death of LZW in image files, and that the Net will develop a replacement based on LZSS, LZ77, LZHUF, Yabba or other (hopefully) non-patented technology. The emerging PNG format could be exactly that.

If and when this occurs, there is a good chance GBM will support it.

On 20th June 2003, US Patent 4,558,302 expired. This is the patent that describes the use of LZW in GIF files. Therefore, from now on, authors of commercial programs should no longer need to pay Compu$erve / UNISYS to use GIF.

### PNG support

This section is applicable if you are using GBM with PNG support.

The Open Source libraries Libpng and Zlib may be used provided they are credited, (which I do so here).

This software is based in part on them.

Heiko Nitzsche has donated `gbmpng.c` and `gbmmap.c` to GBM and they are just as public domain as the rest of GBM.

### TIF support

This section is applicable if you are using GBM with TIF support.

The Open Source libraries Libtiff and Zlib may be used provided they are credited, (which I do so here).

This software is based in part on them.

Heiko Nitzsche has donated `gbmtif.c` and `gbmmap.c` to GBM and they are just as public domain as the rest of GBM.

## Change Log

    11/5/1992	Initial general release.

    29/11/1993	Supplied to IBM OS/2 Developer Connection.

    1/8/1994	Submitted to Internet hobbes.nmsu.edu.

    10/1/1995	Added gbm_version(), better error checking, const's.
    		Added clarification on LZW 'software patent'.
    		Submitted to hobbes.nmsu.edu.

    16/1/1995	Added support for Portrait files (.CVP files).

    21/3/1995	Fixed palettes in XIMG GemRas files (thanks Eero).
    		Fixed GIF writing transcol=edge, & reading local colour tables.
    		Added GBMLOGO.EXE to ease use of MAKELOGO.EXE on DevCon CD 6.

    16/5/1995	Distribution now uses InfoZIP ZIP.EXE, not PKZIP.EXE 2.04g.
    		Added Product Information dialog box to GBMV2.EXE.
    		Fixed GBMLOGO.EXE error message trap for non 640x400 bitmaps.

    25/3/1996	Improved Bitmap reader to tolerate bad #colours in header.
    		Fixed reading XBitmaps with digits in their identifiers.
    		Added support for ilace flag on GIF output.

    1/4/1996	Fixed reading XBitmaps with other chars in their identifiers.
    		Fixed interlaced GIF support.
    		Added Win32 makefile and compilability.
    		Added ability to cause GBM.DLL to use user defined I/O funcs.
    		Added accessibility of I/O funcs used by GBM.

    16/4/1996	Applied fixes found by Wonkoo in 1/4/1996 release.
    		Increase warning levels for OS/2 compile and cleaned up source.
    		Added /Os- to work around C-Set++ bug.

    29/4/1996	Applied fix to GIF/TIFF readers found by David Wendt.

    19/6/1996	Applied fixes found by Ralf and Andreas.
    		Fixed RLE4 Bitmap decoder (thanks for Marc for bug report).

    28/10/1996	Changed over from IBM C-Set++ to IBM VisualAge C++ with CTC305.
    		Fixed 16bpp display bug in GBMV2.EXE.

    18/11/1996	Added darkfg option on 1bpp BMP writing.
    		Fixed printout of 1bpp bitmaps problem.

    1/2/1997  	Changed colour->greyscale coefficients, as Wonkoo suggested.
    		Added JPEG support.
    		Changed documentation to HTML.
    		Submitted to Internet hobbes.nmsu.edu.

    1/5/1998	Added initial Linux port.
    		Support GIF files without EOI code in compressed data.
    		Included source for OS/2 PM Scroller control.

    12/7/1998 	Fixed writing 1bpp PCXs with reverse palettes (ta Wonkoo).
    		Fixed OS/2 c0000005 Trap by increasing stack size (ta Gunter).

    1/1/1999	Added OS/2 _System Gbm_ entrypoints.
    		Added support for filenames starting with -, via -- convention.
    		Initial port to 32 bit DOS, via Watcom C/C++ and CauseWay.

    20/1/1999	Fixed reading of .pgm palettes (ta Wonkoo Kim).
    		Fixed 2 low probability bugs in LZW encoders in GIF and TIFF.

    ?/?/1999	Change to gbmpgm.c and gbmppm.c to use \n in header.
    		Splitting out of OS/2 specific stuff to seperate package.
    		Fixed 32 bit DOS port to work properly with JPEG support.

    21/11/1999	Fixed reading OS/2 bitmaps with < 2**N colours.

    04/01/2000	Fixed reading of 24 bit GemRas image files.

    12/05/2000	Improved TIFF and GIF LZW readers corrupt data detection.
    		Improved TIFF LZW decompressor to work if EOI missing (ta Doug).

    31/12/2000	A few minor tweaks to make source more friendly to Mac compiler.
    		Basically factored in Karl Timmermann suggestions, fixed a few
    		minor signed/unsigned char problems, and removed some #includes.

    05/02/2001	gbmsize -a option, Jeroen Mosterts idea.

    12/02/2001	gbmbpp -c palNbpp options to map to user defined palette.

    18/02/2004	Added 4x4x4 truncate, halftone and error-diffuse functions.
    		Added gbmbpp -m 4x4x4 option.

    24/08/2005      Heiko Nitzsche:
                    Added PNG support via Libpng 1.2.8 and Zlib 1.2.3.

    28/09/2005      Heiko Nitzsche: GBM version 1.30

                    TIF support:
                      Replaced original TIF support by Libtiff 3.7.3.
                      This adds many additional compression schemes like LZW (with, w/o predictor),
                      PackBits, JPEG, Deflate, CCITT and more. Simple CMYK (32, 64 bpp) import is
                      available. Now also 32 bpp (with alpha channel), 48 bpp and 64 bpp (with alpha
                      channel) import and export is available. The alpha channel is available to the
                      application if option ext_bpp is used for import.
                      Single bitmaps of multipage TIFFs can be extracted.

                    PNG support:
                      PNG support from previous release got some fixes and was extended.
                      Now also 16 gray level, 32 (with alpha channel), 48 and 64 bpp (with alpha channel)
                      import and export is available. Transparency and user defined background is
                      supported as well. The alpha channel is available to the application if option
                      ext_bpp is used for import.

                    For backward compatibility the extended color depths must be explicitly enabled
                    by the client (see option ext_bpp) otherwise bitmaps downsampled to 24 bpp are
                    provided.

                    GBM command line tools:
                      The following tools have been extended to support 32, 48 and 64 bpp:
                        gbmsize, gbmhdr, gbmref, gbmsub, gbmgamma

                      A new format converter gbmconv has been added (also supports extended bpp).

    10/02/2005      Heiko Nitzsche: GBM version 1.31

                    PPM support: (algorithms replaced)
                      Can now also read and write 48 bpp RGB files.
                      Reading a bitmap from a multipage file is now possible.

    12/12/2005      Heiko Nitzsche: GBM version 1.32

                    TIF support:
                      Update to Libtiff 3.7.4
                      Fix decoding of separated RGB tiffs
                      Fix decoding of non-separated CMYK tiffs (8/16 bits per channel)

                    GBM File Dialog:
                      Redesign to match standard file dialog (eComStation)
                      Add bitmap preview

    08/03/2006      Heiko Nitzsche: GBM version 1.35

                    gbm.htm now has an overview table of all supported bitmap formats and colour depths.

                    OS/2 compiler support extended:
                      GBM.DLL, command line tools, GBM file dialog, GBMV and GBMV2 can
                      now also be compiled with Open Watcom 1.4. IBM Visual Age C++ for
                      OS/2 is still supported. Binaries created with Open Watcom are
                      fully compatible with older VAC builds (_Optlink is supported).
                      The makefiles use nmake syntax but you can use "wmake /ms /f makefile.wat"
                      to compile with Open Watcom's wmake.

                    Regression tests:
                      A simple set of regression tests has been created. See gbmtest directory.

                    BMP support:
                      Add support for reading RLE24 compressed bitmaps

                    Code changes:
                      All bitmap format descriptions have been moved to gbmdesc.h to
                      support simplified localization.

                    API extensions:
                      New APIs have been added:
                      1. gbm_restore_io_setup()
                      2. gbm_read_imgcount()
                      3. Compiler independent modes for gbm_io_open() and gbm_io_create()
                         are now provided. Use only the new GBM_O_* modes for new applications!
                         The defined values are backward compatible to VAC++ 3.0 to keep
                         compatibility with older applications.
                      4. gbm_io_lseek() should only be used with the new compiler independent
                         origin defines GBM_SEEK_*. The new definitions are backward compatible
                         to VAC++ 3.0 to keep compatibility with older applications.

                      The import library gbm.lib does reflect the extended API.
                      If your application has to be compatible to GBM.DLL releases
                      up to 1.32, you should link against gbmorg.lib. New APIs
                      will not be available then. You should still use the new defines.

                      Supported multipage image formats: BMP, GIF, TIF, PPM, SPR
                      (For all other image formats, the header is tested first and
                       on successful detection, 1 is reported.)

                    GBM command line tools:
                      gbmhdr is now able to display all bitmaps of multipage images.
                      The reported index can be used to reference a specific bitmap
                      by using option index=n in all command line tools.

                      Supported multipage image formats: BMP, GIF, TIF, PPM, SPR

    24-Mar-2006     Heiko Nitzsche: GBM version 1.36

                    TIF support:
                      Update to Libtiff 3.8.2
                      Fix JPEG decoding via RGBA reader for YCbCr JPEGs

                    GBM File Dialog:
                      Fix bitmap preview, sometimes the bitmap was not shown due to scaling issue

    Future?		Palette Manager capability in GBMV.EXE and GBMV2.EXE?
    		Non-scaled and fixed scale print for GBMV2.EXE?
    		Special logic for print to 1bpp and 3bpp printers for GBMV2.EXE?
    		Photo-CD, RLE-Bitmap, G3-Bitmap for GBM.DLL?
    		My free time is scarce - don't hold your breath!

This documentation is written and maintained by the GBM author, Andy Key
Additions have been written by Heiko Nitzsche