home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / Dloads / PROGRAMM / FGL112B.ZIP / USER09.DOC < prev    next >
Text File  |  1992-10-05  |  127KB  |  2,861 lines

  1.  
  2.  
  3. Chapter 9
  4.  
  5. Images and
  6. Image Management
  7. 136  Fastgraph User's Guide
  8.  
  9.  
  10. Overview
  11.  
  12.      Within the context of Fastgraph, an image is a rectangular area of video
  13. memory containing some type of picture.  An image might be something as
  14. simple as a pointing hand icon, or as detailed as the dashboard of a sports
  15. car.  Fastgraph includes several routines to display, retrieve, and
  16. manipulate images, as well as transfer them between different areas of video
  17. memory.  This chapter will discuss these routines in detail.  The information
  18. presented here, combined with the video page management techniques described
  19. in the previous chapter, will provide the tools we need for sophisticated
  20. animation techniques.
  21.  
  22.  
  23. Mode-Independent Bit-Mapped Images
  24.  
  25.      This section will discuss the image display routines that use the same
  26. bit-mapped image format for all graphics video modes.  Another class of
  27. routines, described in the next section, use different formats for different
  28. video modes.  While these mode-independent image display routines are more
  29. general, they achieve this generality at the sake of execution speed.  This
  30. may especially be a concern if the image is large, or if speed is critical in
  31. an application (as in arcade-style graphics).  For many programs, however,
  32. the mode-independent routines provide all the image display capability
  33. needed.
  34.  
  35.      Let's begin with an example of a very simple image.  Suppose we need to
  36. display a small triangle whose perimeter is a different color than its
  37. interior.  To use this image with Fastgraph, we must inscribe it in a
  38. rectangular area.  Hence, the pixel representation of our triangle might
  39. appear as shown below.
  40.  
  41.                               . . . . * . . . .
  42.                               . . . * x * . . .
  43.                               . . * x x x * . .
  44.                               . * x x x x x * .
  45.                               * * * * * * * * *
  46.  
  47.      As shown in this diagram, our triangle is 9 pixels wide at its base and
  48. 5 pixels high.  The pixels indicated by an asterisk (*) are the triangle's
  49. perimeter, while those indicated by an x represent its interior points.  We
  50. need to distinguish between these pixels because they will be different
  51. colors.  The pixels shown as periods (.) are not part of the triangle itself.
  52. They are required to make the image rectangular, so from Fastgraph's
  53. perspective they are indeed part of the image.
  54.  
  55.      The Fastgraph routine fg_drawmap is a suitable routine for drawing our
  56. triangle.  To use fg_drawmap, we must create separate bit maps for each color
  57. in the image (excluding the points used to fill the rectangular region, which
  58. is considered transparent).  In this example, we will thus need two bit
  59. maps -- one for the perimeter points, and one for the interior points.  Let's
  60. break the image into these two bit maps.
  61.                                   Chapter 9:  Images and Image Management  137
  62.  
  63.                   . . . . * . . . .        . . . . . . . . .
  64.                   . . . * . * . . .        . . . . x . . . .
  65.                   . . * . . . * . .        . . . x x x . . .
  66.                   . * . . . . . * .        . . x x x x x . .
  67.                   * * * * * * * * *        . . . . . . . . .
  68.  
  69.                   perimeter points          interior points
  70.  
  71.      The next step is to convert these two bit maps into their binary
  72. representations.  Just as there are eight bits in a byte, we will create a
  73. data structure (an array in this case) with each byte holding eight pixels.
  74. Bits that are set (1) indicate the corresponding pixel will appear displayed
  75. in the color associated with that bit map.  Bits that are reset (0) leave the
  76. corresponding pixel unchanged.  The size of each bit map array must be at
  77. least 10 bytes because each bit map contains five rows with nine pixels in
  78. each row (that is, two bytes are required for each row of the image).  Hence,
  79. when we convert these bit maps to their binary representations, and
  80. subsequently to their hexadecimal equivalent, the results will appear as
  81. shown below.  The boldface bits represent the actual image; the other bits
  82. are filler bits needed to complete each row of the bit maps after the ninth
  83. pixel.  All filler bits must be zero.
  84.  
  85.               0 0 0 0 1 0 0 0   0 0 0 0 0 0 0 0         08   00
  86.               0 0 0 1 0 1 0 0   0 0 0 0 0 0 0 0         14   00
  87.               0 0 1 0 0 0 1 0   0 0 0 0 0 0 0 0         22   00
  88.               0 1 0 0 0 0 0 1   0 0 0 0 0 0 0 0         41   00
  89.               1 1 1 1 1 1 1 1   1 0 0 0 0 0 0 0         FF   80
  90.  
  91.                               perimeter bit map
  92.  
  93.  
  94.               0 0 0 0 0 0 0 0   0 0 0 0 0 0 0 0         00   00
  95.               0 0 0 0 1 0 0 0   0 0 0 0 0 0 0 0         08   00
  96.               0 0 0 1 1 1 0 0   0 0 0 0 0 0 0 0         1C   00
  97.               0 0 1 1 1 1 1 0   0 0 0 0 0 0 0 0         3E   00
  98.               0 0 0 0 0 0 0 0   0 0 0 0 0 0 0 0         00   00
  99.  
  100.                                interior bit map
  101.  
  102.      The next question is the order in which the bit maps are stored in the
  103. corresponding data structures.  Since our data structure is an array, it is
  104. only necessary to show the relationship of the subscripts to the bit map
  105. structures above.  The next diagram shows the subscript order for the case of
  106. a two-column by five-row bit map.
  107.  
  108.                                   [8]   [9]
  109.  
  110.                                   [6]   [7]
  111.  
  112.                                   [4]   [5]
  113.  
  114.                                   [2]   [3]
  115.  
  116.                                   [0]   [1]
  117.  
  118. 138  Fastgraph User's Guide
  119.  
  120.  
  121.      From this diagram, we see the first element of the array (that is, the
  122. element with subscript [0]) represents the lower left corner of the image.
  123. The subscript progression then continues right until reaching the end of the
  124. first row.  It then resumes at the leftmost element of the second row and
  125. continues to the right until the end of that row.  It continues in this
  126. manner for all remaining rows.
  127.  
  128.      We are now ready to present an example program to display our triangle.
  129. The program will use the Fastgraph routine fg_drawmap, which expects three
  130. arguments.  The first argument is the bit map array (passed by reference),
  131. the second is the width of the bit map in bytes, and the last is the height
  132. of the bit map in pixel rows.  The fg_drawmap routine displays the image such
  133. that its lower left corner is at the graphics cursor position on the active
  134. video page.  The routine has no effect in text video modes.  Additionally,
  135. fg_drawmap displays the image using the current color index, which means we
  136. will need to call fg_drawmap once for each color in the image.
  137.  
  138.      Example 9-1 runs in any 320 by 200 color graphics mode (it could be made
  139. to run in mode 12 too, but that would detract from the purpose of the
  140. example).  After establishing the video mode, the program uses fg_rect to
  141. fill the entire screen with a gray rectangle (white in CGA).  Next, the
  142. program establishes (156,101) as the graphics cursor position; this causes
  143. the triangle to be centered on the screen.  The two calls to fg_drawmap, one
  144. for each of the colors in the image, actually display the triangle.  Note
  145. especially how fg_setcolor is used before each call to fg_drawmap to define
  146. the current color index.  The result is a triangle with a blue perimeter
  147. (cyan in CGA) and green interior (magenta in CGA).
  148.  
  149.                                  Example 9-1.
  150.  
  151.              #include <fastgraf.h>
  152.              #include <stdio.h>
  153.              #include <stdlib.h>
  154.              void main(void);
  155.  
  156.              char perimeter[] = {
  157.                 0xFF,0x80,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00
  158.                 };
  159.              char interior[] = {
  160.                 0x00,0x00,0x3E,0x00,0x1C,0x00,0x08,0x00,0x00,0x00
  161.                 };
  162.  
  163.              void main()
  164.              {
  165.                 int old_mode, new_mode;
  166.  
  167.                 new_mode = fg_bestmode(320,200,1);
  168.                 if (new_mode < 0 || new_mode == 12) {
  169.                    printf("This program requires a 320 ");
  170.                    printf("x 200 color graphics mode.\n");
  171.                    exit(1);
  172.                    }
  173.  
  174.                 old_mode = fg_getmode();
  175.                 fg_setmode(new_mode);
  176.  
  177.                                   Chapter 9:  Images and Image Management  139
  178.  
  179.  
  180.                 fg_setcolor(7);
  181.                 fg_rect(0,319,0,199);
  182.  
  183.                 fg_move(156,101);
  184.                 fg_setcolor(1);
  185.                 fg_drawmap(perimeter,2,5);
  186.                 fg_setcolor(2);
  187.                 fg_drawmap(interior,2,5);
  188.                 fg_waitkey();
  189.  
  190.                 fg_setmode(old_mode);
  191.                 fg_reset();
  192.              }
  193.  
  194.  
  195.      The different color bit maps used by fg_drawmap do not all have to be
  196. the same size.  In our triangle example, the perimeter is 9 pixels wide by 5
  197. pixels high, but the interior is only 5 pixels wide by 3 pixels high.  Hence,
  198. the bit map for the interior pixels only requires one byte for each of its
  199. three rows, so we can store it in a three-byte array.  Its structure would
  200. be:
  201.  
  202.                                   [2]   08
  203.                                   [1]   1C
  204.                                   [0]   3E
  205.  
  206.      Example 9-2 is similar to example 9-1, but it uses a three-byte array
  207. for the interior bit map.  Note the second call to fg_move in this example.
  208. It is needed because the bottom row of the smaller interior bit map
  209. corresponds to the second row of the larger perimeter bit map.  In other
  210. words, the interior bit map must be displayed one row above the perimeter bit
  211. map.
  212.  
  213.                                  Example 9-2.
  214.  
  215.              #include <fastgraf.h>
  216.              #include <stdio.h>
  217.              #include <stdlib.h>
  218.              void main(void);
  219.  
  220.              char perimeter[] = {
  221.                 0xFF,0x80,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00
  222.                 };
  223.              char interior[] = {
  224.                 0x3E,0x1C,0x08
  225.                 };
  226.  
  227.              void main()
  228.              {
  229.                 int old_mode, new_mode;
  230.  
  231.                 new_mode = fg_bestmode(320,200,1);
  232.                 if (new_mode < 0 || new_mode == 12) {
  233.  
  234. 140  Fastgraph User's Guide
  235.  
  236.                    printf("This program requires a 320 ");
  237.                    printf("x 200 color graphics mode.\n");
  238.                    exit(1);
  239.                    }
  240.  
  241.                 old_mode = fg_getmode();
  242.                 fg_setmode(new_mode);
  243.  
  244.                 fg_setcolor(7);
  245.                 fg_rect(0,319,0,199);
  246.  
  247.                 fg_move(156,101);
  248.                 fg_setcolor(1);
  249.                 fg_drawmap(perimeter,2,5);
  250.                 fg_move(156,100);
  251.                 fg_setcolor(2);
  252.                 fg_drawmap(interior,1,3);
  253.                 fg_waitkey();
  254.  
  255.                 fg_setmode(old_mode);
  256.                 fg_reset();
  257.              }
  258.  
  259.      In example 9-2, the time required to execute the second call to fg_move
  260. may not be worth the saving of 7 bytes.  When array space is critical, or
  261. when the images are larger, the use of smaller bit maps for certain colors
  262. may be more valuable.
  263.  
  264.      Yet another possibility for example 9-2 would be to shift the elements
  265. of the interior bit map two pixels to the left.  In this way, the bit map
  266. would be aligned against the left side of the array, just as the perimeter
  267. bit map is.  The three values comprising the interior bit map would then
  268. become F8, 70, and 20.  We also would need to change the x coordinate in the
  269. second call to fg_move from 156 to 158.
  270.  
  271.  
  272. Mode-Specific Bit-Mapped Images
  273.  
  274.      This section will discuss the image display routines that use bit-mapped
  275. image formats that are specific to each text and graphics video mode.  The
  276. different image formats closely resemble the structure of video memory in
  277. each mode, so these routines are much faster than displaying mode-independent
  278. bit maps with fg_drawmap.  If you use the mode-specific bit maps in a program
  279. that supports several video modes, there will be some additional programming
  280. that is not needed when using mode-independent bit maps.  Usually, however,
  281. your efforts will be rewarded with faster graphics.
  282.  
  283.      We'll demonstrate the use of mode-specific bit maps in graphics modes
  284. with the familiar two-color triangle whose pixel representation appears
  285. below.
  286.  
  287.                               . . . . * . . . .
  288.                               . . . * x * . . .
  289.                               . . * x x x * . .
  290.                               . * x x x x x * .
  291.                               * * * * * * * * *
  292.                                   Chapter 9:  Images and Image Management  141
  293.  
  294.      As before, our triangle is 9 pixels wide at its base and 5 pixels high.
  295. The pixels indicated by an asterisk (*) are the triangle's perimeter, while
  296. those indicated by an x represent its interior points.  We need to
  297. distinguish between these pixels because they will be different colors.  The
  298. pixels shown as periods (.) are not part of the triangle itself.  They are
  299. required to make the image rectangular, so from Fastgraph's perspective they
  300. are indeed part of the image.
  301.  
  302.  
  303. Regular Images
  304.  
  305.      The Fastgraph routine fg_drwimage displays regular mode-specific bit-
  306. mapped images (by regular, we mean an image that is neither clipped nor
  307. rotated).  Its arguments are the same as for the fg_drawmap routine, and the
  308. bit map array's subscript order is also the same as for fg_drawmap.  The
  309. major difference is the bit map structure -- we combine the information for
  310. all colors into a single bit map, in a way consistent with the structure and
  311. accessibility of video memory for the various modes.  As with the other image
  312. display routines, fg_drwimage displays the image on the active video page
  313. with its lower left corner at the graphics cursor position (or the text
  314. cursor position for text modes).  We'll now examine the use of fg_drwimage in
  315. several video modes.
  316.  
  317. CGA four-color graphics modes
  318.  
  319.      In the four-color CGA graphics modes (modes 4 and 5), each pixel can
  320. assume a value between 0 and 3.  This means it takes two bits to represent a
  321. pixel, or put another way, each byte of video memory holds four pixels.  Our
  322. triangle image is nine pixels wide, so three bytes are needed for each row of
  323. the image.  Because the image is five pixels high, we need a bit map array of
  324. at least 15 bytes (five rows times three bytes per row) to hold the image.
  325.  
  326.      The image's binary representation and its hexadecimal equivalent for the
  327. four-color CGA graphics modes are shown below.  The binary values in boldface
  328. represent the actual image; the others are the filler bits needed to complete
  329. each row of the bit map after the ninth pixel.  We have coded the perimeter
  330. pixels to be color 1 (01 binary) and the interior pixels to be color 2 (10
  331. binary).  Any pixel whose value is zero (00 binary) is transparent and will
  332. thus leave the contents of video memory at that position unchanged.
  333.  
  334.          00 00 00 00   01 00 00 00   00 00 00 00         00   40   00
  335.          00 00 00 01   10 01 00 00   00 00 00 00         01   90   00
  336.          00 00 01 10   10 10 01 00   00 00 00 00         06   A4   00
  337.          00 01 10 10   10 10 10 01   00 00 00 00         1A   A9   00
  338.          01 01 01 01   01 01 01 01   01 00 00 00         55   55   40
  339.  
  340.      Example 9-3 uses this mode-specific bit map to display the triangle in
  341. the standard CGA four-color graphics mode (mode 4).  After establishing the
  342. video mode, the program uses fg_rect to fill the entire screen with a white
  343. rectangle.  Next, the program establishes (156,101) as the graphics cursor
  344. position; this causes the triangle to be centered on the screen.  The call to
  345. 142  Fastgraph User's Guide
  346.  
  347. fg_drwimage produces a triangle with a cyan perimeter (color 1) and a magenta
  348. interior (color 2).
  349.  
  350.                                  Example 9-3.
  351.  
  352.               #include <fastgraf.h>
  353.               #include <stdio.h>
  354.               #include <stdlib.h>
  355.               void main(void);
  356.  
  357.               char triangle[] = {
  358.                  0x55,0x55,0x40, 0x1A,0xA9,0x00, 0x06,0xA4,0x00,
  359.                  0x01,0x90,0x00, 0x00,0x40,0x00
  360.                  };
  361.  
  362.               void main()
  363.               {
  364.                  int old_mode;
  365.  
  366.                  if (fg_testmode(4,1) == 0) {
  367.                     printf("This program requires a 320 ");
  368.                     printf("x 200 CGA graphics mode.\n");
  369.                     exit(1);
  370.                     }
  371.  
  372.                  old_mode = fg_getmode();
  373.                  fg_setmode(4);
  374.  
  375.                  fg_setcolor(7);
  376.                  fg_rect(0,319,0,199);
  377.  
  378.                  fg_move(156,101);
  379.                  fg_drwimage(triangle,3,5);
  380.                  fg_waitkey();
  381.  
  382.                  fg_setmode(old_mode);
  383.                  fg_reset();
  384.               }
  385.  
  386.  
  387. CGA two-color graphics mode
  388.  
  389.      In the two-color CGA graphics mode (mode 6), each pixel can assume the
  390. values 0 or 1.  This means it takes just one bit to represent a pixel, so
  391. each byte of video memory holds eight pixels.  Our triangle image is nine
  392. pixels wide, so two bytes are needed for each row of the image.  Because the
  393. image is five pixels high, we need a bit map array of at least 10 bytes (five
  394. rows times two bytes per row) to hold the image.
  395.  
  396.      The image's binary representation and its hexadecimal equivalent for the
  397. two-color CGA graphics mode is shown below.  The binary values in boldface
  398. represent the actual image; the others are the filler bits needed to complete
  399. each row of the bit map after the ninth pixel.  We have coded both the
  400. perimeter pixels and the interior pixels to be color 1.  Any pixel whose
  401. value is zero is transparent and will thus leave the contents of video memory
  402. at that position unchanged.
  403.                                   Chapter 9:  Images and Image Management  143
  404.  
  405.               0 0 0 0 1 0 0 0   0 0 0 0 0 0 0 0         08   00
  406.               0 0 0 1 1 1 0 0   0 0 0 0 0 0 0 0         1C   00
  407.               0 0 1 1 1 1 1 0   0 0 0 0 0 0 0 0         3E   00
  408.               0 1 1 1 1 1 1 1   0 0 0 0 0 0 0 0         7F   00
  409.               1 1 1 1 1 1 1 1   1 0 0 0 0 0 0 0         FF   80
  410.  
  411.      Example 9-4 uses this mode-specific bit map to display the triangle in
  412. the CGA two-color graphics mode (mode 6).  After establishing the video mode,
  413. the program establishes (316,101) as the graphics cursor position; this
  414. causes the triangle to be centered on the screen.  The call to fg_drwimage
  415. produces a solid triangle.
  416.  
  417.                                  Example 9-4.
  418.  
  419.                   #include <fastgraf.h>
  420.                   #include <stdio.h>
  421.                   #include <stdlib.h>
  422.                   void main(void);
  423.  
  424.                   char triangle[] = {
  425.                      0xFF,0x80, 0x7F,0x00, 0x3E,0x00,
  426.                      0x1C,0x00, 0x08,0x00
  427.                      };
  428.  
  429.                   void main()
  430.                   {
  431.                      int old_mode;
  432.  
  433.                      if (fg_testmode(6,1) == 0) {
  434.                         printf("This program requires a ");
  435.                         printf("CGA graphics mode.\n");
  436.                         exit(1);
  437.                         }
  438.  
  439.                      old_mode = fg_getmode();
  440.                      fg_setmode(6);
  441.  
  442.                      fg_move(316,101);
  443.                      fg_drwimage(triangle,2,5);
  444.                      fg_waitkey();
  445.  
  446.                      fg_setmode(old_mode);
  447.                      fg_reset();
  448.                   }
  449.  
  450.  
  451. Tandy/PCjr 16-color graphics mode
  452.  
  453.      The structure of the mode-specific bit maps for the Tandy/PCjr 16-color
  454. graphics mode (mode 9) is the same as the mode-specific bit map structure for
  455. the native EGA and VGA graphics modes.  Please refer to page 144 for a
  456. discussion of EGA and VGA bit maps.
  457. 144  Fastgraph User's Guide
  458.  
  459. Hercules graphics modes
  460.  
  461.      The structure of the mode-specific bit maps for the Hercules graphics
  462. modes (modes 11 and 12) is the same as two of the CGA graphics modes.  For
  463. the standard Hercules graphics mode (mode 11), please refer to the discussion
  464. of CGA two-color (mode 6) bit maps on page 142.  For the low-resolution
  465. Hercules graphics mode (mode 12), please refer to the discussion of the CGA
  466. four-color (mode 4) bit maps on page 141.
  467.  
  468. EGA and VGA graphics modes
  469.  
  470.      In the native EGA and VGA graphics modes (modes 13 through 18), each
  471. pixel can assume a value between 0 and 15.  This means it takes four bits to
  472. represent a pixel, so each byte of the bit map holds two pixels.  Our
  473. triangle image is nine pixels wide, so five bytes are needed for each row of
  474. the image.  Because the image is five pixels high, we need a bit map array of
  475. at least 25 bytes (five rows times five bytes per row) to hold the image.
  476.  
  477.      In these modes, it is easy to develop the hexadecimal representation of
  478. a bit map without first producing its binary equivalent.  This is because a
  479. pixel value and a hexadecimal digit each occupy four bits.  The triangle's
  480. hexadecimal representation for the native EGA and VGA modes is shown below.
  481. The pixels in boldface represent the actual image; the others are the filler
  482. values needed to complete each row of the bit map after the ninth pixel.  We
  483. have chosen to display the perimeter pixels in color 1 and the interior
  484. pixels in color 2.  Any pixel whose value is zero is transparent and will
  485. thus leave the contents of video memory at that position unchanged.
  486.  
  487.                             00   00   10   00   00
  488.                             00   01   21   00   00
  489.                             00   12   22   10   00
  490.                             01   22   22   21   00
  491.                             11   11   11   11   10
  492.  
  493.      Example 9-5 is similar to example 9-3, but it uses the 320 x 200 EGA
  494. graphics mode (mode 13) and the mode-specific bit map just constructed to
  495. display the triangle.  The call to fg_drwimage produces a triangle with a
  496. blue perimeter (color 1) and a green interior (color 2).
  497.  
  498.                                  Example 9-5.
  499.  
  500.                 #include <fastgraf.h>
  501.                 #include <stdio.h>
  502.                 #include <stdlib.h>
  503.                 void main(void);
  504.  
  505.                 char triangle[] = {
  506.                    0x11,0x11,0x11,0x11,0x10,
  507.                    0x01,0x22,0x22,0x21,0x00,
  508.                    0x00,0x12,0x22,0x10,0x00,
  509.                    0x00,0x01,0x21,0x00,0x00,
  510.                    0x00,0x00,0x10,0x00,0x00
  511.                    };
  512.  
  513.                                   Chapter 9:  Images and Image Management  145
  514.  
  515.                 void main()
  516.                 {
  517.                    int old_mode;
  518.  
  519.                    if (fg_testmode(13,1) == 0) {
  520.                       printf("This program requires a 320 ");
  521.                       printf("x 200 EGA graphics mode.\n");
  522.                       exit(1);
  523.                       }
  524.  
  525.                    old_mode = fg_getmode();
  526.                    fg_setmode(13);
  527.  
  528.                    fg_setcolor(7);
  529.                    fg_rect(0,319,0,199);
  530.  
  531.                    fg_move(156,101);
  532.                    fg_drwimage(triangle,5,5);
  533.                    fg_waitkey();
  534.  
  535.                    fg_setmode(old_mode);
  536.                    fg_reset();
  537.                 }
  538.  
  539.  
  540. MCGA and VGA 256-color graphics modes
  541.  
  542.      In the MCGA and VGA 256-color graphics modes (modes 19 through 23), each
  543. pixel can assume a value between 0 and 255 (FF hex).  This means it takes
  544. eight bits to represent a pixel, or each byte of video memory holds one
  545. pixel.  Our triangle image is nine pixels wide, so nine bytes are needed for
  546. each row of the image.  Because the image is five pixels high, we need a bit
  547. map array of at least 45 bytes (five rows times nine bytes per row) to hold
  548. the image.  Note we will never need any filler bits in the 256-color video
  549. modes.
  550.  
  551.      In the 256-color graphics video modes, it is simple to develop the bit
  552. map for an image because each byte holds exactly one pixel.  The triangle's
  553. hexadecimal representation for the 256-color graphics modes is shown below.
  554. As before, we have coded the perimeter pixels to be color 1 (01 hex) and the
  555. interior pixels to be color 2 (02 hex).  Any pixel whose value is zero is
  556. transparent and will thus leave the contents of video memory at that position
  557. unchanged.
  558.  
  559.                   00   00   00   00   01   00   00   00   00
  560.                   00   00   00   01   02   01   00   00   00
  561.                   00   00   01   02   02   02   01   00   00
  562.                   00   01   02   02   02   02   02   01   00
  563.                   01   01   01   01   01   01   01   01   01
  564.  
  565. 146  Fastgraph User's Guide
  566.  
  567.      Example 9-6 is also similar to example 9-3, but it uses the MCGA 256-
  568. color graphics mode (mode 19) and the mode-specific bit map just constructed
  569. to display the triangle.  The call to fg_drwimage produces a triangle with a
  570. blue perimeter (color 1) and a green interior (color 2).
  571.  
  572.                                  Example 9-6.
  573.  
  574.                #include <fastgraf.h>
  575.                #include <stdio.h>
  576.                #include <stdlib.h>
  577.                void main(void);
  578.  
  579.                char triangle[] = {
  580.                   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
  581.                   0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
  582.                   0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
  583.                   0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
  584.                   0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00
  585.                   };
  586.  
  587.                void main()
  588.                {
  589.                   int old_mode;
  590.  
  591.                   if (fg_testmode(19,1) == 0) {
  592.                      printf("This program requires a 320 ");
  593.                      printf("x 200 MCGA graphics mode.\n");
  594.                      exit(1);
  595.                      }
  596.  
  597.                   old_mode = fg_getmode();
  598.                   fg_setmode(19);
  599.  
  600.                   fg_setcolor(7);
  601.                   fg_rect(0,319,0,199);
  602.  
  603.                   fg_move(156,101);
  604.                   fg_drwimage(triangle,9,5);
  605.                   fg_waitkey();
  606.  
  607.                   fg_setmode(old_mode);
  608.                   fg_reset();
  609.                }
  610.  
  611.  
  612.  
  613. Text Modes
  614.  
  615.      You also can use the fg_drwimage routine to display images in text video
  616. modes (modes 0, 1, 2, 3, and 7).  As one might expect, the image structure in
  617. the text modes is rather different from the graphics modes.  In Chapter 5 we
  618. saw that each character cell on the screen actually consists of a character
  619. and an attribute.  The character value determines what character is
  620. displayed, while the attribute value controls the character's appearance.
  621. The structure of the attribute is:
  622.                                   Chapter 9:  Images and Image Management  147
  623.  
  624.  
  625.                             bits  attribute
  626.  
  627.                             0-3   foreground color
  628.                             4-6   background color
  629.                              7    blinking
  630.  
  631.      The text mode image structure used with fg_drwimage also consists of a
  632. series of characters and attributes.  For example, the following diagram
  633. illustrates the structure of an image that is three characters wide and two
  634. characters high.
  635.  
  636.                    char   attr   char   attr   char   attr
  637.  
  638.                    char   attr   char   attr   char   attr
  639.  
  640.      To illustrate the use of fg_drwimage in a text video mode, we'll display
  641. the phrase "hello there" on two different lines in the center of the screen.
  642. Furthermore, let's assume we would like the first character of each word to
  643. appear in foreground color 1, the second in color 2, and so forth.  Our image
  644. will consist of two lines each containing five characters, and each character
  645. requires two bytes of storage (one for the character and another for its
  646. attribute), so we'll need a 20-byte array for holding the image.  The array
  647. really doesn't hold a bit map as in the graphics modes, so in the text modes
  648. the first argument passed to fg_drwimage is instead called the image array.
  649. In our example, the structure of the image array is:
  650.  
  651.            'h'    1    'e'    2    'l'    3    'l'    4    'o'    5
  652.  
  653.            't'    1    'h'    2    'e'    3    'r'    4    'e'    5
  654.  
  655. The subscript order that fg_drwimage uses for text modes is the same as for
  656. the graphics modes.  For our five-row by two-column image, this means the
  657. array subscripts would be numbered as follows:
  658.  
  659.               [10] [11] [12] [13] [14] [15] [16] [17] [18] [19]
  660.  
  661.                [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]  [8]  [9]
  662.  
  663.      Depending on the character and attribute values in the image array,
  664. fg_drwimage can display new characters and attributes, new characters leaving
  665. the existing attribute unchanged, new attributes leaving the existing
  666. character unchanged, or leave both the existing character and attribute
  667. unchanged in video memory.  To keep an existing character or attribute,
  668. simply specify a value of 0 in the corresponding element of the image array.
  669. This capability is analogous to the fact that zero-valued pixels in graphics
  670. mode bit maps leave video memory unchanged.
  671. 148  Fastgraph User's Guide
  672.  
  673.      Example 9-7 demonstrates the use of the fg_drwimage routine in the 80-
  674. column color text mode (mode 3).  After establishing the video mode and
  675. making the cursor invisible, the program calls fg_drwimage to display the
  676. "hello there" image just discussed (note we pass the dimensions of the image
  677. array as the number of bytes, not the number of characters).  The program
  678. waits for a keystroke and then calls fg_drwimage again, passing a different
  679. image array (called "image") of the same size.  This array changes the first
  680. letter of both words from lower case to upper case (leaving the attribute
  681. unchanged), and it makes the remaining characters have the same attribute as
  682. the first character.  This is done in part by using zero-valued characters
  683. and attributes to leave video memory unchanged.  After waiting for another
  684. keystroke, the program exits.
  685.  
  686.                                  Example 9-7.
  687.  
  688.                     #include <fastgraf.h>
  689.                     void main(void);
  690.  
  691.                     char hello[] = {
  692.                        't',1, 'h',2, 'e',3, 'r',4, 'e',5,
  693.                        'h',1, 'e',2, 'l',3, 'l',4, 'o',5
  694.                        };
  695.  
  696.                     char image[] = {
  697.                        'T',0, 0,1, 0,1, 0,1, 0,1,
  698.                        'H',0, 0,1, 0,1, 0,1, 0,1
  699.                        };
  700.  
  701.                     void main()
  702.                     {
  703.                        int old_mode;
  704.  
  705.                        old_mode = fg_getmode();
  706.                        fg_setmode(3);
  707.                        fg_cursor(0);
  708.  
  709.                        fg_locate(12,37);
  710.                        fg_drwimage(hello,10,2);
  711.                        fg_waitkey();
  712.  
  713.                        fg_drwimage(image,10,2);
  714.                        fg_waitkey();
  715.  
  716.                        fg_setmode(old_mode);
  717.                        fg_reset();
  718.                     }
  719.  
  720.  
  721. Clipped Images
  722.  
  723.      The fg_drwimage routine displays an image without regard to the current
  724. clipping limits.  If you want the image to be displayed with respect to the
  725. clipping limits (as established by the most recent call to fg_setclip), you
  726. should use the fg_clpimage routine instead of fg_drwimage.  Fg_clpimage takes
  727. the same three arguments as fg_drwimage, and also displays the image such
  728. that its lower left corner is at the graphics cursor position.  Unlike
  729. fg_drwimage, the fg_clpimage routine has no effect when used in a text video
  730.                                   Chapter 9:  Images and Image Management  149
  731.  
  732. mode.  Refer to pages 149 and 151 for example programs that use fg_clpimage.
  733. Because of the additional overhead involved in checking the clipping limits,
  734. fg_clpimage is not as fast as fg_drwimage.
  735.  
  736.  
  737. Reversed Images
  738.  
  739.      The fg_revimage routine displays an image reversed (that is, mirrored
  740. about the y-axis).  Fg_revimage takes the same three arguments as
  741. fg_drwimage, and also displays the image such that its lower left corner is
  742. at the graphics cursor position.  The fg_revimage routine has no effect when
  743. used in a text video mode.  Refer to pages 150 and 151 for example programs
  744. that use fg_revimage.
  745.  
  746.  
  747. Reversed Clipped Images
  748.  
  749.      The fg_flpimage routine combines the effects of the fg_revimage and
  750. fg_clpimage routines -- it displays a reversed image with respect to the
  751. current clipping limits.  Fg_flpimage takes the same three arguments as
  752. fg_drwimage, and also displays the image such that its lower left corner is
  753. at the graphics cursor position.  Like the fg_clpimage routine, fg_flpimage
  754. has no effect when used in a text video mode.  Refer to pages 149 and 151 for
  755. example programs that use fg_flpimage.
  756.  
  757.  
  758. Some Examples
  759.  
  760.      Example 9-8 illustrates the use of the fg_drwimage, fg_clpimage,
  761. fg_revimage, and fg_flpimage routines in the standard CGA four-color graphics
  762. mode (mode 4).  The program uses each of these routines to display a small
  763. white arrow, as shown in the pixel map below.
  764.  
  765.                              . . . . . . * . . .
  766.                              . . . . . . * * . .
  767.                              * * * * * * * * * .
  768.                              * * * * * * * * * *
  769.                              * * * * * * * * * .
  770.                              . . . . . . * * . .
  771.                              . . . . . . * . . .
  772.  
  773. As before, we must first convert this image to a bit map.  The image is ten
  774. pixels wide and seven high.  In mode 4, each pixel occupies two bits, so we
  775. need a 21-byte array (7 rows by 3 columns) to store the image.  Since we want
  776. to make the arrow white, each pixel will be displayed in color 3 (11 binary).
  777. Here is the bit map and its hexadecimal equivalent for the arrow image in
  778. mode 4 (the actual image is in boldface).
  779.  
  780.          00 00 00 00   00 00 11 00   00 00 00 00         00   0C   00
  781.          00 00 00 00   00 00 11 11   00 00 00 00         00   0F   00
  782.          11 11 11 11   11 11 11 11   11 00 00 00         FF   FF   C0
  783.          11 11 11 11   11 11 11 11   11 11 00 00         FF   FF   F0
  784.          11 11 11 11   11 11 11 11   11 00 00 00         FF   FF   C0
  785.          00 00 00 00   00 00 11 11   00 00 00 00         00   0F   00
  786.          00 00 00 00   00 00 11 00   00 00 00 00         00   0C   00
  787.  
  788. 150  Fastgraph User's Guide
  789.  
  790.  
  791.      After establishing the video mode, the program defines the clipping
  792. region.  It then uses fg_drwimage to display the arrow pointing to the right
  793. and fg_clpimage to do the same thing, but with respect to the clipping
  794. limits.  Because the left edge of the arrow is displayed at x=10 and the
  795. right clipping limit is at x=15, the call to fg_clpimage only draws the first
  796. six columns of the arrow (that is, it does not draw the arrow head).
  797.  
  798.      Next, example 9-8 uses fg_revimage to display the arrow pointing to the
  799. left.  To allow for the filler pixels, we must establish the graphics cursor
  800. position two pixels to the left of the position used by fg_drwimage if we
  801. want the tip of the left-pointing arrow to align with the tail of the right-
  802. pointing arrow.  Finally, the program uses fg_flpimage to display an arrow
  803. pointing to the left with regard to the clipping limits.  The call to
  804. fg_flpimage displays the arrow head and the first two columns of the arrow
  805. shaft.
  806.  
  807.                                  Example 9-8.
  808.  
  809.               #include <fastgraf.h>
  810.               #include <stdio.h>
  811.               #include <stdlib.h>
  812.               void main(void);
  813.  
  814.               char arrow[] = {
  815.                  0x00,0x0C,0x00, 0x00,0x0F,0x00, 0xFF,0xFF,0xC0,
  816.                  0xFF,0xFF,0xF0, 0xFF,0xFF,0xC0, 0x00,0x0F,0x00,
  817.                  0x00,0x0C,0x00
  818.                  };
  819.  
  820.               void main()
  821.               {
  822.                  int old_mode;
  823.  
  824.                  if (fg_testmode(4,1) == 0) {
  825.                     printf("This program requires a 320 ");
  826.                     printf("x 200 CGA graphics mode.\n");
  827.                     exit(1);
  828.                     }
  829.  
  830.                  old_mode = fg_getmode();
  831.                  fg_setmode(4);
  832.                  fg_setclip(0,15,0,199);
  833.  
  834.                  fg_move(10,10);
  835.                  fg_drwimage(arrow,3,7);
  836.                  fg_move(10,20);
  837.                  fg_clpimage(arrow,3,7);
  838.                  fg_move(8,30);
  839.                  fg_revimage(arrow,3,7);
  840.                  fg_move(8,40);
  841.                  fg_flpimage(arrow,3,7);
  842.                  fg_waitkey();
  843.                  fg_setmode(old_mode);
  844.                  fg_reset();
  845.               }
  846.  
  847.                                   Chapter 9:  Images and Image Management  151
  848.  
  849.      Example 9-9 is the same as example 9-8, but it uses the low resolution
  850. EGA graphics mode (mode 13).  If we changed the mode number specified in the
  851. calls to fg_testmode and fg_setmode, the program also would run in any native
  852. EGA or VGA graphics mode, or in the Tandy/PCjr 16-color graphics mode.  In
  853. these modes, we store two pixels per byte in the bit map array, so we need a
  854. 35-byte array (7 rows by 5 columns) to store the image.  Here is the bit
  855. map's hexadecimal equivalent for the arrow image in mode 13, followed by the
  856. program to display it.
  857.  
  858.                             00   00   00   F0   00
  859.                             00   00   00   FF   00
  860.                             FF   FF   FF   FF   F0
  861.                             FF   FF   FF   FF   FF
  862.                             FF   FF   FF   FF   F0
  863.                             00   00   00   FF   00
  864.                             00   00   00   F0   00
  865.  
  866.  
  867.                                  Example 9-9.
  868.  
  869.                 #include <fastgraf.h>
  870.                 #include <stdio.h>
  871.                 #include <stdlib.h>
  872.                 void main(void);
  873.  
  874.                 char arrow[] = {
  875.                    0x00,0x00,0x00,0xF0,0x00,
  876.                    0x00,0x00,0x00,0xFF,0x00,
  877.                    0xFF,0xFF,0xFF,0xFF,0xF0,
  878.                    0xFF,0xFF,0xFF,0xFF,0xFF,
  879.                    0xFF,0xFF,0xFF,0xFF,0xF0,
  880.                    0x00,0x00,0x00,0xFF,0x00,
  881.                    0x00,0x00,0x00,0xF0,0x00
  882.                    };
  883.  
  884.                 void main()
  885.                 {
  886.                    int old_mode;
  887.  
  888.                    if (fg_testmode(13,1) == 0) {
  889.                       printf("This program requires a 320 ");
  890.                       printf("x 200 EGA graphics mode.\n");
  891.                       exit(1);
  892.                       }
  893.  
  894. 152  Fastgraph User's Guide
  895.  
  896.                    old_mode = fg_getmode();
  897.                    fg_setmode(13);
  898.                    fg_setclip(0,15,0,199);
  899.  
  900.                    fg_move(10,10);
  901.                    fg_drwimage(arrow,5,7);
  902.                    fg_move(10,20);
  903.                    fg_clpimage(arrow,5,7);
  904.                    fg_move(8,30);
  905.                    fg_revimage(arrow,5,7);
  906.                    fg_move(8,40);
  907.                    fg_flpimage(arrow,5,7);
  908.                    fg_waitkey();
  909.  
  910.                    fg_setmode(old_mode);
  911.                    fg_reset();
  912.                 }
  913.  
  914.  
  915. Pixel Run Maps
  916.  
  917.      The bit maps used with the fg_drawmap, fg_drwimage, and related routines
  918. can consume array space quite rapidly.  This is especially true if the image
  919. is large or contains many colors.  For example, a mode-independent bit-mapped
  920. image that occupies the entire screen in a 320 by 200 graphics mode requires
  921. 8,000 bytes of space per color.  Fastgraph provides another mode-independent
  922. image format called pixel run maps, which are more efficient in terms of
  923. space.  In pixel run maps, you store the entire image in a single array.
  924. Pixel run maps are particularly useful for displaying static images such as
  925. backgrounds.
  926.  
  927.      Let's return to our familiar triangle example and show how we could use
  928. a pixel run map to display it.
  929.  
  930.                               . . . . * . . . .
  931.                               . . . * x * . . .
  932.                               . . * x x x * . .
  933.                               . * x x x x x * .
  934.                               * * * * * * * * *
  935.  
  936. As before, the pixels indicated by an asterisk (*) are the triangle's
  937. perimeter, while those indicated by an x represent its interior points.  The
  938. pixels shown as periods (.) are not part of the triangle itself, but they are
  939. part of the pixel run map.
  940.  
  941.      If we start at the lower left corner of the image and proceed to the
  942. right, we could represent the first row of the image as nine pixels of color
  943. "asterisk".  Such a group of consecutive identically colored pixels is called
  944. a pixel run, so a single pixel run describes the first row of the image.  The
  945. row above this one is a bit more complex.  It consists of five pixel runs:
  946. one pixel of color "period", followed by one of color "asterisk", then five
  947. of color "x", one of color "asterisk", and finally one of color "period".
  948.  
  949.      While we could construct separate pixel runs for each row of the image,
  950. notice that three of the five rows in our triangle begin with the same color
  951. pixel as the rightmost pixel in the previous row.  Fastgraph's pixel run map
  952. format lets you take advantage of this property by allowing pixel runs to
  953.                                   Chapter 9:  Images and Image Management  153
  954.  
  955. wrap from one row to the next.  This means we can represent the pixel run of
  956. color "period" extending from the right side of the second row to the left
  957. side of the third row as a single run of three pixels.
  958.  
  959.      The Fastgraph routine fg_display displays an image stored as a pixel run
  960. map.  The fg_display routine expects three arguments.  The first is an array
  961. containing the pixel runs (passed by reference), the second is the number of
  962. pixel runs in the array, and the third is the width in pixels of the image.
  963. As with the other image display routines, the fg_display routine displays the
  964. image such that its lower left corner is at the graphics cursor position on
  965. the active video page.  The pixel run array is of the following format:
  966.  
  967.                              [0]   color for run 1
  968.  
  969.                              [1]   count for run 1
  970.  
  971.                              [2]   color for run 2
  972.  
  973.                              [3]   count for run 2
  974.                                           .
  975.                                           .
  976.                                           .
  977.                           [2n-2]   color for run n
  978.  
  979.                           [2n-1]   count for run n
  980.  
  981. Each color is a value between 0 and 255 specifying the color index for that
  982. pixel run.  Each count is a value between 0 and 255 specifying the length in
  983. pixels of that pixel run.  If a run is longer than 255 pixels, it must be
  984. broken into two or more runs.  For example, we could represent a pixel run of
  985. length 265 as a run of length 255 followed by a run of length 10 of the same
  986. color.  Note also the array space in bytes needed to store a pixel run map is
  987. twice the number of runs.
  988.  
  989.      It requires 16 pixel runs to store our triangle image as a pixel run
  990. map.  If we want to display the perimeter pixels in color 1, the interior
  991. pixels in color 2, and the filler area in color 7, the pixel run map would
  992. contain 16 sets of (color,count) pairs:  (1,9), (7,1), (1,1), (2,5), (1,1),
  993. (7,3), (1,1), (2,3), (1,1), (7,5), (1,1), (2,1), (1,1), (7,7), (1,1), and
  994. (7,4).
  995.  
  996.      Example 9-10 uses the fg_display routine to display the triangle as a
  997. pixel run map in a 320 by 200 graphics mode.  The program displays the
  998. triangle against a background of color 7, so the selection of color 7 for the
  999. filler area was important.  If some other color were chosen, the filler area
  1000. would not blend in with the background.
  1001.  
  1002.                                 Example 9-10.
  1003.  
  1004.                 #include <fastgraf.h>
  1005.                 #include <stdio.h>
  1006.                 #include <stdlib.h>
  1007.                 void main(void);
  1008.  
  1009. 154  Fastgraph User's Guide
  1010.  
  1011.                 char triangle[] = {
  1012.                    1,9, 7,1, 1,1, 2,5, 1,1, 7,3, 1,1, 2,3,
  1013.                    1,1, 7,5, 1,1, 2,1, 1,1, 7,7, 1,1, 7,4
  1014.                    };
  1015.  
  1016.                 void main()
  1017.                 {
  1018.                    int old_mode, new_mode;
  1019.  
  1020.                    new_mode = fg_bestmode(320,200,1);
  1021.                    if (new_mode < 0 || new_mode == 12) {
  1022.                       printf("This program requires a 320 ");
  1023.                       printf("x 200 color graphics mode.\n");
  1024.                       exit(1);
  1025.                       }
  1026.  
  1027.                    old_mode = fg_getmode();
  1028.                    fg_setmode(new_mode);
  1029.  
  1030.                    fg_setcolor(7);
  1031.                    fg_rect(0,319,0,199);
  1032.  
  1033.                    fg_move(156,101);
  1034.                    fg_display(triangle,16,9);
  1035.                    fg_waitkey();
  1036.  
  1037.                    fg_setmode(old_mode);
  1038.                    fg_reset();
  1039.                 }
  1040.  
  1041.      If you have a pixel run map that only uses the first 16 color indices (0
  1042. to 15), you can use Fastgraph's packed pixel run map image format.  This
  1043. format packs two color values into each color byte and thus needs 25% less
  1044. array space to store an image.  The Fastgraph routine fg_displayp displays an
  1045. image stored as a packed pixel run map.  It is the same as the fg_display
  1046. routine except for the structure of the pixel run array.  Like fg_display,
  1047. the pixel run array used with fg_displayp is a list of pixel runs, but two
  1048. runs are packed into three bytes.  In each such set of three bytes, the high
  1049. four bits of the first byte contain the color of the first run, and the low
  1050. four bits contain the color of the second run.  The second byte contains the
  1051. length of the first run, and the third byte contains the length of the second
  1052. run.
  1053.  
  1054.      The following diagram illustrates the format of the pixel run array used
  1055. with the fg_displayp routine.  The image is assumed to contain n pixel runs,
  1056. where n is an even number.  If n is odd, the index of the last element is
  1057. 3n/2 (truncated) instead of 3n/2-1, and the low four bits of the last color
  1058. byte (that is, the color for pixel run n+1) are ignored.
  1059.  
  1060.                         7                4   3                0
  1061.  
  1062.                    [0]    color for run 1     color for run 2
  1063.  
  1064.                    [1]              count for run 1
  1065.  
  1066.                    [2]              count for run 2
  1067.  
  1068.                                   Chapter 9:  Images and Image Management  155
  1069.  
  1070.  
  1071.                    [3]    color for run 3     color for run 4
  1072.  
  1073.                    [4]              count for run 3
  1074.  
  1075.                    [5]              count for run 4
  1076.                                            .
  1077.                                            .
  1078.                                            .
  1079.               [3n/2-3]   color for run n-1    color for run n
  1080.  
  1081.               [3n/2-2]             count for run n-1
  1082.  
  1083.               [3n/2-1]              count for run n
  1084.  
  1085.      The structure of the packed pixel run array allows for color values to
  1086. be between 0 and 15, and pixel run lengths to be between 0 and 255.  The
  1087. array space in bytes needed to store a packed pixel run map is 1.5 times the
  1088. number of runs, compared to twice the number of runs for the standard pixel
  1089. run format.
  1090.  
  1091.      Example 9-11 is the same as example 9-10, but it uses fg_displayp rather
  1092. than fg_display to display the image.  Note the use of hexadecimal numbers
  1093. for defining the packed color values, which of course is not necessary but
  1094. certainly easier to read than expressing the quantities as decimal numbers.
  1095.  
  1096.                                 Example 9-11.
  1097.  
  1098.                 #include <fastgraf.h>
  1099.                 #include <stdio.h>
  1100.                 #include <stdlib.h>
  1101.                 void main(void);
  1102.  
  1103.                 char triangle[] = {
  1104.                    0x17,9,1, 0x12,1,5, 0x17,1,3, 0x12,1,3,
  1105.                    0x17,1,5, 0x12,1,1, 0x17,1,7, 0x17,1,4
  1106.                    };
  1107.  
  1108.                 void main()
  1109.                 {
  1110.                    int old_mode, new_mode;
  1111.  
  1112.                    new_mode = fg_bestmode(320,200,1);
  1113.                    if (new_mode < 0 || new_mode == 12) {
  1114.                       printf("This program requires a 320 ");
  1115.                       printf("x 200 color graphics mode.\n");
  1116.                       exit(1);
  1117.                       }
  1118.  
  1119.                    old_mode = fg_getmode();
  1120.                    fg_setmode(new_mode);
  1121.  
  1122.                    fg_setcolor(7);
  1123.                    fg_rect(0,319,0,199);
  1124.  
  1125.                    fg_move(156,101);
  1126.  
  1127. 156  Fastgraph User's Guide
  1128.  
  1129.                    fg_displayp(triangle,16,9);
  1130.                    fg_waitkey();
  1131.  
  1132.                    fg_setmode(old_mode);
  1133.                    fg_reset();
  1134.                 }
  1135.  
  1136.      Both the fg_display and fg_displayp routines require the pixel run image
  1137. to be stored in an array.  In examples 9-10 and 9-11, the image is defined
  1138. within the program itself.  However, if the image is stored in a file, it
  1139. must first be read into the pixel run array.  Example 9-12 demonstrates this
  1140. procedure.  The program displays two images stored in files, one in standard
  1141. pixel run format and the other in packed pixel run format.  Each image is a
  1142. picture of the sea floor and some coral, as might be used for the background
  1143. in an aquarium.  The program runs in a 320 by 200 graphics mode, and the
  1144. image fills the entire screen.  It is assumed the image files contain the
  1145. list of pixel runs as a single byte stream that does not include embedded
  1146. characters such as carriage returns or line feeds.
  1147.  
  1148.      The first image, in standard pixel run format, is in the file coral.spr.
  1149. Note the program must open the file for reading in binary mode ("rb" in the
  1150. call to fopen).  The program reads the file's entire contents into the
  1151. pixel_runs array, whose size must be at least as large as the file size.
  1152. Because the image is stored in standard pixel run format, the number of pixel
  1153. runs is one-half the file size.  The program then uses the fg_move routine to
  1154. establish the lower left corner of the screen as the graphics cursor position
  1155. and then calls fg_display to display the image.  As mentioned earlier, the
  1156. image fills the entire screen, so its width is 320 pixels.
  1157.  
  1158.      After waiting for a keystroke, the program similarly displays the second
  1159. image.  This image is in the file coral.ppr and is stored in packed pixel run
  1160. format.  Because the image is packed, the number of pixel runs is two-thirds
  1161. the file size.  The program then clears the previous image from the screen
  1162. and calls fg_displayp to display the image.  After another keystroke, the
  1163. program restores the original video mode and screen attributes and returns to
  1164. DOS.
  1165.  
  1166.                                 Example 9-12.
  1167.  
  1168.              #include <fastgraf.h>
  1169.              #include <io.h>
  1170.              #include <stdio.h>
  1171.              #include <stdlib.h>
  1172.              void main(void);
  1173.  
  1174.              char pixel_runs[20000];
  1175.  
  1176.              void main()
  1177.              {
  1178.                 long filelength();
  1179.                 FILE *stream;
  1180.                 int file_size, run_count;
  1181.                 int old_mode, new_mode;
  1182.  
  1183.                 new_mode = fg_bestmode(320,200,1);
  1184.                 if (new_mode < 0 || new_mode == 12) {
  1185.  
  1186.                                   Chapter 9:  Images and Image Management  157
  1187.  
  1188.                    printf("This program requires a 320 ");
  1189.                    printf("x 200 color graphics mode.\n");
  1190.                    exit(1);
  1191.                    }
  1192.                 old_mode = fg_getmode();
  1193.                 fg_setmode(new_mode);
  1194.  
  1195.                 stream = fopen("coral.spr","rb");
  1196.                 file_size = (int)(filelength(fileno(stream)));
  1197.                 fread(pixel_runs,sizeof(char),file_size,stream);
  1198.                 fclose(stream);
  1199.                 run_count = file_size / 2;
  1200.                 fg_move(0,199);
  1201.                 fg_display(pixel_runs,run_count,320);
  1202.                 fg_waitkey();
  1203.  
  1204.                 stream = fopen("coral.ppr","rb");
  1205.                 file_size = (int)(filelength(fileno(stream)));
  1206.                 fread(pixel_runs,sizeof(char),file_size,stream);
  1207.                 fclose(stream);
  1208.                 run_count = file_size / 3 * 2;
  1209.                 fg_erase();
  1210.                 fg_displayp(pixel_runs,run_count,320);
  1211.                 fg_waitkey();
  1212.  
  1213.                 fg_setmode(old_mode);
  1214.                 fg_reset();
  1215.              }
  1216.  
  1217.      Another Fastgraph routine, fg_dispfile, displays an image directly from
  1218. a file.  This eliminates the need to read the file contents into an array
  1219. before displaying the image, and it also eliminates the need to compute the
  1220. number of pixel runs in the image.  The fg_dispfile routine can display
  1221. images stored in either standard or packed pixel run images.  The first of
  1222. its three arguments is the name of the file containing the image (it may
  1223. include a path name).  The file name must be terminated with a null
  1224. character, so QuickBASIC, FORTRAN, and Turbo Pascal programmers will need to
  1225. store a zero byte as the last character of the file name string.  The second
  1226. argument is the width in pixels of the image, and the third argument defines
  1227. the image format (that is, standard or packed).  As with fg_display and
  1228. fg_displayp, the fg_dispfile routine displays the image such that its lower
  1229. left corner is at the graphics cursor position.
  1230.  
  1231.      Example 9-13 illustrates how to use the fg_dispfile routine to display
  1232. an image stored in a pixel run file.  It is functionally identical to example
  1233. 9-12, but it is much simpler because it uses fg_dispfile instead of fg_display
  1234. and fg_displayp to display the images.  The value of fg_dispfile's third
  1235. argument tells Fastgraph the image format.  A value of 0 indicates the file
  1236. contains an image in standard pixel run format, while a value of 1 indicates
  1237. an image in packed pixel run format.  As in example 9-12, the image files are
  1238. assumed to contain the list of pixel runs as a single byte stream that does
  1239. not include embedded characters such as carriage returns or line feeds.
  1240.  
  1241.                                 Example 9-13.
  1242.  
  1243.                 #include <fastgraf.h>
  1244.  
  1245. 158  Fastgraph User's Guide
  1246.  
  1247.                 #include <stdio.h>
  1248.                 #include <stdlib.h>
  1249.                 void main(void);
  1250.  
  1251.                 void main()
  1252.                 {
  1253.                    int old_mode, new_mode;
  1254.  
  1255.                    new_mode = fg_bestmode(320,200,1);
  1256.                    if (new_mode < 0 || new_mode == 12) {
  1257.                       printf("This program requires a 320 ");
  1258.                       printf("x 200 color graphics mode.\n");
  1259.                       exit(1);
  1260.                       }
  1261.  
  1262.                    old_mode = fg_getmode();
  1263.                    fg_setmode(new_mode);
  1264.  
  1265.                    fg_move(0,199);
  1266.                    fg_dispfile("coral.spr",320,0);
  1267.                    fg_waitkey();
  1268.  
  1269.                    fg_erase();
  1270.                    fg_dispfile("coral.ppr",320,1);
  1271.                    fg_waitkey();
  1272.  
  1273.                    fg_setmode(old_mode);
  1274.                    fg_reset();
  1275.                 }
  1276.  
  1277.  
  1278.      To display the image, the fg_dispfile routine tries to allocate enough
  1279. dynamic memory to read the entire file.  If it is unable to do so, it
  1280. allocates the available memory and displays the image in more than one pass.
  1281. In either case, Fastgraph deallocates the memory after fg_dispfile displays
  1282. the image.
  1283.  
  1284.      The SNAPSHOT utility distributed with Fastgraph is a terminate and stay
  1285. resident program (TSR) that can capture graphics mode screen images and save
  1286. them in standard pixel run files.  Thus, you can easily create files with
  1287. SNAPSHOT and display them with the fg_dispfile routine.  Another TSR utility,
  1288. GrabRGB, is useful for capturing RGB color values from 256-color images.
  1289. Appendix A contains complete descriptions of the SNAPSHOT and GrabRGB
  1290. utilities.
  1291.  
  1292.  
  1293. Display Patterns
  1294.  
  1295.      Examples 9-11, 9-12, and 9-13 work well in the graphics video modes with
  1296. 16 or 256 available colors.  However, in the four-color CGA graphics modes
  1297. the resulting image is not too good because of our limited color choices, and
  1298. it would look even worse in the Hercules graphics mode.  The Fastgraph
  1299. routine fg_pattern allows you to associate a dither pattern (actually, any
  1300. pixel sequence) with one of Fastgraph's 256 color indices appearing in a
  1301. pixel run map.  When displaying a pixel run map (with fg_display,
  1302. fg_displayp, or fg_dispfile), Fastgraph will use the pattern associated with
  1303. that color index instead of displaying the color itself.
  1304.                                   Chapter 9:  Images and Image Management  159
  1305.  
  1306.      The fg_pattern routine requires two integer arguments -- a color index
  1307. (between 0 and 255) and the display pattern defined for that color index.  A
  1308. display pattern's structure resembles the structure of video memory and is
  1309. thus dependent on the current video mode.  The following sections list the
  1310. initial display patterns and explain how to construct new display patterns
  1311. for different graphics video modes.
  1312.  
  1313. CGA four-color graphics modes
  1314.  
  1315.      In the four-color CGA graphics modes (modes 4 and 5), the display
  1316. pattern is a 16-bit quantity consisting of an 8-bit shift count followed by
  1317. an 8-bit pixel pattern.  Each pixel assumes a value between 0 and 3, so the
  1318. pattern represents four pixels.  In even-numbered pixel rows, Fastgraph uses
  1319. the pixel pattern itself.  In odd-numbered pixel rows, Fastgraph rotates the
  1320. original pattern to the left by the number of bits specified by the shift
  1321. count.
  1322.  
  1323.      For example, if we are using the default CGA color palette, we could
  1324. create a lighter shade of cyan by alternating cyan pixels (color 1, 01
  1325. binary) with white pixels (color 3, 11 binary), as shown below.
  1326.  
  1327.                                  01 11 01 11
  1328.  
  1329. If we convert this pixel pattern to its hexadecimal equivalent, we get the
  1330. value 77.
  1331.  
  1332.      To complete the display pattern, we need to determine the shift count.
  1333. If we use a shift count of zero, the resulting display will simply be a
  1334. series of cyan and white vertical lines.  What we really need is a
  1335. checkerboard effect where a white pixel is above and below each cyan pixel,
  1336. and vice versa.  If we rotate the pattern one pixel (two bits) to the left,
  1337. we will achieve the desired effect.  That is, a shift count of two produces
  1338. the following pixel patterns:
  1339.  
  1340.                        even-numbered rows   01 11 01 11
  1341.                         odd-numbered rows   11 01 11 01
  1342.  
  1343. Combining the shift count with the pixel pattern yields the display pattern
  1344. 0277 hex.  The shift count is normally a multiple of two; note that a zero
  1345. shift count results in the same pattern being applied to all pixel rows.
  1346.  
  1347.      For the CGA four-color graphics modes, the fg_setmode routine
  1348. establishes the following initial display patterns:
  1349.  
  1350.                        color  shift count  hexadecimal
  1351.                        index  and pattern  equivalent
  1352.  
  1353.                          0    0 00000000   0000
  1354.                          1    0 01010101   0055
  1355.                          2    0 10101010   00AA
  1356.                          3    0 11111111   00FF
  1357.  
  1358. 160  Fastgraph User's Guide
  1359.  
  1360. These values are repeated as necessary to define color indices 4 to 255.
  1361. That is, colors 4, 8, 12, ... , 252 use the same defaults as color 0.  Colors
  1362. 5, 9, 13, ... , 253 use the same defaults as color 1, and so forth.  Also
  1363. note that pattern 0000 represents four pixels of color 0, 0055 represents
  1364. four pixels of color 1, 00AA represents four pixels of color 2, and 00FF
  1365. represents four pixels of color 3.
  1366.  
  1367. CGA two-color graphics mode
  1368.  
  1369.      In the two-color CGA graphics mode (mode 6), the display pattern is also
  1370. a 16-bit quantity consisting of an 8-bit shift count followed by an 8-bit
  1371. pixel pattern.  Each pixel assumes the value 0 or 1, so the pattern
  1372. represents eight pixels.  In even-numbered pixel rows, Fastgraph uses the
  1373. pixel pattern itself.  In odd-numbered pixel rows, Fastgraph rotates the
  1374. original pattern to the left by the number of bits specified by the shift
  1375. count.
  1376.  
  1377.      For example, we could create a lighter shade of white by alternating
  1378. black pixels (color 0) with white pixels (color 1), as shown below.
  1379.  
  1380.                                0 1 0 1 0 1 0 1
  1381.  
  1382. If we convert this pixel pattern to its hexadecimal equivalent, we get the
  1383. value 55.
  1384.  
  1385.      To complete the display pattern, we need to determine the shift count.
  1386. We must rotate the pattern one pixel (one bit) to the left to achieve the
  1387. checkerboard effect as in the CGA four color graphics modes.  That is, a
  1388. shift count of one produces the following pixel patterns:
  1389.  
  1390.                      even-numbered rows   0 1 0 1 0 1 0 1
  1391.                       odd-numbered rows   1 0 1 0 1 0 1 0
  1392.  
  1393. Combining the shift count with the pixel pattern yields the display pattern
  1394. 0155 hex.
  1395.  
  1396.      For the CGA two-color graphics mode, the fg_setmode routine establishes
  1397. the initial display patterns such that all even-numbered color indices are
  1398. assigned the value 0000, while all odd-numbered color indices are assigned
  1399. the value 00FF.  Note that pattern 0000 represents eight pixels of color 0,
  1400. and 00FF represents eight pixels of color 1.
  1401.  
  1402. Tandy/PCjr 16-color graphics mode
  1403.  
  1404.      In the Tandy/PCjr 16-color graphics mode (mode 9), the display pattern
  1405. is also 16-bit quantity consisting of an 8-bit shift count followed by an 8-
  1406. bit pixel pattern.  Each pixel assumes a value between 0 and 15, so the
  1407. pattern represents two pixels.  In even-numbered pixel rows, Fastgraph uses
  1408. the pixel pattern itself.  In odd-numbered pixel rows, Fastgraph rotates the
  1409. original pattern to the left by the number of bits specified by the shift
  1410. count.
  1411.  
  1412.      For example, we could create a lighter shade of blue by alternating blue
  1413. pixels (color 1, 0001 binary) with white pixels (color 15, 1111 binary), as
  1414. shown below.
  1415.                                   Chapter 9:  Images and Image Management  161
  1416.  
  1417.                                   0001 1111
  1418.  
  1419. If we convert this pixel pattern to its hexadecimal equivalent, we get the
  1420. value 1F.
  1421.  
  1422.      To complete the display pattern, we need to determine the shift count.
  1423. Using the same process as in the CGA graphics modes, we must rotate the
  1424. pattern one pixel (four bits) to the left to achieve the checkerboard effect.
  1425. That is, a shift count of four produces the following pixel patterns:
  1426.  
  1427.                         even-numbered rows   0001 1111
  1428.                          odd-numbered rows   1111 0001
  1429.  
  1430. Combining the shift count with the pixel pattern yields the display pattern
  1431. 041F hex.  The shift count is normally zero or four; note that a zero shift
  1432. count results in the same pattern being applied to all pixel rows.
  1433.  
  1434.      For the Tandy/PCjr 16-color graphics modes, the fg_setmode routine
  1435. establishes the initial display patterns such that color 0 is assigned the
  1436. value 0000 (two pixels of color 0), color 1 is assigned the value 0011 (two
  1437. pixels of color 1), color 2 is assigned the value 0022 (two pixels of color
  1438. 2), and so forth.  These values are repeated as necessary to define color
  1439. indices 16 to 255.  That is, colors 0, 16, 32, ... , 240 use the same
  1440. defaults as color 0.  Colors 1, 17, 33, ... , 241 use the same defaults as
  1441. color 1, and so forth.
  1442.  
  1443. Hercules graphics modes
  1444.  
  1445.      The structure of the display patterns for the Hercules graphics modes
  1446. (modes 11 and 12) is the same as two of the CGA graphics modes.  For the
  1447. standard Hercules graphics mode (mode 11), please refer to the discussion of
  1448. CGA two-color (mode 6) display patterns on page 160.  For the low-resolution
  1449. Hercules graphics mode (mode 12), please refer to the discussion of the CGA
  1450. four-color (mode 4) display patterns on page 159.
  1451.  
  1452. EGA graphics modes
  1453.  
  1454.      In the EGA graphics modes (modes 13 to 16), the display pattern is an 8-
  1455. bit quantity consisting of two 4-bit color values (for consistency with the
  1456. other video modes, we still pass the display pattern as a 16-bit quantity).
  1457. Each pixel assumes a value between 0 and 15 (0 and 5 in the EGA monochrome
  1458. graphics mode), so the pattern represents two pixels.  In even-numbered pixel
  1459. rows, Fastgraph uses the pixel pattern itself.  In odd-numbered pixel rows,
  1460. Fastgraph rotates the original pattern one pixel (four bits) to the left.
  1461.  
  1462.      For example, we could create a lighter shade of blue by alternating blue
  1463. pixels (color 1, 0001 binary) with white pixels (color 15, 1111 binary), as
  1464. shown below.
  1465.  
  1466.                                   0001 1111
  1467.  
  1468. If we convert this pixel pattern to its hexadecimal equivalent, we get the
  1469. value 1F.  The implied four-bit shift count produces the following pixel
  1470. patterns:
  1471. 162  Fastgraph User's Guide
  1472.  
  1473.                         even-numbered rows   0001 1111
  1474.                          odd-numbered rows   1111 0001
  1475.  
  1476. Extending the pixel pattern to a 16-bit quantify yields the display pattern
  1477. 001F hex.
  1478.  
  1479.      For the EGA and VGA 16-color graphics modes, the fg_setmode routine
  1480. establishes the initial display patterns such that color 0 is assigned the
  1481. value 0000 (two pixels of color 0), color 1 is assigned the value 0011 (two
  1482. pixels of color 1), color 2 is assigned the value 0022 (two pixels of color
  1483. 2), and so forth.  These values are repeated as necessary to define color
  1484. indices 16 to 255.  That is, colors 0, 16, 32, ... , 240 use the same
  1485. defaults as color 0.  Colors 1, 17, 33, ... , 241 use the same defaults as
  1486. color 1, and so forth.
  1487.  
  1488. MCGA/VGA 2-color graphics mode
  1489.  
  1490.      In the two-color MCGA/VGA graphics mode (mode 17), the display pattern
  1491. is a 2-bit quantity consisting of two 1-bit color values (for consistency
  1492. with the other video modes, we still pass the display pattern as a 16-bit
  1493. quantity).  Each pixel assumes the value 0 or 1, so the pattern represents
  1494. two pixels.  In even-numbered pixel rows, Fastgraph uses the pixel pattern
  1495. itself.  In odd-numbered pixel rows, Fastgraph rotates the original pattern
  1496. one pixel (one bit) to the left.
  1497.  
  1498.      For example, we could create a lighter shade of white by alternating
  1499. black pixels (color 0) with white pixels (color 1), as shown below.
  1500.  
  1501.                                      0 1
  1502.  
  1503. If we convert this pixel pattern to its hexadecimal equivalent, we get the
  1504. value 01.  The implied one-bit shift count produces the following pixel
  1505. patterns:
  1506.  
  1507.                            even-numbered rows   0 1
  1508.                             odd-numbered rows   1 0
  1509.  
  1510. Extending the pixel pattern to a 16-bit quantity yields the display pattern
  1511. 0001 hex.
  1512.  
  1513.      For the MCGA/VGA two-color graphics mode, the fg_setmode routine
  1514. establishes the initial display patterns such that all even-numbered color
  1515. indices are assigned the value 0000 (two pixels of color 0), while all odd-
  1516. numbered color indices are assigned the value 0003 (11 binary, or two pixels
  1517. of color 1).
  1518.  
  1519. VGA 16-color graphics mode
  1520.  
  1521.      The structure of the display patterns for the VGA 16-color graphics mode
  1522. (mode 18) is the same as that of the EGA graphics modes.  A discussion of EGA
  1523. display patterns appears on page 161.
  1524.                                   Chapter 9:  Images and Image Management  163
  1525.  
  1526. MCGA and VGA 256-color graphics modes
  1527.  
  1528.      The MCGA and VGA 256-color graphics modes (modes 19 through 23) offer
  1529. 262,144 different colors, so dithering is seldom (if ever) required.  For
  1530. this reason, the fg_pattern routine has no effect in these video modes.
  1531.  
  1532. An example
  1533.  
  1534.      Example 9-14 illustrates the use of display patterns in several graphics
  1535. modes.  This program runs in any 320 by 200 color graphics mode and displays
  1536. the coral image in packed pixel run format, as in example 9-13, but it
  1537. redefines one or more of the color indices.  If the program runs in the
  1538. standard CGA four-color mode (mode 4), it redefines the first 16 display
  1539. patterns using the fg_pattern routine and the values in the CGApatterns
  1540. array.  In the Tandy/PCjr 16-color graphics mode (mode 9) and the EGA low-
  1541. resolution graphics mode (mode 13), the program redefines color index 15 to
  1542. produce an alternating gray and bright white dither pattern.  In the MCGA
  1543. 256-color mode (mode 19), display patterns are not available, so the program
  1544. uses fg_setrgb to define color index 15 as slightly darker shade of gray than
  1545. the default for color 7.
  1546.  
  1547.                                 Example 9-14.
  1548.  
  1549.                 #include <fastgraf.h>
  1550.                 #include <stdio.h>
  1551.                 #include <stdlib.h>
  1552.                 void main(void);
  1553.  
  1554.                 int CGApatterns[] = {
  1555.                    0x0000,0x00FF,0x00FF,0x00FF,
  1556.                    0x02BB,0x0000,0x0222,0x0255,
  1557.                    0x00FF,0x00FF,0x00FF,0x0055,
  1558.                    0x00AA,0x00AA,0x00FF,0x0277
  1559.                    };
  1560.  
  1561.                 void main()
  1562.                 {
  1563.                    int color;
  1564.                    int old_mode, new_mode;
  1565.  
  1566.                    new_mode = fg_bestmode(320,200,1);
  1567.                    if (new_mode < 0 || new_mode == 12) {
  1568.                       printf("This program requires a 320 ");
  1569.                       printf("x 200 color graphics mode.\n");
  1570.                       exit(1);
  1571.                       }
  1572.  
  1573.                    old_mode = fg_getmode();
  1574.                    fg_setmode(new_mode);
  1575.  
  1576.                    if (new_mode == 4) {
  1577.                       fg_palette(0,0);
  1578.                       for (color = 0; color < 16; color++)
  1579.                          fg_pattern(color,CGApatterns[color]);
  1580.                       }
  1581.                    else if (new_mode == 9 || new_mode == 13)
  1582.  
  1583. 164  Fastgraph User's Guide
  1584.  
  1585.                       fg_pattern(15,0x04F7);
  1586.                    else
  1587.                       fg_setrgb(15,38,38,38);
  1588.  
  1589.                    fg_move(0,199);
  1590.                    fg_dispfile("coral.ppr",320,1);
  1591.                    fg_waitkey();
  1592.  
  1593.                    fg_setmode(old_mode);
  1594.                    fg_reset();
  1595.                 }
  1596.  
  1597.  
  1598.  
  1599. PCX Images
  1600.  
  1601.      The PCX file format was originally developed by ZSoft Corporation for
  1602. their commercial paint program, PC Paintbrush.  It has evolved into one of
  1603. the more popular image file formats because so many products can read PCX
  1604. files to at least some extent.  Fastgraph includes routines for displaying
  1605. and creating PCX files.
  1606.  
  1607.      The fg_disppcx routine displays an image stored in a PCX file.  It
  1608. positions the image such that its upper left corner is at the graphics cursor
  1609. position on the active video page.  The first argument to fg_disppcx is the
  1610. name of the PCX file (it may include a path name), and its second argument is
  1611. a 16-bit mask that controls how the image is displayed.  The file name must
  1612. be terminated with a null character, so QuickBASIC, FORTRAN, and Turbo Pascal
  1613. programmers will need to store a zero byte as the last character of the file
  1614. name string.  In the current version of Fastgraph, only the low-order bit
  1615. (bit 0) of the bit mask argument is meaningful.  If the bit is set,
  1616. fg_disppcx will use the current palette settings.  If it is zero, fg_disppcx
  1617. will use the palette values stored in the PCX file.  All other bits are
  1618. reserved and should be zero.  The fg_disppcx routine returns a value of 0 if
  1619. successful, 1 if the specified file wasn't found, and 2 if the file is not a
  1620. PCX file.
  1621.  
  1622.      The fg_makepcx routine creates a PCX file from the specified rectangular
  1623. region of the active video page.  Its first four arguments define the minimum
  1624. x, maximum x, minimum y, and maximum y screen space coordinates of the region
  1625. (the minimum x coordinate is reduced to a byte boundary if necessary).  Its
  1626. fifth argument is the name of the PCX file to create (it may include a path
  1627. name).  As with fg_disppcx, the file name must be terminated with a null
  1628. character.  If an identically named file exists, it is overwritten.  The
  1629. fg_makepcx routine returns a value of 0 if successful, and 1 if the PCX file
  1630. was not created.
  1631.  
  1632.      Example 9-15 uses the fg_disppcx and fg_makepcx routines to create a new
  1633. PCX file from selected rows of an existing 256-color 320 x 200 PCX file.  As
  1634. written, the program uses the file CORAL.PCX to create NEW.PCX, but it could
  1635. easily be extended to work with any PCX files.  The call to fg_disppcx
  1636. displays the contents of CORAL.PCX using the palette settings defined in the
  1637. PCX file.  After waiting for a keystroke, the program calls fg_makepcx to
  1638. create a PCX file named NEW.PCX from pixel rows 80 through 99 of the original
  1639. image.  In case the program encounters any problems, it prints an error
  1640. message before exiting.
  1641.                                   Chapter 9:  Images and Image Management  165
  1642.  
  1643.                                 Example 9-15.
  1644.  
  1645.            #include <fastgraf.h>
  1646.            #include <stdio.h>
  1647.            #include <stdlib.h>
  1648.            void main(void);
  1649.  
  1650.            void main()
  1651.            {
  1652.               int old_mode;
  1653.               int read_status, write_status;
  1654.  
  1655.               if (fg_testmode(19,1) == 0) {
  1656.                  printf("This program requires a 320 ");
  1657.                  printf("x 200 MCGA graphics mode.\n");
  1658.                  exit(1);
  1659.                  }
  1660.               old_mode = fg_getmode();
  1661.               fg_setmode(19);
  1662.  
  1663.               read_status = fg_disppcx("coral.pcx",0);
  1664.               fg_waitkey();
  1665.               if (read_status == 0)
  1666.                  write_status = fg_makepcx(0,319,80,99,"new.pcx");
  1667.               else
  1668.                  write_status = 1;
  1669.  
  1670.               fg_setmode(old_mode);
  1671.               fg_reset();
  1672.  
  1673.               if (read_status == 1)
  1674.                  printf("CORAL.PCX not found.\n");
  1675.               else if (read_status == 2)
  1676.                  printf("CORAL.PCX is not a PCX file.\n");
  1677.               if (write_status == 1)
  1678.                  printf("NEW.PCX not created.\n");
  1679.            }
  1680.  
  1681.  
  1682.      Because their structure parallels the structure of video memory, PCX
  1683. files are specific to certain video modes.  The following table summarizes
  1684. the compatible video modes for PCX files.
  1685.  
  1686.                      If PCX file was   You can display
  1687.                      created in mode   it in these modes
  1688.  
  1689.                      4 or 5            4 or 5
  1690.                      6 or 11           6, 11, 13 to 18
  1691.                      9                 9
  1692.                      13 to 18          13 to 18
  1693.                      19                19 to 23
  1694.  
  1695. Displaying a PCX file at a lower resolution (for example, a 640x480 PCX file
  1696. at 320x200) will truncate the display on the right and on the bottom.  This
  1697. effectively displays the upper left corner of the PCX file.  If you try to
  1698. 166  Fastgraph User's Guide
  1699.  
  1700. display a PCX file in an incompatible video mode, fg_disppcx will still
  1701. display something, but it will be garbled.
  1702.  
  1703.      In the Tandy/PCjr 16-color graphics mode (mode 9) and the native EGA
  1704. graphics modes (modes 13 through 16), the palette registers are not readable.
  1705. Hence, fg_makepcx will use the default palette settings when used in these
  1706. video modes.  In 640-column EGA modes, you can get around this problem by
  1707. creating PCX files in mode 18 and only using the first 200 or 350 pixel rows.
  1708. PCX files created in mode 18 preserve the current palette settings and will
  1709. display properly in EGA modes.  The fg_disppcx and fg_makepcx routines have
  1710. no effect in text video modes or in the Hercules low-resolution graphics
  1711. mode.
  1712.  
  1713.  
  1714. Masking Maps
  1715.  
  1716.      It is not possible to include color 0 pixels in an image displayed with
  1717. the fg_drwimage, fg_clpimage, fg_revimage, or fg_flpimage routines.  This is
  1718. because these routines consider color 0 pixels to be transparent, which means
  1719. such pixels do not affect the corresponding pixels in video memory.  There
  1720. are times, however, when you will want color 0 pixels to be destructive, or
  1721. replace the video memory contents.
  1722.  
  1723.      Consider again the arrow image of example 9-8 (see page 149).  In this
  1724. example, we displayed a bright white (color 3) arrow against a black (color
  1725. 0) background in the standard CGA four-color graphics mode.  Suppose, though,
  1726. that we want to do just the opposite -- display a black (color 0) arrow
  1727. against a bright white (color 3) background.  Example 9-9 (see page 151) does
  1728. this in an EGA graphics mode, but how would we display the black arrow in a
  1729. CGA graphics mode?  We could of course use the fg_drawmap routine or one of
  1730. the routines for displaying pixel run maps, but fg_drawmap does not support
  1731. clipping or reversing an image.   There are, however, four Fastgraph routines
  1732. designed just for this purpose.  These routines are fg_drawmask, fg_clipmask,
  1733. fg_revmask, and fg_flipmask.
  1734.  
  1735.      Each of these routines uses a data structure called a masking map.  A
  1736. masking map is similar in structure to a pixel run map, but it does not
  1737. include any information about colors.  Instead, it consists of a series of
  1738. pixel runs that alternate between protected and unprotected pixels.  An
  1739. example might best clarify this.
  1740.  
  1741.      Once again, here is the arrow image of examples 9-8 and 9-9.
  1742.  
  1743.                              . . . . . . * . . .
  1744.                              . . . . . . * * . .
  1745.                              * * * * * * * * * .
  1746.                              * * * * * * * * * *
  1747.                              * * * * * * * * * .
  1748.                              . . . . . . * * . .
  1749.                              . . . . . . * . . .
  1750.  
  1751. This time, though, we want the arrow to appear in color 0.  Put another way,
  1752. we need the "period" pixels (.) to protect video memory, while we want the
  1753. "asterisk" pixels (*) to zero video memory.  Looking at this problem from the
  1754. perspective of a pixel run map, we have an alternating series of "protect"
  1755. and "zero" runs.  We don't need any information about pixel colors, just
  1756. whether to protect or to zero video memory.
  1757.                                   Chapter 9:  Images and Image Management  167
  1758.  
  1759.      This is precisely the structure of a masking map.  Starting from the
  1760. lower left corner of the image and proceeding to the right, wrapping up to
  1761. the next row when needed, we could represent this image as a masking map with
  1762. 6 protected pixels, 1 zeroed pixel, 9 protected pixels, 2 zeroed pixels, and
  1763. so on.  In general, the structure of a masking map is as follows.
  1764.  
  1765.  
  1766.                       [1]   length of 1st protect run
  1767.  
  1768.                       [2]   length of 1st  zero   run
  1769.  
  1770.                       [3]   length of 2nd protect run
  1771.  
  1772.                       [4]   length of 2nd  zero   run
  1773.                                         .
  1774.                                         .
  1775.                                         .
  1776.                     [n-2]   length of final protect run
  1777.  
  1778.                     [n-1]   length of final  zero   run
  1779.  
  1780.  
  1781.      Looking at this diagram, we see that the even-numbered array elements
  1782. hold the length of the "protect" runs, and the odd-numbered elements hold the
  1783. length of the "zero" runs.  If you need the first run to be a "zero" run,
  1784. just include a "protect" run of length zero as the first element of the
  1785. array.  If the final run is a "protect" run, you do not need to include a
  1786. zero-length "zero" run at the end of the array.  Finally, if either type of
  1787. run exceeds 255 pixels, you'll need to split this into two or more pixel
  1788. runs.  In this case, be sure to include a zero-length run of the other type
  1789. between the two array elements.
  1790.  
  1791.      Example 9-16 illustrates the use of a masking map through the
  1792. fg_drawmask, fg_clipmask, fg_revmask, and fg_flipmask routines in the
  1793. standard CGA four-color graphics mode (mode 4) to draw a black (color 0)
  1794. arrow against a bright white background.  These four routines are
  1795. respectively analogous to the fg_drwimage, fg_clpimage, fg_revimage, and
  1796. fg_flpimage routines, but they use masking maps rather than bit maps.  The
  1797. first argument of each routine is the masking map array (passed by
  1798. reference), the second argument is the number of runs (that is, the number of
  1799. elements) in the masking map array, and the third argument is the width in
  1800. pixels of the image.
  1801.  
  1802.                                 Example 9-16.
  1803.  
  1804.                 #include <fastgraf.h>
  1805.                 #include <stdio.h>
  1806.                 #include <stdlib.h>
  1807.                 void main(void);
  1808.  
  1809.                 char arrow[] = {6,1,9,2,2,9,1,19,7,2,8,1};
  1810.  
  1811.                 void main()
  1812.                 {
  1813.                    int old_mode;
  1814.  
  1815. 168  Fastgraph User's Guide
  1816.  
  1817.                    if (fg_testmode(4,1) == 0) {
  1818.                       printf("This program requires a 320 ");
  1819.                       printf("x 200 CGA graphics mode.\n");
  1820.                       exit(1);
  1821.                       }
  1822.                    old_mode = fg_getmode();
  1823.                    fg_setmode(4);
  1824.                    fg_setclip(0,15,0,199);
  1825.  
  1826.                    fg_setcolor(3);
  1827.                    fg_rect(0,319,0,199);
  1828.                    fg_move(10,10);
  1829.                    fg_drawmask(arrow,12,10);
  1830.                    fg_move(10,20);
  1831.                    fg_clipmask(arrow,12,10);
  1832.                    fg_move(10,30);
  1833.                    fg_revmask(arrow,12,10);
  1834.                    fg_move(10,40);
  1835.                    fg_flipmask(arrow,12,10);
  1836.                    fg_waitkey();
  1837.  
  1838.                    fg_setmode(old_mode);
  1839.                    fg_reset();
  1840.                 }
  1841.  
  1842.      One of the more useful features of masking maps is the ability to clear
  1843. a portion of video memory before placing an image there.  This technique
  1844. provides an efficient, simple way to include color 0 pixels in an image.  It
  1845. is especially effective when displaying large or dithered images because the
  1846. masking map is typically much smaller than the bit map required by fg_drawmap
  1847. or its related routines.  Example 9-17 illustrates this process in the
  1848. standard CGA four-color graphics mode (mode 4) by displaying our arrow image
  1849. against a colored background.  In this example, the arrow has a bright white
  1850. (color 3) perimeter and a black (color 0) interior.
  1851.  
  1852.      The program displays the arrow in two steps.  It first uses fg_drawmask
  1853. to clear the video memory where the arrow will be displayed.  It then draws
  1854. the arrow's perimeter using the fg_drwimage routine.  The interior pixels in
  1855. the perimeter bit map are transparent, but since we just zeroed that video
  1856. memory, they appear in color 0.  Note we could improve this example by
  1857. creating a smaller masking map that only applies to the rectangle inscribing
  1858. the arrow's interior.  That is, we don't need to zero the video memory under
  1859. the arrow's perimeter because we will immediately display other pixels there.
  1860.  
  1861.                                 Example 9-17.
  1862.  
  1863.               #include <fastgraf.h>
  1864.               #include <stdio.h>
  1865.               #include <stdlib.h>
  1866.               void main(void);
  1867.  
  1868.               char arrow_white[] = {
  1869.                  0x00,0x0C,0x00, 0x00,0x0F,0x00, 0xFF,0xFC,0xC0,
  1870.                  0xC0,0x00,0x30, 0xFF,0xFC,0xC0, 0x00,0x0F,0x00,
  1871.                  0x00,0x0C,0x00
  1872.                  };
  1873.  
  1874.                                   Chapter 9:  Images and Image Management  169
  1875.  
  1876.               char arrow_black[] = {6,1,9,2,2,9,1,19,7,2,8,1};
  1877.  
  1878.               void main()
  1879.               {
  1880.                  int old_mode;
  1881.  
  1882.                  if (fg_testmode(4,1) == 0) {
  1883.                     printf("This program requires a 320 ");
  1884.                     printf("x 200 CGA graphics mode.\n");
  1885.                     exit(1);
  1886.                     }
  1887.  
  1888.                  old_mode = fg_getmode();
  1889.                  fg_setmode(4);
  1890.  
  1891.                  fg_setcolor(2);
  1892.                  fg_rect(0,319,0,199);
  1893.  
  1894.                  fg_move(10,10);
  1895.                  fg_drawmask(arrow_black,12,10);
  1896.                  fg_drwimage(arrow_white,3,7);
  1897.                  fg_waitkey();
  1898.  
  1899.                  fg_setmode(old_mode);
  1900.                  fg_reset();
  1901.               }
  1902.  
  1903.  
  1904.  
  1905. Retrieving Images
  1906.  
  1907.      Sometimes it is necessary to retrieve an image from video memory and
  1908. store it in one or more bit map arrays.  Fastgraph includes two routines,
  1909. fg_getmap and fg_getimage, for this purpose.  The fg_getmap routine retrieves
  1910. pixels of the current color index and stores them in the mode-independent bit
  1911. map format used by fg_drawmap.  The fg_getimage routine retrieves an image
  1912. and stores it in the mode-specific bit map format used by fg_drwimage,
  1913. fg_clpimage, fg_revimage, and fg_flpimage.  The arguments to fg_getmap and
  1914. fg_getimage are respectively analogous to those of fg_drawmap and
  1915. fg_drwimage:  the first is an array (passed by reference) to receive the bit
  1916. map, the second is the width of the bit map in bytes, and the last is the
  1917. height of the bit map in pixel rows.  With either routine, the graphics
  1918. cursor position on the active video page defines the lower left corner of the
  1919. image to retrieve.
  1920.  
  1921.      If we want to use the fg_getmap routine to retrieve an image containing
  1922. more than one color, we must call the routine once per color.  In this case
  1923. we'll usually want to pass different bit map arrays to fg_getmap (or perhaps
  1924. different offsets into the same array).  This might seem unusual at first,
  1925. but it parallels the behavior of the fg_drawmap routine.  That is, to display
  1926. a multicolor image using fg_drawmap, we must call it once for each color in
  1927. the image.
  1928.  
  1929.      Example 9-18 demonstrates a typical use of the fg_getmap routine.  The
  1930. program displays the word "text" in the upper left corner of the screen using
  1931. a 320 by 200 graphics mode.  It uses fg_getmap to retrieve the word as an
  1932. 170  Fastgraph User's Guide
  1933.  
  1934. image and then displays it in a new position with the fg_drawmap routine.
  1935. Let's look at the program now, and afterward we'll more closely examine the
  1936. screen coordinates and the structure of the bit map array.
  1937.  
  1938.                                 Example 9-18.
  1939.  
  1940.                 #include <fastgraf.h>
  1941.                 #include <stdio.h>
  1942.                 #include <stdlib.h>
  1943.                 void main(void);
  1944.  
  1945.                 void main()
  1946.                 {
  1947.                    char bitmap[32];
  1948.                    int old_mode, new_mode;
  1949.  
  1950.                    new_mode = fg_bestmode(320,200,1);
  1951.                    if (new_mode < 0 || new_mode == 12) {
  1952.                       printf("This program requires a 320 ");
  1953.                       printf("x 200 color graphics mode.\n");
  1954.                       exit(1);
  1955.                       }
  1956.  
  1957.                    old_mode = fg_getmode();
  1958.                    fg_setmode(new_mode);
  1959.  
  1960.                    fg_setcolor(9);
  1961.                    fg_text("text",4);
  1962.                    fg_waitkey();
  1963.  
  1964.                    fg_move(0,7);
  1965.                    fg_getmap(bitmap,4,8);
  1966.                    fg_move(4,15);
  1967.                    fg_drawmap(bitmap,4,8);
  1968.                    fg_waitkey();
  1969.  
  1970.                    fg_setmode(old_mode);
  1971.                    fg_reset();
  1972.                 }
  1973.  
  1974.      In all 320 by 200 graphics video modes, individual characters are 8
  1975. pixels wide and 8 pixels high.  This means the lower left corner of the (0,0)
  1976. character cell is referenced by the screen coordinates (0,7).  Hence, these
  1977. are the coordinates of the first call to fg_move.  The image retrieved in
  1978. example 9-18 is four characters long (32 pixels wide), so we need a bit map
  1979. array capable of holding 8 rows of 32 pixels (4 bytes) each.  Our bit map
  1980. array is therefore a 32-byte array, logically structured to have 4 columns
  1981. and 8 rows.  These values are the width and height arguments passed to
  1982. fg_getmap and fg_drawmap.
  1983.  
  1984.      After it retrieves the image, example 9-18 displays it one line below
  1985. and one-half character cell (four pixels) to the right of its original
  1986. position.  In other words, the program displays the image four pixels to the
  1987. right of the (1,0) character cell.  The lower left corner of that cell is
  1988. referenced by the screen coordinates (0,15), so the image should appear at
  1989. the position (4,15).  These are the coordinates of the second call to
  1990. fg_move.
  1991.                                   Chapter 9:  Images and Image Management  171
  1992.  
  1993.      Example 9-19 illustrates the use of the fg_getmap and fg_drawmap
  1994. routines to retrieve and display two-color image.  This example is similar to
  1995. example 9-18, but this program first draws a rectangle in the upper left
  1996. corner of the screen and then displays the word "text" on top of the
  1997. rectangle in a different color.  Each character in a 320 by 200 graphics
  1998. video mode is 8 pixels wide and 8 pixels high, so the rectangle must be 32
  1999. pixels wide (4 characters times 8 pixels per character) and 8 pixels high.
  2000. The image to retrieve will be the same size as the rectangle.
  2001.  
  2002.      The image retrieved in example 9-18 required a 32-byte array, logically
  2003. structured to have 4 columns and 8 rows.  Example 9-19 will retrieve an image
  2004. of the same structure, but the image contains two colors instead of just one.
  2005. This means we need two 32-byte arrays, one for each color, to hold the image.
  2006. We could instead use a single 64-byte array and pass an offset into that
  2007. array (specifically, &bitmap[32]) for processing the second color.
  2008.  
  2009.                                 Example 9-19.
  2010.  
  2011.                 #include <fastgraf.h>
  2012.                 #include <stdio.h>
  2013.                 #include <stdlib.h>
  2014.                 void main(void);
  2015.  
  2016.                 void main()
  2017.                 {
  2018.                    char bitmap1[32], bitmap2[32];
  2019.                    int old_mode, new_mode;
  2020.  
  2021.                    new_mode = fg_bestmode(320,200,1);
  2022.                    if (new_mode < 0 || new_mode == 12) {
  2023.                       printf("This program requires a 320 ");
  2024.                       printf("x 200 color graphics mode.\n");
  2025.                       exit(1);
  2026.                       }
  2027.  
  2028.                    old_mode = fg_getmode();
  2029.                    fg_setmode(new_mode);
  2030.  
  2031.                    fg_setcolor(7);
  2032.                    fg_rect(0,31,0,7);
  2033.                    fg_setcolor(9);
  2034.                    fg_text("text",4);
  2035.                    fg_waitkey();
  2036.  
  2037.                    fg_move(0,7);
  2038.                    fg_setcolor(7);
  2039.                    fg_getmap(bitmap1,4,8);
  2040.                    fg_setcolor(9);
  2041.                    fg_getmap(bitmap2,4,8);
  2042.  
  2043.                    fg_move(4,15);
  2044.                    fg_setcolor(7);
  2045.                    fg_drawmap(bitmap1,4,8);
  2046.                    fg_setcolor(9);
  2047.                    fg_drawmap(bitmap2,4,8);
  2048.                    fg_waitkey();
  2049.  
  2050. 172  Fastgraph User's Guide
  2051.  
  2052.                    fg_setmode(old_mode);
  2053.                    fg_reset();
  2054.                 }
  2055.  
  2056.      Example 9-20 is similar to example 9-19, but it uses fg_getimage and
  2057. fg_drwimage instead of fg_getmap and fg_drawmap to retrieve and display the
  2058. image.  That is, it uses the mode-specific rather than the mode-independent
  2059. image retrieval and display routines.  When using the mode-specific routines,
  2060. the size of the bit map needed to hold the image depends on the video mode.
  2061. For programs that run in only one video mode, bit map widths are constant,
  2062. but when a program must run in several video modes, the width is variable.
  2063. The Fastgraph routine fg_imagesiz computes the number of bytes required to
  2064. store a mode-specific bit-mapped image of specified dimensions.  Its two
  2065. integer arguments specify the image width and height in pixels.
  2066.  
  2067.      The program computes the image width in bytes by passing a height of 1
  2068. to fg_imagesiz.  The size of the bit map array in example 9-20 is 256 bytes,
  2069. the size required in the MCGA graphics mode (32 bytes times 8 bytes).  The
  2070. other video modes require less storage, so in these modes only a portion of
  2071. the bit map array will actually be used.  The image width is then used in the
  2072. calls to both fg_getimage and fg_drwimage.
  2073.  
  2074.                                 Example 9-20.
  2075.  
  2076.                 #include <fastgraf.h>
  2077.                 #include <stdio.h>
  2078.                 #include <stdlib.h>
  2079.                 void main(void);
  2080.  
  2081.                 void main()
  2082.                 {
  2083.                    char bitmap[256];
  2084.                    int old_mode, new_mode;
  2085.                    int width;
  2086.  
  2087.                    new_mode = fg_bestmode(320,200,1);
  2088.                    if (new_mode < 0 || new_mode == 12) {
  2089.                       printf("This program requires a 320 ");
  2090.                       printf("x 200 color graphics mode.\n");
  2091.                       exit(1);
  2092.                       }
  2093.                    old_mode = fg_getmode();
  2094.                    fg_setmode(new_mode);
  2095.                    width = (int)fg_imagesiz(32,1);
  2096.  
  2097.                    fg_setcolor(7);
  2098.                    fg_rect(0,31,0,7);
  2099.                    fg_setcolor(9);
  2100.                    fg_text("text",4);
  2101.                    fg_waitkey();
  2102.  
  2103.                    fg_move(0,7);
  2104.                    fg_getimage(bitmap,width,8);
  2105.                    fg_move(4,15);
  2106.                    fg_drwimage(bitmap,width,8);
  2107.                    fg_waitkey();
  2108.  
  2109.                                   Chapter 9:  Images and Image Management  173
  2110.  
  2111.                    fg_setmode(old_mode);
  2112.                    fg_reset();
  2113.                 }
  2114.  
  2115. While this example used an array to store the image, it's usually preferable
  2116. to allocate dynamic memory for this purpose.  We could have done this in
  2117. example 9-20 by calling fg_imagesiz with arguments of 32 (width) and 8
  2118. (height).  The routine's return value would then tell us the number of bytes
  2119. we would need to allocate.
  2120.  
  2121.      We also can use the fg_getimage routine to retrieve images in text video
  2122. modes.  In text modes, however, there are a few differences we must consider
  2123. when using fg_getimage.  First, the text cursor position, not the graphics
  2124. cursor position, specifies the lower left corner of the image.  Hence, we
  2125. must use the fg_locate routine instead of fg_move to define the image
  2126. location.  Second, the image width is always twice the number of characters
  2127. per image row (that is, for each character we have a character byte and an
  2128. attribute byte).  The fg_getmap routine has no effect when used in a text
  2129. video mode.
  2130.  
  2131.      Example 9-21 shows a simple use of fg_getimage in text modes.  This
  2132. program is similar to example 9-20, but it runs in an 80-column text mode
  2133. rather than a 320 by 200 graphics mode.  As before, the program will retrieve
  2134. the four characters "text" as an image from the upper left corner of the
  2135. screen and then display it in a different location.  Because the image
  2136. consists of four characters in one row, the image width is 8 bytes and the
  2137. image height is 1.
  2138.  
  2139.                                 Example 9-21.
  2140.  
  2141.                    #include <fastgraf.h>
  2142.                    #include <stdio.h>
  2143.                    #include <stdlib.h>
  2144.                    void main(void);
  2145.  
  2146.                    void main()
  2147.                    {
  2148.                       int old_mode;
  2149.                       char image[8];
  2150.  
  2151.                       old_mode = fg_getmode();
  2152.  
  2153.                       if (fg_testmode(3,1))
  2154.                          fg_setmode(3);
  2155.                       else if (fg_testmode(7,1))
  2156.                          fg_setmode(7);
  2157.                       else {
  2158.                          printf("This program requires\n");
  2159.                          printf("an 80-column display.\n");
  2160.                          exit(1);
  2161.                          }
  2162.  
  2163.                       fg_cursor(0);
  2164.  
  2165.                       fg_setattr(9,7,0);
  2166.                       fg_text("text",4);
  2167.  
  2168. 174  Fastgraph User's Guide
  2169.  
  2170.                       fg_waitkey();
  2171.  
  2172.                       fg_locate(0,0);
  2173.                       fg_getimage(image,8,1);
  2174.                       fg_locate(1,1);
  2175.                       fg_drwimage(image,8,1);
  2176.                       fg_waitkey();
  2177.  
  2178.                       fg_setmode(old_mode);
  2179.                       fg_reset();
  2180.                    }
  2181.  
  2182.  
  2183.  
  2184. Byte Boundaries
  2185.  
  2186.      Video memory, like standard random-access memory, is divided into units
  2187. called bytes.  In text modes, each byte holds either a character or an
  2188. attribute.  In graphics modes, each byte of video memory holds one or more
  2189. horizontally contiguous pixels.  If two adjacent horizontal pixels are stored
  2190. in different bytes, then we say that a byte boundary exists between the two
  2191. pixels.
  2192.  
  2193.      The number of pixels per byte depends on the video mode being used, so
  2194. the byte boundaries also depend on the video mode.  That is, a byte boundary
  2195. in a CGA graphics mode is not necessarily a byte boundary in an EGA graphics
  2196. mode.  The following table summarizes the number of pixels per byte of video
  2197. memory and the byte boundary sequences for each supported graphics video
  2198. mode.  Note that any horizontal coordinate whose value is a multiple of 8 is
  2199. always a byte boundary, regardless of the video mode.
  2200.  
  2201.                   mode    pixels   horizontal coordinates
  2202.                  number  per byte  of byte boundaries
  2203.  
  2204.                    4         4     0, 4,  8, 12, ... , 316
  2205.                    5         4     0, 4,  8, 12, ... , 316
  2206.                    6         8     0, 8, 16, 24, ... , 632
  2207.                    9         2     0, 2,  4,  6, ... , 318
  2208.                    11        8     0, 8, 16, 24, ... , 712
  2209.                    12        4     0, 4,  8, 12, ... , 316
  2210.                    13        8     0, 8, 16, 24, ... , 312
  2211.                    14        8     0, 8, 16, 24, ... , 632
  2212.                    15        8     0, 8, 16, 24, ... , 632
  2213.                    16        8     0, 8, 16, 24, ... , 632
  2214.                    17        8     0, 8, 16, 24, ... , 632
  2215.                    18        8     0, 8, 16, 24, ... , 632
  2216.                    19        1     0, 1,  2,  3, ... , 319
  2217.                    20        1     0, 1,  2,  3, ... , 319
  2218.                    21        1     0, 1,  2,  3, ... , 319
  2219.                    22        1     0, 1,  2,  3, ... , 319
  2220.                    23        1     0, 1,  2,  3, ... , 319
  2221.  
  2222.                                   Chapter 9:  Images and Image Management  175
  2223.  
  2224.  
  2225. Image Transfer Routines
  2226.  
  2227.      The Fastgraph routines described in this section transfer images between
  2228. areas of video memory.  These routines are often used in animation sequences
  2229. requiring high-performance graphics, so they must be as efficient as
  2230. possible.  To this end, Fastgraph will force their horizontal pixel
  2231. coordinates to byte boundaries, which eliminates the need to process any
  2232. pixels individually.  Fastgraph accomplishes this by reducing minimum
  2233. horizontal coordinates to a byte boundary and extending maximum horizontal
  2234. coordinates to the last pixel in a video memory byte.  Note that since we are
  2235. talking about pixel coordinates and not character cells, the coordinate
  2236. modification only occurs in graphics video modes.
  2237.  
  2238.      An example might best help explain this important feature.  The CGA
  2239. four-color graphics modes (modes 4 and 5) store four pixels in each byte of
  2240. video memory.  This means the byte boundaries occur at multiples of four
  2241. pixels.  Thus, when you use the image transfer routines in modes 4 and 5,
  2242. Fastgraph reduces minimum x coordinates to the next lower multiple of four.
  2243. Similarly, it extends their maximum x coordinates to the next higher multiple
  2244. of four, less one pixel.  That is, if a minimum x coordinate is 7 and a
  2245. maximum x coordinate is 30, Fastgraph will modify these values to 4 and 31
  2246. respectively.  If the x coordinates were originally 4 and 31, Fastgraph would
  2247. leave them unchanged.  Note, too, that because each pixel in the MCGA and VGA
  2248. 256-color graphics modes (modes 19 through 23) occupies a separate byte of
  2249. video memory, Fastgraph does not need to modify horizontal coordinates in
  2250. these video modes.
  2251.  
  2252.      Fastgraph's simplest image transfer routine is fg_copypage, which we
  2253. introduced in Chapter 8.  The fg_copypage routine transfers the entire
  2254. contents of one video page to another.  The first argument is the number of
  2255. the source video page, and the second argument is the number of the
  2256. destination video page.  The pages may be physical, virtual, or logical video
  2257. pages.  If both the source and destination pages are logical pages, the pages
  2258. must exist in the same type of memory.  For example, you cannot copy a
  2259. logical page in extended memory to a logical page in conventional memory.
  2260.  
  2261.      Example 9-22 illustrates the use of the fg_copypage routine in a 320 x
  2262. 200 color graphics mode.  The program displays the word "test" in the middle
  2263. of the visual page (page 0) and then uses fg_allocate to create a virtual
  2264. video page (page 1).  The virtual page is needed in case the program is
  2265. running in a video mode with only one physical page.  Next, the program uses
  2266. 176  Fastgraph User's Guide
  2267.  
  2268. fg_copypage to transfer the visual page contents to page 1.  After waiting
  2269. for a keystroke, the program erases the visual page, waits for another
  2270. keystroke, and copies the contents of page 1 back to the visual page.  It
  2271. then releases the virtual page and exits.
  2272.  
  2273.                                 Example 9-22.
  2274.  
  2275.                 #include <fastgraf.h>
  2276.                 #include <stdio.h>
  2277.                 #include <stdlib.h>
  2278.                 void main(void);
  2279.  
  2280.                 void main()
  2281.                 {
  2282.                    int new_mode, old_mode;
  2283.  
  2284.                    new_mode = fg_bestmode(320,200,2);
  2285.                    if (new_mode < 0 || new_mode == 12) {
  2286.                       printf("This program requires a 320 ");
  2287.                       printf("x 200 color graphics mode.\n");
  2288.                       exit(1);
  2289.                       }
  2290.                    old_mode = fg_getmode();
  2291.                    fg_setmode(new_mode);
  2292.  
  2293.                    fg_setcolor(7);
  2294.                    fg_rect(0,319,0,199);
  2295.                    fg_setcolor(9);
  2296.                    fg_locate(12,18);
  2297.                    fg_text("test",4);
  2298.                    fg_waitkey();
  2299.  
  2300.                    fg_allocate(1);
  2301.                    fg_copypage(0,1);
  2302.                    fg_erase();
  2303.                    fg_waitkey();
  2304.  
  2305.                    fg_copypage(1,0);
  2306.                    fg_waitkey();
  2307.  
  2308.                    fg_freepage(1);
  2309.                    fg_setmode(old_mode);
  2310.                    fg_reset();
  2311.                 }
  2312.  
  2313.      Several of Fastgraph's image transfer routines reference a video page
  2314. called the hidden page.  The Fastgraph routine fg_sethpage defines which
  2315. video page will be used as the hidden page.  This routine takes as its only
  2316. argument an integer value specifying the hidden page number.  If you are
  2317. using a virtual video page for the hidden page, you must call the fg_sethpage
  2318. routine after allocating that page.  There is also a routine named
  2319. fg_gethpage that returns the hidden page number, as specified in the most
  2320. recent call to fg_sethpage, as its function value.  The fg_gethpage routine
  2321. takes no arguments.
  2322.  
  2323.      The next two image transfer routines we'll discuss are fg_save and
  2324. fg_restore.  The fg_save routine transfers a rectangular region from the
  2325.                                   Chapter 9:  Images and Image Management  177
  2326.  
  2327. active video page (as defined in the most recent call to fg_setpage) to the
  2328. same position on the hidden video page (as defined in the most recent call to
  2329. fg_sethpage).  The fg_restore routine performs the complementary task -- it
  2330. transfers a rectangular region from the hidden page to the active page.  Each
  2331. of these routines requires four arguments that define the coordinates of the
  2332. region to transfer, in the order minimum x, maximum x, minimum y, and maximum
  2333. y.  In text modes, the coordinates are expressed as character space
  2334. quantities (rows and columns).  In graphics modes, they are expressed as
  2335. screen space values (pixels); the x coordinates are extended to byte
  2336. boundaries if required.  There are also world space versions of these
  2337. routines named fg_savew and fg_restorew available in graphics modes.
  2338.  
  2339.      Example 9-23 demonstrates the use of Fastgraph's fg_save, fg_restore,
  2340. and fg_sethpage routines in an 80-column text video mode.  After establishing
  2341. the video mode (note the calls to fg_testmode specify that two video pages
  2342. are needed), the program fills the screen with text and then waits for a
  2343. keystroke.  Following this, the program displays a small pop-up window
  2344. prompting for another keystroke.  After waiting for the second keystroke, the
  2345. program erases the pop-up window by restoring the original screen contents,
  2346. and then waits for yet another keystroke before returning to DOS.  We'll
  2347. present the program now, and afterward analyze it in detail.
  2348.  
  2349.                                 Example 9-23.
  2350.  
  2351.                 #include <fastgraf.h>
  2352.                 #include <stdio.h>
  2353.                 #include <stdlib.h>
  2354.                 void main(void);
  2355.  
  2356.                 void main()
  2357.                 {
  2358.                    int row;
  2359.                    int old_mode;
  2360.                    char string[17];
  2361.  
  2362.                    old_mode = fg_getmode();
  2363.  
  2364.                    if (fg_testmode(3,2))
  2365.                       fg_setmode(3);
  2366.                    else if (fg_testmode(7,2))
  2367.                       fg_setmode(7);
  2368.                    else {
  2369.                       printf("This program requires\n");
  2370.                       printf("an 80-column display.\n");
  2371.                       exit(1);
  2372.                       }
  2373.                    fg_cursor(0);
  2374.                    fg_setattr(9,7,0);
  2375.  
  2376.                    for (row = 0; row < 25; row++) {
  2377.                       sprintf(string," This is row %2d ",row);
  2378.                       fg_locate(row,0);
  2379.                       fg_text(string,16);
  2380.                       fg_text(string,16);
  2381.                       fg_text(string,16);
  2382.                       fg_text(string,16);
  2383.  
  2384. 178  Fastgraph User's Guide
  2385.  
  2386.                       fg_text(string,16);
  2387.                       }
  2388.                    fg_waitkey();
  2389.  
  2390.                    fg_allocate(1);
  2391.                    fg_sethpage(1);
  2392.                    fg_save(32,47,11,13);
  2393.                    fg_setcolor(1);
  2394.                    fg_rect(32,47,11,13);
  2395.                    fg_setattr(15,1,0);
  2396.                    fg_locate(12,33);
  2397.                    fg_text("Press any key.",14);
  2398.                    fg_waitkey();
  2399.  
  2400.                    fg_restore(32,47,11,13);
  2401.                    fg_waitkey();
  2402.  
  2403.                    fg_freepage(1);
  2404.                    fg_setmode(old_mode);
  2405.                    fg_reset();
  2406.                 }
  2407.  
  2408.      Example 9-23 first establishes the video mode and uses the fg_cursor
  2409. routine to make the BIOS cursor invisible.  It then executes a for loop that
  2410. fills each row of the screen with the phrase "This is row n", where n is the
  2411. row number (between 0 and 24).  Next, the program uses the fg_allocate
  2412. routine to create video page 1 as a virtual video page.  This is needed in
  2413. case the program is running in mode 7, which has only one true page (if the
  2414. program is running in mode 3, the call to fg_allocate has no effect).  The
  2415. program then makes page 1 the hidden page by calling the fg_sethpage routine.
  2416.  
  2417.      After setting up the hidden video page, but before displaying the pop-up
  2418. window, example 9-23 uses the fg_save routine to save the current contents of
  2419. the area that the pop-up window will replace.  The fg_save routine copies
  2420. this region to the hidden page.  The program then displays the pop-up window
  2421. in the middle of the screen and leaves it there until a key is pressed.  After
  2422. this, the program uses the fg_restore routine to replace the pop-up window
  2423. with the original contents of that region.  This effectively erases the pop-up
  2424. window and restores the original screen.  The program then waits for another
  2425. keystroke, after which it releases the virtual page and returns to DOS.
  2426.  
  2427.      The next example, 9-24, is similar to example 9-23, but it runs in a 320
  2428. by 200 color graphics mode instead of a text mode.  The main differences
  2429. between this program and example 9-23 are the use of 40-column text and the
  2430. use of screen space coordinates instead of character space coordinates in the
  2431. calls to fg_save, fg_restore, and fg_rect.  Note that the call to fg_allocate
  2432. creates a virtual page if the program is running in modes 4, 9, or 19.  In
  2433. mode 13, which has 8 true pages, the fg_allocate routine does nothing.
  2434.  
  2435.                                 Example 9-24.
  2436.  
  2437.               #include <fastgraf.h>
  2438.               #include <stdio.h>
  2439.               #include <stdlib.h>
  2440.               void main(void);
  2441.  
  2442.                                   Chapter 9:  Images and Image Management  179
  2443.               void main()
  2444.               {
  2445.                  int row;
  2446.                  int new_mode, old_mode;
  2447.                  char string[21];
  2448.  
  2449.                  new_mode = fg_bestmode(320,200,2);
  2450.                  if (new_mode < 0 || new_mode == 12) {
  2451.                     printf("This program requires a 320 ");
  2452.                     printf("x 200 color graphics mode.\n");
  2453.                     exit(1);
  2454.                     }
  2455.                  old_mode = fg_getmode();
  2456.                  fg_setmode(new_mode);
  2457.  
  2458.                  fg_setcolor(7);
  2459.                  fg_rect(0,319,0,199);
  2460.                  fg_setcolor(9);
  2461.  
  2462.                  for (row = 0; row < 25; row++) {
  2463.                     sprintf(string,"   This is row %2d   ",row);
  2464.                     fg_locate(row,0);
  2465.                     fg_text(string,20);
  2466.                     fg_text(string,20);
  2467.                     }
  2468.                  fg_waitkey();
  2469.  
  2470.                  fg_allocate(1);
  2471.                  fg_sethpage(1);
  2472.                  fg_save(96,223,88,111);
  2473.                  fg_setcolor(1);
  2474.                  fg_rect(96,223,88,111);
  2475.                  fg_setcolor(15);
  2476.                  fg_locate(12,13);
  2477.                  fg_text("Press any key.",14);
  2478.                  fg_waitkey();
  2479.  
  2480.                  fg_restore(96,223,88,111);
  2481.                  fg_waitkey();
  2482.  
  2483.                  fg_freepage(1);
  2484.                  fg_setmode(old_mode);
  2485.                  fg_reset();
  2486.               }
  2487.  
  2488.      The fg_save and fg_restore routines each copy a rectangular region from
  2489. one video page to the same position on another video page.  What if you need
  2490. to copy the region to a different position on another video page, or copy it
  2491. elsewhere on the same video page?  Fastgraph provides a more general image
  2492. transfer routine named fg_transfer.  The fg_transfer routine copies a
  2493. rectangular region on any video page to any position on any video page.  Like
  2494. fg_save and fg_restore, the fg_transfer routine works in text and graphics
  2495. video modes.  In graphics modes, fg_transfer extends its x coordinates to
  2496. byte boundaries if necessary.
  2497.  
  2498.      The fg_transfer routine requires eight integer arguments.  The first
  2499. four arguments define the region to copy, in the same order as expected by
  2500. the fg_save and fg_restore routines.  The next two arguments define the lower
  2501. 180  Fastgraph User's Guide
  2502.  
  2503. left corner of the image destination, while the final two arguments
  2504. respectively specify the source and destination video page numbers.  In
  2505. short, fg_transfer copies the specified region from the source page to the
  2506. specified position on the destination page.
  2507.  
  2508.      Example 9-25 is the same as example 9-23, but it uses fg_transfer rather
  2509. than fg_save and fg_restore.  We have arbitrarily chosen to copy the region
  2510. overwritten by the pop-up window to the lower left corner of the hidden page
  2511. (page 1).  When we copy this region back to the visual page, we copy from the
  2512. lower left corner of the hidden page back to the original position on the
  2513. visual page (page 0).  This sequence is shown in the following diagram.
  2514.  
  2515.              (11,32)    (11,47)               (22,0)     (22,15)
  2516.                                 first call
  2517.                This is row 11   ------------>   This is row 11
  2518.                This is row 12                   This is row 12
  2519.                This is row 13   <------------   This is row 13
  2520.                                   second call
  2521.              (13,32)    (13,47)               (24,0)     (24,15)
  2522.  
  2523.                 visual page (0)                  hidden page (1)
  2524.  
  2525. To copy one region to a new position and then back to its original position,
  2526. note how we make the fifth and sixth arguments in the first call to
  2527. fg_transfer the same values as the first and fourth arguments in the second
  2528. call.  Similarly, the fifth and sixth arguments in the second call must be
  2529. the same as the first and fourth arguments in the first call.  Now, here is
  2530. example 9-25.
  2531.  
  2532.                                 Example 9-25.
  2533.  
  2534.                 #include <fastgraf.h>
  2535.                 #include <stdio.h>
  2536.                 #include <stdlib.h>
  2537.                 void main(void);
  2538.  
  2539.                 void main()
  2540.                 {
  2541.                    int row;
  2542.                    int old_mode;
  2543.                    char string[17];
  2544.  
  2545.                    old_mode = fg_getmode();
  2546.  
  2547.                    if (fg_testmode(3,2))
  2548.                       fg_setmode(3);
  2549.                    else if (fg_testmode(7,2))
  2550.                       fg_setmode(7);
  2551.                    else {
  2552.                       printf("This program requires\n");
  2553.                       printf("an 80-column display.\n");
  2554.                       exit(1);
  2555.                       }
  2556.  
  2557.                    fg_cursor(0);
  2558.                    fg_setattr(9,7,0);
  2559.  
  2560.                                   Chapter 9:  Images and Image Management  181
  2561.  
  2562.                    for (row = 0; row < 25; row++) {
  2563.                       sprintf(string," This is row %2d ",row);
  2564.                       fg_locate(row,0);
  2565.                       fg_text(string,16);
  2566.                       fg_text(string,16);
  2567.                       fg_text(string,16);
  2568.                       fg_text(string,16);
  2569.                       fg_text(string,16);
  2570.                       }
  2571.                    fg_waitkey();
  2572.  
  2573.                    fg_allocate(1);
  2574.                    fg_transfer(32,47,11,13,0,24,0,1);
  2575.                    fg_setcolor(1);
  2576.                    fg_rect(32,47,11,13);
  2577.                    fg_setattr(15,1,0);
  2578.                    fg_locate(12,33);
  2579.                    fg_text("Press any key.",14);
  2580.                    fg_waitkey();
  2581.  
  2582.                    fg_transfer(0,15,22,24,32,13,1,0);
  2583.                    fg_fg_waitkey();
  2584.  
  2585.                    fg_freepage(1);
  2586.                    fg_setmode(old_mode);
  2587.                    fg_reset();
  2588.                 }
  2589.  
  2590.      Example 9-26 illustrates another use of the fg_transfer routine.  This
  2591. example is functionally identical to example 9-18 (see page 170), but it uses
  2592. fg_transfer instead of fg_getmap and fg_drawmap.  With the fg_transfer
  2593. routine, we eliminate the calls to fg_getmap and fg_drawmap, the two calls to
  2594. fg_move, and the 32-byte array needed to retrieve the image.  As an added
  2595. bonus, using fg_transfer is much faster than the technique of example 9-18,
  2596. although we probably won't notice this gain with such a small image.
  2597.  
  2598.      The image copied in example 9-26 is one row of four characters, so its
  2599. width in screen space is 32 pixels and its height is 8 pixels.  Because the
  2600. image is in the upper left corner of the screen, the image boundaries are
  2601. xmin=0, xmax=31, ymin=0, and ymax=7.  We want to move the image one-half
  2602. character cell (4 pixels) to the right and one row (8 pixels) down, so our
  2603. destination coordinates are x=4 (xmin+4) and y=15 (ymax+8).  Also, we are
  2604. copying the image from one position to another on the visual page, so both
  2605. the source and destination pages are 0.
  2606.  
  2607.                                 Example 9-26.
  2608.  
  2609.                 #include <fastgraf.h>
  2610.                 #include <stdio.h>
  2611.                 #include <stdlib.h>
  2612.                 void main(void);
  2613.  
  2614.                 void main()
  2615.                 {
  2616.                    int old_mode, new_mode;
  2617.  
  2618. 182  Fastgraph User's Guide
  2619.  
  2620.                    new_mode = fg_bestmode(320,200,1);
  2621.                    if (new_mode < 0 || new_mode == 12) {
  2622.                       printf("This program requires a 320 ");
  2623.                       printf("x 200 color graphics mode.\n");
  2624.                       exit(1);
  2625.                       }
  2626.  
  2627.                    old_mode = fg_getmode();
  2628.                    fg_setmode(new_mode);
  2629.  
  2630.                    fg_setcolor(9);
  2631.                    fg_text("text",4);
  2632.                    fg_waitkey();
  2633.  
  2634.                    fg_transfer(0,31,0,7,4,15,0,0);
  2635.                    fg_waitkey();
  2636.  
  2637.                    fg_setmode(old_mode);
  2638.                    fg_reset();
  2639.                 }
  2640.  
  2641.      Example 9-27 shows yet another application of the fg_transfer routine in
  2642. a graphics video mode.  The program displays a rectangle in the upper left
  2643. quadrant of the screen and then centers the word "quadrant" inside the
  2644. rectangle.  After waiting for a keystroke, the program uses fg_transfer to
  2645. first copy the upper left quadrant to the upper right quadrant.  It then uses
  2646. fg_transfer again to copy the upper half of the screen to the lower half.
  2647. The result of this is the screen being filled with what was originally in the
  2648. upper left quadrant.
  2649.  
  2650.                                 Example 9-27.
  2651.  
  2652.                 #include <fastgraf.h>
  2653.                 #include <stdio.h>
  2654.                 #include <stdlib.h>
  2655.                 void main(void);
  2656.  
  2657.                 void main()
  2658.                 {
  2659.                    int new_mode, old_mode;
  2660.  
  2661.                    new_mode = fg_bestmode(320,200,1);
  2662.                    if (new_mode < 0 || new_mode == 12) {
  2663.                       printf("This program requires a 320 ");
  2664.                       printf("x 200 color graphics mode.\n");
  2665.                       exit(1);
  2666.                       }
  2667.                    old_mode = fg_getmode();
  2668.                    fg_setmode(new_mode);
  2669.  
  2670.                    fg_setcolor(7);
  2671.                    fg_rect(0,159,0,99);
  2672.                    fg_setcolor(9);
  2673.                    fg_locate(6,6);
  2674.                    fg_text("quadrant",8);
  2675.                    fg_waitkey();
  2676.  
  2677.                                   Chapter 9:  Images and Image Management  183
  2678.  
  2679.                    fg_transfer(0,159,0,99,160, 99,0,0);
  2680.                    fg_transfer(0,319,0,99,  0,199,0,0);
  2681.                    fg_waitkey();
  2682.  
  2683.                    fg_setmode(old_mode);
  2684.                    fg_reset();
  2685.                 }
  2686.  
  2687.      The final routines pertaining to image transfer are fg_tcxfer and
  2688. fg_tcmask.  The fg_tcxfer routine is similar to fg_transfer in that it copies
  2689. a rectangular region from one position to another, but fg_tcxfer allows you
  2690. to treat one or more colors as transparent (the name fg_tcxfer stands for
  2691. "transparent color transfer").  In other words, any pixel whose color value
  2692. is defined to be transparent is not copied to the destination area.  The
  2693. fg_tcxfer routine's arguments are the same as for the fg_transfer routine, but
  2694. fg_tcxfer has no effect in text video modes.  Because fg_tcxfer must examine
  2695. the color of individual pixels, it is not as fast as the fg_transfer routine.
  2696.  
  2697.      The fg_tcmask routine defines which colors are considered transparent in
  2698. subsequent calls to fg_tcxfer.  Its argument is an integer bit mask
  2699. (specifically, a 16-bit mask) where each bit indicates whether or not the
  2700. color is transparent.  For example, if bit 0 (the rightmost bit) is set in
  2701. the mask, then color 0 will be transparent; if bit 0 is reset, color 0 will
  2702. not be transparent.  Because the bit mask size is 16 bits, only the first 16
  2703. color values may be defined as transparent.
  2704.  
  2705.      Example 9-28 illustrates the use of the fg_tcxfer and fg_tcmask routines.
  2706. This program is the same as example 9-27, except the color of the word
  2707. "quadrant" (color 9) is defined to be transparent, and fg_tcxfer is used in
  2708. place of fg_transfer.  Because color 9 maps to color 1 in the CGA four-color
  2709. graphics mode (mode 4), we must define both colors 1 and 9 to be transparent
  2710. (remember, fg_tcmask considers actual color values transparent, not color
  2711. indices).  The bit mask passed to fg_tcmask thus will be 0000 0010 0000 0010
  2712. binary, or 0202 hex.  The result of this program is the same as example 9-27,
  2713. but the word "quadrant" appears in the background color (color 0) instead of
  2714. color 9 in the upper right, lower left, and lower right quadrants.
  2715.  
  2716.                                 Example 9-28.
  2717.  
  2718.                 #include <fastgraf.h>
  2719.                 #include <stdio.h>
  2720.                 #include <stdlib.h>
  2721.                 void main(void);
  2722.  
  2723.                 void main()
  2724.                 {
  2725.                    int new_mode, old_mode;
  2726.  
  2727.                    new_mode = fg_bestmode(320,200,1);
  2728.                    if (new_mode < 0 || new_mode == 12) {
  2729.                       printf("This program requires a 320 ");
  2730.                       printf("x 200 color graphics mode.\n");
  2731.                       exit(1);
  2732.                       }
  2733.                    old_mode = fg_getmode();
  2734.                    fg_setmode(new_mode);
  2735.  
  2736. 184  Fastgraph User's Guide
  2737.  
  2738.                    fg_setcolor(7);
  2739.                    fg_rect(0,159,0,99);
  2740.                    fg_setcolor(9);
  2741.                    fg_locate(6,6);
  2742.                    fg_text("quadrant",8);
  2743.                    fg_waitkey();
  2744.  
  2745.                    fg_tcmask(0x0202);
  2746.                    fg_tcxfer(0,159,0,99,160, 99,0,0);
  2747.                    fg_tcxfer(0,319,0,99,  0,199,0,0);
  2748.                    fg_waitkey();
  2749.  
  2750.                    fg_setmode(old_mode);
  2751.                    fg_reset();
  2752.                 }
  2753.  
  2754.  
  2755.  
  2756. Summary of Image Display Routines
  2757.  
  2758.      This section summarizes the functional descriptions of the Fastgraph
  2759. routines presented in this chapter.  More detailed information about these
  2760. routines, including their arguments and return values, may be found in the
  2761. Fastgraph Reference Manual.
  2762.  
  2763.      For all image display routines, images are positioned so their lower
  2764. left corner is at the graphics cursor position (or text cursor position for
  2765. those routines that also work in text video modes).  For all image transfer
  2766. routines, Fastgraph extends the horizontal pixel coordinates to a byte
  2767. boundary when the routines are used in a graphics video mode.
  2768.  
  2769.      FG_CLIPMASK displays a clipped image stored as a masking map.  This
  2770. routine has no effect when used in a text video mode.
  2771.  
  2772.      FG_CLPIMAGE displays a clipped image stored as a mode-specific bit map.
  2773. This routine has no effect when used in a text video mode.
  2774.  
  2775.      FG_COPYPAGE transfers the contents of one video page to another.  The
  2776. pages may be physical, virtual, or logical video pages.  If both pages are
  2777. logical pages, they must exist in the same type of memory.
  2778.  
  2779.      FG_DISPFILE displays an image stored in Fastgraph's standard or packed
  2780. pixel run format, where the image resides in an external file.  This routine
  2781. has no effect when used in a text video mode.
  2782.  
  2783.      FG_DISPLAY displays an image stored in Fastgraph's standard pixel run
  2784. format, where the image resides in an array.  This routine has no effect when
  2785. used in a text video mode.
  2786.  
  2787.      FG_DISPLAYP displays an image stored in Fastgraph's packed pixel run
  2788. format, where the image resides in an array.  This routine has no effect when
  2789. used in a text video mode.
  2790.  
  2791.      FG_DISPPCX displays an image stored in a PCX file.  The image will be
  2792. positioned so its upper left corner is at the graphics cursor position of the
  2793. active video page.
  2794.                                   Chapter 9:  Images and Image Management  185
  2795.  
  2796.      FG_DRAWMAP displays an image stored as a mode-independent bit map.  This
  2797. routine has no effect when used in a text video mode.
  2798.  
  2799.      FG_DRAWMASK displays an image stored as a masking map.  This routine has
  2800. no effect when used in a text video mode.
  2801.  
  2802.      FG_DRWIMAGE displays an image stored as a mode-specific bit map.
  2803.  
  2804.      FG_FLIPMASK displays a reversed clipped image stored as a masking map.
  2805. This routine has no effect when used in a text video mode.
  2806.  
  2807.      FG_FLPIMAGE displays a reversed clipped image stored as a mode-specific
  2808. bit map.  This routine has no effect when used in a text video mode.
  2809.  
  2810.      FG_GETHPAGE returns the hidden page number, as defined in the most
  2811. recent call to fg_sethpage.
  2812.  
  2813.      FG_GETIMAGE retrieves an image as a mode-specific bit map.
  2814.  
  2815.      FG_GETMAP retrieves an image as a mode-independent bit map.  This
  2816. routine has no effect when used in a text video mode.
  2817.  
  2818.      FG_IMAGESIZ determines the number of bytes required to store a mode-
  2819. specific bit-mapped image of specified dimensions.
  2820.  
  2821.      FG_MAKEPCX creates a PCX file from the specified rectangular region of
  2822. the active video page.  The region's extremes are expressed in screen space
  2823. units.
  2824.  
  2825.      FG_PATTERN defines a display pattern for use with the fg_dispfile,
  2826. fg_display, or fg_displayp routines.  This routine has no effect when used in
  2827. a text video mode.
  2828.  
  2829.      FG_RESTORE copies an image from the hidden video page to the same
  2830. position on the active video page.
  2831.  
  2832.      FG_RESTOREW is the same as fg_restore, but the image extremes are
  2833. specified as world space coordinates.
  2834.  
  2835.      FG_REVIMAGE displays a reversed image stored as a mode-specific bit map.
  2836. This routine has no effect when used in a text video mode.
  2837.  
  2838.      FG_REVMASK displays a reversed image stored as a masking map.  This
  2839. routine has no effect when used in a text video mode.
  2840.  
  2841.      FG_SAVE copies an image from the active video page to the same position
  2842. on the hidden video page.
  2843.  
  2844.      FG_SAVEW is the same as fg_save, but the image extremes are specified as
  2845. world space coordinates.
  2846.  
  2847.      FG_SETHPAGE defines the hidden video page (used by fg_restore,
  2848. fg_restorew, fg_save, and fg_savew).
  2849.  
  2850.      FG_TCMASK defines which colors the fg_tcxfer routine will consider
  2851. transparent.  This routine has no effect when used in a text video mode.
  2852. 186  Fastgraph User's Guide
  2853.  
  2854.      FG_TCXFER copies an image from any position on any video page to any
  2855. position on any video page, excluding any pixels whose color value is
  2856. transparent.  This routine has no effect when used in a text video mode.
  2857.  
  2858.      FG_TRANSFER copies an image from any position on any video page to any
  2859. position on any video page.  It is Fastgraph's most general image transfer
  2860. routine.
  2861.