Older Version
Newer Version
JanetTerra
Jul 22, 2006
==How to FLUSH Without Running Out of Resources==
===Flushing Your Graphics===
[[user:JanetTerra|1153581444]]
Drawing graphics with **[[http://www.libertybasic.com|Liberty BASIC]]** is very easy. Using native **[[http://www.libertybasic.com|Liberty BASIC]]** commands, the programmer can draw lines, circles, boxes and other Turtle graphics. In addition, the commands **LOADBMP** and **DRAWBMP** allows the programmer to draw //bitmaps// retrieved from file.
Graphics consume memory, though, especially when graphics are meant to //persist//. A //persisted graphic// is one that will redraw itself whenever the window becomes minimized, obscured, or dragged offscreen. The **[[http://www.libertybasic.com|Liberty BASIC]]** command that causes a graphic to //persist// or //stick// is **FLUSH**. Run this demo to see how **FLUSH** works.
[[code format="vb"]]
Nomainwin
WindowWidth = 787
WindowHeight = 594
UpperLeftX = Int((DisplayWidth - WindowWidth) / 2)
UpperLeftY = Int((DisplayHeight - WindowHeight) / 2)
Graphicbox #demo.g, 0, 0, 780, 560
Open "Flushed and Non-Flushed Graphics" for Window as #demo
Print #demo, "Trapclose [QuitDemo]"
' Put the pen in the down position and assign the color
Print #demo.g, "Down; Fill Buttonface; Color Buttonface"
' Draw the upper concentric circles
' Place the pen in the center of the upper half
Print #demo.g, "Place 390 180"
' Choose 5 background colors
hue$ = "Red Yellow White Blue Green"
' Draw a colorful figure
ct = 1
For i = 100 to 10 Step -10
Print #demo.g, "Backcolor ";Word$(hue$, ct)
Print #demo.g, "Circlefilled ";i
ct = ct + 1
If ct = 6 Then
ct = 1
End If
Next i
' FLUSH the upper picture
Print #demo.g, "Flush"
' Draw the lower concentric circles
' Place the pen in the center of the lower half
Print #demo.g, "Place 390 420"
' Choose 5 background colors
hue$ = "Red Yellow White Blue Green"
' Draw a colorful figure
For i = 100 to 10 Step -10
Print #demo.g, "Backcolor ";Word$(hue$, ct)
Print #demo.g, "Circlefilled ";i
ct = ct + 1
If ct = 6 Then
ct = 1
End If
Next i
' Don't FLUSH the lower picture
Wait
[QuitDemo]
Close #demo
End
[[code]]
Once the program has been executed, drag the window partway off the display screen and then back onto the display screen. The **FLUSH**ed, upper figure becomes redrawn as the window becomes viewable again. The Non-**FLUSH**ed, lower figure does not.
From the **[[http://www.libertybasic.com|Liberty BASIC]] Help File**
**print #handle, "flush"**
//This command ensures that drawn graphics 'stick'. Each time a flush command is issued after one or more drawing operations, a new group (called a segment) is created. Each segment of drawn items has an ID number. The segment command retrieves the ID number of the current segment. Each time a segment is flushed, a new empty segment is created, and the ID number increases by one. See also the commands cls, delsegment, discard, redraw, and segment.//
**FLUSH**ing does make the final display //persist//, but it does so by reexecuting each step in the sequence of the building of the **FLUSH**ed graphic. To see this reexecution of code in action, run this next demo.
//**Warning: This demo WILL cause flashing. DO NOT run this demo if you have a history of seizures.**//
[[code format="vb"]]
Nomainwin
WindowWidth = 787
WindowHeight = 594
UpperLeftX = Int((DisplayWidth - WindowWidth) / 2)
UpperLeftY = Int((DisplayHeight - WindowHeight) / 2)
Graphicbox #demo.g, 0, 0, 780, 560
Open "Windows Repainting FLUSHED Graphics" for Window as #demo
Print #demo, "Trapclose [QuitDemo]"
' Put the pen in the down position and assign the color
Print #demo.g, "Down; Fill Buttonface; Color Buttonface"
' Fill the box with concentric circles
' Place the pen in the center of the graphicbox
Print #demo.g, "Home"
' Choose 5 background colors
hue$ = "Red Yellow White Blue Green"
' Draw a colorful figure 5 times
ct = 1
For i = 1 to 5
For j = 700 to 10 Step -10
Print #demo.g, "Backcolor ";Word$(hue$, ct)
Print #demo.g, "Circlefilled ";j
ct = ct + 1
If ct = 6 Then
ct = 1
End If
Next j
Next i
' FLUSH the upper picture
Print #demo.g, "Flush"
Wait
[QuitDemo]
Close #demo
End
[[code]]
When the code has been executed, maximize and restore the window several times. Watch how the window //repaint// itself. For more information on //segments// and **FLUSH**ed graphics see //**[[http://babek.info/libertybasicfiles/lbnews/nl102/4.htm|Segments and Flushing - a Graphics Tutorial]]**// by **[[http://www.alycesrestaurant.com|Alyce Watson]]** in the **[[http://babek.info/libertybasicfiles/lbnews/|Liberty BASIC Newsletter]]**, **[[http://lbpe.wikispaces.com/space/showimage/nl102.zip|Issue #102]]**.
===The Problem with Memory and Graphics===
It is obviously good programming technique to keep your graphics **FLUSH**ed. This is especially true when the program calls for the graphics to change throughout the program. Unfortunately, **FLUSH**ing comes at a high cost and that price can very quickly deplete your system's resources. One way to keep an eye on resources is to open //**Task Manager**// and watch the //Commit Charge// numbers in the lower right corner.
[[Image:FlushTutPic01.png]]
Each **FLUSH** command increases this //Commit Charge//, very quickly to the point of slowing and eventually crashing the program. Open //**Task Manager**// while this next demo runs. You may want to change the
[[code format="vb"]]
For i = 1 to 5
[[code]]
to
[[code format="vb"]]
For i = 1 to 3
[[code]]
to be sure the program doesn't crash. If you encounter a crash, highlight liberty.exe in Task Manager > Applications and press End Process. While the program is running, the //Commit Charge// gradually, yet steadily, increases. Even when [[http://www.libertybasic.com|Liberty BASIC]] is dutifully closed, the resources aren't completely restored to the pre-run level.
===The Full Demo===
[[code format="vb"]]
' Demo1 - Flush each tile
' Nomainwin
WindowWidth = 787
WindowHeight = 594
UpperLeftX = Int((DisplayWidth - WindowWidth) / 2)
UpperLeftY = Int((DisplayHeight - WindowHeight) / 2)
Graphicbox #demo.g, 0, 0, 780, 560
Open "Flushing Demo 1" for Window as #demo
Print #demo, "Trapclose [QuitDemo]"
' Put the pen in the down position and assign the color
Print #demo.g, "Down; Color Pink"
' Choose 5 background colors
hue$ = "Red Yellow White Blue Green"
' Draw a tiled background, flushing with each tile drawn
For i = 1 to 5
Print #demo.g, "Backcolor ";Word$(hue$, i)
For y = 0 to 540 Step 20
For x = 0 to 760 Step 20
Print #demo.g, "Place ";x;" ";y
Print #demo.g, "Boxfilled ";x + 20;" ";y + 20
' Flush after each tile drawn
Print #demo.g, "Flush"
Next x
Next y
Next i
Print "Done"
Wait
[QuitDemo]
Close #demo
End
[[code]]
Look again at the //Commit Charge//.
[[Image:FlushTutPic02.png]]
Here it has risen from 338 to 355. The //Commit Charge// will continue to rise with each **FLUSH** until the program crashes.
===Using GETBMP and DRAWBMP===
What can the programmer do, then, to make graphics //persist// without consuming large resources of memory? One way is to not **FLUSH** each step or //segment// of the draw, but to capture the final output as a //bitmap// and draw the whole display in one step. **GETBMP** captures the graphic display from the screen rather than loading it from a file. **DRAWBMP** then draws that //bitmap//. When a //bitmap// is drawn, the whole picture is drawn as one //segment// rather than a series of individual //segments//.
[[code format="vb"]]
Nomainwin
WindowWidth = 787
WindowHeight = 594
UpperLeftX = Int((DisplayWidth - WindowWidth) / 2)
UpperLeftY = Int((DisplayHeight - WindowHeight) / 2)
Graphicbox #demo.g, 0, 0, 780, 560
Open "Capturing a Bitmap" for Window as #demo
Print #demo, "Trapclose [QuitDemo]"
' Put the pen in the down position and assign the color
Print #demo.g, "Down; Fill Buttonface; Color Buttonface"
' Draw some concentric circles
' Choose 5 background colors
hue$ = "Red Yellow White Blue Green"
' Position the pen
Print #demo.g, "Place 100 100"
' Set the counter to 1
ct = 1
' Draw concentric circles
For i = 100 to 10 Step -10
Print #demo.g, "Backcolor ";Word$(hue$, ct)
Print #demo.g, "Circlefilled ";i
ct = ct + 1
If ct = 6 Then
ct = 1
End If
Next i
' Get the bitmap
Print #demo.g, "Getbmp ConcentricCircles 0 0 200 200"
' Let mouse click select a position
Print #demo.g, "When leftButtonUp [DrawBitmap]"
' Wait for mouseclick
Wait
[DrawBitmap]
' Get the mouse coordinates
x = MouseX
y = MouseY
' Clear the screen - Cls clears all graphics memory as well
Print #demo.g, "Cls"
' Position the upper left corner at x, y
Print #demo.g, "Drawbmp ConcentricCircles ";x;" ";y
' Flush the drawing
Print #demo.g, "Flush"
Wait
[QuitDemo]
Close #demo
End
[[code]]
===Capturing the Graphic Window===
Using this same **GETBMP** technique, the entire window can be captured as a //bitmap//. The drawn //bitmap// is then **FLUSH**ed rather than the multitude of individual //segments//. Demo2 is a modification of Demo1, **FLUSH**ing the drawn //bitmaps//. In addition, as each //bitmap// is drawn, the prior //segment// is deleted with the **DELSEGMENT** command. This allows just one //segment// to remain in memory at any given time, thus relieving the drain on resources required for storing hundreds of //segments//.
[[code format="vb"]]
' Demo2 - Deleting Segments and Flushing Bitmaps
' Nomainwin
WindowWidth = 787
WindowHeight = 594
UpperLeftX = Int((DisplayWidth - WindowWidth) / 2)
UpperLeftY = Int((DisplayHeight - WindowHeight) / 2)
Graphicbox #demo.g, 0, 0, 780, 560
Open "Flushing Demo 2" for Window as #demo
Print #demo, "Trapclose [QuitDemo]"
' Put the pen in the down position and assign the color
Print #demo.g, "Down; Color Pink"
' Capture the initial bitmap
Print #demo.g, "Getbmp DemoPic 0 0 780 560"
' Get the segment number
Print #demo.g, "Segment segID"
' Flush
Print #demo.g, "Flush"
' Choose 5 background colors
hue$ = "Red Yellow White Blue Green"
' Draw a tiled background, flushing with each tile drawn
For i = 1 to 3
Print #demo.g, "Backcolor ";Word$(hue$, i)
For y = 0 to 540 Step 20
For x = 0 to 760 Step 20
Print #demo.g, "Place ";x;" ";y
Print #demo.g, "Boxfilled ";x + 20;" ";y + 20
' Delete the old segment
Print #demo.g, "Delsegment ";segID
' Unload the previous bitmap
Unloadbmp "DemoPic"
' Capture the entire graphic as a bitmap
Print #demo.g, "Getbmp DemoPic 0 0 780 560"
' Draw the entire window
Print #demo.g, "Drawbmp DemoPic 0 0"
' Get the segment number
Print #demo.g, "Segment segID"
' Flush the bitmap
Print #demo.g, "Flush"
Next x
Next y
Next i
Print "Done"
Wait
[QuitDemo]
Close #demo
End
[[code]]
[[Image:FlushTutPic03.png]]
Using **DELSEGMENT**, the //Commit Charge// remains at a consistent, safe level. //**Segment.bas**// is an example program that ships with **[[http://www.libertybasic.com|Liberty BASIC]]**. //**Segment.bas**// demonstrates the **DELSEGMENT** command.
When running these demos, you may notice that the **DELSEGMENT**, **GETBMP**, **DRAWBMP**, **SEGMENT**, **FLUSH**, sequence takes a bit more time than just a simple **FLUSH**. In most programs, the increased time will be negligible and virtually imperceptible.
===Special Considerations with GETBMP===
The **GETBMP** command captures the visible portion of the display. Areas extending beyond these visible limits will result in images of the topmost display. One way to avoid unintended capturing of another window is to keep the Liberty BASIC graphic window topmost with stylebits.
[[code format="vb"]]
Stylebits #demo, 0, 0, _WS_EX_TOPMOST, 0
[[code]]
More experienced **[[http://www.libertybasic.com|Liberty BASIC]]** users may want to first draw the images and then capture those images in memory. The captured //bitmap// can then be drawn to the partially visible graphic window and **FLUSH**ed like any other drawing. For more information on drawing in memory, see //**[[http://babek.info/libertybasicfiles/lbnews/nl102/4.htm|Drawing in Memory]]**// by **[[http://www.alycesrestaurant.com|Alyce Watson]]** in the **[[http://babek.info/libertybasicfiles/lbnews/|Liberty BASIC Newsletter]]**, **[[http://lbpe.wikispaces.com/space/showimage/nl101.zip|Issue #101]]**.
===Summary===
**FLUSH** is a viable option for preserving graphics when only a few **FLUSH** commands are scattered throughout the program. **FLUSH**ing thousands, hundreds, or even dozens of times in your program will very quickly drain system resources. **CLS** is the most expedient way to free these graphics resources. When **CLS** isn't feasible, consider using the **DELSEGMENT**, **GETBMP**, **DRAWBMP**, **SEGMENT**, **FLUSH** sequence to keep your graphics program running smoothly and to prevent your program from crashing.