How to Use Multidimensional Arrays with Graphics GET and PUT (72672)



The information in this article applies to:

  • Microsoft QuickBASIC 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBASIC 4.5
  • Microsoft Basic Professional Development System (PDS) for MS-DOS and MS OS/2 7.0
  • Microsoft Basic Professional Development System (PDS) for MS-DOS and MS OS/2 7.1
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0b

This article was previously published under Q72672

SUMMARY

When using Basic's graphics GET and PUT statements and specifying the index(es) of the array where you want to start storing the graphics image, it is important to remember how the array is physically stored in memory. If you fail to do so, each GET statement may actually overwrite some of the information from the proceeding GET statement, which can result in an "Illegal function call" on succeeding PUT statements.

MORE INFORMATION

By default, Basic stores arrays in "column major order" in memory. Column major order means that the array is stored in memory one column at a time. For example, an array declared as
   DIM x(1 to 2, 1 to 1)
				
will be stored in memory in the following order:
   x(1,1)  x(2,1)  x(1,2)  x(2,2)
				
Another option is to use the BC /R option to store arrays in row major order. (Note: The QB.EXE or QBX.EXE environment does not have an option for row major array order.) In row major order, the same array above is stored in memory as follows:
   x(1,1)  x(1,2)  x(2,1)  x(2,2)
				
Basic's graphics GET statement copies video memory directly into the array you specify (straight from video memory into the memory occupied by the array). This can overwrite the existing array contents in a way that you may not expect. The following example demonstrates a common method of attempting to use graphics GET with a multidimensional array, as well as the correct method:
DEFINT A-Z
CONST NUMIMAGES = 2
CONST IMAGESIZE = 100
DIM images(1 to NUMIMAGES, 1 to IMAGESIZE)
SCREEN 1
LINE (10,10)-(20,20),,BF
GET (10,10)-(20,20), images(1,1)
CLS
CIRCLE (15,15), 5
GET (10,10)-(20,20), images(2,1)   ' Overwrites array from first GET
                                   ' when not using BC /R
				
The above program may appear to be the obvious approach to using a multidimensional array to store several graphics images. The problem with the above program is that the array is stored in column major order, as follows:
    _____ _____ _____ _____ _____ _____
   | 1,1 | 2,1 | 1,2 | 2,2 | 1,3 | 2,3 | .......
    ----- ----- ----- ----- ----- -----
				
So the first GET statement above copies an image from video memory straight into the array starting at element (1,1). Because GET performs a direct copy into the array, element (2,1), (2,2), (2,3), and so forth, are also used to hold the image. If we immediately PUT the image starting at (1,1) back to the screen, it will appear correctly.

The second GET statement in the example copies directly from video memory into the array starting at element (2,1). This will actually overwrite the first image starting at element (2,1) and continue through the array. If we try to PUT images(2,1), the image will be displayed correctly. If we try to PUT images(1,1), which has now been overwritten, we will either see a corrupted image or receive an "Illegal function call" error message.

There are two ways to avoid this behavior:

  1. Store arrays in row major order by using the /R option on the BC.EXE compile line (this option is not available in the QB.EXE and QBX.EXE environments). -or-

  2. Change the way you use the array in your program to take the array's physical storage into account. The following example demonstrates how to change the above program to avoid overwriting the images on successive GET statements:
       DEFINT A-Z
       CONST NUMIMAGES = 2
       CONST IMAGESIZE = 100
       DIM images(1 to IMAGESIZE, 1 to NUMIMAGES)
       SCREEN 1
       LINE (10,10)-(20,20),,BF
       GET (10,10)-(20,20), images(1,1)
       CLS
       CIRCLE (15,15), 5
       GET (10,10)-(20,20), images(1,2)  ' Image stores OK when
                                         ' not using BC/R
    						
    In this example, separate images are stored in separate columns of the array, rather than in separate rows. Because the array is arranged by columns in memory, as follows,
           _____ _____ _____     _____ _____ _____ _____     _____
          | 1,1 | 2,1 | 3,1 |...|100,1| 1,2 | 2,2 | 3,2 |...|100,2|
           ----- ----- -----     ----- ----- ----- -----     -----
    						
    the images will not overwrite each other, and you can PUT both images back to the screen correctly.

Modification Type:MinorLast Reviewed:8/16/2005
Keywords:KB72672