Read one pixel

gontran

Member
Joined
Apr 27, 2020
Location
México City
Helo again , I try to find a simple form to read one pixel in my canvas. I don´t need to read a block off pixels.
How can I do this ?

I need to use a databuffer and readpixels function?
I´m using mojo2

Thanks for the help
 
Last edited:

gontran

Member
Joined
Apr 27, 2020
Location
México City
Ok now my problem is this I have
PantallaJuego.ReadPixels(dedox,dedoy,1,1,pixel1)
ok in pixel1 are databuffer. ok now I need to read the content. I try to use GET but cerberus say identifier get not found.
I'm little lost
How can I read the content in my databuffer?

Thanks for the help
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
I can't test here but it should be something like this.

You have a combination of 3 things, a canvas for input (reading pixels), a image for output (plotting), and a data buffer, because you this process is very visible and you need a data buffer to do both the plotting and reading.


Cerberus X:
Import mojo2
Import brl

Class MyApp Extends App

    Field canvas:Canvas
    Field myCanvas:Canvas
    Field myImage:Image
    Field myData:DataBuffer
   
    Method OnCreate:Int()
        canvas = New Canvas()
       
        ' Set up a sprite that you can draw to
        myImage = New Image(256, 256)
        myCanvas = New Canvas(myImage)
        myData = New DataBuffer(256 * 256 * 4)  
    End
   
    Method OnRender:Int()

        ' Draw 256 x 256 green sprite
       
        myCanvas.Clear(0,1,0)

        ' Plot pixel
        myData.PokeInt(0,myData.PeekInt(0) & $00000000) ' Make a pixel in the sprite black (0 is mapped to x & y)
        myImage.WritePixels(0,0,1,1, myData)
        myCanvas.Flush()

        ' Read pixel
        myCanvas.ReadPixels(0,0,1,1,myData)
        Local value:Int = myData.PeekInt(0) ' Read a pixel in the sprite black (0 is mapped to x & y)
   
        ' ---------------------------------------
   
        ' Draw our canvas-image-combo, to main canvas
        canvas.SetBlendMode(BlendMode.Opaque2)
        canvas.Clear(0,0,0)
        canvas.DrawImage(myImage, 50,50)
        canvas.Flush()
    End
   
End

Function Main:Int()
    New MyApp()
End
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
Here is working example that writes and reads a pixel of a green sprite.


I don't know why it looks like there's black area around the pixel though but this is how you read and plot a pixel.

Cerberus X:
Import mojo2
Import brl.databuffer

Class MyApp Extends App

    Field mainCanvas:Canvas
    Field myImage:Image
    Field myData:DataBuffer
    Field myCanvas:Canvas
    
    Method OnCreate:Int()
        mainCanvas = New Canvas()
        myImage = New Image(256, 256)
        myCanvas = New Canvas(myImage)
        myData = New DataBuffer(256 * 256 * 4)
    End
    
    Method OnRender:Int() 
        myCanvas.Clear(0,1,0)         

        ' Plot pixel
        myData.PokeInt(0, $ffffffff)
        myImage.WritePixels(0, 0, 1,1, myData)
        myCanvas.Flush() 
        
        ' Read pixel
        myCanvas.ReadPixels(0, 0, 1,1 myData)
        Local value:Int = myData.PeekInt(0)

        mainCanvas.SetBlendMode(BlendMode.Opaque2)
        mainCanvas.Clear()   
        mainCanvas.DrawImage(myImage, 200,200)
        mainCanvas.Flush()
    End
End

Function Main:Int()
    New MyApp()
    Return 0
End
readpixel.png
 

gontran

Member
Joined
Apr 27, 2020
Location
México City
Ok but I dont whant to plot nothing I only need to read 1 pixel in canvas
I need to know the color in any type off data rgb or any.
If I use

Field pixel1: DataBuffer

on create()
pixel1 = New DataBuffer(1 * 1 * 4)

on render()
PantallaJuego.ReadPixels(dedox,dedoy,1,1,pixel1)
pixel2 = pixel1[0]

I have an error . say only strings and array are indexed
How can I read the data or convert to string or int ?

Thanks for the help
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
You need to use the code tag for code.
No look in the code. Also ignore the drawing if you do not want drawing.

The actual reading of the pixel is this line :
Cerberus X:
Local value:Int = myData.PeekInt(0) ' This is the read
Here's another example, that also converts the pixel to a string
Cerberus X:
Import mojo2
Import brl

Class MyApp Extends App

    Field mainCanvas:Canvas
    Field myImage:Image
    Field myData:DataBuffer
    Field myCanvas:Canvas

    Method OnCreate:Int()
        mainCanvas = New Canvas()
        myImage = New Image(256, 256)
        myCanvas = New Canvas(myImage)
        myData = New DataBuffer(256 * 256 * 4)
    End

    Method OnRender:Int()

        myCanvas.Clear(0,0.1,0) 
    
        ' Read all pixels so we can change a single pixel because reading and writing 1x1 area gives artefacts)
        myCanvas.ReadPixels(0,0,256,256,myData)
    
        ' Plot pixel
        myData.PokeInt(0,$ffffffff)
        myImage.WritePixels(0,0,256,256,myData)
        myCanvas.Flush()

        ' Read pixel
        Local value:Int = myData.PeekInt(0) ' This is the read
    
        ' To proove we read it, let's write a clone-pixel, 2 steps to the right
        myData.PokeInt(2*4,value)
        myImage.WritePixels(0,0,256,256,myData)
        myCanvas.Flush()

        Local myString:String = Int(value) ' Cast (meaning convert) the integer (which is the pixel we read) to a string

        mainCanvas.SetBlendMode(BlendMode.Opaque2)
        mainCanvas.Clear(0,0,0)
        mainCanvas.DrawImage(myImage,200,200)
          mainCanvas.DrawText "The pixel value is",200,200,.5,.5
        mainCanvas.DrawText myString,200,240,.5,.5
        mainCanvas.Flush()
    End
End

Function Main:Int()
    New MyApp()
End
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
I'm not sure that it's okay to access a small areas or even just a single pixel at a time. Look at the first example and see what happens when you write a pixel that way. I think the safest for both reading and writing pixels would be to read the whole buffer and after that access the one pixel you need using the peekInt instruction. It's not optimal but it works.
 

gontran

Member
Joined
Apr 27, 2020
Location
México City
Thanks for the time, now works perfect, I really appreciate your time.
Other question is .
In the integer data, how I can know the red, green and blue and if this have the alpha.

Thanks for you´re help
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
It would help to write the value as hexadecimal instead of decimal.

The integer is 64 bit I guess but you use only the low 32 bits normally for graphics.
Here's how you create a value of your own using the trick of shifting bits.
Cerberus X:
Local rgba:Int = a  Shl 24 | b Shl 16 | g Shl 8 | r
You can do the opposite when you read the pixel values, you can can divide the integer up into red, green, blue, and alpha parts.
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
If you need some help with this kind of tricks, this is how can do it.
You shift the original value as many steps as you need to get it to the lowest 8 bits, then you get only those 8 bits using AND logic.

Cerberus X:
   a = rgba Shr 24) & $ff
   b = (rgba Shr 16) & $ff
   g = (rgba Shr 8) & $ff
   r = (rgba) & $ff
 

gontran

Member
Joined
Apr 27, 2020
Location
México City
Hmm ok but again I´m confused, were :
Local rgba:Int = a Shl 24 | b Shl 16 | g Shl 8 | r
this got my peek data?

Thanks for the patience
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
I won't plot a pixel in this one to make it simpler, I just read the pixel of whatever happens to be there.
Hope this helps.
Cerberus X:
Import mojo2
Import brl

Class MyApp Extends App

    Field mainCanvas:Canvas
    Field myImage:Image
    Field myData:DataBuffer
    Field myCanvas:Canvas

    Method OnCreate:Int()
        mainCanvas = New Canvas()
        myImage = New Image(256, 256)
        myCanvas = New Canvas(myImage)
        myData = New DataBuffer(256 * 256 * 4)
    End

    Method OnRender:Int()

        myCanvas.Clear(0,0.1,0)
        myCanvas.ReadPixels(0,0,256,256,myData) ' Step one is to read all pixels from canvas into buffer (myData)
        myCanvas.Flush()

        Local rgba:Int = myData.PeekInt(0)      ' Next step is to read pixel from the buffer
  
          Local a:Int = (rgba Shr 24) & $ff        ' Now check the pixel out
          Local b:Int = (rgba Shr 16) & $ff
          Local g:Int = (rgba Shr 8) & $ff
          Local r:Int = (rgba) & $ff

          Local myString:String = Int(a)             ' We want to print alpha of pixel
        
        mainCanvas.Clear(0,0,0)
        mainCanvas.DrawText myString,200,240,.5,.5
        mainCanvas.Flush()
    End
End

Function Main:Int()
    New MyApp()
End
 
Last edited:

gontran

Member
Joined
Apr 27, 2020
Location
México City
Hello again , ok this is very extrange. I think is because I use :
PantallaJuego.SetViewport(0, 0,canvasWidth,canvasHeight)
PantallaJuego.SetProjection2d(0, VWIDTH, 0, VHEIGHT)

if I try to read the pixel in my canvas , I see the pixel read is not in the position on my mouse or my finger , How is this posible?
Iny ideas ?

My problem is a game for android I try to set the bottons positions but there are many resolutions.


I would appreciate any idea
Thanks for the time
 

Jimmy

Active Member
Tutorial Author
Joined
Jan 2, 2020
Sorry I can't help you there, I'm struggling with understanding how Cerberus-X deals with different resolutions myself right now.
 

gontran

Member
Joined
Apr 27, 2020
Location
México City
Ok hello again. Now I solve my problem with the buttons and diferent resolutions. This is the idea

I have 4 buttons , aceleration , stop button, up and down
I develope my game in 1920 x 1080 resolution , then I know my 1st button are in x1 = 128 y1 = 769 x2 =256 y2=897
Ok if the android divece have other resolution I use % to reset de buttons position in the touch , not in my image not in my game
then it work

canvasWidth = DeviceWidth()
canvasHeight = DeviceHeight()
VWIDTH = 1920
VHEIGHT = 1080
de_128_ax = (canvasWidth * 100) / VWIDTH
de_128_ay = (canvasHeight * 100) / VHEIGHT
ace_x1 = ace_x1 * (de_128_ax/100)
ace_y1 = ace_y1 * (de_128_ay/100)
ace_x2 = ace_x2 * (de_128_ax/100)
ace_y2 = ace_y2 * (de_128_ay/100)

And voila it works :)
Regards
Gontran Noble V.
 
Top Bottom