Elora
New Member
Posts: 18
|
Post by Elora on Nov 17, 2018 19:39:16 GMT
At the bottom of the page in the link is a nearly complete list of commands for Justbasic
Although the above is missing a few simple things like "flush" and a couple others I forgot while going through the process of signing up in the forum, so I'm still hoping to find a specific standard functionality, such as the built-in command to read RGB information from on-screen coords.
My avatar is a render from a generator that makes specific things I made a couple years ago in this language.
Anyway, in coding generators for specific things, I often want to read the on-screen color information of a sizeable chunk of the displayed screen, as currently all the image data is stored in an array, but when loading a 1kx1k bitmap file, the bitmap information can be placed on screen, but the generator has no way of moving the displayed information into the array for processing.
|
|
|
Post by B+ on Nov 17, 2018 20:04:10 GMT
The BASIC POINT command does not come with JB but tsh73 has come up with this: GetPixelValue$ function
open "test" for graphics as #gr #gr "trapclose [quit]" #gr "home; down; posxy cx cy"
#gr "font times_new_roman italic 24 " #gr "\x" #gr "place ";cx+14;" ";cy+7 #gr "font times_new_roman italic 16 bold" #gr "\B" #gr "flush"
i = 0 maxXLtr=22 print "maxXLtr=";maxXLtr print "dim ltr$(maxXLtr) 'Times New Roman italic via GetPixelValue$ " for y = cy-15 to cy-15+maxXLtr-1 SCAN i =i+1 print "ltr$(";using("##",i);")="+chr$(34); for x = cx-2 to cx+28 c$=" " ' if GetPixelValue$(x, y, "#gr")=" 0 0 0" then c$="*" if GetPixelValue$(x, y, "#gr")<>"255 255 255" then c$="*" print c$; next print chr$(34) next
wait
[quit] close #gr end
'------------------------------ 'GetPixelValue$ returns a string with the RGB values of the pixel 'in coordinates x and y in window/graphicbox names handle$ (e.g, "#main.graph") function GetPixelValue$(x, y, handle$)
'Grab a 1*1 bitmap #handle$, "getbmp gpv "; x; " "; y; " "; 1; " "; 1
'Save in a bmp file bmpsave "gpv", "getpvaluetemp.bmp"
'Open the file for string input and get it's full contents open "getpvaluetemp.bmp" for input as #gpv s$ = input$(#gpv, lof(#gpv)) close #gpv
'Check if user's display is 32-bit, and read the red-green-blue values 'If display 16 bit, then colors are masked. So some last (3 for red, 2 for green, 3 for blue) bits always 0 'That means that you did not get 255 255 255 for white - (248 252 248) instead. You have to experiment 'otherwise function returns nothing (support for other display types could be added (?)) bpp = asc(mid$(s$, 29, 1)) select case bpp case 32 red = asc(mid$(s$, 69, 1)) green = asc(mid$(s$, 68, 1)) blue = asc(mid$(s$, 67, 1)) case 24 red = asc(mid$(s$, 57, 1)) green = asc(mid$(s$, 56, 1)) blue = asc(mid$(s$, 55, 1)) case 16 bytes = asc(mid$( s$, 67, 1)) + 256*asc(mid$( s$, 68, 1)) red = (bytes AND 63488) /256 '0xF800 green = (bytes AND 2016) / 32 * 4 '0x7E0 blue = (bytes AND 31) * 8 '0x1F end select
'concatenate the return value, delete temporary file and free memory GetPixelValue$ = using("###",red)+using("####",green)+using("####",blue) kill "getpvaluetemp.bmp" unloadbmp "gpv" end function
|
|
|
Post by B+ on Nov 17, 2018 20:07:30 GMT
BTW nice avatar! Welcome to the forum.
|
|
Elora
New Member
Posts: 18
|
Post by Elora on Nov 17, 2018 20:36:32 GMT
Hi and thanks for the welcome! I was kind of afraid that post would come up as I do not intend to save/load/delete literally a million files to my harddrive (1k x 1k) for every time I want to check the onscreen information. However manually parsing the original 1k x 1k file for the color information is likely to be the way to do it, since any color information originating within the program would just stay in the array. I was hoping not to have to manually parse the bmp file format, and am more likely to create a personal file format for internal program use, either that or would be inclined to create a read/write system for something current like PNG, but would still tend to create a personal file format in that case as well.
Maybe there is a way to apply the rule xor and draw over a point twice to somehow get a trace on the information displayed on screen.
I previously tried the Get command applied directly to the window (defined as: open "" for graphics_nsb as #1), but it insisted that the command is used only for file i/o system.
|
|
|
Post by Rod on Nov 17, 2018 21:17:55 GMT
There are drawing modes that take notice of the current pixel info. But that is drawing by rule semi blind. If you need to know the pixel color then the file analysis method works. But it is cumbersome and slow. As is the API method available in Liberty BASIC which is really driven by the current complexity of Windows. So finding a pixel color st the click of a mouse at mouse click speed is possible. Janet has posted a Capitals of the US program that uses color differences to ID States. But processing many pixels becomes slow, very slow. Bit like the flood fill API.
But if you explain the task you might get better advice on how to check the color. Since you are painting the color, remembering it is usually the fastest option.
|
|
|
Post by tsh73 on Nov 17, 2018 21:20:14 GMT
Here's code to read whole bitmap You can read and store it into array - when to do whatever you want, not reading 1x1 pixel files all the time. Old forum had codes that read whole bitmap and processed that - and it was faster then I expected. Using 32 bit BMP format has good points - it's uncompressed (== easy and fast), and you can view/ read /write your files with ordinary tools. Now making your own file format will give you - as for please explain what you are hope to get. 'read BMP pixel by pixel 'by tsh73 'compiled from various sources (sources in C and QB) to Just Basic 1.01 '10 May 2007 'released to public domain ' - to all Just Basic users who find this interesting (or useful)
'all color depths I've seen (1, 4, 8 and 24) 'no compression 'examples created by Gimp from very old file of unknown origin YROSE.JPG
filedialog "Open BMP file", "*.bmp", fname$ open fname$ for binary as #1 print "File "+stripPath$(fname$) +" length is ";lof(#1)
print " ======= BMPHeader ============" print "ValidID (first 2 bytes) is: (should be BM)";tab(45);readStr$(2) print "fileSize";tab(45);readLong() print "reserved";tab(45);readLong() offset = readLong() print "offset";tab(45);offset print " ======= WindowsInfoHeader ===========" print "SizeOfHeader (should be 40)";tab(45); readLong() BMwidth = readLong() print "width";tab(45); BMwidth BMheight = readLong() print "height";tab(45); BMheight print "planes (should be 1)" ;tab(45);read2Bytes() bpp = read2Bytes() print "BitsPerPixel (bpp)";tab(45); bpp CompressMethod = readLong() print "CompressMethod";tab(45); CompressMethod;" ";word$("Uncompressed|8 Bit RLE Compression|4 Bit RLE Compression|bi_bitfields",CompressMethod+1,"|") imagebytes = readLong() print "imagebytes";tab(45); imagebytes print "xres";tab(45); readLong() print "yres";tab(45); readLong() colch = readLong() print "ColorsUsed";tab(45); colch ' could be 0 - All Used print "ImportantColors";tab(45); readLong()
print " ======= calculated info ===========" currPos = LOC(#1) print "curr pos is ";tab(45);currPos print "for palette left ";tab(45); offset - currPos print "for palette colors ";tab(45); (offset - currPos)/4 ' == colch if colch = 0 then colch = (offset - currPos)/4 '??? 'because it could be 0 - All Used print "imagebytes + offset " ;tab(45); imagebytes + offset
byteWidth = BMwidth*bpp/8 if int(byteWidth)<> byteWidth then byteWidth= int(byteWidth)+1 actualWidth = byteWidth if actualWidth mod 4 <>0 then actualWidth = actualWidth + 4-actualWidth mod 4 'padded to 4 bytes print "line length in bytes ";tab(45);actualWidth print "imagebytes / line length in bytes ";tab(45);imagebytes / actualWidth
if inlist(CompressMethod, "1,2") then print "Compressed bitmaps (RLE encoding) are not supported" close #1 end end if
if not(inlist(bpp,"1,4,8,16,24,32")) then print "Color depth (bits per pixel, bpp) other then 1,4,8,16,24,32 is not supported" close #1 end end if
if colch = 0 then print " ======= No palette present ===========" goto [skipPalette] end if
'** palette goes here dim rpal(255),gpal(255),bpal(255),spal$(255) for i = 0 to colch-1 bpal(i) = readByte() gpal(i) = readByte() rpal(i) = readByte() spal$(i) = str$( rpal(i))+" "+str$( gpal(i))+" "+str$( bpal(i)) 'print spal$(i) dummy$ = input$(#1, 1) 'skip one byte next i
if CompressMethod = 3 then print "Color masks are:" i = 0 redMask = ((rpal(i)*256)+ gpal(i))*256+ bpal(i) print "Red"; tab(8); hex$(redMask) i = 1 greenMask = ((rpal(i)*256)+ gpal(i))*256+ bpal(i) print "green";tab(8); hex$(greenMask) i = 2 blueMask = ((rpal(i)*256)+ gpal(i))*256+ bpal(i) print "blue"; tab(8); hex$(blueMask) end if
'show palette WindowWidth = 400 WindowHeight = 400 open "Palette" for graphics_nf_nsb as #pal print #pal, "trapclose [endPalette]"
for i =0 to 15 for j =0 to 15 y = i*20+20 x = j*20+20 x1 = x+15 y1 = y+15 ind = i*16+j if ind > colch-1 then exit for print #pal, "backcolor ";spal$(ind) print #pal, "up" print #pal, "goto ";x;" ";y print #pal, "down" print #pal, "boxfilled ";x1;" ";y1
next j if ind > colch-1 then exit for next i print #pal, "flush" 'make the graphics stick print " ======= palette present ===========" print colch; " colors" print "close palette window to view image" wait
[endPalette] close #pal
[skipPalette]
startTime = time$("ms") '** now the picture itself... WindowWidth = BMwidth+8 ' + window border 'WindowHeight = BMheight+20 ' + window header, win2000 style WindowHeight = BMheight+34 ' + window header, XP style open "picture" for graphics_nf_nsb as #gr1 'print #gr1, "trapclose Quit" print #gr1, "trapclose [gr1End]" print #gr1, "down" 'ready to draw print #gr1, "north ; turn 90"
oldInd = 999 'magic FOR y = BMheight-1 TO 0 step -1 ' Countdown for upsidedown image aLine$ = readStr$(actualWidth) print #gr1, "place 0 ";y FOR x = 0 TO BMwidth-1 select case bpp case 1 byte = asc(mid$( aLine$, int(x/8)+1, 1)) ' pos = 7 - x mod 8 ' pow2 = 2^pos ' if (byte and pow2) <> 0 then ' ind = 1 ' else ' ind = 0 ' end if ind = ((byte and (2^(7 - x mod 8))) <> 0) if oldInd <> ind then print #gr1, "color "; spal$(ind) oldInd = ind end if print #gr1, "go 1" case 4 byte = asc(mid$( aLine$, int(x/2)+1, 1)) if x mod 2 <> 0 then ind = byte mod 16 else ind = int(byte / 16) end if if oldInd <> ind then print #gr1, "color "; spal$(ind) oldInd = ind end if print #gr1, "go 1" case 8 ind = asc(mid$( aLine$, x+1, 1)) if oldInd <> ind then print #gr1, "color "; spal$(ind) oldInd = ind end if print #gr1, "go 1"
case 16 bytes = byte2Num(mid$( aLine$, 2*x+1, 2)) 'if CompressMethod = 3 then r = (bytes AND redMask) /256 g = (bytes AND greenMask) / 32 * 4 b = (bytes AND blueMask) * 8 'end if print #gr1, "color ";r;" ";g;" ";b print #gr1, "go 1" case 24 r = asc(mid$( aLine$, 3*x+3, 1)) g = asc(mid$( aLine$, 3*x+2, 1)) b = asc(mid$( aLine$, 3*x+1, 1)) print #gr1, "color ";r;" ";g;" ";b print #gr1, "go 1" case 32 r = asc(mid$( aLine$, 4*x+3, 1)) g = asc(mid$( aLine$, 4*x+2, 1)) b = asc(mid$( aLine$, 4*x+1, 1)) print #gr1, "color ";r;" ";g;" ";b print #gr1, "go 1" end select NEXT x next y
print #gr1, "flush" 'make the graphics stick 'print #gr1, "redraw" endTime=time$("ms") print print "Drawing BMP (not incl. palette) took "; print endTime-startTime; " milliseconds" close #1
wait
[gr1End] close #gr1
end
' some functions ********************************************8 function readByte() readByte = asc(input$(#1, 1)) end function
function readLong() readLong = byte2Num(input$(#1, 4)) end function
function read2Bytes() read2Bytes = byte2Num(input$(#1, 2)) end function
function readStr$(n) readStr$ = input$(#1, n) end function
function byte2Num(c$) res = 0 for i = len(c$) to 1 step -1 'lower byte first res = res * 256+asc(mid$(c$,i,1)) next i byte2Num = res end function
function stripPath$(fname$) found = 0 for i = len(fname$) to 1 step -1 c$=mid$(fname$,i,1) 'print i; c$, if c$="\" then found = 1 exit for end if next i if found then stripPath$ = mid$(fname$,i+1) else stripPath$ = fname$ end if end function
function inlist(aVal, list$) list$ = ","+list$+"," inlist = (instr(list$, ","+str$(aVal)+",")<>0) end function
Function hex$(n) h$ = "" do h$ = mid$("0123456789ABCDEF", (n mod 16)+1, 1) + h$ n = int(n/16) loop while n > 0 hex$ = h$ End Function
|
|
Elora
New Member
Posts: 18
|
Post by Elora on Nov 18, 2018 0:46:59 GMT
Thank you for your helpfulness, it's mostly a tangent exploration of curiosity as I wanted to see how some of the functions in my generator would process certain types of information, specifically to see if I could sharpen the details in this ancient photo, as a benchmarking test: en.wikipedia.org/wiki/Roswell_UFO_incident#/media/File:Gen_Ramey_Roswell_memo_1947.jpg Of course the subject matter is meaningless as my interest is in the algorithm's performance. processing many pixels becomes slow, very slow. Bit like the flood fill API. But if you explain the task you might get better advice on how to check the color. Since you are painting the color, remembering it is usually the fastest option. A lot of time can be shaved off of generation times, in all sorts of various ways, such as ASL and ASR when applicable, and usually using the system clock to benchmark the speed of alternate methods. Saving the drawing pass as the last step can also save a lot of redundant plotting as it has the highest overhead.
|
|
|
Post by tenochtitlanuk on Nov 18, 2018 9:04:46 GMT
Yes, welcome, Elora.. Image processing is great fun. I've used variations of all the mentioned techniques- arrays, single-pixel getbmp analysis ( originally KC Dan's idea), and the LB call-the-dll. I've also used the ability to call ImageMagick a lot- it's well documented and does everything from scaling, image sharpening, convolution, Fourier.... Luckily I can usually use the time large images may take to process to do something else or have an English 'cuppa tea.! Have a look at some of my LB pages- eg Lena changes!Calling ImageMagicklinkRaster processing'3D' photo processing(LB is a free download, and significantly extends JB. You pay only if you want to unlock a few of the extra commands... especially the runtime engine)
|
|
Elora
New Member
Posts: 18
|
Post by Elora on Nov 24, 2018 17:10:58 GMT
I've been doing some benchmarking to hopefully speed things up, and it occurred to me the print command is as slow as it is because the command has so many functionalities coded into it, that the processor time used to cycle through the options is massively longer than it takes to perform any of the functions.
A 64x64 array with 4096 pixels takes just under a second to print, and that time is with all algorithmic code stripped from the loops, so the overhead of the print command is the largest factor in speed testing.
A long time ago I used the Aurora compiler, and it could handle 64 thousand pixel drawing operations in 1/20 of a second, including all the algorithms to process all the data. There may have been other optimizations, but each command had a specialized functionality.
I'm aware that the print command is designed to handle Turtle graphics, and that is why there are so many different functionalities coded into a single command.
Hypothetically speaking, if printing text were split off as a separate function, it may improve performance, an in the above reference, there was a specialized put-pixel function that handled only one thing, and it was amazingly fast, over 300 times faster than its counterpart in Justbasic. If even a fraction of that increase in speed were achieved, then a full screen render wouldn't take 8 and a half minutes, and the size of the working area could be scaled up.
|
|
|
Post by tsh73 on Nov 24, 2018 20:22:58 GMT
well we REALLY cannot help without seeing some code but you surely can write directly to BMP file and see it it is faster. And if speed is critical then you really could consider using faster language. JB just not that fast from the start.
I have code for writing bitmaps but is is for 256 (paletted) bitmap, not trueColor 32-bit. If you want it I'll post it here.
|
|
|
Post by tsh73 on Nov 24, 2018 20:33:21 GMT
Such kind of benchmark?
N=64 open "test" for graphics as #gr #gr "trapclose [quit]" #gr "down" 'empty run, no graphics drawn t0=time$("ms") randomize .5 for i = 1 to N for j = 1 to N color$=int(rnd(0)*256);" ";int(rnd(0)*256);" ";int(rnd(0)*256) next next t1=time$("ms")
'full run, with graphics drawn randomize .5 for i = 1 to N for j = 1 to N color$=int(rnd(0)*256);" ";int(rnd(0)*256);" ";int(rnd(0)*256) #gr "color ";color$ #gr "set ";i;" ";j next next
t2=time$("ms") #gr "flush" notice "Time taken";chr$(13);"empty ";t1-t0;chr$(13);"with points ";t2-t1
wait [quit] close #gr
|
|
Elora
New Member
Posts: 18
|
Post by Elora on Nov 25, 2018 0:02:58 GMT
Hi, my suggestion directly above postulates a root cause for a portion of the slowness of the language itself, as a helpful gesture, and I posted this thread because I wanted to find out if there was a native command for a particular functionality, which there isn't, and the hope was that a native command without a workaround existed. So it makes no sense whatsoever why you would ask for code in such a circumstance where there the only people with the code for the programming language are the developers of the language itself.
I also thought that having an index of commands would be useful for the forum, which is why I have linked an index of commands for this language in my very first post, to provide the resource that was missing for those who may be new to the language.
|
|
|
Post by B+ on Nov 25, 2018 0:20:05 GMT
Hi Elora, Are you aware that the Help Reference links are working in JB v2.0? Here is a snap of it. The Help materials from that are outstanding!
|
|
|
Post by tsh73 on Nov 25, 2018 6:50:03 GMT
>>Hi, my suggestion directly above postulates a root cause for a portion of the slowness of the language itself, You may be right.
But I am not a Just BASIC developer so I cannot help with that. Noone here can help with that.
There is a possibility that I (we, programmers on forum) could help with code running faster, using such commands that exists in Just BASIC. (It may go only so far, and you as well may have optimized it to the brink. In that case - no, we cannot help you).
|
|