# GBM Tools

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

### GBMVER - Display information about GBM DLLs

    usage: gbmver [dllpath]
           dllpath   Path to look for GBM.DLL, GBMDLG.DLL, GBMRX.DLL, GBMDLGRX.DLL

Depending on the platform, different information is provided. On OS/2 the location and the version of GBM.DLL, GBMDLG.DLL, GBMRX.DLL and GBMDLGRX.DLL is shown.

Example output:

      ===============================================
      Checking for "GBM.DLL"...
      -> Found version 1.54
      -> Found "E:\GBM2\GBM.DLL"
      -----------------------------------------------
      Exported  Function name           Found   Since
      -----------------------------------------------
      _System   Gbm_version               *     1.00
      _System   Gbm_init                  *     1.00
      _System   Gbm_deinit                *     1.00
      _System   Gbm_io_open               *     1.09
      _System   Gbm_io_create             *     1.09
      _System   Gbm_io_close              *     1.09
      _System   Gbm_io_lseek              *     1.09
      _System   Gbm_io_read               *     1.09
      _System   Gbm_io_write              *     1.09
      _System   Gbm_query_n_filetypes     *     1.00
      _System   Gbm_guess_filetype        *     1.00
      _System   Gbm_query_filetype        *     1.00
      _System   Gbm_read_header           *     1.00
      _System   Gbm_read_palette          *     1.00
      _System   Gbm_read_data             *     1.00
      _System   Gbm_write                 *     1.00
      _System   Gbm_err                   *     1.00
      _Optlink  gbm_version               *     1.00
      _Optlink  gbm_init                  *     1.00
      _Optlink  gbm_deinit                *     1.00
      _Optlink  gbm_io_setup              *     1.07
      _Optlink  gbm_io_open               *     1.07
      _Optlink  gbm_io_create             *     1.07
      _Optlink  gbm_io_close              *     1.07
      _Optlink  gbm_io_lseek              *     1.07
      _Optlink  gbm_io_read               *     1.07
      _Optlink  gbm_io_write              *     1.07
      _Optlink  gbm_query_n_filetypes     *     1.00
      _Optlink  gbm_guess_filetype        *     1.00
      _Optlink  gbm_query_filetype        *     1.00
      _Optlink  gbm_read_header           *     1.00
      _Optlink  gbm_read_palette          *     1.00
      _Optlink  gbm_read_data             *     1.00
      _Optlink  gbm_write                 *     1.00
      _Optlink  gbm_err                   *     1.00
      _System   gbm_restore_io_setup      *     1.35
      _System   gbm_read_imgcount         *     1.35

      This GBM.DLL can be used with all applications
      developed for GBM.DLL version >=1.00.

      ===============================================
      Checking for "GBMDLG.DLL"...
      -> Found "E:\GBM2\GBMDLG.DLL"
      -----------------------------------------------
      Exported  Function name           Found   Since
      -----------------------------------------------
      _System   GbmFileDlg                *     1.00
      _System   GbmDefFileDlgProc         *     1.31

      ===============================================
      Checking for "GBMRX.DLL"...
      -> Found "E:\GBM2\GBMRX.DLL"
      -----------------------------------------------
      Exported  Function name           Found   Since
      -----------------------------------------------
      _System   GBM_LOADFUNCS             *     1.00
      _System   GBM_DROPFUNCS             *     1.00
      _System   GBM_VERSION               *     1.00
      _System   GBM_VERSIONREXX           *     1.00
      _System   GBM_TYPES                 *     1.00
      _System   GBM_ISBPPSUPPORTED        *     1.00
      _System   GBM_FILETYPE              *     1.00
      _System   GBM_FILEPAGES             *     1.00
      _System   GBM_FILEHEADER            *     1.00
      _System   GBM_FILEPALETTE           *     1.00
      _System   GBM_FILEDATA              *     1.00
      _System   GBM_FILEWRITE             *     1.00
      _System   GBM_SCALEALGORITHMS       *     1.10
      _System   GBM_SCALEISSUPPORTED      *     1.10
      _System   GBM_SCALE                 *     1.10
      _System   GBM_REFLECT               *     1.10
      _System   GBM_ROTATE                *     1.10
      _System   GBM_PALETTEDATATO24BPP    *     1.10

      ===============================================
      Checking for "GBMDLGRX.DLL"...
      -> Found "E:\GBM2\GBMDLGRX.DLL"
      -----------------------------------------------
      Exported  Function name           Found   Since
      -----------------------------------------------
      _System   GBMDLG_LOADFUNCS          *     1.00
      _System   GBMDLG_DROPFUNCS          *     1.00
      _System   GBMDLG_OPENFILEDLG        *     1.00
      _System   GBMDLG_SAVEASFILEDLG      *     1.00
      _System   GBMDLG_VERSIONREXX        *     1.01

If no path has been specified, the DLLs will be tried to detect via the systems search path (on OS/2 this is LIBPATH in CONFIG.SYS).

### GBMHDR - Display header information from bitmap files

    usage: gbmhdr [-g] [-s] [--] {"\"fn.ext\"{,opt}"} ...
           -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 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]
                        Bit-map when ext in [PBM]
                        Greymap when ext in [PGM]
                        Pixmap when ext in [PPM]
                        Anymap when ext in [PNM]
                        KIPS when ext in [KPS]
                        IAX when ext in [IAX]
                        XBitmap when ext in [XBM]
                        XPixMap when ext in [XPM]
                        Sprite when ext in [SPR SPRITE]
                        PSEG when ext in [PSE PSEG PSEG38PP PSEG3820]
                        GemRas when ext in [IMG XIMG]
                        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

            In case the filename contains a comma or spaces and options
            need to be added, the syntax "\"fn.ext\"{,opt}" must be used
            to clearly separate the filename from the options.

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%

GBMHDR always reports the full colour depth up to the so far supported colour depth of the GBM library (64bpp).
Note:
Not all of the GBM tools behave this way. For backward compatibility reasons they will require the ext_bpp option be specified by the user for the input file name to enable deep colour depth support. Otherwise these bitmaps will be converted to 24bpp first and then processing is done.

### 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)
                         ext's are used to deduce desired bitmap file formats
                         bitmap formats and options as before
           opt's         bitmap format specific options

Instead of having to use gbmsize or other provided utilities to do file format conversions, a separate tool is provided.
Note:
For backward compatibility reasons it is required to specify the ext_bpp option for the input file name to enable deep colour depth support. Otherwise these bitmaps will be converted to 24bpp first and then processing is done.

### 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 by y
           fn1.ext{,opt}  input filename (with any format specific options)
           fn2.ext{,opt}  optional output filename (or will use fn1 if not present)
                          ext's are used to deduce desired bitmap file formats
                          bitmap formats and options as before
           opt's          bitmap format specific options

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.

Note:
For backward compatibility reasons it is required to specify the ext_bpp option for the input file name to enable deep colour depth support. Otherwise these bitmaps will be converted to 24bpp first and then processing is done.

### 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)
                          ext's are used to deduce desired bitmap file formats
                          bitmap formats and options as before
           opt's          bitmap format specific options

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.
Note:
For backward compatibility reasons it is required to specify the ext_bpp option for the input file name to enable deep colour depth support. Otherwise these bitmaps will be converted to 24bpp first and then processing is done.

### GBMSIZE - Change the size of a bitmap

    usage:
    gbmsize [-w w] [-h h] [-a] [-f f] [--] "\"fn1.ext\"{,opt}" ["\"fn2.ext\"{,opt}"]
    -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
    -f f           do quality scaling using one of the algorithms:
                   * simple (default)
                   * nearestneighbor,bilinear,bell,bspline,mitchell,lanczos
                     Note: Only grayscale and true color images.
    fn1.ext{,opt}  input filename (with any format specific options)
    fn2.ext{,opt}  optional output filename (or will use fn1 if not present)
                   ext's are used to deduce desired bitmap file formats
                   bitmap formats and options as before
    opt's          bitmap format specific options

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 simple scaling algorithm simply uses pixel skipping and/or replication. All other algorithms use resampling to improve the scaling quality to the cost of performance.
Note:
For backward compatibility reasons it is required to specify the ext_bpp option for the input file name to enable deep colour depth support. Otherwise these bitmaps will be converted to 24bpp first and then processing is done.

### 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 formats and options as before
           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.
Note:
GBMBPP does not yet support deep colour depth bitmaps (> 24bpp).

### 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)
                          ext's are used to deduce desired bitmap file formats
                          bitmap formats and options as before
           opt's          bitmap format specific options

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.
Note:
For backward compatibility reasons it is required to specify the ext_bpp option for the input file name to enable deep colour depth support. Otherwise these bitmaps will be converted to 24bpp first and then processing is done.

### 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
           opt's          bitmap format specific options

       eg: gbmcpal -m mcut256 0 100 1 24bit%03d.bmp 8bit%03d.bmp

           In case the spec contains a comma or spaces and options
           need to be added, the syntax "\"fspec\"{,opt}" must be used
           to clearly separate it from the options.

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.
Note:
GBMCPAL does not yet support deep colour depth bitmaps (> 24bpp).

## 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 Andy Key's homebrew Ray Tracer, RT. RT was originally written to allow tracing snazzy animations. For example, here is what can be done to make a spinning globe animation.

First he traced a largish number of individual bitmap frames using RT. These were written out under the names `globeNNN.tif` where `NNN` is `000`, `010`, `020`, ... `350` (ie: the angle of rotation in degrees). You can use 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, GBMCPAL can be used:

      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

    gbmhdr -c "\"*.tif\""
      Displays the headers of all the TIFF files. If the bitmap has multiple pages
      their information is shown as well.

    gbmconv file.bmp file.tif,lzw
      Simply converts file from Bitmap to LZW compressed TIF format!

    gbmconv "\"file with,1.bmp\",invd" "\"file.tif\",lzw"
      Converts a B/W Bitmap containing a comma to LZW compressed TIF format (data is inverted when read)!

    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.