rwg
New Member
Posts: 49
|
Post by rwg on Apr 1, 2020 22:24:31 GMT -5
hi - Filled areas like pie's, circles, ellipses etc hardcopy print perfectly well.
But I can't print areas of say circle segments or polygons which I've filled using calldll #gdi32, "Polygon",_ The areas fill on the screen but do not appear on the hardcopy when using the "print " command. For scaling reasons, I do not want to involve bitmaps. Any suggestions ?
|
|
|
Post by Rod on Apr 2, 2020 1:55:31 GMT -5
Liberty is printing the segments it creates not the screen you are looking at. So if you use api drawing you need to get it into a segment. You can do that with getbmp,drawbmp,flush then print. As always the advice for printing is to do all drawing getbmp drawbmp Etc then flush ONCE and print.
it is probably possible to print the dc you are drawing to via api but that would need more research.
|
|
|
Post by Rod on Apr 2, 2020 3:21:33 GMT -5
|
|
|
Post by Rod on Apr 2, 2020 3:25:27 GMT -5
Also, if you cant use getbmp drawbmp you could roll your own fill command That way if you are drawing a very large off screen graphicbox the fill will be inside the segment. It will be slow to fill but a lot easier than API printing. I will look out some fill code. THe more you can tell us about the task in hand the better the advice.
nomainwin WindowWidth = 300 WindowHeight = 300 UpperLeftX=int((DisplayWidth-WindowWidth)/2) UpperLeftY=int((DisplayHeight-WindowHeight)/2) graphicbox #main.gbox, 0,0,300,300 open "Flood Fill - Click a Color" For Window As #main #main "trapclose quit" #main.gbox "down; fill black; place 125 125; backcolor white" #main.gbox "circlefilled 115; place 105 105; backcolor black" #main.gbox "circlefilled 50; flush floodfill" #main.gbox "when leftButtonUp gBoxClick" #main.gbox "size 1"
'get the handle of the graphicbox and its associated DC global hDC,hWnd hWnd=hwnd(#main.gbox) calldll #user32, "GetDC", hWnd as ulong, hDC as ulong Wait
sub quit handle$ 'release the DC calldll #user32,"ReleaseDC", hWnd as ulong, hDC as ulong, ret as long close #main end end sub
sub gBoxClick handle$, x, y 'stop mouse handling #handle$ "when leftButtonUp" 'get the pixel color clicked target= getPixel(x,y) 'get the desired color colordialog "", color$ replacement = val(word$(color$,1))+256*val(word$(color$,2))+256*256*val(word$(color$,3)) if color$ = "" then exit sub 'set the drawing pen #main.gbox "color " + color$ nul=floodfill(x,y,target,replacement) 'start mouse handling again #handle$ "when leftButtonUp gBoxClick" End Sub
function floodfill(x,y,target,replacement) if target = replacement then exit function if getPixel(x,y) <> target then exit function else #main.gbox "set ";x;" ";y end if nul=floodfill(x,y+1,target,replacement) nul=floodfill(x,y-1,target,replacement) nul=floodfill(x-1,y,target,replacement) nul=floodfill(x+1,y,target,replacement) end function
function getPixel(x,y) calldll #gdi32, "GetPixel", hDC as ulong, x as long, y as long, getPixel as long end function
There is a lot of code in the demo its just the last two functions you need to use. flooffill(x,y,target,replacement) will start at the point you give it and flood the target color with the replacement color.
|
|
rwg
New Member
Posts: 49
|
Post by rwg on Apr 2, 2020 19:10:28 GMT -5
again thanks for your help Rod. i think all the api stuff is beyond me. i've boiled down what i was trying to achieve, and attach the following code. many thanks
'create a graphics window WindowWidth = 740:WindowHeight = 750 UpperLeftX=650:UpperLeftY=1 OPEN "fill a triangle" for graphics as #1
'set a color #1 "down" #1 "backcolor red"
'create three verticies and fill triangle with red j=hwnd(#1) calldll #user32, "GetDC",_ j as ulong,_ k as ulong x1=350:y1=350 x2=500:y2=350 x3=500:y3=100 STRUCT PolyPoints,_ x1 as long,_ y1 as long,_ x2 as long,_ y2 as long,_ x3 as long,_ y3 as long nCount=3
PolyPoints.x1.struct = x1 PolyPoints.y1.struct = y1 PolyPoints.x2.struct = x2 PolyPoints.y2.struct = y2 PolyPoints.x3.struct = x3 PolyPoints.y3.struct = y3
calldll #gdi32, "Polygon",_ k as ulong,_ PolyPoints as struct,_ nCount as long,_ result as long
calldll #user32, "ReleaseDC",_ j as ulong,_ k as ulong,_ ret as long
'print to default printer #1,"FLUSH" #1,"PRINT"
wait
|
|
|
Post by Rod on Apr 3, 2020 3:35:48 GMT -5
Ok, the simplest solution first. This copys the screen and redraws it so creating the graphic segment we need to print. It is the simplest solution but, it needs the graphics to be visible on screen. If you are going to be drawing graphics off screen and using scrollbars we will need a different solution.
'create a graphics window 'I will use a graphic box because it is cleaner 'by that I mean the client area is easier to discern 'look at the window and the graphic box and the 'difference in sizes The window has theme settings and margins 'and scrollbars. The graphicbox just has a pixel border ' nomainwin graphicbox #1.gb, 10, 10, 720, 730 WindowWidth = 760:WindowHeight = 790 UpperLeftX=650:UpperLeftY=1 OPEN "fill a triangle" for window as #1 #1 "trapclose [end]"
'set a color #1.gb "down" #1.gb "backcolor red"
'create three verticies and fill triangle with red j=hwnd(#1.gb) calldll #user32, "GetDC",_ j as ulong,_ k as ulong x1=350:y1=350 x2=500:y2=350 x3=500:y3=100 STRUCT PolyPoints,_ x1 as long,_ y1 as long,_ x2 as long,_ y2 as long,_ x3 as long,_ y3 as long nCount=3
PolyPoints.x1.struct = x1 PolyPoints.y1.struct = y1 PolyPoints.x2.struct = x2 PolyPoints.y2.struct = y2 PolyPoints.x3.struct = x3 PolyPoints.y3.struct = y3
calldll #gdi32, "Polygon",_ k as ulong,_ PolyPoints as struct,_ nCount as long,_ result as long
'now trap the drawn polygon into a segment 'to do this we simply copy the entire screen and repaint it #1.gb "getbmp bmp 0 0 718 728"'less the borders #1.gb "cls ; drawbmp bmp 0 0" #1.gb "flush"
'now to print it we need to set the print size parameter 'since your window is 720 we will use 750 to fill the printed page 'and leave a bit of a margin. Other values would increase or 'decrease the printed size, experiment.
#1.gb "print 750" wait
[end] calldll #user32, "ReleaseDC",_ j as ulong,_ k as ulong,_ ret as long close #1 end
|
|
rwg
New Member
Posts: 49
|
Post by rwg on Apr 3, 2020 23:56:38 GMT -5
thanks Rod. the bitmap solution is certainly ok if my plot wholly within the graphics window. i've had a play at using your "floodfill" solution. my plots may have a number of filled triangles and circle segments, all of different colors. sometimes there maybe no fills, just lines and points. so i've just inserted these lines into my program to achieve a solution of sorts. to print a 740x750 graphics window from my laptop takes 11 minutes and 20 seconds. many thanks
INPUT " *(N) Print filled polygons Y/N : ";A$ IF A$="" OR A$="N" OR A$="n" THEN GOTO [NOPOLYPLOTS] global hDC,hWnd hWnd=hwnd(#5) calldll #user32, "GetDC", hWnd as ulong, hDC as ulong FOR x=1 TO 740 FOR y=1 TO 750 calldll #gdi32, "GetPixel", hDC as ulong, x as long, y as long, getPixel as long IF getPixel=255 THEN print #5,"color red":print #5,"SET ";STR$(x);" ";STR$(y) IF getPixel=0 THEN print #5,"color black":print #5,"SET ";STR$(x);" ";STR$(y) 'etc etc for all possible colors NEXT y NEXT x [NOPOLYPLOTS] #5 "FLUSH" #5 "PRINT XGA" wait
|
|
|
Post by Rod on Apr 4, 2020 2:09:37 GMT -5
I would persevere with the floodfill function I posted. Give it xy coordinates inside your polygon and the color to replace, the target color and the colour to paint instead, the replacement color. Then it will flood fill the polygon only. So it will be a little quicker than assessing all points.
|
|
|
Post by tenochtitlanuk on Apr 4, 2020 5:33:43 GMT -5
For me, working under Linux/Wine, 'getbmp' just gets the blank area and not the graphics. However it is easy to screengrab the area of interest with suitable software- for me, GIMP. Following example off my site.. nomainwin
WindowWidth =550 WindowHeight =550
graphicbox #w.gb, 20, 5, 500, 500
open "Fill-me" for window as #w
#w.gb "trapclose quit"
hw =hwnd( #w.gb) ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< calldll #user32, "GetDC", hw as ulong, hdc as ulong ' <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
filedialog "Choose a 500x500 BMP", "ol2.bmp", fn$ loadbmp "scr", fn$
#w.gb "down" #w.gb "drawbmp scr 0 0" #w.gb "flush"
calldll #kernel32, "Sleep", 2000 as long, ret as void ' flood-fill the areas one at a time at 10/second."
for i =1 to 20 r =int( 256 *rnd( 1)) g =int( 256 *rnd( 1)) b =int( 256 *rnd( 1)) fillCol$ =str$( r) +" " +str$( g); " " +str$( b) if fillCol$ <>"0 0 0" then #w.gb "color "; fillCol$; " ; up ; backcolor "; fillCol$
xVar =int( 500 *rnd( 1)) yVar =int( 500 *rnd( 1)) targetcolor =0 ' this is the colour of the outline to fill out to.
calldll #gdi32, "ExtFloodFill",_ hdc as ulong,_ xVar as long,_ yVar as long,_ targetcolor as long,_ _FLOODFILLBORDER as long,_ ' ' ie fill out 'til this colour is met... <<<<<<<<<<<<<<<<<<<<<<<<<< result as long
calldll #kernel32, "Sleep", 100 as long, ret as void scan end if next i
#w.gb "flush ; getbmp scr 0 0 500 500" bmpsave "scr", "fillDemo.bmp" #w.gb "cls ; drawbmp scr 0 0" #w.gb "print 800"
wait
sub quit h$ calldll #user32, "ReleaseDC", hw as ulong, hdc as ulong, ret as void 'release the DC <<<<<<<<<<<<<<<<<<<<< close #w end end sub
Copy the code and bitmap to the same directory. NOTE LB prints to your default printer- I set it to print to PDF when testing to avoid wasting paper. EDIT It DOES work if I use... #w.gb "flush ; getbmp scr 0 0 500 500" bmpsave "scr", "fillDemo.bmp" #w.gb "cls ; down ; drawbmp scr 0 0 ; flush" #w.gb "print 800"
|
|
|
Post by Rod on Apr 4, 2020 9:33:44 GMT -5
Having written some example code I am finding that getPixel only seems to work if the pixel is actually visible. Rather like getbmp. So my solution for off screen drawing needs work. You can draw off screen and print. This code shows it can be done. So what you perhaps need is a native routine for filled polygons. I am sure there are examples.
So we need a polygon routine added to this code if anyone is up for the challenge or has example code already.
I am reminded that to print large offscreen graphics you need to draw and flush once but also start with a big outline box drawing to define the size of the "canvas"
ImageWidth = 4958 ImageHeight = 7015 midW=int(ImageWidth/2) midH=int(ImageHeight/2) nomainwin WindowWidth = 400 WindowHeight = 400 UpperLeftX = (DisplayWidth-WindowWidth)/2 UpperLeftY = (DisplayHeight-WindowHeight)/2 graphicbox #1.g, 50,50,300,300 open "Graphics Printing" for window_nf as #1 #1 "trapclose [quit]"
#1.g "down ; place 0 0; color black ; box ";ImageWidth;" ";ImageHeight #1.g "place ";midW;" ";midH #1.g "circle ";midW #1.g "place ";midW;" ";midH #1.g "circle ";midH #1.g "place ";midW;" ";midH for n=0 to 255 #1.g "color ";n;" 255 255 ; circle ";n next #1.g "font ariel 24" #1.g "color black ; backcolor white ;\Hello" #1.g "flush" #1.g "print 4960"
wait
[quit] close #1 end
'http://lbpe.wikispaces.com/GraphicPrinting 'http://lbpe.wikispaces.com/GraphicPrinting2
So the OP question was about printing without resorting to getbmp drawbmp and as it now turns out getPixel!
|
|
rwg
New Member
Posts: 49
|
Post by rwg on Apr 5, 2020 0:15:42 GMT -5
thanks tenochtitlanuk - i'm working through that one. and shame about the getPixel situation Rod. If you come across a native routine that can overcome my dilemma I would be grateful if you could let me know. regards rwg
|
|
rwg
New Member
Posts: 49
|
Post by rwg on Apr 5, 2020 18:29:36 GMT -5
Rod - it would solve my problem if LB added a command called say print #handle "trifilled x1 y1 x2 y2 x3 y3" , where the x and y's are the verticies of a triangle. like "boxfilled" , "circlefilled" , and "piefilled" , the filled areas off screen would be printed. pretty much all shapes can be split up into triangles by hook or by crook, so a "trifilled" command would be beneficial to many. regards rwg
|
|
|
Post by Rod on Apr 6, 2020 1:55:06 GMT -5
Yes a polygon fill or even a triangle fill command would be a great addition. We can roll our own have a browse here justbasiccom.proboards.com/thread/469/filled-polygonsHowever I have thought of a quicker fix. You need two windows. One to use your API drawing code on which should be visible. A second graphicbox window will be the main but unseen drawing window. Then you just getbmp from the visible drawing window and drawbmp to the main. The drawing window need not be visible for long it can just pop up when it’s needed. I will code a demo sometime today.
|
|
|
Post by Rod on Apr 6, 2020 2:52:53 GMT -5
Ok this is fast but it comes with the burden of organizing the drawing and placing of the bmp. You would just keep reusing the #2 window to draw and then place your API drawing. Perhaps one of the polygon routines, though slower, will integrate better.
ImageWidth = 4958 ImageHeight = 7015 midW=int(ImageWidth/2) midH=int(ImageHeight/2) nomainwin WindowWidth = 400 WindowHeight = 400 UpperLeftX = (DisplayWidth-WindowWidth)/2 UpperLeftY = (DisplayHeight-WindowHeight)/2 graphicbox #1.g, 50,50,300,300 open "Graphics Printing" for window_nf as #1 UpperLeftX=UpperLeftX-500
open "Drawing Window" for graphics_nf_nsb as #2 #1 "trapclose [quit]" #2 "down"
'get the DC for #2 hWindow=hwnd(#2) calldll #user32, "GetDC",_ hWindow as ulong,_ hDeviceContext as ulong
'we draw to the graphicbox normally if it is a Liberty drawing command #1.g "down ; place 0 0; color black ; box ";ImageWidth;" ";ImageHeight #1.g "place ";midW;" ";midH #1.g "circle ";midW #1.g "place ";midW;" ";midH #1.g "circle ";midH #1.g "place ";midW;" ";midH for n=0 to 255 #1.g "color ";n;" 255 255 ; circle ";n next #1.g "font ariel 48" #1.g "color black ; backcolor white ;\Hello"
'if we want to use API drawing we need to draw to a visible window 'create three verticies and fill triangle with red #2 "backcolor red"
x1=0:y1=250 x2=250:y2=250 x3=250:y3=0 STRUCT PolyPoints,_ x1 as long,_ y1 as long,_ x2 as long,_ y2 as long,_ x3 as long,_ y3 as long nCount=3
PolyPoints.x1.struct = x1 PolyPoints.y1.struct = y1 PolyPoints.x2.struct = x2 PolyPoints.y2.struct = y2 PolyPoints.x3.struct = x3 PolyPoints.y3.struct = y3
calldll #gdi32, "Polygon",_ hDeviceContext as ulong,_ PolyPoints as struct,_ nCount as long,_ result as long
'now get and draw then bmp image #2 "getbmp bmp 0 0 250 250" #1.g "drawbmp bmp 500 500"
'now flush and print 'this demo packs a massive 5000 pixels 'across the printed page. If you use a 'smaller value for size the triangle and text 'will be larger, experiment. Just remember the size 'parameter spreads your choosen pixel width across 'the entire printed page 1000 pixels size = 1000 #1.g "flush" #1.g "print 4960"
wait
[quit] calldll #user32, "ReleaseDC",_ hWindow as ulong,_ hDeviceContext as ulong,_ ret as long close #2 close #1 end
'http://lbpe.wikispaces.com/GraphicPrinting 'http://lbpe.wikispaces.com/GraphicPrinting2
|
|
|
Post by Rod on Apr 6, 2020 6:21:19 GMT -5
Here is Andy's triangle sub. Have not seen Andy for a while, missing classic solutions like his.
This is pretty fast and flexible, because it is using line drawing it will be in the segment and printable.
nomainwin
WindowWidth = 800 WindowHeight = 600 open "filledTriangle" for graphics_nsb as #main #main "trapclose [quit]" #main "down"
x1=350:y1=350 x2=500:y2=350 x3=500:y3=100
call fillTriangle x1, y1, x2, y2, x3, y3,"red"
wait
[quit] close #main end
'Title: Filled Triangle Sub 'Programmer: JB port by Andy Amaya 'Date: 2010.10.27 Sub fillTriangle x1, y1, x2, y2, x3, y3,col$ 'set the color #main "color ";col$
'triangle coordinates must be ordered: where x1 < x2 < x3 If x2 < x1 Then x = x2 : y = y2 : x2 = x1 : y2 = y1 : x1 = x : y1 = y
'swap x1, y1, with x3, y3 If x3 < x1 Then x = x3 : y = y3 : x3 = x1 : y3 = y1 : x1 = x : y1 = y
'swap x2, y2 with x3, y3 If x3 < x2 Then x = x3 : y = y3 : x3 = x2 : y3 = y2 : x2 = x : y2 = y
If x1 <> x3 Then slope1 = (y3-y1)/(x3-x1)
'draw the first half of the triangle length = x2 - x1 If length <> 0 Then slope2 = (y2-y1)/(x2-x1) For x = 0 To length #main "Line ";Int(x+x1);" ";Int(x*slope1+y1);" ";Int(x+x1);" ";Int(x*slope2+y1) Next End If
'draw the second half of the triangle y = length*slope1+y1 : length = x3-x2 If length <> 0 Then slope3 = (y3-y2)/(x3-x2) For x = 0 To length #main "Line ";Int(x+x2);" ";Int(x*slope1+y);" ";Int(x+x2);" ";Int(x*slope3+y2) Next End If End Sub
|
|