Images and Screenmodes - QB64 Wiki

Images and Screenmodes

From QB64 Wiki

Jump to: navigation, search

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.


TERMS


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)


LEGACY SCREENS


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:


SCREEN 7

SCREEN 9

SCREEN 12

SCREEN 13

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).


QB64 SCREENS


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.


Download all the image files used in the previous example and which are used in the following ones here [[1]].


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. What if we know the color depth, but not the size of the image? We can load it as shown in this example:

REM Example of loading an image of unknown size, but known color depth, REM and make it immediately visible on the screen and determine its sizes DEFLNG A-Z SCREEN _LOADIMAGE("Lilies16.bmp", 256) 'a 16 colour image Wide& = _WIDTH(0) High& = _HEIGHT(0) PRINT "Width="; Wide&, "Height="; High& SLEEP SYSTEM

The above example loads a 16 color (Legacy SCREEN 12). Note that the mode used is 256!


REM Example of loading an image of unknown size, but known colour depth REM and make it immediately visible on the screen and determine its size DEFLNG A-Z SCREEN _LOADIMAGE("Lilies256.bmp", 256) '256 colour image Wide& = _WIDTH(0) High& = _HEIGHT(0) PRINT "Width="; Wide&, "Height="; High& SLEEP SYSTEM

The above example loads a 256 colour (Legacy SCREEN 13). Note that the mode used is 256!

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.


To summarize: we use parameter 256 to load a known 16 color and a known 256 color images, but we use parameter 32 to load 32 bit color images.


The reader might be wondering and thinking "Is there a way to load a 32 bit image into a legacy screen?" The answer is yes! The following example illustrates this:


REM Example of loading a 32 bit image into a QBasic screen DEFLNG A-Z Video1& = _NEWIMAGE(640, 480, 12) 'a screen for user to select on SCREEN Video1& _DELAY 1 DO GOSUB Message LOOP UNTIL _KEYDOWN(27) SLEEP SYSTEM Message: PRINT "press ESCAPE key to exit" PRINT "Press (A) for SCREEN 1" PRINT "Press (B) for SCREEN 2" PRINT "Press (C) for SCREEN 7" PRINT "Press (D) for SCREEN 9" PRINT "Press (E) for SCREEN 10" PRINT "Press (F) for SCREEN 11" PRINT "Press (G) for SCREEN 12" PRINT "Press (H) for SCREEN 13" Dummy$ = UCASE$(INPUT$(1)) LetsLook% = 1 SELECT CASE Dummy$ CASE IS = "A" Video2& = _NEWIMAGE(640, 480, 1) Mode% = 1 CASE IS = "B" Video2& = _NEWIMAGE(640, 480, 2) Mode% = 2 CASE IS = "C" Video2& = _NEWIMAGE(640, 480, 7) Mode% = 7 CASE IS = "D" Video2& = _NEWIMAGE(640, 480, 9) Mode% = 9 CASE IS = "E" Video2& = _NEWIMAGE(640, 480, 10) Mode% = 10 CASE IS = "F" Video2& = _NEWIMAGE(640, 480, 11) Mode% = 11 CASE IS = "G" Video2& = _NEWIMAGE(640, 480, 12) Mode% = 12 CASE IS = "H" Video2& = _NEWIMAGE(640, 480, 13) Mode% = 13 CASE ELSE LetsLook% = 0 END SELECT IF LetsLook% = 1 THEN Picture& = _LOADIMAGE("Earth1.jpg") _PUTIMAGE , Picture&, Video2& SCREEN Video2& PRINT "Press any key to try new MODE" PRINT "this is SCREEN "; Mode% Junk$ = INPUT$(1) END IF SCREEN Video1& CLS RETURN


The above example correctly loads the picture, but only displays the amount of colors that are available in that legacy screen mode. So what would happen if the user wanted to load the following:


16 bit picture in a 16 bit screen, 256 colors screen or 32 bit screen? 256 colors picture in a 16 bit screen, 256 colors screen or 32 bit screen? 32 bit picture in a 16 bit screen, 256 colors screen or 32 bit screen?

REM Example of select loading a ?? bit picture onto an ?? bit screen and made visible DEFLNG A-Z What = -1 _DELAY 1 DO GOSUB Message LOOP UNTIL _KEYDOWN(27) SLEEP SYSTEM Message: SCREEN 0 IF What = -1 THEN PRINT PRINT "press (1) to Select Lillies picture or (2) to select Colours picture" What$ = UCASE$(INPUT$(1)) What = VAL(What$) PRINT END IF PRINT PRINT "press ESCAPE key to exit" PRINT PRINT "Press (A) for 16 bit picture in 16 bit Screen" PRINT "Press (B) for 16 bit picture in 256 bit Screen" PRINT "Press (C) for 16 bit picture in 32 bit Screen" PRINT "Press (D) for 256 colors picture in 16 bit Screen" PRINT "Press (E) for 256 colors picture in 256 bit Screen" PRINT "Press (F) for 256 colors picture in 32 bit Screen" PRINT "Press (G) for 32 bit picture in 16 bit Screen" PRINT "Press (H) for 32 bit picture in 256 bit Screen" PRINT "Press (I) for 32 bit picture in 32 bit Screen" Dummy$ = UCASE$(INPUT$(1)) LetsLook% = 1 SELECT CASE Dummy$ CASE IS = "A" Video2& = _NEWIMAGE(640, 480, 12) SCREEN Video2& Mode% = 16 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies16.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("16BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "B" Video2& = _NEWIMAGE(640, 480, 256) SCREEN Video2& Mode% = 256 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies16.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("16BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "C" Video2& = _NEWIMAGE(640, 480, 32) SCREEN Video2& Mode% = 32 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies16.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("16BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "D" Video2& = _NEWIMAGE(640, 480, 12) SCREEN Video2& Mode% = 16 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies256.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("256BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "E" Video2& = _NEWIMAGE(640, 480, 256) SCREEN Video2& Mode% = 256 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies256.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("256BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "F" Video2& = _NEWIMAGE(640, 480, 32) SCREEN Video2& Mode% = 32 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies256.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("256BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "G" Video2& = _NEWIMAGE(640, 480, 12) SCREEN Video2& Mode% = 16 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies32.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("32BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "H" Video2& = _NEWIMAGE(640, 480, 256) SCREEN Video2& Mode% = 256 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies32.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("32BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE IS = "I" Video2& = _NEWIMAGE(640, 480, 32) SCREEN Video2& Mode% = 32 IF What$ = "1" THEN Picture& = _LOADIMAGE("Lilies32.bmp") IF What$ = "2" THEN Picture& = _LOADIMAGE("32BitColors.bmp") _PUTIMAGE , Picture&, Video2& CASE ELSE LetsLook% = 0 END SELECT IF LetsLook% = 1 THEN PRINT "Press any key to try new MODE" PRINT "this is SCREEN "; Mode% Junk$ = INPUT$(1) SCREEN 0 _FREEIMAGE Video2& _FREEIMAGE Picture& END IF CLS RETURN


The above program will illustrate all of these differences clearer than any of the examples so far. You have the choice of loading 2 varying different colored pictures to see the changes clearer!

Views
Personal tools