BASIC

Author Topic: Get and store RGB values per pixel on a sprite.  (Read 4532 times)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4212
    • View Profile
    • Portfolio
Hi guys, gotta a question here and am sorry I didn´t try to figure out much by my own yet.
I thought to ask about to who did this before at least to easy some time.

I want to open an image, loadsprite, and create an 3 arrays holding RGB values of it.
So I did loadsprite and am pasting it on 640x480 screen.
I have the required dim variables at r(640x480), g(640x480) and same for b.

What I´m not getting it how to use the GETPIXEL command in a for/next loop to fill up those arrays.
I´m probably missing something here, is this possible in the first place?
 

Offline mentalthink

  • Prof. Inline
  • *****
  • Posts: 3366
  • Integrated Brain
    • View Profile
Hi Erico yes the problem it's when you get the colors you get all the channels at the same time, you have to make a "division" in 2^8,2¹16 and 2²4....

I think in sample forlders we have a project doing this... leave I search beacuse I don't know how doing too  :nana:

Here it's Erico...
http://www.glbasic.com/forum/index.php?topic=1637.msg11177#msg11177


Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4212
    • View Profile
    • Portfolio
...you have to make a "division" in 2^8,2¹16 and 2²4....

What? :O You got to be jocking?

I went to check the link, code is a bit complex on that r,g or b function for me.
But that gives a head on how to approach it, I will check further, thanks! :good:

I must admit I didn´t do much before on checking this, I always thought the GETPIXEL command would deliver something like that but I have never used it.
I did a quick try on 123 basic a couple days ago and I could not work it out, I haven´t checked further but I thought to ask first.

The main reason for knowing how to pull this, is to try write gfx filters. Is that a good approach at all?
It also seems to me that MEM2SPRITE command might be important speed wise somewhere within, but I haven´t used it either.

Anyways, thanks for the answer, the thread is from 2008 so maybe if I just study it I may figure it out.
I wonder if it is possible to read a common shader stuff into GLB, even if it is PC only.
Like read shaders from here maybe?
https://www.shadertoy.com/

 

Offline kanonet

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 1142
    • View Profile
    • My GLBasic code archiv
Sounds like MEM2SPRITE is exactly what you need.
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
MEM2SPRITE/SPRITE2MEM will do what you require, however you will suffer a big performance hit. Somewhere on the forum is a Mandelbrot generator I posted that uses them commands to simulate colour cycling & the frame rate drops to around 30 fps & all that's doing is rotating a table of 256 colours in an array, nothing complex. Both commands add overheads from copying the data from sprite to an array & again back from array to a sprite.

If you want to try & go down that route & need code on the above commands to convert to your array format then let me know but that will incur a performance hit converting the sprite array into the 3 separate arrays you mentioned. If possible it's best to work on the actual array that the sprite commands generate.

GLB doesn't provide support for locked buffer operations hence why SETPIXEL/GETPIXEL are slow, if your could read/write directly to a locked buffer then all manner of pixel effects open up. I know it can be done in SDL but I'm not 100% GLB uses SDL on all platforms & if so how to access it, other than possibly with inline.
Lee

EDIT, found my forum post http://www.glbasic.com/forum/index.php?topic=8670.msg73590#msg73590. Give that a go & see what your FPS does.
« Last Edit: 2014-Aug-21 by fuzzy70 »
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline kanonet

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 1142
    • View Profile
    • My GLBasic code archiv
Actually you di not need SPRITE 2MEM every frame. Just do it once and and then keep it in memory. so just do your manipulations on it and MEM2SPRITE each frame. Still a performance hit, but less then using both commands each time (classic trade memory for performance).
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
True, that was accounting for worse case scenario as don't know exactly what needs to be accomplished.

My mandelbrot prg doesn't use SPRITE2MEM at all as it creates the set directly into the array & MEM2SPRITE is called after the colours have been cycled.

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4212
    • View Profile
    • Portfolio
Thanks for all answers.

What I want to do is to have control at each image pixesl on a per RGB base.
Simple things first, to write some code to desaturate an image.

Later I think I would like to try some sort of filters, like detect borders and threshold PB image.
That is for image analysis.

Offline spacefractal

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 3669
    • View Profile
    • Space Fractal
if you want to do that run time, then its can been very slow, and on some systems, its might not even working.

SPRITE2MEM is what you looking for.
Greedy Mouse - Karma Miwa - Spot Race - CatchOut - Android Extras - is on a vacation trip, home before end of few days in jan.

Offline Moru

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 1774
    • View Profile
    • Homepage
...you have to make a "division" in 2^8,2¹16 and 2²4....

What? :O You got to be jocking?


I'm affraid not :-)

Colours are stored in one word, 32 bit. Usually something like this in hexadecimal. Not sure about the colour order though but that you can find out in some example or the documentation or just try it out :-)

0xAARRGGBB
A = Alpha channel
R = Red
G = Green
B = Blue

To separate out the different colours from the combined value you need to divide by 256 for each value and then isolate it.

I'm sure you have figured this out already by now but here it is anyway:

To get the separate colour channels you just use a bitmask like this: (untested...)

Code: GLBasic [Select]
colour% = 0xffdd99
blue% = BAND( colour%, 0xFF)
green% = BAND( (colour% / 0x100), 0xFF)
red% = BAND( (colour% / 0x10000), 0xFF)
alpha% = BAND( (colour% / 0x1000000), 0xFF)
 

Dividing with hexadecimal 256 (0x100) is just like when we divide decimal 100 to move the decimal point two steps to the left.
Try it out with the windows calculator in programmer mode and you see what I mean :-)

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Get and store RGB values per pixel on a sprite.
« Reply #10 on: 2014-Sep-02 »
Here's some example code for you erico that both do the same thing, the 1st uses GETPIXEL & SETPIXEL & the 2nd MEM2SPRITE. All they do is reset the red value to zero so nothing complicated but shows the difference in speed other the 2 methods. I've tried to keep the code as simple as possible with comments & it's intentionally laid out that way so you can see how it works rather than optimal way.

If you don't understand the bitwise operations on modifying the MEM2SPRITE array (bAND) I can explain that in more detail with other examples as to how they work, just PM me or post here & I'll see what I can do.

Example 1, using GET/SETPIXEL, btw the GETPIXEL part takes a long time (~20 seconds on my machine) so don't think the program has crashed just be patient  :D
Code: GLBasic [Select]
GLOBAL sw%=800,sh%=600
GLOBAL loop%
GLOBAL red%[],green%[],blue%[],alpha%[]
GLOBAL pixel_value%
GLOBAL x%,y%
GLOBAL timer,timetaken

DIM   red[sw][sh]
DIM green[sw][sh]
DIM  blue[sw][sh]
DIM alpha[sw][sh]               // Pretty pointless as setpixel has no alpha

SETSCREEN sw,sh,FALSE

// Create some random coloured boxes
        FOR loop = 0 TO 1000

                DRAWRECT RND(300),RND(300),RND(500),RND(500),RGB(RND(255),RND(255),RND(255))

        NEXT

// Loop through the entire screen & read the pixel values into an array
        timer = GETTIMERALL()
       
        FOR x=0 TO sw-1
                FOR y=0 TO sh-1

                        // read the pixel value at x,y
                        pixel_value=GETPIXEL(x,y)

                        // GLB stores pixels in 32bit alpha,blue,green,red format
                        // 1st byte is alpha, 2nd byte green & so on
                        // Read each colour into its respective array
                          red[x][y] = BAND(pixel_value, 0xff)
                        green[x][y] = BAND(ASR(pixel_value,8), 0xff)
                         blue[x][y] = BAND(ASR(pixel_value,16), 0xff)
                        alpha[x][y] = BAND(ASR(pixel_value,24), 0xff)

                NEXT
        NEXT
       
        timetaken = GETTIMERALL()-timer

        PRINT "Pixel colours copied to Array",0,0
        PRINT "Time taken = "+timetaken,0,8
        PRINT "Press any key to continue",0,16

        SHOWSCREEN
        KEYWAIT

// Now to modify the array by removing all the red colour values
        timer = GETTIMERALL()

        FOR x=0 TO sw-1
                FOR y=0 TO sh-1

                        red[x][y] = 0

                NEXT
        NEXT
       
        timetaken = GETTIMERALL()-timer
        PRINT "Colours modified, Press any key to view the result",0,0
        PRINT "Time taken = "+timetaken,0,8
       
        SHOWSCREEN
        KEYWAIT

//Now to draw the array back to screen
        timer = GETTIMERALL()
       
        FOR x=0 TO sw-1
                FOR y=0 TO sh-1

                        SETPIXEL x,y,RGB(red[x][y],green[x][y],blue[x][y])

                NEXT
        NEXT

        timetaken = GETTIMERALL()-timer
        PRINT "All done, press any key to exit",0,0
        PRINT "Time taken = "+timetaken,0,8
       
        SHOWSCREEN
        KEYWAIT

 

Example 2, using MEM2SPRITE
Code: GLBasic [Select]
GLOBAL sw%=800,sh%=600
GLOBAL loop%
GLOBAL x%,y%
GLOBAL timer,timetaken
GLOBAL memsprite%[]

DIM memsprite[sw*sh]

SETSCREEN sw,sh,FALSE

// Create some random coloured boxes
        FOR loop = 0 TO 1000

                DRAWRECT RND(300),RND(300),RND(500),RND(500),RGB(RND(255),RND(255),RND(255))

        NEXT

// Grab the screen as a sprite then load it into memsprite array
// Grab must be done before showscreen as gets the current backbuffer
// If using virtual screens then grabsprite is not required as you
// just pass the screen sprite number to the SPRITE2MEM call
        timer = GETTIMERALL()

        GRABSPRITE 1,0,0,sw,sh
        SPRITE2MEM(memsprite[],1)

        timetaken = GETTIMERALL()-timer

        PRINT "Screen grabbed to Array",0,0
        PRINT "Time taken = "+timetaken,0,8
        PRINT "Press any key to continue",0,16

        SHOWSCREEN
        KEYWAIT

// Now to modify the array by removing all the red colour values
// Since the mem2sprite array is just one dimension you would normally
// loop from 0 to the end of the array. Here I am doing it the same way
// as the getpixel method for consistancy & illustraion purposes
        timer = GETTIMERALL()
       
        FOR x=0 TO sw-1
                FOR y=0 TO sh-1
                       
                        // GLB pixel format is 0xAABBGGRR so as we are just changing the red
                        // value we bAND 0xffffff00 with the current value in array
                        // & that will set only the last byte (in this case the red byte) to 0
                        // leaving the rest untouched
                        memsprite[x + y * sw] = BAND(memsprite[x + y * sw],INTEGER(0xffffff00))

                NEXT
        NEXT

        timetaken = GETTIMERALL()-timer

        PRINT "Colours modified, Press any key to view the result",0,0
        PRINT "Time taken = "+timetaken,0,8
       
        SHOWSCREEN
        KEYWAIT

//Now to draw the array back to screen
        timer = GETTIMERALL()
       
        // Put the array into a sprite then draw the sprite
        MEM2SPRITE(memsprite[],2,sw,sh)
        DRAWSPRITE 2,0,0

        timetaken = GETTIMERALL()-timer
       
        PRINT "All done, press any key to exit",0,0
        PRINT "Time taken = "+timetaken,0,8
       
        SHOWSCREEN
        KEYWAIT

 

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)

Offline Hemlos

  • To boldy go where no pixel has gone before!
  • Global Moderator
  • Prof. Inline
  • *******
  • Posts: 1634
  • Particle Hawk
    • View Profile
Re: Get and store RGB values per pixel on a sprite.
« Reply #11 on: 2014-Sep-02 »
cool stuff on this thread...

hey erico, look inside my program "image2object"
it has routines for dealing with the colors, and scanning images.

http://www.glbasic.com/showroom.php?site=games&game=Image2Object


ps. yes getpixel is slow...its also inacurate!
« Last Edit: 2014-Sep-02 by Hemlos »
Volume_of_Earth(km^3) = 4/3*3.14*POW(6371.392896,3)

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4212
    • View Profile
    • Portfolio
Re: Get and store RGB values per pixel on a sprite.
« Reply #12 on: 2014-Sep-06 »
SUPER! Thanks you for the hand, that is probably something that would take me quite a while to figure out my own if ever.

Hey Fuzzy, I will experiment them on this weekend and post back here the results, thanks again! :good:

Offline erico

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 4212
    • View Profile
    • Portfolio
Re: Get and store RGB values per pixel on a sprite.
« Reply #13 on: 2014-Nov-09 »
heck, haven´t give it a go yet...I must at some point these months.
Thanks all for the help.

Damn those hex crack my mind.

Offline fuzzy70

  • Community Developer
  • Prof. Inline
  • ******
  • Posts: 828
  • Look left, Look right, LOOK OUT!!
    • View Profile
Re: Get and store RGB values per pixel on a sprite.
« Reply #14 on: 2014-Nov-09 »
Damn those hex crack my mind.

HEX is one of those odd things to get going with, but when "The Penny Drops" so to speak it can make a lot of things easier. Binary is another one, however it can become a bit of a handful when dealing larger numbers as the more digits used the more chance of making a typo & like HEX it makes certain things a lot easier then working in human "Decimal" lol

Lee
"Why don't you just make ten louder and make ten be the top number and make that a little louder?"
- "These go to eleven."

This Is Spinal Tap (1984)