JanetTerra
Jul 22, 2006
- "Fixed links to LBPE Newsletter Archives Downloads"
==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/file:nl102.zip|Issue**[[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. ===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]] 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. 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/file:nl101.zip|Issue**[[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.