The IMAGE program
-----------------

The IMAGE demo uses the Fastgraph for Windows image display, creation, and
management routines. It lets you display and create BMP and PCX files, and
also lets you play FLI/FLC files (continuously or one frame at a time). In
addition, IMAGE provides a way to display information about the currently
displayed image. The files in the IMAGE distribution are:

   IMAGE.TXT     this file (ASCII text format)
   IMAGE.WRI     this file (Windows Write 3.1 format)
   IMAGE16.EXE   16-bit Windows executable
   IMAGE32.EXE   32-bit Windows executable (Win32s or Windows 95)

   IMAGE.C       C source code
   IMAGE.PAS     Pascal source code
   IMAGE.RC      C and Pascal resource script file
   IMAGE.H       header file referenced in IMAGE.RC and IMAGE.C

   IMAGE.FRM     Visual Basic 4.0 source code
   IMAGE.VBP     Visual Basic 4.0 project file

   IMAGE.DPR     Delphi project file
   IMAGE.RES     Delphi resource file
   IMAGEU.PAS    Delphi source code unit
   IMAGEU.FRM    Delphi graphical form file

As far as Windows resources, IMAGE uses a top-level menu, with pull-down
menus for each image file type in the top-level menu, plus dialog boxes for
selecting file names. Initially, the BMP menu only lets you open (display) a
BMP file, but once you do, its Make and Info selections are also enabled. The
PCX pull-down menu is the same as the BMP pull-down menu, but the FLI/FLC
pull-down menu is different. It includes selections to open a flic file
(which displays its first frame), play a flic file continuously (until Escape
is pressed), play the next frame of the flic file, rewind it, and obtain
information about it.

Initial setup
-------------

The IMAGE program initially creates a 1x1 virtual buffer. The image files
that IMAGE loads can be any size, so we create a virtual buffer with the same
dimensions as the image when we load the image. Before we do this, however,
we release the virtual buffer containing the previously loaded image (the
switch_buffers() function handles these tasks). Creating the 1x1 virtual
buffer eliminates the need for switch_buffers() to treat the first image it
loads as a special case. In the C and Pascal versions, the WM_CREATE handler
also calls the Windows API function GetMenu() to obtain a handle to the
program's menus; this is needed when we later enable or disable specific menu
items.

Processing menu selections: C and Pascal
----------------------------------------

In the C and Pascal versions of IMAGE, the WM_COMMAND handler processes the
top-level and pull-down menu items, using constants defined in the IMAGE.H
header file. All selections from the BMP, PCX, and FLI/FLC menus are
processed through three action functions, do_bmp(), do_pcx(), and do_flic().
Note how we pass the command identifier to each action function so they can
process the specific commands using a switch/case structure.

The do_bmp() function processes the Open, Make, and Info items on the BMP
menu. As we mentioned earlier, only Open is available until we load an image
(including a PCX or flic image from the other menus). The IDM_BMPOPEN handler
implements the Open item. It first calls get_open_filename() to obtain the
BMP file name. This is done using the Open File dialog box from the Windows
common dialog box library. As the point of the IMAGE program is to
demonstrate the Fastgraph for Windows image file functions, we won't delve
into the mechanics of get_open_filename() here. Suffice it to say,
get_open_filename() sets three global strings: file_name, containing the full
path name of the selected file; file_title, containing only the file name and
extension portions of the file name; and open_file, which contains the same
string as file_title. The get_open_filename() function returns OK if we
selected a file, and ERR if we didn't (for example, if we pressed the Cancel
button in the dialog box).

If we do select a file, the IDM_BMPOPEN handler calls fg_bmphead() to read
the BMP file header and verify that the file really is a BMP file. If not, we
display a message box and return. If we get this far, then we do have a BMP
file, so we call fg_bmpsize() to get the BMP image width and height, storing
these values in the global variables cxBuffer and cyBuffer. IDM_BMPOPEN then
calls switch_buffers() to release to current virtual buffer and create a new
virtual buffer with dimensions equal to those of the BMP file we're loading.
Next, fg_showbmp() loads the BMP file into the virtual buffer, and
fg_vbscale() makes it visible in the client area. We then use fg_bmppal() to
determine the number of colors in the BMP image, storing the result in the
global variable colors (note that we don't do anything with the BMP palette,
fg_bmppal() just provides a convenient way to get the number of colors).
Finally, IDM_BMPOPEN calls the Windows API function EnableMenuItem() to
enable the remaining items on the BMP menu and disable all items on the other
menus except Open and Make.

The IDM_BMPMAKE handler calls get_save_filename() to obtain the name of the
BMP file to create. Like get_open_filename(), the get_save_filename()
function does this through a File Open dialog box, and stores the file name
information in the file_name and file_title globals. If we select a file
name, IDM_BMPMAKE calls fg_makebmp() to create a BMP file with the same
number of colors as the original image.

The IDM_BMPINFO handler displays the image dimensions and number of colors in
a message box, using the values obtained during IDM_BMPOPEN processing.

As you might expect, the do_pcx() action function is very similar to
do_bmp(), but its IDM_PCXOPEN handler does have two minor differences. First,
unlike a BMP file, the PCX file header does not include the image dimensions,
but rather four values defining the image position. The fg_pcxrange()
function returns these values, and we use them to determine the image size,
storing the results as before in the cxBuffer and cyBuffer globals. Second,
note how we set bit 1 of the fg_showpcx() flags parameter. This overrides the
image positioning information in the PCX header, which might specify a
position other than (0,0).

The do_flic() action function processes the five items on the FLI/FLC menu.
Its IDM_FLICOPEN handler first calls get_open_filename() to retrieve the name
of an FLI or FLC file, fg_flichead() to read the flic file header, and
fg_flicsize() to obtain the image dimensions. After switch_buffers() performs
the virtual buffer setup, IDM_FLICOPEN calls fg_flicopen() to set up the
16-byte context descriptor for the low- level flic file routines,
fg_flicplay() to load the first frame into the virtual buffer, and
fg_vbscale() to make it visible in the client area. Next, we set the colors
global to 256 (flic files are always 256-color images) and extract the frame
count from offsets 6 and 7 in the flic file header. As before, we then use
EnableMenuItem() to enable the remaining items in the FLI/FLC menu and
disable the Info items in the other menus.

The IDM_FLICPLAY handler plays the flic file continuously with fg_showflic().
The flic file plays until the Escape key is pressed. After this, IDM_FLICPLAY
calls fg_flicskip() with a negative frame count to rewind the flic file, so
the next call to fg_flicplay() will start with the first frame.

The IDM_FLICFRAME handler calls fg_flicplay() to play the next frame from the
flic file. If fg_flicplay() returns a zero frame count, we've reached the end
of file, so we rewind the flic file and again call fg_flicplay() to replay
the first frame. In any case, IDM_FLICFRAME then calls fg_vbscale() to make
the frame visible in the client area.

The IDM_FLICRESET handler calls fg_flicskip() with a negative frame count to
rewind the flic file, and then calls fg_flicplay() to display the first
frame. As usual, fg_vbscale() makes the first frame visible.

The IDM_FLICINFO handler displays information about the flic file, using
values obtained during the IDM_FLICOPEN processing. Because flic files always
contain 256 colors, we instead display the frame count, which is a more
meaningful metric than the color count for flic files.

Processing menu selections: Delphi
----------------------------------

In the Delphi version, each item on the BMP, PCX, and FLI/FLC menus has its
own corresponding function that gets called whenever we select that menu
item. For example, if we choose Open from the BMP menu, the BMPopen()
function is called.

The BMPopen() handler implements the Open item on the BMP menu. It first
calls get_open_filename() to obtain the BMP file name. This is done using the
Open File dialog box from the Windows common dialog box library. As the point
of the IMAGE program is to demonstrate the Fastgraph for Windows image file
functions, we won't delve into the mechanics of get_open_filename() here.
Suffice it to say, get_open_filename() sets three global strings: file_name,
containing the full path name of the selected file; file_title, containing
only the file name and extension portions of the file name; and open_file,
which contains the same string as file_title. The get_open_filename()
function returns OK if we selected a file, and ERR if we didn't (for example,
if we pressed the Cancel button in the dialog box).

If we do select a file, BMPopen() calls fg_bmphead() to read the BMP file
header and verify that the file really is a BMP file. If not, we display a
message box and return. If we get this far, then we do have a BMP file, so we
call fg_bmpsize() to get the BMP image width and height, storing these values
in the global variables cxBuffer and cyBuffer. We then call switch_buffers()
to release the current virtual buffer and create a new virtual buffer with
dimensions equal to those of the BMP file we're loading. Next, fg_showbmp()
loads the BMP file into the virtual buffer, and fg_vbscale() makes it visible
in the client area. We then use fg_bmppal() to determine the number of colors
in the BMP image, storing the result in the global variable colors (note that
we don't do anything with the BMP palette, fg_bmppal() just provides a
convenient way to get the number of colors). Finally, BMPopen() enables the
remaining items on the BMP menu and disables all items on the other menus
except Open and Make.

The BMPmake() handler calls get_save_filename() to obtain the name of the BMP
file to create. Like get_open_filename(), the get_save_filename() function
does this through a File Open dialog box, and stores the file name
information in the file_name and file_title globals. If we select a file
name, BMPmake() calls fg_makebmp() to create a BMP file with the same number
of colors as the original image.

The BMPinfo() handler displays the image dimensions and number of colors in a
message box, using the values obtained during BMPOpen() processing.

As you might expect, the PCX menu handlers are very similar to the BMP
handlers, but the PCXopen() handler does have two minor differences. First,
unlike a BMP file, the PCX file header does not include the image dimensions,
but rather four values defining the image position. The fg_pcxrange()
function returns these values, and we use them to determine the image size,
storing the results as before in the cxBuffer and cyBuffer globals. Second,
note how we set bit 1 of the fg_showpcx() flags parameter. This overrides the
image positioning information in the PCX header, which might specify a
position other than (0,0).

The FLICopen() handler first calls get_open_filename() to retrieve the name
of an FLI or FLC file, fg_flichead() to read the flic file header, and
fg_flicsize() to obtain the image dimensions. After switch_buffers() performs
the virtual buffer setup, FLICopen() calls fg_flicopen() to set up the
16-byte context descriptor for the low-level flic file routines,
fg_flicplay() to load the first frame into the virtual buffer, and
fg_vbscale() to make it visible in the client area. Next, we set the colors
global to 256 (flic files are always 256-color images) and extract the frame
count from offsets 6 and 7 in the flic file header. As before, we then enable
the remaining items in the FLI/FLC menu and disable the Info items in the
other menus.

The FLICplay() handler plays the flic file continuously with fg_showflic().
The flic file plays until the Escape key is pressed. After this, FLICplay()
calls fg_flicskip() with a negative frame count to rewind the flic file, so
the next call to fg_flicplay() will start with the first frame.

The FLICframe() handler calls fg_flicplay() to play the next frame from the
flic file. If fg_flicplay() returns a zero frame count, we've reached the end
of file, so we rewind the flic file and again call fg_flicplay() to replay
the first frame. In any case, FLICframe() then calls fg_vbscale() to make the
frame visible in the client area.

The FLICreset() handler calls fg_flicskip() with a negative frame count to
rewind the flic file, and then calls fg_flicplay() to display the first
frame. As usual, fg_vbscale() makes the first frame visible.

The FLICinfo() handler displays information about the flic file, using values
obtained during the FLICopen() processing. Because flic files always contain
256 colors, we instead display the frame count, which is a more meaningful
metric than the color count for flic files.

Processing menu selections: Visual Basic
----------------------------------------

In the Visual Basic version, all selections from the BMP, PCX, and FLI/FLC
menus are processed through three action functions, mnuBmpItem_Click(),
mnuPcxItem_Click(), and mnuFliFlcItem_Click(). Note how we pass the menu
selection index to each action function so they can process the specific menu
selections using a select/case structure.

The mnuBmpItem_Click() function processes the Open, Make, and Info items on
the BMP menu. As we mentioned earlier, only Open is available until we load
an image (including a PCX or flic image from the other menus). The BMP Open
handler uses the Open File dialog box to obtain the BMP file name. If we do
select a file, the handler calls fg_bmphead() to read the BMP file header and
verify that the file really is a BMP file. If not, we display a message box
and return. If we get this far, then we do have a BMP file, so we call
fg_bmpsize() to get the BMP image width and height, storing these values in
the global variables cxBuffer and cyBuffer. The BMP open handler then calls
SwitchBuffers() to release the current virtual buffer and create a new
virtual buffer with dimensions equal to those of the BMP file we're loading.
Next, fg_showbmp() loads the BMP file into the virtual buffer, and
fg_vbscale() makes it visible in the client area. We then use fg_bmppal() to
determine the number of colors in the BMP image, storing the result in the
global variable Colors (note that we don't do anything with the BMP palette,
fg_bmppal() just provides a convenient way to get the number of colors).
Finally, the BMP open handler enables the remaining items on the BMP menu and
disables all items on the other menus except Open and Make.

The BMP Make handler obtains the name of the BMP file to create through a
Save File dialog box. If we select a file name, the BMP Make handler calls
fg_makebmp() to create a BMP file with the same number of colors as the
original image.

The BMP Info handler displays the image dimensions and number of colors in a
message box, using the values obtained during BMP Open processing.

As you might expect, the mnuPcxItem_Click() action function is very similar
to mnuBmpItem_Click(), but its PCX Open handler does have two minor
differences. First, unlike a BMP file, the PCX file header does not include
the image dimensions, but rather four values defining the image position. The
fg_pcxrange() function returns these values, and we use them to determine the
image size, storing the results as before in the cxBuffer and cyBuffer
globals. Second, note how we set bit 1 of the fg_showpcx() flags parameter.
This overrides the image positioning information in the PCX header, which
might specify a position other than (0,0).

The mnuFliFlcItem_Click() action function processes the five items on the
FLI/FLC menu. Its FLI/FLC Open handler first retrieves the name of an FLI or
FLC file, calls fg_flichead() to read the flic file header, and calls
fg_flicsize() to obtain the image dimensions. After SwitchBuffers() performs
the virtual buffer setup, the FLI/FLC Open handler calls fg_flicopen() to set
up the 16-byte context descriptor for the low-level flic file routines,
fg_flicplay() to load the first frame into the virtual buffer, and
fg_vbscale() to make it visible in the client area. Next, we set the Colors
global to 256 (flic files are always 256-color images) and extract the frame
count from offsets 6 and 7 in the flic file header. As before, we then enable
the remaining items in the FLI/FLC menu and disable the Info items in the
other menus.

The FLI/FLC Play handler plays the flic file continuously with fg_showflic().
The flic file plays until the Escape key is pressed. After this, the handler
calls fg_flicskip() with a negative frame count to rewind the flic file, so
the next call to fg_flicplay() will start with the first frame.

The FLI/FLC Frame handler calls fg_flicplay() to play the next frame from the
flic file. If fg_flicplay() returns a zero frame count, we've reached the end
of file, so we rewind the flic file and again call fg_flicplay() to replay
the first frame. In any case, the handler then calls fg_vbscale() to make the
frame visible in the client area.

The FLI/FLC Reset handler calls fg_flicskip() with a negative frame count to
rewind the flic file, and then calls fg_flicplay() to display the first
frame. As usual, fg_vbscale() makes the first frame visible.

The FLI/FLC Info handler displays information about the flic file, using
values obtained during the FLI/FLC Open processing. Because flic files always
contain 256 colors, we instead display the frame count, which is a more
meaningful metric than the color count for flic files.

For more information about Fastgraph for Windows, contact:
----------------------------------------------------------

Ted Gruber Software
P.O. Box 13408
Las Vegas, NV  89112

(702) 735-1980 (voice)
(702) 735-4603 (fax)
(702) 796-7134 (bbs)

email: fastgraph@aol.com
ftp: ftp.accessnv.com\fg\Windows
web: http://www.fastgraph.com
