Images and Screenmodes
Written by OlDosLover (April, 2012)
Welcome to QB64 Screen Modes tutorial. Here I will attempt to help QB64 newcomers understand the legacy QBasic graphics screen modes compared to the new QB64 graphics screen commands and how to use them. I will use some terms to describe things later in the text so allow me to define them at the start.
Legacy = QBasic or QB45
QB64 = The new underscored keywords
Graphics surface = a set sized screen of pixels at a certain amount of colors
Pages = a number of associated graphics surfaces all the same size and color depth
Color Depth = maximum number of colors that can be displayed on a graphics surface
Statement = a BASIC keyword used to invoke a command with correct parameters
Monitor = computer screen
Mode = a particular legacy screen
Handle = Identifying label (a name)
In the old DOS QBasic a user could only create fixed legacy screens in preset size and color depth. In QBasic a user would create this single graphics window by using the statement SCREEN with a number. For example, the main graphics screen modes that QBasic features are:
The resolutions of these old screen modes are:
SCREEN 7 => 320 x 200 x 16 colors, 4 pages
SCREEN 9 => 640 x 350 x 16 colors, 2 pages
SCREEN 12 => 640 x 480 x 16 colors, 1 page
SCREEN 13 => 320 x 200 x 256 colors, 1 page
The coder initiates a screen mode by using the SCREEN statement with the desired screen number. It is immediately created and made visible. On today’s modern computer monitors that have much larger resolutions these screens will appear very small. Nevertheless, they can be switched to full screen by using the keyboard command ALT + ENTER (with QBasic, it depends on your video card, in other words, doesn’t always work ~ Ed).
The coder can still use the above QBasic syntax for invoking a screen mode or use the QB64's new command _NEWIMAGE.
_NEWIMAGE allows the user to create a graphics surface. This surface has a horizontal and vertical size and a color depth. The color depth is indicated by using the legacy MODE number (0,1,2,7,8,9,10,11,12,13) or by stating the color depth as 256 (number of colors) or 32 (color bit depth). QB64 allows you to set the horizontal pixel size, the vertical pixel size and the number of colors with the arguments in the statement declaration. For legacy screens the programmer indicates the color depth by using the Screen number (Mode) as the color depth variable. To create the same legacy screen with the _NEWIMAGE command the user would do:
Handle& = _NEWIMAGE(320,200,7) 'Legacy QBasic Screen 7
Handle& = _NEWIMAGE(640,350,9) 'Legacy QBasic Screen 9
Handle& = _NEWIMAGE(640,480,12) 'Legacy QBasic Screen 12
Handle& = _NEWIMAGE(320,200,13) 'Legacy QBasic Screen 13
You can also make a 640 by 480 pixels screen in the above legacy modes like above with the following code:
Handle& = _NEWIMAGE(640,480,7) 'Legacy QBasic Screen 7
Handle& = _NEWIMAGE(640,480,9) 'Legacy QBasic Screen 9
Handle& = _NEWIMAGE(640,480,12) 'Legacy QBasic Screen 12
Handle& = _NEWIMAGE(640,480,13) 'Legacy QBasic Screen 13
HANDLE& is either the keyword SCREEN or a variable defined by the coder. Here are two examples:
SCREEN _NEWIMAGE(640,480,12) 'immediately created and made visible
GraphicSurface& = _NEWIMAGE(640,480,12) 'immediately created, but is not made visible
What is the difference? When the SCREEN statement is used as in the first line of code QB64 immediately creates 640 by 480 pixels surface in legacy SCREEN 12 mode with 16 colors and makes it immediately visible to the user. When the user creates a surface with a handle name, QB64 allocates a negative number that isn’t in use to flag the identity of that surface. Secondly, QB64 immediately creates a 640 by 480 pixels surface with 16 colors. It does not make this surface visible. It exists located in memory, but is not actually shown.
Interestingly, the user can use the print statement on this surface to display the negative number assigned to that surface. Please note that -1 (negative one) is reserved to indicate that an error has occurred. So if your graphics surface variable is -1 then it isn’t created and can’t be used. Observe this piece of code that illustrates this:
GraphicSurface& = _NEWIMAGE(640,480,16) 'create the equivalent Legacy Screen 12 SCREEN GraphicSurface& 'make this Surface visable PRINT GraphicSurface& 'print the surfaces handle number SLEEP SYSTEM
So the user can replicate the old DOS graphics screens, but what about custom screen sizes? Well, with _NEWIMAGE the users can create any screen size they desire with 32 bit colors. This screen can be an 8 by 8 pixels square, up to 1000 by 1000 pixels square! Now, even though you can make a 2500 pixel screen the average computer monitor cannot show the entire surface on the screen. What you will see is part of the screen. If you use your mouse cursor to click on the title bar of this screen and hold the button down you can slide it sideways to see its complete size. The user is better off using standard screen resolutions that most monitors support.
Ok, so _NEWIMAGE would be used to create blank graphics surfaces of varying sizes and color depths. This surface can replicate the old legacy screen modes or be of larger sizes and greater color depths. What if the programmer wanted to load an unknown sized image of unknown color depth? We would use new QB64 command _LOADIMAGE. Here's an example:
REM Example of loading an unknown size and color depth image and make it immediately visable on the screen DEFLNG A-Z SCREEN _LOADIMAGE("Lilies.bmp", 32) ' note the 32 SLEEP SYSTEM
The reader should note 32. This indicates the color depth we will try to display this picture at. As we don’t know the image color depth we need to attempt to load it at the maximum allowable color depth and it should display correctly.
How can we find out the size of the picture? Observe the following code:
REM Example of loading an unknown size and color depth image and make it immediately visable on the REM screen and determine its sizes DEFLNG A-Z SCREEN _LOADIMAGE("Lilies.bmp", 32) Wide& = _WIDTH(0) 'Note the ZERO in brackets High& = _HEIGHT(0) 'Note the ZERO in brackets PRINT "Width="; Wide&, "Height="; High& SLEEP SYSTEM
The zero is used to indicate the currently visible surface. As we have made this surface to be the immediate screen, this works as long as this surface exists and is currently shown.
REM Example of loading an unknown size but known colour depth and make it immediately visable REM on the screen and determine its sizes DEFLNG A-Z SCREEN _LOADIMAGE("Lilies32.bmp", 32) '32 bit image Wide& = _WIDTH(0) High& = _HEIGHT(0) PRINT "Width="; Wide&, "Height="; High& SLEEP SYSTEM
The above example loads a 32 bit image. Note that we use the 32 bit MODE to load a 32 bit colour image.