Strange readpixels behaviour on android
Monkey Targets Forums/Android/Strange readpixels behaviour on android
| ||
Hi I'm using v75d and readpixels seems to not be returning the right color values. Try to run this code, what is wrong here? Import mojo Class Game Extends App Field counter:Int Method OnCreate() SetUpdateRate 60 Seed = Millisecs() End Method OnUpdate() End Method OnRender() Cls(255,255,255) Local r:Int = Rnd(0,255) Local g:Int = Rnd(0,255) Local b:Int = Rnd(0,255) SetColor(r,g,b) DrawLine 2,2,40,2 If counter < 1 Print "Before: " + r + " " + g + " " + b Local pdata:Int[] = New Int[40 * 2] ReadPixels pdata,2,1,10,1 For Local pixel:Int = Eachin pdata Print "After: " + IntToR(pixel) + " " + IntToG(pixel) + " " + IntToB(pixel) Next Endif counter += 1 Return 0 End Method Function IntToA:Int( color:Int ) Return (color Shr 24) & $FF End Function IntToR:Int( color:Int ) Return (color Shr 16) & $FF End Function IntToG:Int( color:Int ) Return (color Shr 8) & $FF End Function IntToB:Int( color:Int ) Return color & $FF End End Class Function Main() New Game() End Function Output example: I/[Monkey](14590): Before: 82 128 129 I/[Monkey](14590): After: 82 125 123 I/[Monkey](14590): After: 82 130 132 I/[Monkey](14590): After: 82 125 123 I/[Monkey](14590): After: 82 130 132 |
| ||
Different Android devices do it in different ways. Sorry to say, but you can't trust ReadPixels in the slightest. I had previously assumed that, even with a terrible display, dividing everything by 8 would at least give me a nice working set of numbers, but not even that works. Alphas are stripped away, odd dithering takes place, it's all a shambles. FWIW, it also happens on Windows. Make a GLFW exe, and set your desktop to 16bit, and you'll see similar issues. But, again, it's hard to compensate for, because every time it happens, each system seems to "fix" the image in a slightly different way. Bottom line : Android Fragmentation sucks. Avoid ReadPixels. |
| ||
This is what I ended up with using, which works for me in my situation: where boxr, boxg and boxb are the r,g,b values of what to expect at the pixel position and pixelr, pixelg and pixelb are the r,g,b actual values read by readpixels If boxr - pixelr < 15 And boxr - pixelr > -15 And boxg - pixelg < 15 And boxg - pixelg > -15 And boxb - pixelb < 15 And boxb - pixelb > -15 |
| ||
For future reference... If Abs(boxr-pixelr)<15 Does both less and greater.. Saves you needing two for everything.. But, no, not even that can be trusted, due to the annoying dithering that some devices do. Even solid coloured blocks come out as obscure patterns of dots. I did a LOT of testing with this!! |
| ||
If you really need this stuff to work on every device out there, even with dithering etc., you could always import your graphics in their own format and process them as arrays in standard RAM using your own basic drawing and blitting functions for any image pre-processing you need to do. Then use CreateImage and WritePixels to generate images for general purposes. |
| ||
Update: I ended up editing mojo, and added a function that turns dithering off. Dithering on android can be disabled with the following java command: GLES11.glDisable(GLES11.GL_DITHER); |
| ||
As much as I want to say "OMG! awesome!!!" I wouldn't want to rely on that. If I've learned anything from Android dev, it's this... Never EVER assume that what you think should happen on one Android device, is what will actually happen on another... Android Fragmentation is a terrible thing. |
| ||
You're right, also even with dithering disabled, fragmentation causes some invisible artifacts on screen. Seems ios is better ;) |