ReadPixels (Mojo2) returns only background color.

Monkey Forums/Monkey Programming/ReadPixels (Mojo2) returns only background color.

Clecius(Posted 2016) [#1]
Hail,

I am new on Monkey X, and i am trying use it in a project of mine.
When using ReadPixels to get data from canvas I'm having an issue.
I can't get data from color drawn but only the background color.
Can anyone help me?


Jesse(Posted 2016) [#2]
it would help if you could post the source code so we could know what you are doing wrong.


Clecius(Posted 2016) [#3]
Sorry. =)

Strict

Import mojo2
Import brl.filestream

Function Main:Int()
  New Game()
  Return 0
End


Class Game Extends App
  Field canvas:Canvas
  Field scrW:Int = 320
  Field scrH:Int = 240

  Method OnCreate:Int()
    SetDeviceWindow(scrW, scrH, 4)
    SetUpdateRate(60)
    canvas = New Canvas()
    canvas.SetProjection2d(0, scrW, 0, scrH)
    Return 0
  End

  Method OnRender:Int()
    Local pixscan:DataBuffer = New DataBuffer((20 * 20) *4)
    Local colors:Int[]
    Local rgba:Int[]
    rgba = rgba.Resize((20 * 20) *4)
    colors = colors.Resize(20 * 20)

    canvas.Clear()
    
    canvas.SetColor(1, 0, 0)
    canvas.DrawPoint(1, 0)
    canvas.SetColor(0, 1, 0)
    canvas.DrawPoint(2, 0)
    canvas.SetColor(0, 0, 1)
    canvas.DrawPoint(3, 0)

    canvas.Flush()

    canvas.ReadPixels(0, 0, 20, 20, pixscan)
    pixscan.PeekBytes(0, rgba) 'Return: [0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, ...]
    pixscan.PeekInts(0, colors) 'Return: [-16777216, -16777216, -16777216, -16777216, ...]
    
    Return 0
  End

End


Doesn't matter if I put the ReadPixels before or after the Canvas Flush.


Jesse(Posted 2016) [#4]
Hi Clecius, I have been trying to figure out how to implement how to read pixels from the screen but for some reason it's not working right, either I don't understand it or it's not working correct, I did some pixel reading. and it appears as if it doesn't read the alpha from the screen and it gets replaced with 0 which makes it invisible when trying to paste it to an image.
And even after modifying the pixels to a visible alpha, it doesn't draw it in the correct color. So i don't know what to tell you. if no one else is able to help, Email BRL(Mark) and see what he tells you.
this is the code I was testing it with:
Strict

Import mojo2
Import brl

Function Main:Int()
  New Game()
  Return 0
End


Class Game Extends App
  Field canvas:Canvas
  Field scrW:Int = 320
  Field scrH:Int = 240
  Field image:Image
  Field icanvas:Canvas
  Field pixscan:DataBuffer
  Field colors:Int[]
  Field rgba:Int[]
  Field color:String
 
  Method OnCreate:Int()
    SetDeviceWindow(scrW, scrH, 4)
    pixscan = New DataBuffer((3*1) *4)
    SetUpdateRate(5)
    canvas = New Canvas()
    image = New Image(50,50)
    icanvas = New Canvas(image)
    icanvas.Clear(0,0,0)
   ' canvas.SetProjection2d(0, scrW, 0, scrH)
    canvas.Clear(0,0,0)
    canvas.SetColor(1.0, 0.0,0.0,255.0)
    canvas.DrawPoint(3, 3)
    'canvas.SetColor(0, 1, 0)
    canvas.DrawPoint(4, 3)
    'canvas.SetColor(0, 0, 1)
    canvas.DrawPoint(5, 3)
    	
    colors = colors.Resize(3 * 1)
    canvas.SetColor(0,0,0,0)
    canvas.ReadPixels(3, 3, 3,1, pixscan)
    Local i:Int = pixscan.PeekInt(0)
   ' pixscan.PokeInt(0,i | $FF)
    i = pixscan.PeekInt(0)
    Print ((i Shr 24) & $FF)+"'"+((i Shr 16) & $FF)+","+((i Shr 8) & $FF)+","+(i & $FF)
    i = pixscan.PeekInt(1)
    'pixscan.PokeInt(1,i | $FF)
    i = pixscan.PeekInt(1)
    Print ((i Shr 24) & $FF)+","+((i Shr 16) & $FF)+","+((i Shr 8) & $FF)+","+(i & $FF)
    i = pixscan.PeekInt(2)
    'pixscan.PokeInt(2,i | $FF)
    i = pixscan.PeekInt(2)
    Print ((i Shr 24) & $FF)+","+((i Shr 16) & $FF)+","+((i Shr 8) & $FF)+","+(i & $FF)
    image.WritePixels(10,10,3,1,pixscan)
    canvas.SetColor(1,1,1,1)
    canvas.DrawImage(image,150,150)
    canvas.Flush()
    Return 0
  End

  Method OnRender:Int()

    
    Return 0
  End

End




skid(Posted 2016) [#5]
ReadPixels seems to be reading from the bottom of the screen not the top (a common problem in OpenGL).


Jesse(Posted 2016) [#6]
I doubt that's reading from the bottom because I can see the correct color values in the right places in the data buffer but the only thing that's different is the alpha value which is 0 and should be 255.
run the code and look at the output. it displays the three color on the upper corner. it saves them to the data buffer but with the alpha value of 0. and when I draw them to the image it is obvious that it is not being drawn correctly.

Clecius what are you trying to do? can you just draw directly to an image and extract the data buffer from it? I am thinking that it might be fast enough for what you are doing and I am guessing it will include the alpha value. Just guessing. Don't really know.


Gerry Quinn(Posted 2016) [#7]
You're not in 16-bit colour by any chance?


Clecius(Posted 2016) [#8]
Well observed Skid, the reading of ReadPixels is reversed.
I made a dump from the array to confirm.

Jesse I found that reading from the PeekBytes is really odd, so I made two functions to convert the Int values.

I am building a routine to analise the pixel pattern from an image. And I intend to use the Canvas to draw on a image and not to the screen, this was just a POC.

Many thanks, people! =D

Strict

Import mojo2
Import brl.filestream

Function Main:Int()
  New Game()
  Return 0
End


Class Game Extends App
  Field canvas:Canvas
  Field scrW:Int = 60
  Field scrH:Int = 40

  Method OnCreate:Int()
    SetDeviceWindow(scrW, scrH, 0)
    SetUpdateRate(60)
    canvas = New Canvas()
    canvas.SetProjection2d(0, scrW, 0, scrH)
    Return 0
  End

  Method OnRender:Int()
    Local pixscan:DataBuffer = New DataBuffer((scrW * scrH) *4)
    Local colors:Int[]
    Local rgba:Int[]
    Local d_rgba:Int[]
    Local dump:FileStream
    rgba = rgba.Resize((scrW * scrH) *4)
    colors = colors.Resize(scrW * scrH)

    canvas.Clear()
    
    canvas.SetColor(1, 0, 0)
    canvas.DrawPoint(1, 0)
    canvas.SetColor(0, 1, 0)
    canvas.DrawPoint(2, 0)
    canvas.SetColor(0, 0, 1)
    canvas.DrawPoint(3, 0)

    canvas.SetColor(0.2, 0.4, 0.6)
    canvas.DrawPoint(58, 0)
    canvas.SetColor(1, 1, 1)
    canvas.DrawPoint(59, 0)

    canvas.Flush()

    canvas.ReadPixels(0, 0, scrW, scrH, pixscan, 0, 0)
    pixscan.PeekBytes(0, rgba)
    pixscan.PeekInts(0, colors)

    dump = New FileStream("rgba.dump", "w")
    For Local i:Int = EachIn rgba
      dump.WriteString(i+ ",")
    Next
    dump.Close()
    
    dump = New FileStream("colors.dump", "w")
    For Local i:Int = EachIn colors
      dump.WriteString(i+ ",")
    Next
    dump.Close()
    
    dump = New FileStream("colorstorgb.dump", "w")
    For Local i:Int = EachIn colors
      d_rgba = ColorToRgb(i)
      dump.WriteString(d_rgba[0]+","+d_rgba[1]+","+d_rgba[2]+","+d_rgba[3]+ "|")
    Next
    dump.Close()
    
    DebugStop()
    Return 0
  End

  Function ColorToRgb:Int[](value:Int)
    Local resp:Int[]
    Local v:Int
    resp = resp.Resize(4)
    v = value
    resp[3] = v & 255
    v = v Shr 8
    resp[2] = v & 255
    v = v Shr 8
    resp[1] = v & 255
    v = v Shr 8
    resp[0] = v & 255
    Return resp
  End
  
  Function RgbToColor:Int(a:Int, r:Int, g:Int, b:Int)
    Local v:Int = 0
    v = v | a
    v = v Shl 8
    v = v | r
    v = v Shl 8
    v = v | g
    v = v Shl 8
    v = v | b
    Return v
  End
  
End



Jesse(Posted 2016) [#9]
Garry, Highly doubt it.
Clecius, be careful when reading bytes. You have to be aware of big Endian and little Endian. what you are doing might be correct in windows but might not work on a Mac or other targets. Windows write integers one way while Macs writes integers in reverse of Windows. when you are try to extract bytes from bytes that were originally stored as integers, you might not get exactly what you want. if you are just going to work on Windows always, you won't need to worry about it though.


Jesse(Posted 2016) [#10]
.


Clecius(Posted 2016) [#11]
Good point, Jesse.
I'm just starting with this tool, but I will keep this in mind for when advancing to other plataforms.

Garry, I forgot in mention your comment on the last post. Sorry.
I'm sure in 32 bit. ;-)

Thanks again.