GetImagePixels()

Monkey Forums/Monkey Code/GetImagePixels()

Nobuyuki(Posted 2013) [#1]
this code takes a path to an image and returns an array of ints compatible with Image.WritePixels. It utiilizes opengl.gles11.LoadImageData() and some byte-juggling to achieve this. The average load time on glfw on my old machine for a 256x256 image is 6ms. On my Nexus S, it's more like 150ms, so there is a non-negligible load time for grabbing images this way.

The benefits, however, should be obvious. You have a full set of pixels to manipulate. Surely this can be optimized later to grab only regions, and I'm guessing that there might be a way to optimize the channel swapping. I encourage anyone who thinks they can optimize it further to give it a shot

This code won't run on non-ogl targets, such as XNA, Flash, or HTML5. Sorry, nothing I can do about that.



Replace references to "sux.png" with your test image of choice.


Midimaster(Posted 2013) [#2]
nice work. I did not know that this is already implemented. I have some questions...

Mark wrote in the manual, that the resulting pixel format is R-G-B-A and not as you detected A-B-G-R. Did you find a bug?

If you believe in the detected resulting format A-B-G-R... Why do you swap Byte i+0 and Byte i+2? Wouldn't it be necessary to swap Byte i+1 and i+3?

Did you really detect A-B-G-R or was it G-R-A-B? Only G-R-A-B would convert to A-R-G-B when you swap bytes i+0 with i+2

Why do you think the first pixel is at position 20?


Nobuyuki(Posted 2013) [#3]
honestly I don't remember, this was coded at 3 in the morning and all I know is that when feeding the data directly from LoadImageData() to WritePixels(), it swaps the blue and red channel. That sounds like either a compatibility or an endianness issue, I don't know which one and frankly I don't care, either, as long as I get the results I want in the end and not at a hit to performance.

If it's a bug and not intentional, it's in the internals of the mojo or ogl modules somewhere and beyond my current willingness to hunt down the reason. There may be a perfectly valid reason why LoadImageData() returns one pixel format and WritePixels expects another. I suspect maybe WritePixels() is the one that's wrong, here, but w/e.

Pixel data coming out of LoadImageData() is in the following format, with most significant bit on the left: B-G-R-A. You can see for yourself using GetColor on the raw data before the bits are swapped by using the below code. I haven't tested GetColor on raw ReadPixels() data. Would you be interested in testing it for me? :)




AdamRedwoods(Posted 2013) [#4]
Mojo puts image data to OpenGL as GL_ABGR. It's an OpenGL thing, suppose to be faster(?).

and try reading only using ints, then bit shift, faster:
	For Local i:Int = 0 Until db.Length Step 4
		Local j:Int = db.PeekInt(i)
		
		data[i / 4] = (j & $ff000000) | ((j & $00ff0000) Shr 16) | (j & $0000ff00) | ((j & $000000ff) Shl 16)
	Next



Nobuyuki(Posted 2013) [#5]
very nice, that is indeed faster. Reduced time to about 50ms on Android, an acceptable time for me.


Midimaster(Posted 2013) [#6]
I need something similar at the moment too. So I'm very interested in this. Thank you both!

But should'nt we have a consistent color format in pixels in Monkey?

Mark, what was the reason for accepting two different formats?


Gerry Quinn(Posted 2013) [#7]
There used to be some reverse of B and R in Windows in the old days, I can't remember the details.