Oxygen Basic
Programming => Example Code => Topic started by: Aaron on March 03, 2014, 09:53:47 AM
-
Hello Easter,
Some new demos.
include "gp.inc"
OpenWindow 320,240,1
fo = LoadFont "verdana",16,3
single fz, vz
skull = LoadImage("png/new_ufo.png",16)
font = LoadTile ("png/font2.png",16,6)
while KeyDown(27)=0
ClsColor Argb(255,0,0,240)
DrawImage skull,80,40,fz
TileText font,112,0,"MY UFO"
DrawText fo,10,220,"Drunken Ufo Navigator!",Argb 255,200,100,0
vz +=.2
if vz >=1 then
vz =0
fz +=1
if fz=16 then
fz=0
end if
end if
Sync
wend
CloseWindow
.
-
New stupid circles.
include "gp.inc"
OpenWindow 640,480,1
sys x, y
Single a
SetSmoothMode 2
while KeyDown(27)=0
ClsColor &HFFFFFFFF
for y=0 to <480 step 40
for x=0 to <640 step 40
DrawCircle x,y,40,1,&HFF000000
DrawCircle x+10,y+10,20,1,&HFF000000
DrawCircle x+15,y+15,10,1,&HFF000000
next
next
for y=0 to <480 step 40
for x=0 to <640 step 40
DrawPoint 20+x+(sin(rad(a)))*20,y+20+cos(rad(a))*20,4, &HFFFF0000
DrawPoint 20+x+(cos(rad(a)))*20,y+20+sin(rad(a))*20,4, &HFF0000FF
next
next
a +=2
if a>=360 then a =-a
Redraw
SetFps 200
wend
CloseWindow
-
Glad to see you posting here again Peter. You were missed.
-
You were missed.
No tears please!
selling snow cones in Antarctica
best sentence of the day ;D
Gdiplus Pixel-speed test
Pixel-test need a new gp.dll
INCLUDE "gp.inc"
OPENWINDOW 320,240,1
'SETSMOOTHMODE 2
CLSCOLOR ARGB 255,255,255,255
FOR y=0,240
FOR x=0,320
SETPIXEL x,y,ARGB 255,RND(32,255),RND(32,255),RND(32,255)
NEXT
NEXT
FILLCIRCLE 100,100,80, GETPIXEL 20,20
FILLRECT 100,20,80,60, GETPIXEL 10,10
WAITKEY
CLOSEWINDOW
.
-
Peter,
Here is your version running under Wine. It started with a transparent window and after 7-10 seconds the following appeared.
(http://files.allbasic.info/O2/o2wine_peterpixel.png)
I took a shot at converting your example to SB GFX. I don't have a get pixel function yet and faked it with a RND.
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_peterpixel.png)
'Peter's Pixel Test - SB GFX
IMPORT gfx.inc
s = gfx::Window(320, 240, "Peter's Pixel Test - SB GFX")
RANDOMIZE(gfx::Time())
gfx::ClearScreen s, 0xffffff
ts = gfx::Time()
FOR y = 0 TO 240
FOR x = 0 TO 320
gfx::pixelRGBA s, x, y, RND() AND 255, RND() AND 255, RND() AND 255, 255
NEXT
NEXT
gfx::filledCircleColor s, 100, 100, 80, RND() AND 255
gfx::boxColor s, 100, 20, 80, 60, RND() AND 255
gfx::Update
te = gfx::Time()
gfx::stringColor s, 20, 215,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
WHILE gfx::KeyName(1) <> "+escape"
WEND
gfx::Close
-
I don't have a get pixel function yet
Hi John,
I have done something like that:
Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Declare Function GetPixelEx Lib "gdi32.dll" Alias "GetPixel" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
string sys_cap = "SDL_app"
long hwnd, hdc
Sub FindWindowSDL()
Hwnd = FindWindow 0, *sys_cap
hdc = GetDC hwnd
End Sub
Function GetPixel(long x, y) as long
Return GetPixelEx hdc, x, y
End Function
-
What I meant was I haven't wrapped the SDL get pixel function yet for the SB GFX ext. module.
-
Okay, I have understood! ;D
-
It was interesting to see the SB GFX module calculate the fill color alpha channel for the circle even though it was in the gray color range. I was happy to see the rendering speed at a 1/10 of a second. Seems GDIPlus is pretty slow. (on Wine ?)
-
Peter,
I tried your pixel test in a VirtualBox XP session and it displayed almost instantly. The problem (slow) seems to be related to Wine. I know OpenGL/SDL runs great under Wine but GDI seems to be a kludge. :-[
(http://files.allbasic.info/O2/peterpixelxp.png)
-
I was able to add a gfx::GetPixel function and did it without locking the surface. I was unable to determine if locking the surface is only needed when creating the pixel.
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_pptgp.png)
'Peter's Pixel Test - SB GFX
IMPORT gfx.inc
s = gfx::Window(320, 240, "Peter's Pixel Test - SB GFX")
RANDOMIZE(gfx::Time())
gfx::ClearScreen s, 0xffffff
ts = gfx::Time()
FOR y = 0 TO 240
FOR x = 0 TO 320
gfx::pixelRGBA s, x, y, RND() AND 255, RND() AND 255, RND() AND 255, 255
NEXT
NEXT
gfx::filledCircleColor s, 100, 100, 80, gfx::GetPixel(s, 20, 20)
gfx::boxColor s, 100, 20, 80, 60, gfx::GetPixel(s, 10, 10)
gfx::Update
te = gfx::Time()
gfx::stringColor s, 20, 215,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
WHILE gfx::KeyName(1) <> "+escape"
WEND
gfx::Close
I think I'm going to have to change my gfx::GetPixel function to return the RGBA color components in a SB passed array. All the pixels were created with the alpha channel at 255 so I should be generating a solid colored circle and box. I think there is a difference in our radius values. I think you are passing full radius value of the circle and I'm passing the radius from the center (origin) of the circle. I haven't looked and the box differences yet.
gfx::GetPixel screen, x, y, color
PRINT "R: ",color[0],"\n"
PRINT "G: ",color[1],"\n"
PRINT "B: ",color[2],"\n"
PRINT "A: ",color[3],"\n"
-
I think there is a difference in our radius values.
Gdiplus does not draws the circle around its center.
That's pitty, I love the centre.
-
I would have never guessed that getting the RGBA color value(s) would be such a complex and elusive task.
If anyone has an example of passing a X and Y position of a pixel in RGBA 32 format and returning it's color value, I would be grateful.
What I'm returning from this function may be correct and all I need to do is get the alpha channel enabled.
videoflags = SDL_HWSURFACE | SDL_SRCALPHA | SDL_RESIZABLE | SDL_DOUBLEBUF;
besFUNCTION(gfx_GetPixel)
DIM AS SDL_Surface PTR this_surface;
DIM AS int x, y;
DIM AS Uint32 PTR pixels;
besARGUMENTS("iii")
AT this_surface, AT x, AT y
besARGEND
pixels = (Uint32 *)this_surface->pixels;
besRETURN_LONG(pixels[(y * this_surface->w) + x]);
besEND
-
Hi John,
'Getting the value of a pixel
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
return *p;
break;
case 2:
return *(Uint16 *)p;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
break;
case 4:
return *(Uint32 *)p;
break;
default:
return 0; /* shouldn't happen, but avoids warnings */
}
}
'Setting the value of a pixel
void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/* Here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp) {
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
} else {
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
-
RGBA 32 is actually the easiest of all. RGB 24 would be much more tiresome.
I'm not very well accustomed to this funny syntax but from what I can see, your function will return exatly what you need. R will be the low-order byte and A will be the high-order byte as is typical for the SDL-compliant color formats; you can then mask out each color and alpha component by AND-ing the return value with &HFF for R, &HFF00 for G, &HFF0000 for B, and &HFF000000 for alpha. Then if you need each component as a separate 32-bit value, you can shift the masked-out value right by a corresponding number of bits, e.g. 24 for alpha, 16 for B, 8 for G, and none for R.
If your color array pixels[] is initialized with zeros then the alpha component of each pixel will be 0 which is completely transparent (invisible). Setting it to 255 will make it completely opaque. The intermittent values will yield varying degrees of transparency. If you decompose your color to separate components, then the algo to reassemble the color will be a direct reverse to what I described above:
// C pseudocode
RGBA32 = (A << 24) + (B << 16) + (G << 8) + R;
RGB 24 is much trickier due to colors being coded in byte triplets (RGBRGB...) rather than quads (RGBARGBA...). Each scan line will also have to be aligned on a DWORD boundary with an arbitrary number of bytes which are not painted but serve as alignment placeholders only. But if course if you're not planning to use RGB 24 then this info is irrelevant for your purposes.
P.S. Hehe, Peter has already given you an exhaustive answer while I was still typing mine. :) However, you need only case 4 from his code and you don't need the pitch parameter or endianness (as long as you code for Intel CPU's) because your colors will always be DWORD's. So you can safely stick to your own implementation of this function.
-
Thanks Mike for the explanation. That clears up a few things for me. I'm going to try and use Charles's SHIFT function he contributed to the project.
Glad to see you posting again after that nasty round with the flu.
@Peter: I have tried the examples you posted but without the info Mike provided it wasn't clear what to expect as a result.
-
You're welcome John and thanks for your care.
I saw your broadcast in my mailbox and I'll email you back tomorrow. I do a quick glance-through of the BASIC forums every day but I hardly post anything unless I have to, and your question was very easy to respond to. The rest will go in my tomorrow's email.
Regards,
-
I think we are close. (guess)
'Peter's Pixel Test - SB GFX
IMPORT gfx.inc
s = gfx::Window(320, 240, "Peter's Pixel Test - SB GFX")
RANDOMIZE(gfx::Time())
gfx::ClearScreen s, 0xffffff
ts = gfx::Time()
FOR y = 0 TO 240
FOR x = 0 TO 320
gfx::pixelRGBA s, x, y, RND() AND 255, RND() AND 255, RND() AND 255, 255
NEXT
NEXT
c = gfx::GetPixel(s, 20, 20)
PRINT "Color: ",c,"\n"
r = c AND 0xff
PRINT "R: ",r,"\n"
g = c AND 0xFF00
PRINT "G: ",g,"\n"
b = c AND 0xFF0000
PRINT "B: ",b,"\n"
a = c AND 0xFF000000
PRINT "A: ",a,"\n"
GOTO done
gfx::filledCircleRGBA s, 100, 100, 80, r, g, b, a
PRINT "Got Here\n"
GOTO done
c = gfx::GetPixel(s, 20, 20)
r = c AND x0FF
g = c AND x0FF00
b = c AND x0FF0000
a = c AND x0FF000000
gfx::boxRGBA s, 100, 20, 80, 60, r, g, b, a
gfx::Update
te = gfx::Time()
gfx::stringColor s, 20, 215,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
WHILE gfx::KeyName(1) <> "+escape"
WEND
done:
gfx::Close
jrs@laptop:~/sb/sb22/gfx$ scriba ppt.sb
Color: 8673871
R: 79
G: 23040
B: 8650752
A: 0
jrs@laptop:~/sb/sb22/gfx$
When I get to the point of getting valid RGBA values, I will print the RGBA values assigned for the pixel locations we retrieve to make sure apples are still apples. :o
-
Hi John,
A quick glance at your code: some bit-shifting is required >>
r = c AND x0FF
g = (c AND x0FF00)>>8
b = (c AND x0FF0000)>>16
a = c >>24
-
Looks good. (guess until validation against values actually used to create the pixel)
I would of thought that the Alpha value would have been 255 as that is how it was created.
c = gfx::GetPixel(s, 20, 20)
PRINT "Color: ",c,"\n"
r = c AND 0xff
PRINT "R: ",r,"\n"
g = gfx::Shift((c AND 0xFF00),-8)
PRINT "G: ",g,"\n"
b = gfx::Shift((c AND 0xFF0000), -16)
PRINT "B: ",b,"\n"
a = gfx::Shift(c, -24)
PRINT "A: ",a,"\n"
jrs@laptop:~/sb/sb22/gfx$ scriba ppt.sb
Color: 3151299
R: 195
G: 21
B: 48
A: 0
jrs@laptop:~/sb/sb22/gfx$
-
I thought I would do some cross checking to validate we are looking at the same pixel and what we set is what we get.
'Peter's Pixel Test - SB GFX
IMPORT gfx.inc
s = gfx::Window(320, 240, "Peter's Pixel Test - SB GFX")
RANDOMIZE(gfx::Time())
gfx::ClearScreen s, 0xffffff
ts = gfx::Time()
FOR y = 0 TO 240
FOR x = 0 TO 320
r = RND() AND 255
g = RND() AND 255
b = RND() AND 255
IF x = 20 AND y = 20 THEN
PRINT "Set R: ",r,"\n"
PRINT "Set G: ",g,"\n"
PRINT "Set B: ",b,"\n"
END IF
gfx::pixelRGBA s, x, y, r, g, b, 255
NEXT
NEXT
c = gfx::GetPixel(s, 20, 20)
PRINT "Color: ",c,"\n"
r = c AND 0xff
PRINT "Get R: ",r,"\n"
g = gfx::Shift((c AND 0xFF00),-8)
PRINT "Get G: ",g,"\n"
b = gfx::Shift((c AND 0xFF0000), -16)
PRINT "Get B: ",b,"\n"
a = gfx::Shift(c, -24)
PRINT "Get A: ",a,"\n"
GOTO done
r = c AND x0FF
g = (c AND x0FF00)>>8
b = (c AND x0FF0000)>>16
a = c >>24
gfx::filledCircleRGBA s, 100, 100, 80, r, g, b, a
PRINT "Got Here\n"
GOTO done
c = gfx::GetPixel(s, 20, 20)
r = c AND x0FF
g = c AND x0FF00
b = c AND x0FF0000
a = c AND x0FF000000
gfx::boxRGBA s, 100, 20, 80, 60, r, g, b, a
gfx::Update
te = gfx::Time()
gfx::stringColor s, 20, 215,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
WHILE gfx::KeyName(1) <> "+escape"
WEND
done:
gfx::Close
jrs@laptop:~/sb/sb22/gfx$ scriba ppt.sb
Set R: 247
Set G: 134
Set B: 201
Color: 16221897
Get R: 201
Get G: 134
Get B: 247
Get A: 0
jrs@laptop:~/sb/sb22/gfx$
-
Easier to verify if you can display in hexadecimal. (the invention of base-10 numbers was an ancient disaster. :) )
-
I swapped R & B but Alpha seems unresponsive. :(
FOR y = 0 TO 240
FOR x = 0 TO 320
r = RND() AND 255
g = RND() AND 255
b = RND() AND 255
IF x = 20 AND y = 20 THEN
PRINT "Set R: ",r,"\n"
PRINT "Set G: ",g,"\n"
PRINT "Set B: ",b,"\n"
END IF
gfx::pixelRGBA s, x, y, r, g, b, 255
NEXT
NEXT
c = gfx::GetPixel(s, 20, 20)
PRINT FORMAT("Color: %0X",c),"\n"
' r = c AND 0xff
r = gfx::Shift((c AND 0xFF0000), -16)
PRINT FORMAT("Get R: %0X",r),"\n"
g = gfx::Shift((c AND 0xFF00),-8)
PRINT FORMAT("Get G: %0X",g),"\n"
' b = gfx::Shift((c AND 0xFF0000), -16)
b = c AND 0xff
PRINT FORMAT("Get B: %0X",b),"\n"
a = gfx::Shift(c, -24)
PRINT FORMAT("Get A: %0X",a),"\n"
GOTO done
jrs@laptop:~/sb/sb22/gfx$ scriba ppt.sb
Set R: 183
Set G: 148
Set B: 238
Color: B794EE
Get R: B7
Get G: 94
Get B: EE
Get A: 0
jrs@laptop:~/sb/sb22/gfx$
-
I'm assuming at this point that the color value being returned doesn't include the alpha channel. I forced it to 255 (solid color) and will call this example completed unless there is something I'm missing. It would be nice to know how to add an alpha value to a returned value from gfx::GetPixel without having to break it down into components. Almost all GFX functions have paired functions. One takes a single color value in the form of 0XRRGGBBAA and the other is passed in its components. Thanks to all that helped get this working!
BTW I thought if I subtracted a known RGB value from a RGBA value, the difference should be the magic number I'm looking for. Not true grasshopper. >:(
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_peterpixel_rgb.png)
'Peter's Pixel Test - SB GFX
IMPORT gfx.inc
s = gfx::Window(320, 240, "Peter's Pixel Test - SB GFX")
RANDOMIZE(gfx::Time())
gfx::ClearScreen s, 0xffffff
ts = gfx::Time()
FOR y = 0 TO 240
FOR x = 0 TO 320
r = RND() AND 255
g = RND() AND 255
b = RND() AND 255
gfx::pixelRGBA s, x, y, r, g, b, 255
NEXT
NEXT
c = gfx::GetPixel(s, 20, 20)
r = gfx::Shift((c AND 0xFF0000), -16)
g = gfx::Shift((c AND 0xFF00),-8)
b = c AND 0xFF
gfx::filledCircleRGBA s, 100, 100, 80, r, g, b, 255
c = gfx::GetPixel(s, 10, 10)
r = gfx::Shift((c AND 0xFF0000), -16)
g = gfx::Shift((c AND 0xFF00),-8)
b = c AND 0xFF
gfx::boxRGBA s, 100, 20, 80, 60, r, g, b, 255
gfx::Update
te = gfx::Time()
gfx::stringColor s, 20, 215,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
WHILE gfx::KeyName(1) <> "+escape"
WEND
gfx::Close
-
I was able to return a pixel color with an alpha value. I had to create a blank surface with pixel masks defined to get an alpha extended value. It looks as if the returned color value is in ABGR. What would the mask / shift be to extract it to a variable in RGBA format?
jrs@laptop:~/sb/sb22/gfx$ scriba ppt.sb
Set R: 88
Set G: 52
Set B: 117
FF753458
-
I think I got this resolved. It looks like the code I used to set the pixel masks in the ext. module for creating a new surface is reversed. Forcing a SDL_BIG_ENDIAN mask set solved the problem so I could use the results of gfx::GetPixel directly which included the alpha channel. It would be nice to be able to define the mask when the initial surface is created. I think this is a bug in SDL 1.2 and the workaround SDL_SetAlpha(screen, SDL_SRCALPHA, 0); didn't seem to work returning alpha values when getting pixel info.
@Peter - Thanks for posting this example which lead to a day of battling with SDL. You forced me to address this crazy pixel unraveling which until now had been successfully avoided. ::)
//IF (SDL_BYTEORDER EQ SDL_BIG_ENDIAN) THEN
rmask = 0xff000000;
gmask = 0x00ff0000;
bmask = 0x0000ff00;
amask = 0x000000ff;
//ELSE
// rmask = 0x000000ff;
// gmask = 0x0000ff00;
// bmask = 0x00ff0000;
// amask = 0xff000000;
//END_IF
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_ppt_final.png)
'Peter's Pixel Test - SB GFX
IMPORT gfx.inc
vs = gfx::Window(320, 240, "Peter's Pixel Test - SB GFX")
s = gfx::CreateSurface(320, 240, 32)
RANDOMIZE(gfx::Time())
ts = gfx::Time()
FOR y = 0 TO 240
FOR x = 0 TO 320
r = RND() AND 255
g = RND() AND 255
b = RND() AND 255
gfx::pixelRGBA s, x, y, r, g, b, 255
NEXT
NEXT
gfx::filledCircleColor s, 100, 100, 80, gfx::GetPixel(s, 20, 20)
gfx::boxColor s, 100, 20, 80, 60, gfx::GetPixel(s, 10, 10)
te = gfx::Time()
gfx::stringColor s, 20, 215,"Time: " & FORMAT("%.4f",(te-ts)/1000) & " Seconds." & CHR(0), 0xffffffff
gfx::BlitSurface s, 0, vs, 0
gfx::Update
WHILE gfx::KeyName(1) <> "+escape"
WEND
gfx::Close
The following example was created with an alpha value of 192.
(http://files.allbasic.info/ScriptBasic/gfx/sbgfxu64_ppt192.png)