home *** CD-ROM | disk | FTP | other *** search
/ C++ Games Programming / CPPGAMES.ISO / fgl / fglight / manuals.arj / USER10.DOC < prev    next >
Text File  |  1995-02-06  |  102KB  |  2,376 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7. Chapter 10
  8.  
  9.  
  10.  
  11.  
  12.  
  13. Bitmapped Images                                                               
  14. 212   Fastgraph User's Guide
  15.  
  16.  
  17. Overview
  18.  
  19.      In this chapter, we'll continue our discussion of images by concentrating
  20. on an important class of images called bitmapped images. Fastgraph includes
  21. routines to display, retrieve, and manipulate bitmapped images in mode-
  22. specific and mode-independent formats. This chapter will discuss the Fastgraph
  23. routines that deal with both classes of bitmapped images.
  24.  
  25.      Displaying bitmapped images is an essential part of animation with
  26. Fastgraph. While the image files discussed in the previous chapter are useful
  27. for displaying backgrounds or importing pictures from other sources, an
  28. animation sequence can only achieve its speed through the bitmapped image
  29. display routines described in this chapter, along with the block transfer
  30. routines of the next chapter.
  31.  
  32.  
  33. Mode-Independent Bitmapped Images
  34.  
  35.      This section will discuss the image display routines that use the same
  36. bitmapped image format for all graphics video modes. Another class of
  37. routines, described in the next section, use different formats for different
  38. video modes. While these mode-independent image display routines are more
  39. general, they achieve this generality at the sake of execution speed. This may
  40. especially be a concern if the image is large, or if speed is critical in an
  41. application (as in arcade-style graphics). For many programs, however, the
  42. mode-independent routines provide all the image display capability needed.
  43.  
  44.      Let's begin by returning to an example of a very simple image -- the
  45. triangle introduced in the previous chapter:
  46.  
  47.                                . . . . * . . . .
  48.                                . . . * x * . . .
  49.                                . . * x x x * . .
  50.                                . * x x x x x * .
  51.                                * * * * * * * * *
  52.  
  53. Recall that the triangle's perimeter is a different color than its interior
  54. pixels, and to use this image with Fastgraph, we must inscribe the triangle in
  55. a rectangular area. As before, our triangle is nine pixels wide at its base
  56. and five pixels high. The pixels indicated by an asterisk (*) are the
  57. triangle's perimeter, while those indicated by an x represent its interior
  58. points. We need to distinguish between these pixels because they will be
  59. different colors. The pixels shown as periods (.) are not part of the triangle
  60. itself. They are required to make the image rectangular, so from Fastgraph's
  61. perspective they are indeed part of the image.
  62.  
  63.      The Fastgraph routine fg_drawmap is a suitable routine for drawing our
  64. triangle. To use fg_drawmap, we must create separate bitmaps for each color in
  65. the image (excluding the points used to fill the rectangular region, which are
  66. considered transparent). In this example, we will thus need two bitmaps -- one
  67. for the perimeter points, and one for the interior points. Let's break the
  68. image into these two bitmaps.                                                  
  69.                                            Chapter 10:  Bitmapped Images   213
  70.  
  71.                   . . . . * . . . .        . . . . . . . . .
  72.                   . . . * . * . . .        . . . . x . . . .
  73.                   . . * . . . * . .        . . . x x x . . .
  74.                   . * . . . . . * .        . . x x x x x . .
  75.                   * * * * * * * * *        . . . . . . . . .
  76.  
  77.                   perimeter points          interior points
  78.  
  79.      The next step is to convert these two bitmaps into their binary
  80. representations. Just as there are eight bits in a byte, we will create a data
  81. structure (an array in this case) with each byte holding eight pixels. Bits
  82. that are set (1) indicate the corresponding pixel will appear displayed in the
  83. color associated with that bitmap. Bits that are reset (0) leave the
  84. corresponding pixel unchanged. The size of each bitmap array must be at least
  85. 10 bytes because each bitmap contains five rows with nine pixels in each row
  86. (that is, two bytes are required for each row of the image). Hence, when we
  87. convert these bitmaps to their binary representations, and subsequently to
  88. their hexadecimal equivalent, the results will appear as shown here. The
  89. boldface bits represent the actual image; the other bits are filler bits
  90. needed to complete each row of the bitmaps after the ninth pixel. All filler
  91. bits must be zero.
  92.  
  93.  
  94.                0 0 0 0 1 0 0 0   0 0 0 0 0 0 0 0         08   00
  95.  
  96.                0 0 0 1 0 1 0 0   0 0 0 0 0 0 0 0         14   00
  97.  
  98.                0 0 1 0 0 0 1 0   0 0 0 0 0 0 0 0         22   00
  99.  
  100.                0 1 0 0 0 0 0 1   0 0 0 0 0 0 0 0         41   00
  101.  
  102.                1 1 1 1 1 1 1 1   1 0 0 0 0 0 0 0         FF   80
  103.  
  104.                                perimeter bitmap
  105.  
  106.  
  107.                0 0 0 0 0 0 0 0   0 0 0 0 0 0 0 0         00   00
  108.  
  109.                0 0 0 0 1 0 0 0   0 0 0 0 0 0 0 0         08   00
  110.  
  111.                0 0 0 1 1 1 0 0   0 0 0 0 0 0 0 0         1C   00
  112.  
  113.                0 0 1 1 1 1 1 0   0 0 0 0 0 0 0 0         3E   00
  114.  
  115.                0 0 0 0 0 0 0 0   0 0 0 0 0 0 0 0         00   00
  116.  
  117.                                 interior bitmap
  118.  
  119.      The next matter is the order in which the bitmaps are stored in the
  120. corresponding data structures. Since our data structure is an array, it is
  121. only necessary to show the relationship of the subscripts to the bitmap
  122. structures above. The next diagram shows the subscript order for the case of a
  123. two-column by five-row bitmap.
  124.  
  125.  
  126.                                    [8]   [9]                                   
  127. 214   Fastgraph User's Guide
  128.  
  129.  
  130.                                    [6]   [7]
  131.  
  132.                                    [4]   [5]
  133.  
  134.                                    [2]   [3]
  135.  
  136.                                    [0]   [1]
  137.  
  138.  
  139.      From this diagram, we see the first element of the array (that is, the
  140. element with subscript [0]) represents the lower left corner of the image. The
  141. subscript progression then continues right until reaching the end of the first
  142. row. It then resumes at the leftmost element of the second row and continues
  143. to the right until the end of that row. It continues in this manner for all
  144. remaining rows.
  145.  
  146.      We are now ready to present an example program to display our triangle.
  147. The program will use the Fastgraph routine fg_drawmap, which expects three
  148. arguments. The first argument is the bitmap array (passed by reference), the
  149. second is the width of the bitmap in bytes, and the last is the height of the
  150. bitmap in pixel rows. The fg_drawmap routine displays the image such that its
  151. lower left corner is at the graphics cursor position on the active video page.
  152. The routine has no effect in text video modes. Additionally, fg_drawmap
  153. displays the image using the current color index, which means we will need to
  154. call fg_drawmap once for each color in the image.
  155.  
  156.      Example 10-1 runs in any 320x200 color graphics mode (it could be made to
  157. run in mode 12 too, but that would detract from the purpose of the example).
  158. After establishing the video mode, the program uses fg_rect to fill the entire
  159. screen with a gray rectangle (white in CGA). Next, the program establishes
  160. (156,101) as the graphics cursor position; this causes the triangle to be
  161. centered on the screen. The two calls to fg_drawmap, one for each color in the
  162. image, actually display the triangle. Note especially how fg_setcolor is used
  163. before each call to fg_drawmap to define the current color index. The result
  164. is a triangle with a blue perimeter (cyan in CGA) and green interior (magenta
  165. in CGA).
  166.  
  167.                                  Example 10-1.
  168.  
  169.              #include <fastgraf.h>
  170.              #include <stdio.h>
  171.              #include <stdlib.h>
  172.              void main(void);
  173.  
  174.              char perimeter[] = {
  175.                 0xFF,0x80,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00
  176.                 };
  177.              char interior[] = {
  178.                 0x00,0x00,0x3E,0x00,0x1C,0x00,0x08,0x00,0x00,0x00
  179.                 };
  180.  
  181.              void main()
  182.              {
  183.                 int old_mode, new_mode;                                        
  184.                                            Chapter 10:  Bitmapped Images   215
  185.  
  186.                 fg_initpm();
  187.                 new_mode = fg_bestmode(320,200,1);
  188.                 if (new_mode < 0 || new_mode == 12) {
  189.                    printf("This program requires a 320 ");
  190.                    printf("x 200 color graphics mode.\n");
  191.                    exit(1);
  192.                    }
  193.  
  194.                 old_mode = fg_getmode();
  195.                 fg_setmode(new_mode);
  196.  
  197.                 fg_setcolor(7);
  198.                 fg_rect(0,319,0,199);
  199.  
  200.                 fg_move(156,101);
  201.                 fg_setcolor(1);
  202.                 fg_drawmap(perimeter,2,5);
  203.                 fg_setcolor(2);
  204.                 fg_drawmap(interior,2,5);
  205.                 fg_waitkey();
  206.  
  207.                 fg_setmode(old_mode);
  208.                 fg_reset();
  209.              }
  210.  
  211.  
  212.      We should mention that fg_drawmap does not perform clipping when
  213. displaying an image. If you want the image to be constrained by the current
  214. clipping limits, use fg_clipmap instead of fg_drawmap. The fg_clipmap routine
  215. takes the same three arguments as fg_drawmap, but it is not as fast as
  216. fg_drawmap because of the additional overhead required when performing the
  217. image clipping.
  218.  
  219.      The different color bitmaps used by fg_drawmap do not all have to be the
  220. same size. In our triangle example, the perimeter is 9 pixels wide by 5 pixels
  221. high, but the interior is only 5 pixels wide by 3 pixels high. Hence, the
  222. bitmap for the interior pixels only requires one byte for each of its three
  223. rows, so we can store it in a three-byte array. Its structure would be:
  224.  
  225.  
  226.                                   [2]   08
  227.  
  228.                                   [1]   1C
  229.  
  230.                                   [0]   3E
  231.  
  232.  
  233.      Example 10-2 is similar to example 10-1, but it uses a three-byte array
  234. for the interior bitmap. Note the second call to fg_move in this example. It
  235. is needed because the bottom row of the smaller interior bitmap corresponds to
  236. the second row of the larger perimeter bitmap. In other words, the interior
  237. bitmap must be displayed one row above the perimeter bitmap.
  238.  
  239.                                  Example 10-2.
  240.  
  241.              #include <fastgraf.h>                                             
  242. 216   Fastgraph User's Guide
  243.  
  244.              #include <stdio.h>
  245.              #include <stdlib.h>
  246.              void main(void);
  247.  
  248.              char perimeter[] = {
  249.                 0xFF,0x80,0x41,0x00,0x22,0x00,0x14,0x00,0x08,0x00
  250.                 };
  251.              char interior[] = {
  252.                 0x3E,0x1C,0x08
  253.                 };
  254.  
  255.              void main()
  256.              {
  257.                 int old_mode, new_mode;
  258.  
  259.                 fg_initpm();
  260.                 new_mode = fg_bestmode(320,200,1);
  261.                 if (new_mode < 0 || new_mode == 12) {
  262.                    printf("This program requires a 320 ");
  263.                    printf("x 200 color graphics mode.\n");
  264.                    exit(1);
  265.                    }
  266.  
  267.                 old_mode = fg_getmode();
  268.                 fg_setmode(new_mode);
  269.  
  270.                 fg_setcolor(7);
  271.                 fg_rect(0,319,0,199);
  272.  
  273.                 fg_move(156,101);
  274.                 fg_setcolor(1);
  275.                 fg_drawmap(perimeter,2,5);
  276.                 fg_move(156,100);
  277.                 fg_setcolor(2);
  278.                 fg_drawmap(interior,1,3);
  279.                 fg_waitkey();
  280.  
  281.                 fg_setmode(old_mode);
  282.                 fg_reset();
  283.              }
  284.  
  285.  
  286.      In example 10-2, the time required to execute the second call to fg_move
  287. may not be worth the saving of 7 bytes. When array space is critical, or when
  288. the images are larger, the use of smaller bitmaps for certain colors may be
  289. more valuable.
  290.  
  291.      Yet another possibility for example 10-2 would be to shift the elements
  292. of the interior bitmap two pixels to the left. In this way, the bitmap would
  293. be aligned against the left side of the array, as the perimeter bitmap is. The
  294. three values comprising the interior bitmap would then become F8, 70, and 20.
  295. We also would need to change the x coordinate in the second call to fg_move
  296. from 156 to 158.                                                               
  297.                                            Chapter 10:  Bitmapped Images   217
  298.  
  299.  
  300. Mode-Specific Bitmapped Images
  301.  
  302.      This section will discuss the image display routines that use bitmapped
  303. image formats specific to each text and graphics video mode. The different
  304. image formats closely resemble the structure of video memory in each mode, so
  305. these routines are much faster than displaying mode-independent bitmaps with
  306. fg_drawmap. If you use the mode-specific bitmaps in a program that supports
  307. several video modes, there will be some additional programming that is not
  308. needed when using mode-independent bitmaps. Usually, however, your efforts
  309. will be rewarded with significantly faster graphics.
  310.  
  311.      We'll demonstrate the use of mode-specific bitmaps in graphics modes with
  312. the familiar two-color triangle whose pixel representation appears below.
  313.  
  314.                                . . . . * . . . .
  315.                                . . . * x * . . .
  316.                                . . * x x x * . .
  317.                                . * x x x x x * .
  318.                                * * * * * * * * *
  319.  
  320.      As before, our triangle is nine pixels wide at its base and five pixels
  321. high. The pixels indicated by an asterisk (*) are the triangle's perimeter,
  322. while those indicated by an x represent its interior points. We need to
  323. distinguish between these pixels because they will be different colors. The
  324. pixels shown as periods (.) are not part of the triangle itself. They are
  325. required to make the image rectangular, so from Fastgraph's perspective they
  326. are indeed part of the image.
  327.  
  328.  
  329. Regular Images
  330.  
  331.      The Fastgraph routine fg_drwimage displays regular mode-specific
  332. bitmapped images (by regular, we mean an image that is neither clipped nor
  333. rotated). Its arguments and the bitmap array's subscript order are the same as
  334. for fg_drawmap. The major difference is the bitmap structure -- we combine the
  335. information for all colors into a single bitmap, in a way consistent with the
  336. structure of video memory for the various modes. As with the other image
  337. display routines, fg_drwimage displays the image on the active video page or
  338. virtual buffer with its lower left corner at the graphics cursor position (or
  339. the text cursor position for text modes). We'll now examine the use of
  340. fg_drwimage in several video modes.
  341.  
  342. CGA four-color graphics modes
  343.  
  344.      In the four-color CGA graphics modes (modes 4 and 5), each pixel can
  345. assume a value between 0 and 3. This means it takes two bits to represent a
  346. pixel, or put another way, each byte of video memory holds four pixels. Our
  347. triangle image is nine pixels wide, so three bytes are needed for each row of
  348. the image. Because the image is five pixels high, we need a bitmap array of at
  349. least 15 bytes (five rows times three bytes per row) to hold the image.
  350.  
  351.      The image's binary representation and its hexadecimal equivalent for the
  352. four-color CGA graphics modes are shown here. The binary values in boldface
  353. represent the actual image; the others are the filler bits needed to complete
  354. each row of the bitmap after the ninth pixel. We have coded the perimeter      
  355. 218   Fastgraph User's Guide
  356.  
  357. pixels to be color 1 (01 binary) and the interior pixels to be color 2 (10
  358. binary). Any pixel whose value is zero (00 binary) is transparent and will
  359. thus leave the contents of video memory at that position unchanged.
  360.  
  361.  
  362.          00 00 00 00   01 00 00 00   00 00 00 00         00   40   00
  363.  
  364.          00 00 00 01   10 01 00 00   00 00 00 00         01   90   00
  365.  
  366.          00 00 01 10   10 10 01 00   00 00 00 00         06   A4   00
  367.  
  368.          00 01 10 10   10 10 10 01   00 00 00 00         1A   A9   00
  369.  
  370.          01 01 01 01   01 01 01 01   01 00 00 00         55   55   40
  371.  
  372.  
  373.      Example 10-3 uses this mode-specific bitmap to display the triangle in
  374. the standard CGA four-color graphics mode (mode 4). After establishing the
  375. video mode, the program uses fg_rect to fill the entire screen with a white
  376. rectangle. Next, the program establishes (156,101) as the graphics cursor
  377. position; this causes the triangle to be centered on the screen. The call to
  378. fg_drwimage produces a triangle with a cyan perimeter (color 1) and a magenta
  379. interior (color 2).
  380.  
  381.                                  Example 10-3.
  382.  
  383.               #include <fastgraf.h>
  384.               #include <stdio.h>
  385.               #include <stdlib.h>
  386.               void main(void);
  387.  
  388.               char triangle[] = {
  389.                  0x55,0x55,0x40, 0x1A,0xA9,0x00, 0x06,0xA4,0x00,
  390.                  0x01,0x90,0x00, 0x00,0x40,0x00
  391.                  };
  392.  
  393.               void main()
  394.               {
  395.                  int old_mode;
  396.  
  397.                  fg_initpm();
  398.                  if (fg_testmode(4,1) == 0) {
  399.                     printf("This program requires a 320 ");
  400.                     printf("x 200 CGA graphics mode.\n");
  401.                     exit(1);
  402.                     }
  403.  
  404.                  old_mode = fg_getmode();
  405.                  fg_setmode(4);
  406.  
  407.                  fg_setcolor(7);
  408.                  fg_rect(0,319,0,199);
  409.  
  410.                  fg_move(156,101);
  411.                  fg_drwimage(triangle,3,5);
  412.                  fg_waitkey();                                                 
  413.                                            Chapter 10:  Bitmapped Images   219
  414.  
  415.  
  416.                  fg_setmode(old_mode);
  417.                  fg_reset();
  418.               }
  419.  
  420.  
  421. CGA two-color graphics mode
  422.  
  423.      In the two-color CGA graphics mode (mode 6), each pixel can assume the
  424. values 0 or 1. This means it takes just one bit to represent a pixel, so each
  425. byte of video memory holds eight pixels. Our triangle image is nine pixels
  426. wide, so two bytes are needed for each row of the image. Because the image is
  427. five pixels high, we need a bitmap array of at least 10 bytes (five rows times
  428. two bytes per row) to hold the image.
  429.  
  430.      The image's binary representation and its hexadecimal equivalent for the
  431. two-color CGA graphics mode are shown here. The binary values in boldface
  432. represent the actual image; the others are the filler bits needed to complete
  433. each row of the bitmap after the ninth pixel. We have coded both the perimeter
  434. pixels and the interior pixels to be color 1. Any pixel whose value is zero is
  435. transparent and will thus leave the contents of video memory at that position
  436. unchanged.
  437.  
  438.  
  439.                0 0 0 0 1 0 0 0   0 0 0 0 0 0 0 0         08   00
  440.  
  441.                0 0 0 1 1 1 0 0   0 0 0 0 0 0 0 0         1C   00
  442.  
  443.                0 0 1 1 1 1 1 0   0 0 0 0 0 0 0 0         3E   00
  444.  
  445.                0 1 1 1 1 1 1 1   0 0 0 0 0 0 0 0         7F   00
  446.  
  447.                1 1 1 1 1 1 1 1   1 0 0 0 0 0 0 0         FF   80
  448.  
  449.  
  450.      Example 10-4 uses this mode-specific bitmap to display the triangle in
  451. the CGA two-color graphics mode (mode 6). After establishing the video mode,
  452. the program establishes (316,101) as the graphics cursor position; this causes
  453. the triangle to be centered on the screen. The call to fg_drwimage produces a
  454. solid triangle.
  455.  
  456.                                  Example 10-4.
  457.  
  458.                    #include <fastgraf.h>
  459.                    #include <stdio.h>
  460.                    #include <stdlib.h>
  461.                    void main(void);
  462.  
  463.                    char triangle[] = {
  464.                       0xFF,0x80, 0x7F,0x00, 0x3E,0x00,
  465.                       0x1C,0x00, 0x08,0x00
  466.                       };
  467.  
  468.                    void main()
  469.                    {
  470.                       int old_mode;                                            
  471. 220   Fastgraph User's Guide
  472.  
  473.  
  474.                       fg_initpm();
  475.                       if (fg_testmode(6,1) == 0) {
  476.                          printf("This program requires a ");
  477.                          printf("CGA graphics mode.\n");
  478.                          exit(1);
  479.                          }
  480.  
  481.                       old_mode = fg_getmode();
  482.                       fg_setmode(6);
  483.  
  484.                       fg_move(316,101);
  485.                       fg_drwimage(triangle,2,5);
  486.                       fg_waitkey();
  487.  
  488.                       fg_setmode(old_mode);
  489.                       fg_reset();
  490.                    }
  491.  
  492.  
  493. Tandy/PCjr 16-color graphics mode
  494.  
  495.      The structure of mode-specific bitmaps for the Tandy/PCjr 16-color
  496. graphics mode (mode 9) is the same as the mode-specific bitmap structure for
  497. the EGA/VGA/SVGA 16-color graphics modes discussed later in this section.
  498.  
  499. Hercules graphics modes
  500.  
  501.      The structure of mode-specific bitmaps for the Hercules graphics modes
  502. (modes 11 and 12) is the same as two of the CGA graphics modes. For the
  503. standard Hercules graphics mode (mode 11), please refer to the discussion of
  504. CGA two-color (mode 6) bitmaps. For the low-resolution Hercules graphics mode
  505. (mode 12), please refer to the discussion of the CGA four-color (mode 4)
  506. bitmaps.
  507.  
  508. EGA/VGA/SVGA 16-color graphics modes
  509.  
  510.      In the native EGA and VGA graphics modes (modes 13 through 18) and the
  511. 16-color SVGA graphics modes (modes 28 and 29), each pixel can assume a value
  512. between 0 and 15. This means it takes four bits to represent a pixel, so each
  513. byte of the bitmap holds two pixels. Our triangle image is nine pixels wide,
  514. so five bytes are needed for each row of the image. Because the image is five
  515. pixels high, we need a bitmap array of at least 25 bytes (five rows times five
  516. bytes per row) to hold the image.
  517.  
  518.      In these modes, it is easy to develop the hexadecimal representation of a
  519. bitmap without first producing its binary equivalent. This is because a pixel
  520. value and a hexadecimal digit each occupy four bits. The triangle's
  521. hexadecimal representation for these video modes is shown here. The pixels in
  522. boldface represent the actual image; the others are the filler values needed
  523. to complete each row of the bitmap after the ninth pixel. We have chosen to
  524. display the perimeter pixels in color 1 and the interior pixels in color 2.
  525. Any pixel whose value is zero is transparent and will thus leave the contents
  526. of video memory at that position unchanged.                                    
  527.                                            Chapter 10:  Bitmapped Images   221
  528.  
  529.                             00   00   10   00   00
  530.  
  531.                             00   01   21   00   00
  532.  
  533.                             00   12   22   10   00
  534.  
  535.                             01   22   22   21   00
  536.  
  537.                             11   11   11   11   10
  538.  
  539.  
  540.      Example 10-5 is similar to example 10-3, but it uses the 320x200 EGA
  541. graphics mode (mode 13) and the mode-specific bitmap just constructed to
  542. display the triangle. The call to fg_drwimage produces a triangle with a blue
  543. perimeter (color 1) and a green interior (color 2).
  544.  
  545.                                  Example 10-5.
  546.  
  547.                  #include <fastgraf.h>
  548.                  #include <stdio.h>
  549.                  #include <stdlib.h>
  550.                  void main(void);
  551.  
  552.                  char triangle[] = {
  553.                     0x11,0x11,0x11,0x11,0x10,
  554.                     0x01,0x22,0x22,0x21,0x00,
  555.                     0x00,0x12,0x22,0x10,0x00,
  556.                     0x00,0x01,0x21,0x00,0x00,
  557.                     0x00,0x00,0x10,0x00,0x00
  558.                     };
  559.  
  560.                  void main()
  561.                  {
  562.                     int old_mode;
  563.  
  564.                     fg_initpm();
  565.                     if (fg_testmode(13,1) == 0) {
  566.                        printf("This program requires a 320 ");
  567.                        printf("x 200 EGA graphics mode.\n");
  568.                        exit(1);
  569.                        }
  570.  
  571.                     old_mode = fg_getmode();
  572.                     fg_setmode(13);
  573.  
  574.                     fg_setcolor(7);
  575.                     fg_rect(0,319,0,199);
  576.  
  577.                     fg_move(156,101);
  578.                     fg_drwimage(triangle,5,5);
  579.                     fg_waitkey();
  580.  
  581.                     fg_setmode(old_mode);
  582.                     fg_reset();
  583.                  }                                                             
  584. 222   Fastgraph User's Guide
  585.  
  586.  
  587. 256-color graphics modes
  588.  
  589.      In 256-color graphics modes (modes 19 through 27), each pixel can assume
  590. a value between 0 and 255 (FF hex). This means it takes eight bits to
  591. represent a pixel, or each byte of video memory holds one pixel. Our triangle
  592. image is nine pixels wide, so nine bytes are needed for each row of the image.
  593. Because the image is five pixels high, we need a bitmap array of at least 45
  594. bytes (five rows times nine bytes per row) to hold the image. Note we will
  595. never need any filler bits in the 256-color video modes.
  596.  
  597.      It is especially simple to develop the bitmap for an image in the 256-
  598. color modes because each byte holds exactly one pixel. The triangle's
  599. hexadecimal representation for the 256-color graphics modes is shown here. As
  600. before, we have coded the perimeter pixels to be color 1 (01 hex) and the
  601. interior pixels to be color 2 (02 hex). Any pixel whose value is zero is
  602. transparent and will thus leave the contents of video memory at that position
  603. unchanged.
  604.  
  605.  
  606.                   00   00   00   00   01   00   00   00   00
  607.  
  608.                   00   00   00   01   02   01   00   00   00
  609.  
  610.                   00   00   01   02   02   02   01   00   00
  611.  
  612.                   00   01   02   02   02   02   02   01   00
  613.  
  614.                   01   01   01   01   01   01   01   01   01
  615.  
  616.  
  617.      Example 10-6 is also similar to example 10-3, but it uses the MCGA 256-
  618. color graphics mode (mode 19) and the mode-specific bitmap just constructed to
  619. display the triangle. The call to fg_drwimage produces a triangle with a blue
  620. perimeter (color 1) and a green interior (color 2).
  621.  
  622.                                  Example 10-6.
  623.  
  624.                #include <fastgraf.h>
  625.                #include <stdio.h>
  626.                #include <stdlib.h>
  627.                void main(void);
  628.  
  629.                char triangle[] = {
  630.                   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
  631.                   0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
  632.                   0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
  633.                   0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
  634.                   0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00
  635.                   };
  636.  
  637.                void main()
  638.                {
  639.                   int old_mode;
  640.  
  641.                   fg_initpm();                                                 
  642.                                            Chapter 10:  Bitmapped Images   223
  643.  
  644.                   if (fg_testmode(19,1) == 0) {
  645.                      printf("This program requires a 320 ");
  646.                      printf("x 200 MCGA graphics mode.\n");
  647.                      exit(1);
  648.                      }
  649.  
  650.                   old_mode = fg_getmode();
  651.                   fg_setmode(19);
  652.  
  653.                   fg_setcolor(7);
  654.                   fg_rect(0,319,0,199);
  655.  
  656.                   fg_move(156,101);
  657.                   fg_drwimage(triangle,9,5);
  658.                   fg_waitkey();
  659.  
  660.                   fg_setmode(old_mode);
  661.                   fg_reset();
  662.                }
  663.  
  664.  
  665.      Sometimes you may need to include black pixels that are not transparent
  666. in a mode-specific bitmapped image. The easiest way to do this is to use
  667. fg_putimage, which we'll describe shortly. Another possibility is using
  668. fg_palette or fg_setrgb to make an unused color index black and then use that
  669. color index for non-transparent black pixels. For example, calling
  670. fg_palette(8,0) in a 16-color graphics mode would display color 8 pixels as
  671. black. Similarly, fg_setrgb(248,0,0,0) in a 256-color graphics mode would
  672. display color 248 pixels as black. The choice of colors 8 and 248 in these
  673. examples is arbitrary; any unused color will do. Yet another possibility is to
  674. use the masking maps discussed later in this chapter.
  675.  
  676. Virtual Buffers
  677.  
  678.           The structure of mode-specific bitmaps for virtual buffers is the
  679. same as the mode-specific bitmap structure for 256-color graphics modes
  680. discussed in the previous section.
  681.  
  682. Text Modes
  683.  
  684.      You also can use the fg_drwimage routine to display images in text video
  685. modes (modes 0, 1, 2, 3, and 7). As one might expect, the image structure in
  686. the text modes is rather different from the graphics modes. In Chapter 5 we
  687. saw that each character cell on the screen actually consists of a character
  688. and an attribute. The character value determines what character is displayed,
  689. while the attribute value controls the character's appearance. The structure
  690. of the attribute is:
  691.  
  692.                        bits         attribute
  693.  
  694.                         0-3     foreground color
  695.                         4-6     background color
  696.                          7          blinking
  697.  
  698.      The text mode image structure used with fg_drwimage also consists of a
  699. series of characters and attributes. For example, the following diagram        
  700. 224   Fastgraph User's Guide
  701.  
  702. illustrates the structure of an image that is three characters wide and two
  703. characters high.
  704.  
  705.  
  706.                     char   attr   char   attr   char   attr
  707.  
  708.                     char   attr   char   attr   char   attr
  709.  
  710.  
  711.      To illustrate the use of fg_drwimage in a text video mode, we'll display
  712. the phrase "hello there" on two different lines in the center of the screen.
  713. Furthermore, let's assume we would like the first character of each word to
  714. appear in foreground color 1, the second in color 2, and so forth. Our image
  715. will consist of two lines each containing five characters, and each character
  716. requires two bytes of storage (one for the character and another for its
  717. attribute), so we'll need a 20-byte array for holding the image. The array
  718. really doesn't hold a bitmap as in the graphics modes, so in the text modes
  719. the first argument passed to fg_drwimage is instead called the image array. In
  720. our example, the structure of the image array is:
  721.  
  722.  
  723.            'h'    1    'e'    2    'l'    3    'l'    4    'o'    5
  724.  
  725.            't'    1    'h'    2    'e'    3    'r'    4    'e'    5
  726.  
  727.  
  728. The subscript order that fg_drwimage uses for text modes is the same as for
  729. the graphics modes. For our five-row by two-column image, this means the array
  730. subscripts would be numbered as follows:
  731.  
  732.  
  733.                [10] [11] [12] [13] [14] [15] [16] [17] [18] [19]
  734.  
  735.                 [0]  [1]  [2]  [3]  [4]  [5]  [6]  [7]  [8]  [9]
  736.  
  737.  
  738.      Depending on the character and attribute values in the image array,
  739. fg_drwimage can display new characters and attributes, new characters leaving
  740. the existing attribute unchanged, new attributes leaving the existing
  741. character unchanged, or leave both the existing character and attribute
  742. unchanged in video memory. To keep an existing character or attribute, simply
  743. specify a value of 0 in the corresponding element of the image array. This
  744. capability is analogous to the fact that zero-valued pixels in graphics mode
  745. bitmaps leave video memory unchanged.
  746.  
  747.      Example 10-7 demonstrates the use of fg_drwimage in the 80-column color
  748. text mode (mode 3). After establishing the video mode and making the cursor
  749. invisible, the program calls fg_drwimage to display the "hello there" image
  750. just discussed (note we pass the dimensions of the image array as the number
  751. of bytes, not the number of characters). The program waits for a keystroke and
  752. then calls fg_drwimage again, passing a different image array (called "image")
  753. of the same size. This array changes the first letter of both words from lower
  754. case to upper case (leaving the attribute unchanged), and it makes the
  755. remaining characters have the same attribute as the first character. This is
  756. done in part by using zero-valued characters and attributes to leave video
  757. memory unchanged. After waiting for another keystroke, the program exits.      
  758.                                            Chapter 10:  Bitmapped Images   225
  759.  
  760.  
  761.                                  Example 10-7.
  762.  
  763.                      #include <fastgraf.h>
  764.                      void main(void);
  765.  
  766.                      char hello[] = {
  767.                         't',1, 'h',2, 'e',3, 'r',4, 'e',5,
  768.                         'h',1, 'e',2, 'l',3, 'l',4, 'o',5
  769.                         };
  770.  
  771.                      char image[] = {
  772.                         'T',0, 0,1, 0,1, 0,1, 0,1,
  773.                         'H',0, 0,1, 0,1, 0,1, 0,1
  774.                         };
  775.  
  776.                      void main()
  777.                      {
  778.                         int old_mode;
  779.  
  780.                         fg_initpm();
  781.                         old_mode = fg_getmode();
  782.                         fg_setmode(3);
  783.                         fg_cursor(0);
  784.  
  785.                         fg_locate(12,37);
  786.                         fg_drwimage(hello,10,2);
  787.                         fg_waitkey();
  788.  
  789.                         fg_drwimage(image,10,2);
  790.                         fg_waitkey();
  791.  
  792.                         fg_setmode(old_mode);
  793.                         fg_reset();
  794.                      }
  795.  
  796.  
  797.  
  798. Clipped Images
  799.  
  800.      The fg_drwimage routine does not perform clipping when displaying an
  801. image. If you want the image to be constrained by the clipping limits (as
  802. established by the most recent call to fg_setclip), use fg_clpimage instead of
  803. fg_drwimage. The fg_clpimage routine takes the same three arguments as
  804. fg_drwimage and also displays the image such that its lower left corner is at
  805. the graphics cursor position. Unlike fg_drwimage, the fg_clpimage routine has
  806. no effect when used in a text video mode. Because of the additional overhead
  807. involved in checking the clipping limits, fg_clpimage is not as fast as
  808. fg_drwimage.
  809.  
  810.  
  811. Reversed Images
  812.  
  813.      The fg_revimage routine displays an image reversed (that is, mirrored
  814. about the y-axis) without clipping. It takes the same three arguments as
  815. fg_drwimage and also displays the image such that its lower left corner is at  
  816. 226   Fastgraph User's Guide
  817.  
  818. the graphics cursor position. The fg_revimage routine has no effect when used
  819. in a text video mode.
  820.  
  821.  
  822. Reversed Clipped Images
  823.  
  824.      The fg_flpimage routine combines the effects of the fg_revimage and
  825. fg_clpimage routines -- it displays a reversed image constrained by the
  826. current clipping limits. It takes the same three arguments as fg_drwimage and
  827. also displays the image such that its lower left corner is at the graphics
  828. cursor position. Like the fg_clpimage routine, fg_flpimage has no effect when
  829. used in a text video mode.
  830.  
  831.  
  832. Images Without Transparent Pixels
  833.  
  834.      The fg_putimage routine is the same as fg_drwimage except it does not
  835. consider color 0 pixels to be transparent. Because it does not need to check
  836. for transparent pixels, fg_putimage is faster than fg_drwimage. Using
  837. fg_putimage is recommended for cases where transparency is not an issue.
  838.  
  839.  
  840. Some Examples
  841.  
  842.      Example 10-8 illustrates the use of fg_drwimage, fg_clpimage,
  843. fg_revimage, fg_flpimage, and fg_putimage in the standard CGA four-color
  844. graphics mode (mode 4). The program uses each of these routines to display a
  845. small white arrow, as shown in this pixel map:
  846.  
  847.                               . . . . . . * . . .
  848.                               . . . . . . * * . .
  849.                               * * * * * * * * * .
  850.                               * * * * * * * * * *
  851.                               * * * * * * * * * .
  852.                               . . . . . . * * . .
  853.                               . . . . . . * . . .
  854.  
  855. As before, we must first convert this image to a bitmap. The image is ten
  856. pixels wide and seven high. In mode 4, each pixel occupies two bits, so we
  857. need a 21-byte array (7 rows by 3 columns) to store the image. Since we want
  858. to make the arrow white, each pixel will be displayed in color 3 (11 binary).
  859. Here is the bitmap and its hexadecimal equivalent for the arrow image in mode
  860. 4 (the actual image is in boldface).
  861.  
  862.  
  863.          00 00 00 00   00 00 11 00   00 00 00 00         00   0C   00
  864.  
  865.          00 00 00 00   00 00 11 11   00 00 00 00         00   0F   00
  866.  
  867.          11 11 11 11   11 11 11 11   11 00 00 00         FF   FF   C0
  868.  
  869.          11 11 11 11   11 11 11 11   11 11 00 00         FF   FF   F0
  870.  
  871.          11 11 11 11   11 11 11 11   11 00 00 00         FF   FF   C0
  872.  
  873.          00 00 00 00   00 00 11 11   00 00 00 00         00   0F   00          
  874.                                            Chapter 10:  Bitmapped Images   227
  875.  
  876.  
  877.          00 00 00 00   00 00 11 00   00 00 00 00         00   0C   00
  878.  
  879.  
  880.      After establishing the video mode, the program fills the screen with
  881. color 1 pixels and defines a clipping region. It then uses fg_drwimage to
  882. display the arrow pointing to the right and fg_clpimage to do the same thing,
  883. but with respect to the clipping limits. Because the left edge of the arrow is
  884. displayed at x=10 and the right clipping limit is at x=15, the call to
  885. fg_clpimage only draws the first six columns of the arrow (that is, it does
  886. not draw the arrow head).
  887.  
  888.      Next, example 10-8 uses fg_revimage to display the arrow pointing to the
  889. left. To allow for the filler pixels, we must establish the graphics cursor
  890. position two pixels to the left of the position used by fg_drwimage if we want
  891. the tip of the left-pointing arrow to align with the tail of the right-
  892. pointing arrow. The program then uses fg_flpimage to display an arrow pointing
  893. to the left with regard to the clipping limits. The call to fg_flpimage
  894. displays the arrow head and the first two columns of the arrow shaft. Finally,
  895. the program uses fg_putimage to display the unclipped right-pointing arrow
  896. without transparent pixels (this produces a black border around the arrow).
  897.  
  898.                                  Example 10-8.
  899.  
  900.               #include <fastgraf.h>
  901.               #include <stdio.h>
  902.               #include <stdlib.h>
  903.               void main(void);
  904.  
  905.               char arrow[] = {
  906.                  0x00,0x0C,0x00, 0x00,0x0F,0x00, 0xFF,0xFF,0xC0,
  907.                  0xFF,0xFF,0xF0, 0xFF,0xFF,0xC0, 0x00,0x0F,0x00,
  908.                  0x00,0x0C,0x00
  909.                  };
  910.  
  911.               void main()
  912.               {
  913.                  int old_mode;
  914.  
  915.                  fg_initpm();
  916.                  if (fg_testmode(4,1) == 0) {
  917.                     printf("This program requires a 320 ");
  918.                     printf("x 200 CGA graphics mode.\n");
  919.                     exit(1);
  920.                     }
  921.  
  922.                  old_mode = fg_getmode();
  923.                  fg_setmode(4);
  924.                  fg_setcolor(1);
  925.                  fg_fillpage();
  926.                  fg_setclip(0,15,0,199);
  927.  
  928.                  fg_move(10,10);
  929.                  fg_drwimage(arrow,3,7);
  930.                  fg_move(10,20);
  931.                  fg_clpimage(arrow,3,7);                                       
  932. 228   Fastgraph User's Guide
  933.  
  934.                  fg_move(8,30);
  935.                  fg_revimage(arrow,3,7);
  936.                  fg_move(8,40);
  937.                  fg_flpimage(arrow,3,7);
  938.                  fg_move(8,50);
  939.                  fg_putimage(arrow,3,7);
  940.                  fg_waitkey();
  941.  
  942.                  fg_setmode(old_mode);
  943.                  fg_reset();
  944.               }
  945.  
  946.  
  947.      Example 10-9 is the same as example 10-8, but it uses the low resolution
  948. EGA graphics mode (mode 13). If we changed the mode number specified in the
  949. calls to fg_testmode and fg_setmode, the program also would run in any 16-
  950. color graphics mode. In these modes, we store two pixels per byte in the
  951. bitmap array, so we need a 35-byte array (7 rows by 5 columns) to store the
  952. image. Here is the bitmap's hexadecimal equivalent for the arrow image in mode
  953. 13, followed by the program to display it.
  954.  
  955.  
  956.                             00   00   00   F0   00
  957.  
  958.                             00   00   00   FF   00
  959.  
  960.                             FF   FF   FF   FF   F0
  961.  
  962.                             FF   FF   FF   FF   FF
  963.  
  964.                             FF   FF   FF   FF   F0
  965.  
  966.                             00   00   00   FF   00
  967.  
  968.                             00   00   00   F0   00
  969.  
  970.  
  971.                                  Example 10-9.
  972.  
  973.                  #include <fastgraf.h>
  974.                  #include <stdio.h>
  975.                  #include <stdlib.h>
  976.                  void main(void);
  977.  
  978.                  char arrow[] = {
  979.                     0x00,0x00,0x00,0xF0,0x00,
  980.                     0x00,0x00,0x00,0xFF,0x00,
  981.                     0xFF,0xFF,0xFF,0xFF,0xF0,
  982.                     0xFF,0xFF,0xFF,0xFF,0xFF,
  983.                     0xFF,0xFF,0xFF,0xFF,0xF0,
  984.                     0x00,0x00,0x00,0xFF,0x00,
  985.                     0x00,0x00,0x00,0xF0,0x00
  986.                     };
  987.  
  988.                  void main()
  989.                  {                                                             
  990.                                            Chapter 10:  Bitmapped Images   229
  991.  
  992.                     int old_mode;
  993.  
  994.                     fg_initpm();
  995.                     if (fg_testmode(13,1) == 0) {
  996.                        printf("This program requires a 320 ");
  997.                        printf("x 200 EGA graphics mode.\n");
  998.                        exit(1);
  999.                        }
  1000.  
  1001.                     old_mode = fg_getmode();
  1002.                     fg_setmode(13);
  1003.                     fg_setcolor(1);
  1004.                     fg_fillpage();
  1005.                     fg_setclip(0,15,0,199);
  1006.  
  1007.                     fg_move(10,10);
  1008.                     fg_drwimage(arrow,5,7);
  1009.                     fg_move(10,20);
  1010.                     fg_clpimage(arrow,5,7);
  1011.                     fg_move(8,30);
  1012.                     fg_revimage(arrow,5,7);
  1013.                     fg_move(8,40);
  1014.                     fg_flpimage(arrow,5,7);
  1015.                     fg_move(8,50);
  1016.                     fg_putimage(arrow,5,7);
  1017.                     fg_waitkey();
  1018.  
  1019.                     fg_setmode(old_mode);
  1020.                     fg_reset();
  1021.                  }
  1022.  
  1023.  
  1024.  
  1025. Retrieving Images
  1026.  
  1027.      Sometimes it's necessary to retrieve an image from video memory and store
  1028. it in one or more arrays as a bitmapped image. Fastgraph includes two
  1029. routines, fg_getmap and fg_getimage, for this purpose. The fg_getmap routine
  1030. retrieves pixels of the current color index and stores them in the mode-
  1031. independent bitmap format used by fg_drawmap. The fg_getimage routine
  1032. retrieves an image and stores it in the mode-specific bitmap format used by
  1033. fg_drwimage, fg_clpimage, fg_revimage, fg_flpimage, and fg_putimage. The
  1034. arguments to fg_getmap and fg_getimage are respectively analogous to those of
  1035. fg_drawmap and fg_drwimage: the first is an array (passed by reference) to
  1036. receive the bitmap, the second is the width of the bitmap in bytes, and the
  1037. last is the height of the bitmap in pixel rows. With either routine, the
  1038. graphics cursor position on the active video page defines the lower left
  1039. corner of the image to retrieve.
  1040.  
  1041.      If we want to use fg_getmap to retrieve an image containing more than one
  1042. color, we must call the routine once per color. In this case we'll usually
  1043. want to pass different bitmap arrays to fg_getmap (or perhaps different
  1044. offsets into the same array). This might seem unusual at first, but it
  1045. parallels the behavior of the fg_drawmap routine. That is, to display a
  1046. multicolor image using fg_drawmap, we must call it once for each color in the
  1047. image.                                                                         
  1048. 230   Fastgraph User's Guide
  1049.  
  1050.  
  1051.      Example 10-10 demonstrates a typical use of the fg_getmap routine. The
  1052. program displays the word "text" in the upper left corner of the screen using
  1053. a 320x200 graphics mode. It uses fg_getmap to retrieve the word as an image
  1054. and then displays it in a new position with the fg_drawmap routine. Let's look
  1055. at the program now, and afterward we'll more closely examine the screen
  1056. coordinates and the structure of the bitmap array.
  1057.  
  1058.                                 Example 10-10.
  1059.  
  1060.                  #include <fastgraf.h>
  1061.                  #include <stdio.h>
  1062.                  #include <stdlib.h>
  1063.                  void main(void);
  1064.  
  1065.                  void main()
  1066.                  {
  1067.                     char bitmap[32];
  1068.                     int old_mode, new_mode;
  1069.  
  1070.                     fg_initpm();
  1071.                     new_mode = fg_bestmode(320,200,1);
  1072.                     if (new_mode < 0 || new_mode == 12) {
  1073.                        printf("This program requires a 320 ");
  1074.                        printf("x 200 color graphics mode.\n");
  1075.                        exit(1);
  1076.                        }
  1077.  
  1078.                     old_mode = fg_getmode();
  1079.                     fg_setmode(new_mode);
  1080.  
  1081.                     fg_setcolor(9);
  1082.                     fg_text("text",4);
  1083.                     fg_waitkey();
  1084.  
  1085.                     fg_move(0,7);
  1086.                     fg_getmap(bitmap,4,8);
  1087.                     fg_move(4,15);
  1088.                     fg_drawmap(bitmap,4,8);
  1089.                     fg_waitkey();
  1090.  
  1091.                     fg_setmode(old_mode);
  1092.                     fg_reset();
  1093.                  }
  1094.  
  1095.  
  1096.      In all 320x200 graphics video modes, individual characters are 8 pixels
  1097. wide and 8 pixels high. This means the lower left corner of the (0,0)
  1098. character cell is referenced by the screen coordinates (0,7). Hence, these are
  1099. the coordinates of the first call to fg_move. The image retrieved in example
  1100. 10-10 is four characters long (32 pixels wide), so we need a bitmap array
  1101. capable of holding 8 rows of 32 pixels (4 bytes) each. Our bitmap array is
  1102. therefore a 32-byte array, logically structured to have 4 columns and 8 rows.
  1103. These values are the width and height arguments passed to fg_getmap and
  1104. fg_drawmap.                                                                    
  1105.                                            Chapter 10:  Bitmapped Images   231
  1106.  
  1107.      After it retrieves the image, example 10-10 displays it one line below
  1108. and one-half character cell (four pixels) to the right of its original
  1109. position. In other words, the program displays the image four pixels to the
  1110. right of the (1,0) character cell. The lower left corner of that cell is
  1111. referenced by the screen coordinates (0,15), so the image should appear at the
  1112. position (4,15). These are the coordinates of the second call to fg_move.
  1113.  
  1114.      Example 10-11 illustrates the use of fg_getmap and fg_drawmap to retrieve
  1115. and display a two-color image. This example is similar to example 10-10, but
  1116. this program first draws a rectangle in the upper left corner of the screen
  1117. and then displays the word "text" on top of the rectangle in a different
  1118. color. Each character in a 320x200 graphics video mode is 8 pixels wide and 8
  1119. pixels high, so the rectangle must be 32 pixels wide (4 characters times 8
  1120. pixels per character) and 8 pixels high. The image to retrieve will be the
  1121. same size as the rectangle.
  1122.  
  1123.      The image retrieved in example 10-10 required a 32-byte array, logically
  1124. structured to have 4 columns and 8 rows. Example 10-11 will retrieve an image
  1125. of the same structure, but the image contains two colors instead of just one.
  1126. This means we need two 32-byte arrays, one for each color, to hold the image.
  1127. We could instead use a single 64-byte array and pass an offset into that array
  1128. (specifically, &bitmap[32]) for processing the second color.
  1129.  
  1130.                                 Example 10-11.
  1131.  
  1132.                  #include <fastgraf.h>
  1133.                  #include <stdio.h>
  1134.                  #include <stdlib.h>
  1135.                  void main(void);
  1136.  
  1137.                  void main()
  1138.                  {
  1139.                     char bitmap1[32], bitmap2[32];
  1140.                     int old_mode, new_mode;
  1141.  
  1142.                     fg_initpm();
  1143.                     new_mode = fg_bestmode(320,200,1);
  1144.                     if (new_mode < 0 || new_mode == 12) {
  1145.                        printf("This program requires a 320 ");
  1146.                        printf("x 200 color graphics mode.\n");
  1147.                        exit(1);
  1148.                        }
  1149.  
  1150.                     old_mode = fg_getmode();
  1151.                     fg_setmode(new_mode);
  1152.  
  1153.                     fg_setcolor(7);
  1154.                     fg_rect(0,31,0,7);
  1155.                     fg_setcolor(9);
  1156.                     fg_text("text",4);
  1157.                     fg_waitkey();
  1158.  
  1159.                     fg_move(0,7);
  1160.                     fg_setcolor(7);
  1161.                     fg_getmap(bitmap1,4,8);
  1162.                     fg_setcolor(9);                                            
  1163. 232   Fastgraph User's Guide
  1164.  
  1165.                     fg_getmap(bitmap2,4,8);
  1166.  
  1167.                     fg_move(4,15);
  1168.                     fg_setcolor(7);
  1169.                     fg_drawmap(bitmap1,4,8);
  1170.                     fg_setcolor(9);
  1171.                     fg_drawmap(bitmap2,4,8);
  1172.                     fg_waitkey();
  1173.  
  1174.                     fg_setmode(old_mode);
  1175.                     fg_reset();
  1176.                  }
  1177.  
  1178.  
  1179.      Example 10-12 is similar to example 10-11, but it uses fg_getimage and
  1180. fg_drwimage instead of fg_getmap and fg_drawmap to retrieve and display the
  1181. image. That is, it uses the mode-specific rather than the mode-independent
  1182. image retrieval and display routines. When using the mode-specific routines,
  1183. the size of the bitmap needed to hold the image depends on the video mode. For
  1184. programs that run in only one video mode, bitmap widths are constant, but when
  1185. a program must run in several video modes, the width is variable. The
  1186. Fastgraph routine fg_imagesiz computes the number of bytes required to store a
  1187. mode-specific bitmapped image of specified dimensions. Its two integer
  1188. arguments specify the image width and height in pixels.
  1189.  
  1190.      The program computes the image width in bytes by passing a height of 1 to
  1191. fg_imagesiz. The size of the bitmap array in example 10-12 is 256 bytes, the
  1192. size required in 256-color graphics modes (32 bytes times 8 bytes). Other
  1193. video modes require less storage, so in these modes only a portion of the
  1194. bitmap array will actually be used. The image width is then used in the calls
  1195. to both fg_getimage and fg_drwimage.
  1196.  
  1197.                                 Example 10-12.
  1198.  
  1199.                  #include <fastgraf.h>
  1200.                  #include <stdio.h>
  1201.                  #include <stdlib.h>
  1202.                  void main(void);
  1203.  
  1204.                  void main()
  1205.                  {
  1206.                     char bitmap[256];
  1207.                     int old_mode, new_mode;
  1208.                     int width;
  1209.  
  1210.                     fg_initpm();
  1211.                     new_mode = fg_bestmode(320,200,1);
  1212.                     if (new_mode < 0 || new_mode == 12) {
  1213.                        printf("This program requires a 320 ");
  1214.                        printf("x 200 color graphics mode.\n");
  1215.                        exit(1);
  1216.                        }
  1217.  
  1218.                     old_mode = fg_getmode();
  1219.                     fg_setmode(new_mode);
  1220.                     width = (int)fg_imagesiz(32,1);                            
  1221.                                            Chapter 10:  Bitmapped Images   233
  1222.  
  1223.  
  1224.                     fg_setcolor(7);
  1225.                     fg_rect(0,31,0,7);
  1226.                     fg_setcolor(9);
  1227.                     fg_text("text",4);
  1228.                     fg_waitkey();
  1229.  
  1230.                     fg_move(0,7);
  1231.                     fg_getimage(bitmap,width,8);
  1232.                     fg_move(4,15);
  1233.                     fg_drwimage(bitmap,width,8);
  1234.                     fg_waitkey();
  1235.  
  1236.                     fg_setmode(old_mode);
  1237.                     fg_reset();
  1238.                  }
  1239.  
  1240.  
  1241. While this example used an array to store the image, it's usually preferable
  1242. to allocate dynamic memory for this purpose. We could have done this in
  1243. example 10-12 by calling fg_imagesiz with arguments of 32 (width) and 8
  1244. (height). The routine's return value would then tell us the number of bytes we
  1245. would need to allocate.
  1246.  
  1247.      We can also use fg_getimage to retrieve images in text video modes. In
  1248. text modes, however, there are a few differences we must consider when using
  1249. fg_getimage. First, the text cursor position, not the graphics cursor
  1250. position, specifies the lower left corner of the image. Hence, we must use
  1251. fg_locate instead of fg_move to define the image location. Second, the image
  1252. width is always twice the number of characters per image row (that is, for
  1253. each character we have a character byte and an attribute byte). The fg_getmap
  1254. routine has no effect when used in a text video mode.
  1255.  
  1256.      Example 10-13 shows a simple use of fg_getimage in text modes. This
  1257. program is similar to example 10-12, but it runs in an 80-column text mode
  1258. rather than a 320x200 graphics mode. As before, the program will retrieve the
  1259. four characters "text" as an image from the upper left corner of the screen
  1260. and then display it in a different location. Because the image consists of
  1261. four characters in one row, the image width is 8 bytes and the image height is
  1262. 1.
  1263.  
  1264.                                 Example 10-13.
  1265.  
  1266.                    #include <fastgraf.h>
  1267.                    #include <stdio.h>
  1268.                    #include <stdlib.h>
  1269.                    void main(void);
  1270.  
  1271.                    void main()
  1272.                    {
  1273.                       int old_mode;
  1274.                       char image[8];
  1275.  
  1276.                       fg_initpm();
  1277.                       old_mode = fg_getmode();                                 
  1278. 234   Fastgraph User's Guide
  1279.  
  1280.                       if (fg_testmode(3,1))
  1281.                          fg_setmode(3);
  1282.                       else if (fg_testmode(7,1))
  1283.                          fg_setmode(7);
  1284.                       else {
  1285.                          printf("This program requires\n");
  1286.                          printf("an 80-column display.\n");
  1287.                          exit(1);
  1288.                          }
  1289.                       fg_cursor(0);
  1290.  
  1291.                       fg_setattr(9,7,0);
  1292.                       fg_text("text",4);
  1293.                       fg_waitkey();
  1294.  
  1295.                       fg_locate(0,0);
  1296.                       fg_getimage(image,8,1);
  1297.                       fg_locate(1,1);
  1298.                       fg_drwimage(image,8,1);
  1299.                       fg_waitkey();
  1300.  
  1301.                       fg_setmode(old_mode);
  1302.                       fg_reset();
  1303.                    }
  1304.  
  1305.  
  1306.      Finally, here's a tip that's worth remembering. In the native EGA and VGA
  1307. graphics modes (13 to 18) and the 16-color SVGA graphics modes (28 and 29),
  1308. the routines for displaying and retrieving mode-specific bitmaps can be
  1309. anywhere from 10% to 20% faster if the current graphics x position is an even
  1310. number. This is because these routines must perform additional bitmap
  1311. alignment when displaying or retrieving images starting at odd-numbered
  1312. pixels.
  1313.  
  1314.  
  1315. Inverting Bitmaps
  1316.  
  1317.      Fastgraph's mode-independent and mode-specific bitmapped image display
  1318. routines expect images to be stored starting with the bottom row and
  1319. proceeding toward the top. This convention is often contrary to the "top to
  1320. bottom" row order used in other graphics libraries. The fg_invert routine
  1321. reverses the row order of bitmapped images, so a "top to bottom" image becomes
  1322. a "bottom to top" image, or vice versa. This will often make it easier to
  1323. import such images from other sources for use with Fastgraph's bitmapped image
  1324. display routines. Note that fg_invert does not change the orientation for
  1325. Fastgraph's bitmapped image display routines; it merely reverses the row order
  1326. of the image itself.
  1327.  
  1328.      The fg_invert routine requires three arguments. The first is the address
  1329. of the array containing the mode-independent or mode-specific bitmapped image
  1330. data. The resulting inverted image is stored in this same array. The second
  1331. and third arguments respectively specify the bitmap width and height in bytes.
  1332.  
  1333.      Example 10-14 is a modified version of example 10-6 that defines the
  1334. triangle's bitmap data starting with the top row and proceeding toward the
  1335. bottom. To display this image with Fastgraph's fg_drwimage routine, we must    
  1336.                                            Chapter 10:  Bitmapped Images   235
  1337.  
  1338. translate the bitmapped image to the "bottom to top" format. The program
  1339. performs this translation with fg_invert immediately after setting the video
  1340. mode (though it could be done anytime before calling fg_drwimage). Other than
  1341. the additional fg_invert call and the order of the bitmap data, example 10-14
  1342. is the same as example 10-6.
  1343.  
  1344.                                 Example 10-14.
  1345.  
  1346.                #include <fastgraf.h>
  1347.                #include <stdio.h>
  1348.                #include <stdlib.h>
  1349.                void main(void);
  1350.  
  1351.                char triangle[] = {
  1352.                   0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
  1353.                   0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
  1354.                   0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
  1355.                   0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
  1356.                   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01
  1357.                   };
  1358.  
  1359.                void main()
  1360.                {
  1361.                   int old_mode;
  1362.  
  1363.                   fg_initpm();
  1364.                   if (fg_testmode(19,1) == 0) {
  1365.                      printf("This program requires a 320 ");
  1366.                      printf("x 200 MCGA graphics mode.\n");
  1367.                      exit(1);
  1368.                      }
  1369.  
  1370.                   old_mode = fg_getmode();
  1371.                   fg_setmode(19);
  1372.                   fg_invert(triangle,9,5);
  1373.  
  1374.                   fg_setcolor(7);
  1375.                   fg_rect(0,319,0,199);
  1376.  
  1377.                   fg_move(156,101);
  1378.                   fg_drwimage(triangle,9,5);
  1379.                   fg_waitkey();
  1380.  
  1381.                   fg_setmode(old_mode);
  1382.                   fg_reset();
  1383.                }
  1384.  
  1385.  
  1386.      Note that fg_invert also can be used to create inverted versions of any
  1387. mode-independent or mode-specific bitmapped image. This means you can create
  1388. versions of bitmaps mirrored about the x-axis, somewhat analogous to the way
  1389. fg_revimage displays images mirrored about the y-axis.                         
  1390. 236   Fastgraph User's Guide
  1391.  
  1392.  
  1393. Converting Mode-Specific Bitmaps
  1394.  
  1395.      Earlier in this chapter we presented a bitmapped image format that was
  1396. independent of the video mode (such images are displayed with fg_drawmap or
  1397. fg_clipmap). While this format works well for images with one or two colors,
  1398. the performance can degrade significantly if the image contains many colors.
  1399. In this section we'll show how Fastgraph's "one pixel per byte" mode-specific
  1400. bitmap format used with 256-color graphics modes and virtual buffers can
  1401. provide an alternate way to use the same image data in multiple video modes.
  1402.  
  1403.      The basis of this scheme is to store all bitmaps in the "one pixel per
  1404. byte" format. When using 256-color graphics modes or virtual buffers, we
  1405. simply use the "one pixel per byte" bitmaps with the fg_drwimage family of
  1406. routines because the bitmaps are already in the expected format. However, when
  1407. using graphics modes with fewer colors, we must translate the bitmaps to a
  1408. suitable format for those modes. Fastgraph's fg_pack routine provides an easy
  1409. way to do this: it converts bitmapped images in the "one pixel per byte"
  1410. format to the mode-specific bitmap format for the current video mode. The
  1411. converted bitmaps can then be displayed with the fg_drwimage family.
  1412.  
  1413.      The fg_pack routine's first two arguments are the addresses of the source
  1414. and destination bitmap arrays. The source array contains the "one pixel per
  1415. byte" bitmapped image, and the destination array will receive the converted
  1416. mode-specific image (it's important to make sure the destination array is
  1417. large enough to hold the converted image). The last two fg_pack arguments
  1418. specify the width and height in pixels of the source bitmap. In 256-color
  1419. graphics modes, or when a virtual buffer is active, fg_pack merely copies the
  1420. source array contents to the destination array.
  1421.  
  1422.      Example 10-15 shows how you can use the same bitmap data in 256-color and
  1423. 16-color graphics modes. We define our familiar triangle bitmap in the 256-
  1424. color mode-specific format, as in example 10-6. The program first displays the
  1425. triangle bitmap in the standard VGA/MCGA 320x200 256-color graphics mode (mode
  1426. 19) against a gray background. After a keystroke, the program switches to the
  1427. EGA/VGA 320x200 16-color graphics mode (mode 13). In this mode, fg_drwimage
  1428. expects two pixels per bitmap byte, so we must call fg_pack to convert the
  1429. bitmap data to this format. We store the resulting bitmap in the triangle16
  1430. array and again use fg_drwimage to display the triangle bitmap.
  1431.  
  1432.                                 Example 10-15.
  1433.  
  1434.                #include <fastgraf.h>
  1435.                void main(void);
  1436.  
  1437.                char triangle[] = {
  1438.                   0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
  1439.                   0x00,0x01,0x02,0x02,0x02,0x02,0x02,0x01,0x00,
  1440.                   0x00,0x00,0x01,0x02,0x02,0x02,0x01,0x00,0x00,
  1441.                   0x00,0x00,0x00,0x01,0x02,0x01,0x00,0x00,0x00,
  1442.                   0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00
  1443.                   };
  1444.                char triangle16[25];
  1445.  
  1446.                void main()
  1447.                {                                                               
  1448.                                            Chapter 10:  Bitmapped Images   237
  1449.  
  1450.                   int old_mode;
  1451.  
  1452.                   fg_initpm();
  1453.                   old_mode = fg_getmode();
  1454.  
  1455.                   fg_setmode(19);
  1456.                   fg_setcolor(7);
  1457.                   fg_fillpage();
  1458.                   fg_move(156,101);
  1459.                   fg_drwimage(triangle,9,5);
  1460.                   fg_waitkey();
  1461.  
  1462.                   fg_setmode(13);
  1463.                   fg_setcolor(7);
  1464.                   fg_fillpage();
  1465.                   fg_pack(triangle,triangle16,9,5);
  1466.                   fg_move(156,101);
  1467.                   fg_drwimage(triangle16,5,5);
  1468.                   fg_waitkey();
  1469.  
  1470.                   fg_setmode(old_mode);
  1471.                   fg_reset();
  1472.                }
  1473.  
  1474.  
  1475. Note that the 256-color bitmap is nine bytes wide and five bytes tall. When we
  1476. convert the image to the 16-color mode-specific format, the bitmap width is
  1477. reduced to five bytes because two pixels are packed into each byte. The second
  1478. pixel in the last byte of each row becomes a transparent filler pixel (that
  1479. is, its value is zero).
  1480.  
  1481.      As you might guess, Fastgraph's fg_unpack routine performs the opposite
  1482. function of fg_pack. That is, it converts a bitmap from the mode-specific
  1483. format of the current video mode to the "one pixel per byte" format. The
  1484. fg_unpack routine is intended as a helper function for displaying mode-
  1485. specific images in virtual buffers when using video modes with fewer than 256
  1486. colors. When a virtual buffer is active, fg_drwimage always expects the bitmap
  1487. to be in the "one pixel per byte" format, regardless of the current video
  1488. mode. The fg_unpack routine makes it easy to convert images to this format
  1489. before displaying them in a virtual buffer.
  1490.  
  1491.      The fg_unpack routine's first two arguments are the addresses of the
  1492. source and destination bitmap arrays. The source array contains the mode-
  1493. specific bitmapped image, and the destination array will receive the converted
  1494. "one pixel per byte" image. The last fg_unpack argument specifies the size of
  1495. the source array in bytes. Like fg_pack, fg_unpack merely copies the source
  1496. array contents to the destination array in 256-color graphics modes or when a
  1497. virtual buffer is active.
  1498.  
  1499.      Example 10-16 illustrates how to use fg_unpack to convert mode-specific
  1500. bitmaps to the virtual buffer format. The program uses the 10-pixel by 7-pixel
  1501. arrow bitmap of example 10-9 and runs in the EGA/VGA 320x200 16-color graphics
  1502. mode (mode 13). In this mode, two pixels are packed into each bitmap byte, so
  1503. the size of the bitmap array is 5x7, or 35 bytes. The call to fg_unpack
  1504. converts the mode-specific image in the 35-byte arrow array into a "one pixel
  1505. per byte" format image, storing the result in the 70-byte arrow256 array.      
  1506. 238   Fastgraph User's Guide
  1507.  
  1508. We'll create a 70-byte virtual buffer -- just large enough to hold the 10x7
  1509. arrow bitmap -- and display the arrow256 bitmap in it against a light blue
  1510. (color 9) background. Finally, we'll use fg_vbpaste to display the virtual
  1511. buffer contents in the middle of the screen.
  1512.  
  1513.                                 Example 10-16.
  1514.  
  1515.                  #include <fastgraf.h>
  1516.                  #include <stdio.h>
  1517.                  #include <stdlib.h>
  1518.                  void main(void);
  1519.  
  1520.                  char arrow[] = {
  1521.                     0x00,0x00,0x00,0xF0,0x00,
  1522.                     0x00,0x00,0x00,0xFF,0x00,
  1523.                     0xFF,0xFF,0xFF,0xFF,0xF0,
  1524.                     0xFF,0xFF,0xFF,0xFF,0xFF,
  1525.                     0xFF,0xFF,0xFF,0xFF,0xF0,
  1526.                     0x00,0x00,0x00,0xFF,0x00,
  1527.                     0x00,0x00,0x00,0xF0,0x00
  1528.                     };
  1529.                  char arrow256[70];
  1530.  
  1531.                  #ifdef FG32
  1532.                  char buffer[70];
  1533.                  #else
  1534.                  char far buffer[70];
  1535.                  #endif
  1536.  
  1537.                  void main()
  1538.                  {
  1539.                     int handle;
  1540.                     int old_mode;
  1541.  
  1542.                     fg_initpm();
  1543.                     if (fg_testmode(13,1) == 0) {
  1544.                        printf("This program requires a 320 ");
  1545.                        printf("x 200 EGA graphics mode.\n");
  1546.                        exit(1);
  1547.                        }
  1548.  
  1549.                     old_mode = fg_getmode();
  1550.                     fg_setmode(13);
  1551.                     fg_unpack(arrow,arrow256,35);
  1552.  
  1553.                     fg_vbinit();
  1554.                     handle = fg_vbdefine(buffer,10,7);
  1555.                     fg_vbopen(handle);
  1556.                     fg_setcolor(9);
  1557.                     fg_fillpage();
  1558.                     fg_move(0,6);
  1559.                     fg_drwimage(arrow256,10,7);
  1560.  
  1561.                     fg_vbpaste(0,9,0,6,156,101);
  1562.                     fg_waitkey();                                              
  1563.                                            Chapter 10:  Bitmapped Images   239
  1564.  
  1565.                     fg_vbclose();
  1566.                     fg_setmode(old_mode);
  1567.                     fg_reset();
  1568.                  }
  1569.  
  1570.  
  1571.  
  1572. Bitmap Scaling and Shearing
  1573.  
  1574.      Fastgraph's fg_scale routine performs horizontal and vertical scaling of
  1575. bitmapped images. It expects a source bitmap stored in the "one pixel per
  1576. byte" format of Fastgraph's 256-color modes, and it returns an expanded or
  1577. reduced bitmap in the same format. To scale images in graphics modes with
  1578. fewer than 256 colors, you must first use fg_unpack to convert the bitmap to
  1579. the format expected by fg_scale, perform the scaling, and finally use fg_pack
  1580. to convert the scaled image back to the mode-specific format. Because
  1581. Fastgraph's virtual buffers also use the one pixel per byte format, you can
  1582. also use fg_scale to scale images stored in virtual buffers.
  1583.  
  1584.      The fg_scale routine has six arguments. The first two specify the
  1585. addresses of the source and destination bitmap arrays. The source array
  1586. contains the original (unscaled) bitmapped image; the destination array will
  1587. receive the expanded or reduced (scaled) bitmap. Both bitmaps are stored in
  1588. the "one pixel per byte" format. The third and fourth arguments specify the
  1589. width and height in pixels of the unscaled image, while the fifth and sixth
  1590. arguments do the same for the resulting scaled image.
  1591.  
  1592.      Example 10-17 shows how to expand and reduce bitmapped images with
  1593. fg_scale. The program displays a 64x40 light blue rectangle with a white
  1594. border and the word SCALE centered inside it, in the upper left corner of the
  1595. screen. It retrieves the rectangle contents as a mode-specific bitmap using
  1596. fg_getimage. The first fg_scale call increases the size of this bitmap by 10
  1597. pixels in both directions, meaning the 64x40 image becomes a 74x50 image. The
  1598. program then displays the expanded bitmap in the lower left corner of the
  1599. screen using fg_putimage. The second fg_scale call reduces the original bitmap
  1600. by a factor of two to create a 32x20 bitmap. The reduced bitmap is then
  1601. displayed in the lower right corner, again using fg_putimage. Note that
  1602. example 10-17 runs in mode 19, which is a 256-color graphics mode, so
  1603. fg_getimage automatically stores the original bitmap in the "one pixel per
  1604. byte" format expected by fg_scale.
  1605.  
  1606.                                 Example 10-17.
  1607.  
  1608.        #include <fastgraf.h>
  1609.        void main(void);
  1610.  
  1611.        char source[64*40], dest[74*50];
  1612.  
  1613.        void main()
  1614.        {
  1615.           /* initialize the video environment */
  1616.  
  1617.           fg_initpm();
  1618.           fg_setmode(19);
  1619.  
  1620.           /* draw a blue rectangle with a thick white border */                
  1621. 240   Fastgraph User's Guide
  1622.  
  1623.  
  1624.           fg_setcolor(9);
  1625.           fg_rect(0,63,0,39);
  1626.           fg_setcolor(15);
  1627.           fg_boxdepth(5,5);
  1628.           fg_box(0,63,0,39);
  1629.           fg_move(32,20);
  1630.           fg_justify(0,0);
  1631.           fg_print("SCALE",5);
  1632.  
  1633.           /* retrieve the rectangle as a mode-specific bitmap */
  1634.  
  1635.           fg_move(0,39);
  1636.           fg_getimage(source,64,40);
  1637.           fg_waitkey();
  1638.  
  1639.           /* expand the bitmap by 10 pixels in each direction and   */
  1640.           /* then display it in the lower left corner of the screen */
  1641.  
  1642.           fg_move(0,199);
  1643.           fg_scale(source,dest,64,40,74,50);
  1644.           fg_putimage(dest,74,50);
  1645.           fg_waitkey();
  1646.  
  1647.           /* reduce the original bitmap by 50% in each direction and */
  1648.           /* then display it in the lower right corner of the screen */
  1649.  
  1650.           fg_move(288,199);
  1651.           fg_scale(source,dest,64,40,32,20);
  1652.           fg_putimage(dest,32,20);
  1653.           fg_waitkey();
  1654.  
  1655.           /* restore 80x25 text mode and exit */
  1656.  
  1657.           fg_setmode(3);
  1658.           fg_reset();
  1659.        }
  1660.  
  1661.  
  1662.      Shearing can be thought of as anchoring one corner of a rectangular
  1663. region and stretching the opposite corner horizontally or vertically. For
  1664. example, bitmaps containing text or other characters could be sheared
  1665. horizontally to the right for an italic effect. A sheared image will always be
  1666. larger than the original image, and it will contain empty triangular areas at
  1667. its corners. The empty areas will be filled with color 0 pixels, meaning they
  1668. will be transparent when you display a sheared image with the fg_drwimage
  1669. family of routines. Like fg_scale, fg_shear expects bitmaps in the "one pixel
  1670. per byte" format and can likewise be used with images stored in virtual
  1671. buffers.
  1672.  
  1673.      The fg_shear routine has six arguments. The first two specify the
  1674. addresses of the source and destination bitmap arrays. The source array
  1675. contains the original bitmapped image; the destination array will receive the
  1676. sheared bitmap. Both bitmaps are stored in the "one pixel per byte" format.
  1677. The third and fourth arguments specify the width and height in pixels of the
  1678. original image. For horizontal shears, the fifth argument specifies the        
  1679.                                            Chapter 10:  Bitmapped Images   241
  1680.  
  1681. resulting width in pixels of the sheared bitmap. For vertical shears, it
  1682. specifies the resulting height.
  1683.  
  1684.      The final fg_shear argument defines the shear type. Four distinct shear
  1685. types are available:
  1686.  
  1687.      * horizontal left shear (region's bottom edge is stretched to the right)
  1688.      * horizontal right shear (region's top edge is stretched to the right)
  1689.      * vertical left shear (region's left edge is stretched up)
  1690.      * vertical right shear (region's right edge is stretched up)
  1691.  
  1692. The type is selected by a value between 0 and 3, respectively corresponding to
  1693. the above four shear types. For example, shear type 2 represents a vertical
  1694. left shear.
  1695.  
  1696.      Example 10-18 displays a 64x40 light blue rectangle with a white border
  1697. and the word SHEAR centered inside it, in the upper left corner of the screen.
  1698. It retrieves the rectangle contents as a mode-specific bitmap using
  1699. fg_getimage. The program then calls fg_shear to perform a 16-pixel horizontal
  1700. right shear, which stretches the image's top edge 16 pixels to the right. This
  1701. produces an 80x40 bitmap, which is then displayed in the lower left corner of
  1702. the screen with fg_putimage. Because this example runs in mode 19, which is a
  1703. 256-color graphics mode, fg_getimage automatically stores the original bitmap
  1704. in the "one pixel per byte" format expected by fg_shear.
  1705.  
  1706.                                 Example 10-18.
  1707.  
  1708.        #include <fastgraf.h>
  1709.        void main(void);
  1710.  
  1711.        char source[64*40], dest[80*40];
  1712.  
  1713.        void main()
  1714.        {
  1715.           /* initialize the video environment */
  1716.  
  1717.           fg_initpm();
  1718.           fg_setmode(19);
  1719.  
  1720.           /* draw a blue rectangle with a thick white border */
  1721.  
  1722.           fg_setcolor(9);
  1723.           fg_rect(0,63,0,39);
  1724.           fg_setcolor(15);
  1725.           fg_boxdepth(5,5);
  1726.           fg_box(0,63,0,39);
  1727.           fg_move(32,20);
  1728.           fg_justify(0,0);
  1729.           fg_print("SHEAR",5);
  1730.  
  1731.           /* retrieve the rectangle as a mode-specific bitmap */
  1732.  
  1733.           fg_move(0,39);
  1734.           fg_getimage(source,64,40);
  1735.           fg_waitkey();                                                        
  1736. 242   Fastgraph User's Guide
  1737.  
  1738.           /* shear the bitmap horizontally and to the right 16 pixels */
  1739.           /* then display it in the lower left corner of the screen   */
  1740.  
  1741.           fg_move(0,199);
  1742.           fg_shear(source,dest,64,40,80,1);
  1743.           fg_putimage(dest,80,40);
  1744.           fg_waitkey();
  1745.  
  1746.           /* restore 80x25 text mode and exit */
  1747.  
  1748.           fg_setmode(3);
  1749.           fg_reset();
  1750.        }
  1751.  
  1752.  
  1753.      It's possible to use fg_shear for rudimentary bitmap rotation. Shearing
  1754. an image horizontally left and then vertically right by the same amount will
  1755. rotate an image counterclockwise. Similarly, shearing horizontally right and
  1756. then vertically left will rotate it clockwise.
  1757.  
  1758.      Virtual buffers use the same "one pixel per byte" format expected by
  1759. fg_scale and fg_shear. This means you can pass virtual buffer addresses to
  1760. these functions and apply scaling and shearing operations on virtual buffers.
  1761. Note, however that 16-bit modes limit the size of arrays passed to fg_scale
  1762. and fg_shear to 64K bytes, meaning you cannot apply these functions to larger
  1763. virtual buffers. Further, the address of a real mode virtual buffer is a
  1764. segment:offset pair, so you must use the large memory model to scale or shear
  1765. images residing in virtual buffers in real mode programs.
  1766.  
  1767.      Example 10-19 demonstrates how to scale the contents of a virtual buffer.
  1768. The program creates two virtual buffers -- one is 320x200 pixels and the other
  1769. is one-fourth this size, or 80x50 pixels. The CORAL.PCX image is loaded into
  1770. the 320x200 virtual buffer using the fg_loadpcx routine and then copied to the
  1771. visual page. The program then calls fg_scale, passing it the two virtual
  1772. buffer handles, to reduce the image to one-fourth its original size. The
  1773. resulting image is stored in the 80x50 virtual buffer and finally copied to
  1774. the lower left corner of the visual page.
  1775.  
  1776.                                 Example 10-19.
  1777.  
  1778.            #include <fastgraf.h>
  1779.            #include <stdio.h>
  1780.            #include <stdlib.h>
  1781.            #if defined(__TURBOC__)
  1782.            #include <alloc.h>
  1783.            #else
  1784.            #include <malloc.h>
  1785.            #endif
  1786.            void main(void);
  1787.  
  1788.            void main()
  1789.            {
  1790.               int handle1, handle2;
  1791.            #if defined(__WATCOMC__) || defined(__HIGHC__)
  1792.               char *buffer1, *buffer2;
  1793.            #else                                                               
  1794.                                            Chapter 10:  Bitmapped Images   243
  1795.  
  1796.               char far *buffer1, far *buffer2;
  1797.            #endif
  1798.  
  1799.               fg_initpm();
  1800.               fg_setmode(19);
  1801.               fg_vbinit();
  1802.  
  1803.            #if defined(__WATCOMC__) || defined(__HIGHC__)
  1804.               buffer1 = (char *)malloc(320*200);
  1805.               buffer2 = (char *)malloc(80*50);
  1806.            #elif defined(__TURBOC__)
  1807.               buffer1 = (char far *)farmalloc(320L*200L);
  1808.               buffer2 = (char far *)farmalloc(80L*50L);
  1809.            #else
  1810.               buffer1 = (char far *)halloc(320L*200L,1);
  1811.               buffer2 = (char far *)halloc(80L*50L,1);
  1812.            #endif
  1813.               if (buffer1 == NULL || buffer2 == NULL)
  1814.               {
  1815.                  fg_setmode(3);
  1816.                  fg_reset();
  1817.                  printf("Could not create the virtual buffers.\n");
  1818.                  exit(1);
  1819.               }
  1820.               handle1 = fg_vbdefine(buffer1,320,200);
  1821.               handle2 = fg_vbdefine(buffer2,80,50);
  1822.  
  1823.               fg_vbopen(handle1);
  1824.               fg_loadpcx("CORAL.PCX",0);
  1825.               fg_vbpaste(0,319,0,199,0,199);
  1826.               fg_waitkey();
  1827.  
  1828.               fg_scale(buffer1,buffer2,320,200,80,50);
  1829.               fg_vbopen(handle2);
  1830.               fg_vbpaste(0,79,0,49,0,199);
  1831.               fg_waitkey();
  1832.  
  1833.               fg_vbclose();
  1834.               fg_setmode(3);
  1835.               fg_reset();
  1836.            }
  1837.  
  1838.  
  1839.      In example 10-19, we created the virtual buffers with fg_vbdefine, so we
  1840. knew their addresses. What if we were using BASIC or real mode Pascal and
  1841. created them with fg_vballoc? In this case the virtual buffer addresses
  1842. wouldn't be immediately available to the program. Fortunately, there is an
  1843. easy solution. Fastgraph's fg_vbaddr function returns the address of the
  1844. specified virtual buffer; its only argument is the virtual buffer handle. In
  1845. 16-bit modes, the address will be a real mode segment:offset pair or protected
  1846. mode selector:offset pair. In 32-bit modes, it will be an offset into the
  1847. default data segment. If you were using fg_vballoc in example 10-19, the
  1848. virtual buffer creation and address retrieval could be done as follows:
  1849.  
  1850.      char far *buffer1, far *buffer2;                                          
  1851. 244   Fastgraph User's Guide
  1852.  
  1853.      handle1 = fg_vballoc(320,200);
  1854.      handle2 = fg_vballoc(80,50);
  1855.      if (handle1 < 0 || handle2 < 0) {
  1856.         fg_setmode(3);
  1857.         fg_reset();
  1858.         printf("Could not create the virtual buffers.\n");
  1859.         exit(1);
  1860.         }
  1861.      buffer1 = (char far *)fg_vbaddr(handle1);
  1862.      buffer2 = (char far *)fg_vbaddr(handle2);
  1863.  
  1864. The statements to release the memory allocated to the virtual buffers would
  1865. be:
  1866.  
  1867.      fg_vbclose();
  1868.      fg_vbfree(handle1);
  1869.      fg_vbfree(handle2);
  1870.  
  1871.  
  1872. Pixel Run Maps
  1873.  
  1874.      The bitmaps used with the fg_drawmap, fg_drwimage, and related routines
  1875. can consume array space quite rapidly. This is especially true if the image is
  1876. large or contains many colors. For example, a mode-independent bitmapped image
  1877. that occupies the entire screen in a 320x200 graphics mode requires 8,000
  1878. bytes of space per color. Fastgraph provides another mode-independent image
  1879. format called pixel run maps, which are more efficient in terms of space.
  1880. Pixel run maps are structured just like the pixel run files introduced in the
  1881. previous chapter, but the image resides in an array instead of a file.
  1882.  
  1883.      Let's return to our familiar triangle example and show how we could use a
  1884. pixel run map to display it.
  1885.  
  1886.                                . . . . * . . . .
  1887.                                . . . * x * . . .
  1888.                                . . * x x x * . .
  1889.                                . * x x x x x * .
  1890.                                * * * * * * * * *
  1891.  
  1892. As before, the pixels indicated by an asterisk (*) are the triangle's
  1893. perimeter, while those indicated by an x represent its interior points. The
  1894. pixels shown as periods (.) are not part of the triangle itself, but they are
  1895. part of the pixel run map.
  1896.  
  1897.      Using the standard pixel run format introduced in the previous chapter,
  1898. we see it takes 16 pixel runs to store our triangle image as a pixel run map.
  1899. If we want to display the perimeter pixels in color 1, the interior pixels in
  1900. color 2, and the filler area in color 7, the pixel run map would contain 16
  1901. sets of (color,count) pairs: (1,9), (7,1), (1,1), (2,5), (1,1), (7,3), (1,1),
  1902. (2,3), (1,1), (7,5), (1,1), (2,1), (1,1), (7,7), (1,1), and (7,4). Unlike the
  1903. bitmapped image formats already discussed, pixel run maps have no provision
  1904. for transparent colors.
  1905.  
  1906.      The Fastgraph routine fg_display displays an image stored as a pixel run
  1907. map. The fg_display routine expects three arguments. The first is an array
  1908. containing the pixel runs (passed by reference), the second is the number of   
  1909.                                            Chapter 10:  Bitmapped Images   245
  1910.  
  1911. pixel runs in the array, and the third is the width in pixels of the image. As
  1912. with the other image display routines, fg_display displays the image such that
  1913. its lower left corner is at the graphics cursor position on the active video
  1914. page or virtual buffer. Again, the format of the pixel run map is the same as
  1915. that of a standard pixel run file. In addition, any display patterns defined
  1916. by fg_pattern also apply to fg_display.
  1917.  
  1918.      Example 10-20 uses the fg_display routine to display the triangle as a
  1919. pixel run map in a 320x200 graphics mode. The program displays the triangle
  1920. against a background of color 7, so the selection of color 7 for the filler
  1921. area was important. If some other color were chosen, the filler area would not
  1922. blend in with the background.
  1923.  
  1924.                                 Example 10-20.
  1925.  
  1926.                  #include <fastgraf.h>
  1927.                  #include <stdio.h>
  1928.                  #include <stdlib.h>
  1929.                  void main(void);
  1930.  
  1931.                  char triangle[] = {
  1932.                     1,9, 7,1, 1,1, 2,5, 1,1, 7,3, 1,1, 2,3,
  1933.                     1,1, 7,5, 1,1, 2,1, 1,1, 7,7, 1,1, 7,4
  1934.                     };
  1935.  
  1936.                  void main()
  1937.                  {
  1938.                     int old_mode, new_mode;
  1939.  
  1940.                     fg_initpm();
  1941.                     new_mode = fg_bestmode(320,200,1);
  1942.                     if (new_mode < 0 || new_mode == 12) {
  1943.                        printf("This program requires a 320 ");
  1944.                        printf("x 200 color graphics mode.\n");
  1945.                        exit(1);
  1946.                        }
  1947.  
  1948.                     old_mode = fg_getmode();
  1949.                     fg_setmode(new_mode);
  1950.  
  1951.                     fg_setcolor(7);
  1952.                     fg_rect(0,319,0,199);
  1953.  
  1954.                     fg_move(156,101);
  1955.                     fg_display(triangle,16,9);
  1956.                     fg_waitkey();
  1957.  
  1958.                     fg_setmode(old_mode);
  1959.                     fg_reset();
  1960.                  }
  1961.  
  1962.  
  1963.      As you might guess, Fastgraph also offers a packed pixel run map image
  1964. format analogous to the packed pixel run file format introduced in the
  1965. previous chapter. Example 10-21 is the same as example 10-20, but it uses
  1966. fg_displayp rather than fg_display to display the image. Note the use of       
  1967. 246   Fastgraph User's Guide
  1968.  
  1969. hexadecimal numbers for defining the packed color values, which of course is
  1970. not necessary but certainly easier to read than expressing the quantities as
  1971. decimal numbers. As with fg_display, any display patterns defined by
  1972. fg_pattern also apply to fg_displayp.
  1973.  
  1974.                                 Example 10-21.
  1975.  
  1976.                  #include <fastgraf.h>
  1977.                  #include <stdio.h>
  1978.                  #include <stdlib.h>
  1979.                  void main(void);
  1980.  
  1981.                  char triangle[] = {
  1982.                     0x17,9,1, 0x12,1,5, 0x17,1,3, 0x12,1,3,
  1983.                     0x17,1,5, 0x12,1,1, 0x17,1,7, 0x17,1,4
  1984.                     };
  1985.  
  1986.                  void main()
  1987.                  {
  1988.                     int old_mode, new_mode;
  1989.  
  1990.                     fg_initpm();
  1991.                     new_mode = fg_bestmode(320,200,1);
  1992.                     if (new_mode < 0 || new_mode == 12) {
  1993.                        printf("This program requires a 320 ");
  1994.                        printf("x 200 color graphics mode.\n");
  1995.                        exit(1);
  1996.                        }
  1997.  
  1998.                     old_mode = fg_getmode();
  1999.                     fg_setmode(new_mode);
  2000.  
  2001.                     fg_setcolor(7);
  2002.                     fg_rect(0,319,0,199);
  2003.  
  2004.                     fg_move(156,101);
  2005.                     fg_displayp(triangle,16,9);
  2006.                     fg_waitkey();
  2007.  
  2008.                     fg_setmode(old_mode);
  2009.                     fg_reset();
  2010.                  }
  2011.  
  2012.  
  2013.      Both fg_display and fg_displayp require the pixel run image to be stored
  2014. in an array. In examples 10-20 and 10-21, the image is defined within the
  2015. program itself. We can also use these routines in place of fg_dispfile when
  2016. the image is stored in a file if we first read the file contents into an
  2017. array. Example 10-22 demonstrates this procedure. The program displays two
  2018. identical images stored in files, one in standard pixel run format and the
  2019. other in packed pixel run format.
  2020.  
  2021.      The first image, in standard pixel run format, is in the file CORAL.SPR.
  2022. Note the program must open the file for reading in binary mode ("rb" in the
  2023. call to fopen). The program reads the file's entire contents into the
  2024. pixel_runs array, whose size must be at least as large as the file size.       
  2025.                                            Chapter 10:  Bitmapped Images   247
  2026.  
  2027. Because the image is stored in standard pixel run format, the number of pixel
  2028. runs is one-half the file size. The program then uses fg_move to establish the
  2029. lower left corner of the screen as the graphics cursor position and then calls
  2030. fg_display to display the image. The image fills the entire screen, so its
  2031. width is 320 pixels.
  2032.  
  2033.      After waiting for a keystroke, the program similarly displays the second
  2034. image. This image is in the file CORAL.PPR and is stored in packed pixel run
  2035. format. Because the image is packed, the number of pixel runs is two-thirds
  2036. the file size. The program then clears the previous image from the screen and
  2037. calls fg_displayp to display the image. After another keystroke, the program
  2038. restores the original video mode and screen attributes and returns to DOS.
  2039.  
  2040.                                 Example 10-22.
  2041.  
  2042.               #include <fastgraf.h>
  2043.               #include <io.h>
  2044.               #include <stdio.h>
  2045.               #include <stdlib.h>
  2046.               void main(void);
  2047.  
  2048.               char pixel_runs[20000];
  2049.  
  2050.               void main()
  2051.               {
  2052.                  FILE *stream;
  2053.                  int file_size, run_count;
  2054.                  int old_mode, new_mode;
  2055.  
  2056.                  fg_initpm();
  2057.                  new_mode = fg_bestmode(320,200,1);
  2058.                  if (new_mode < 0 || new_mode == 12) {
  2059.                     printf("This program requires a 320 ");
  2060.                     printf("x 200 color graphics mode.\n");
  2061.                     exit(1);
  2062.                     }
  2063.  
  2064.                  old_mode = fg_getmode();
  2065.                  fg_setmode(new_mode);
  2066.  
  2067.                  stream = fopen("CORAL.SPR","rb");
  2068.                  file_size = (int)(filelength(fileno(stream)));
  2069.                  fread(pixel_runs,sizeof(char),file_size,stream);
  2070.                  fclose(stream);
  2071.                  run_count = file_size / 2;
  2072.                  fg_move(0,199);
  2073.                  fg_display(pixel_runs,run_count,320);
  2074.                  fg_waitkey();
  2075.  
  2076.                  stream = fopen("CORAL.PPR","rb");
  2077.                  file_size = (int)(filelength(fileno(stream)));
  2078.                  fread(pixel_runs,sizeof(char),file_size,stream);
  2079.                  fclose(stream);
  2080.                  run_count = file_size / 3 * 2;
  2081.                  fg_erase();
  2082.                  fg_displayp(pixel_runs,run_count,320);                        
  2083. 248   Fastgraph User's Guide
  2084.  
  2085.                  fg_waitkey();
  2086.  
  2087.                  fg_setmode(old_mode);
  2088.                  fg_reset();
  2089.               }
  2090.  
  2091.  
  2092.  
  2093. Masking Maps
  2094.  
  2095.      It is not possible to include color 0 pixels in an image displayed with
  2096. fg_drwimage, fg_clpimage, fg_revimage, or fg_flpimage. This is because these
  2097. routines consider color 0 pixels to be transparent, which means such pixels do
  2098. not affect the corresponding pixels in video memory. There are times, however,
  2099. when you will want color 0 pixels to be destructive, or replace the video
  2100. memory contents.
  2101.  
  2102.      Consider again the arrow image of example 10-8. In that example, we
  2103. displayed a white (color 3) arrow against a black (color 0) background in the
  2104. standard CGA four-color graphics mode. Suppose, though, that we want to do
  2105. just the opposite -- display a black (color 0) arrow against a white (color 3)
  2106. background. We could of course use fg_putimage, fg_drawmap, or one of the
  2107. routines for displaying pixel run maps, but these methods do not support
  2108. clipping or reversing an image. There are, however, four Fastgraph routines
  2109. designed just for this purpose. These routines are fg_drawmask, fg_clipmask,
  2110. fg_revmask, and fg_flipmask.
  2111.  
  2112.      Each of these routines uses a data structure called a masking map. A
  2113. masking map is similar in structure to a pixel run map, but it does not
  2114. include any information about colors. Instead, it consists of a series of
  2115. pixel runs that alternate between protected and unprotected pixels. An example
  2116. might best clarify this.
  2117.  
  2118.      Once again, here is the arrow image of example 10-8.
  2119.  
  2120.                               . . . . . . * . . .
  2121.                               . . . . . . * * . .
  2122.                               * * * * * * * * * .
  2123.                               * * * * * * * * * *
  2124.                               * * * * * * * * * .
  2125.                               . . . . . . * * . .
  2126.                               . . . . . . * . . .
  2127.  
  2128. This time, though, we want the arrow to appear in color 0. Put another way, we
  2129. need the "period" pixels (.) to protect video memory, while we want the
  2130. "asterisk" pixels (*) to zero video memory. Looking at this problem from the
  2131. perspective of a pixel run map, we have an alternating series of "protect" and
  2132. "zero" runs. We don't need any information about pixel colors, just whether to
  2133. protect or to zero video memory.
  2134.  
  2135.      This is precisely the structure of a masking map. Starting from the lower
  2136. left corner of the image and proceeding to the right, wrapping up to the next
  2137. row when needed, we could represent this image as a masking map with 6
  2138. protected pixels, 1 zeroed pixel, 9 protected pixels, 2 zeroed pixels, and so
  2139. on. In general, the structure of a masking map is as follows.                  
  2140.                                            Chapter 10:  Bitmapped Images   249
  2141.  
  2142.  
  2143.                        [1]   length of 1st protect run
  2144.  
  2145.                        [2]   length of 1st  zero   run
  2146.  
  2147.                        [3]   length of 2nd protect run
  2148.  
  2149.                        [4]   length of 2nd  zero   run
  2150.  
  2151.                                          .
  2152.                                          .
  2153.                                          .
  2154.  
  2155.                      [n-2]   length of final protect run
  2156.  
  2157.                      [n-1]   length of final  zero   run
  2158.  
  2159.  
  2160.      Looking at this diagram, we see the even-numbered array elements hold the
  2161. length of the "protect" runs, and the odd-numbered elements hold the length of
  2162. the "zero" runs. If you need the first run to be a "zero" run, just include a
  2163. "protect" run of length zero as the first element of the array. If the final
  2164. run is a "protect" run, you do not need to include a zero-length "zero" run at
  2165. the end of the array. Finally, if either type of run exceeds 255 pixels,
  2166. you'll need to split this into two or more pixel runs. In this case, be sure
  2167. to include a zero-length run of the other type between the two array elements.
  2168.  
  2169.      Example 10-23 illustrates the use of a masking map through fg_drawmask,
  2170. fg_clipmask, fg_revmask, and fg_flipmask in the standard CGA four-color
  2171. graphics mode (mode 4) to draw a black (color 0) arrow against a white
  2172. background. These four routines are respectively analogous to fg_drwimage,
  2173. fg_clpimage, fg_revimage, and fg_flpimage, but they use masking maps rather
  2174. than bitmaps. The first argument of each routine is the masking map array
  2175. (passed by reference), the second argument is the number of runs (that is, the
  2176. number of elements) in the masking map array, and the third argument is the
  2177. width in pixels of the image.
  2178.  
  2179.                                 Example 10-23.
  2180.  
  2181.                  #include <fastgraf.h>
  2182.                  #include <stdio.h>
  2183.                  #include <stdlib.h>
  2184.                  void main(void);
  2185.  
  2186.                  char arrow[] = {6,1,9,2,2,9,1,19,7,2,8,1};
  2187.  
  2188.                  void main()
  2189.                  {
  2190.                     int old_mode;
  2191.  
  2192.                     fg_initpm();
  2193.                     if (fg_testmode(4,1) == 0) {
  2194.                        printf("This program requires a 320 ");
  2195.                        printf("x 200 CGA graphics mode.\n");
  2196.                        exit(1);
  2197.                        }                                                       
  2198. 250   Fastgraph User's Guide
  2199.  
  2200.  
  2201.                     old_mode = fg_getmode();
  2202.                     fg_setmode(4);
  2203.                     fg_setclip(0,15,0,199);
  2204.  
  2205.                     fg_setcolor(3);
  2206.                     fg_rect(0,319,0,199);
  2207.  
  2208.                     fg_move(10,10);
  2209.                     fg_drawmask(arrow,12,10);
  2210.                     fg_move(10,20);
  2211.                     fg_clipmask(arrow,12,10);
  2212.                     fg_move(10,30);
  2213.                     fg_revmask(arrow,12,10);
  2214.                     fg_move(10,40);
  2215.                     fg_flipmask(arrow,12,10);
  2216.                     fg_waitkey();
  2217.  
  2218.                     fg_setmode(old_mode);
  2219.                     fg_reset();
  2220.                  }
  2221.  
  2222.  
  2223.      One of the more useful features of masking maps is their ability to clear
  2224. a portion of video memory before placing an image there. This technique
  2225. provides an efficient, simple way to include color 0 pixels in an image. It is
  2226. especially effective when displaying large or dithered images because the
  2227. masking map is typically much smaller than the bitmap required by fg_drawmap
  2228. or its related routines. Example 10-24 illustrates this process in the
  2229. standard CGA four-color graphics mode (mode 4) by displaying our arrow image
  2230. against a colored background. In this example, the arrow has a white (color 3)
  2231. perimeter and a black (color 0) interior.
  2232.  
  2233.      The program displays the arrow in two steps. It first uses fg_drawmask to
  2234. clear the video memory where the arrow will be displayed. It then draws the
  2235. arrow's perimeter using fg_drwimage. The interior pixels in the perimeter
  2236. bitmap are transparent, but since we just zeroed that video memory, they
  2237. appear in color 0. Note we could improve this example by creating a smaller
  2238. masking map that only applies to the rectangle inscribing the arrow's
  2239. interior. That is, we don't need to zero the video memory under the arrow's
  2240. perimeter because we will immediately display other pixels there.
  2241.  
  2242.                                 Example 10-24.
  2243.  
  2244.               #include <fastgraf.h>
  2245.               #include <stdio.h>
  2246.               #include <stdlib.h>
  2247.               void main(void);
  2248.  
  2249.               char arrow_white[] = {
  2250.                  0x00,0x0C,0x00, 0x00,0x0F,0x00, 0xFF,0xFC,0xC0,
  2251.                  0xC0,0x00,0x30, 0xFF,0xFC,0xC0, 0x00,0x0F,0x00,
  2252.                  0x00,0x0C,0x00
  2253.                  };
  2254.  
  2255.               char arrow_black[] = {6,1,9,2,2,9,1,19,7,2,8,1};                 
  2256.                                            Chapter 10:  Bitmapped Images   251
  2257.  
  2258.  
  2259.               void main()
  2260.               {
  2261.                  int old_mode;
  2262.  
  2263.                  fg_initpm();
  2264.                  if (fg_testmode(4,1) == 0) {
  2265.                     printf("This program requires a 320 ");
  2266.                     printf("x 200 CGA graphics mode.\n");
  2267.                     exit(1);
  2268.                     }
  2269.  
  2270.                  old_mode = fg_getmode();
  2271.                  fg_setmode(4);
  2272.  
  2273.                  fg_setcolor(2);
  2274.                  fg_rect(0,319,0,199);
  2275.  
  2276.                  fg_move(10,10);
  2277.                  fg_drawmask(arrow_black,12,10);
  2278.                  fg_drwimage(arrow_white,3,7);
  2279.                  fg_waitkey();
  2280.  
  2281.                  fg_setmode(old_mode);
  2282.                  fg_reset();
  2283.               }
  2284.  
  2285.  
  2286.  
  2287. Summary of Bitmapped Image Display Routines
  2288.  
  2289.      This section summarizes the functional descriptions of the Fastgraph
  2290. routines presented in this chapter. More detailed information about these
  2291. routines, including their arguments and return values, may be found in the
  2292. Fastgraph Reference Manual.
  2293.  
  2294.      For all bitmapped image routines, images are displayed or retrieved so
  2295. their lower left corner is at the graphics cursor position (or text cursor
  2296. position for those routines that also work in text video modes). In 16-bit
  2297. environments, the size of any arrays passed to these routines is limited to
  2298. 64K bytes.
  2299.  
  2300.      FG_CLIPMAP displays a clipped image stored as a mode-independent bitmap.
  2301. This routine has no effect when used in a text video mode.
  2302.  
  2303.      FG_CLIPMASK displays a clipped image stored as a masking map. This
  2304. routine has no effect when used in a text video mode.
  2305.  
  2306.      FG_CLPIMAGE displays a clipped image stored as a mode-specific bitmap.
  2307. Color 0 pixels are considered transparent. This routine has no effect when
  2308. used in a text video mode.
  2309.  
  2310.      FG_DISPLAY displays an image stored in Fastgraph's standard pixel run
  2311. format, where the image resides in an array. This routine has no effect when
  2312. used in a text video mode.                                                     
  2313. 252   Fastgraph User's Guide
  2314.  
  2315.      FG_DISPLAYP displays an image stored in Fastgraph's packed pixel run
  2316. format, where the image resides in an array. This routine has no effect when
  2317. used in a text video mode.
  2318.  
  2319.      FG_DRAWMAP displays an image stored as a mode-independent bitmap. This
  2320. routine has no effect when used in a text video mode.
  2321.  
  2322.      FG_DRAWMASK displays an image stored as a masking map. This routine has
  2323. no effect when used in a text video mode.
  2324.  
  2325.      FG_DRWIMAGE displays an image stored as a mode-specific bitmap. Color 0
  2326. pixels are considered transparent.
  2327.  
  2328.      FG_FLIPMASK displays a reversed clipped image stored as a masking map.
  2329. This routine has no effect when used in a text video mode.
  2330.  
  2331.      FG_FLPIMAGE displays a reversed clipped image stored as a mode-specific
  2332. bitmap. Color 0 pixels are considered transparent. This routine has no effect
  2333. when used in a text video mode.
  2334.  
  2335.      FG_GETIMAGE retrieves an image as a mode-specific bitmap.
  2336.  
  2337.      FG_GETMAP retrieves an image as a mode-independent bitmap. This routine
  2338. has no effect when used in a text video mode.
  2339.  
  2340.      FG_IMAGESIZ determines the number of bytes required to store a mode-
  2341. specific bitmapped image of specified dimensions.
  2342.  
  2343.      FG_INVERT inverts the row order of a mode-specific or mode-independent
  2344. bitmapped image, so a "top to bottom" image becomes a "bottom to top" image,
  2345. or vice versa.
  2346.  
  2347.      FG_PACK converts a bitmap in the "one pixel per byte" format used in
  2348. 256-color graphics modes and virtual buffers to the mode-specific bitmap
  2349. format for the current video mode.
  2350.  
  2351.      FG_PUTIMAGE displays an image stored as a mode-specific bitmap. No
  2352. support is provided for transparent pixels.
  2353.  
  2354.      FG_REVIMAGE displays a reversed image stored as a mode-specific bitmap.
  2355. Color 0 pixels are considered transparent. This routine has no effect when
  2356. used in a text video mode.
  2357.  
  2358.      FG_REVMASK displays a reversed image stored as a masking map. This
  2359. routine has no effect when used in a text video mode.
  2360.  
  2361.      FG_SCALE expands or reduces a bitmapped image stored in the "one pixel
  2362. per byte" format.
  2363.  
  2364.      FG_SHEAR shears a bitmapped image stored in the "one pixel per byte"
  2365. format.
  2366.  
  2367.      FG_UNPACK converts a mode-specific bitmapped image to the "one pixel per
  2368. byte" format used in 256-color graphics modes and virtual buffers.             
  2369.                                            Chapter 10:  Bitmapped Images   253
  2370.  
  2371.      FG_VBADDR returns the address of the specified virtual buffer. In 16-bit
  2372. modes, the address will be a real mode segment:offset pair or protected mode
  2373. selector:offset pair. In 32-bit modes, it will be an offset into the default
  2374. data segment.                                                                  
  2375. 254   Fastgraph User's Guide
  2376.