I don't understand ReadPixels()

Monkey Forums/Monkey Beginners/I don't understand ReadPixels()

GfK(Posted 2014) [#1]
[edit] Forget it. I'm pretty much at the end of my rope with Monkey.

Everything I attempt with it is a total non-starter. Today I've been attempting to come up with some sort of collisions by using an array (created with ReadPixels()). This is horribly wasteful but seemed to be the only way of doing it.

Turns out I can't even do it that way, because in order to do so, I need to draw the image to the buffer. To do that, I apparently have to be inside OnRender(). Except I've just loaded the image in OnCreate() (for testing purposes, I know it should be in OnUpdate()) and want to create the array immediately, one-shot, at load-time. But by Monkey's logic I need to go through at least one render loop and I cannot even begin to fathom why it has to be done like this.

It feels like everything I ask of Monkey, it turns around and goes "ahhhh, but... you cannot do that because Mars is not fully aligned with Uranus"!

Can somebody tell me - am I REALLY missing something here? Why is there no access to image data? Image.GetPixel(x,y)?


ziggy(Posted 2014) [#2]
I agree that having a PixMap class of some kind would be very convenient in lots of situations


rIKmAN(Posted 2014) [#3]
Not ideal, but you could call a Method/Function to do whatever you want for your array in the first OnRender() and then set a flag so it isn't called ever again?


GfK(Posted 2014) [#4]
I thought of that, and it'd probably work for a single image. But what if I need to do this for a bunch of images? It just becomes exponentially more complicated.


ziggy(Posted 2014) [#5]
My take would be to be able to access pixel data in an array form. It should be doable, as it brings lots of useful things like strength maps on platform games, better collisions, etc. I don't know what target is making this impossible, but if it is html5, maybe trans could generate a per-image metadata document with pixel information (ala bitmap) and use that instead, or create a temporary hidden canvas for each image, get the info into an array, and dispose those canvases. Not sure how slow it may be, but it maybe helps solving the thing, by not too complex usage of the DOM.


therevills(Posted 2014) [#6]
Do really need pixel perfect collisions, hit boxes are normally good enough anyway and are pretty fast.


ziggy(Posted 2014) [#7]
This could be handy, not only for collisions


GfK(Posted 2014) [#8]
I don't especially want it for collisions. I want to find the pixel within an image below the mouse pointer. So box collisions are unworkable here. The bottom line is, I need access to the raw image data in one form or another and it just seems impossible in Monkey's current state.


Gerry Quinn(Posted 2014) [#9]
Your issue is with the mojo framework, not with Monkey. What's happening is that you want to use the framework but still do stuff outside the standard way it works. Any framework is going to bite when you do that.

What rlkMan said is correct. I have used something of the kind in puzzle games where graphics sometimes need to be pre-generated. Basically, I call a PregenerateGraphics() method before the Draw() method in the class that uses them. It checks whether any of the images are set to null, and if so, it generates them using ReadPixels() and WritePixels() - otherwise it simply returns.

If some pre-generated graphics become obsolete due to a change in window size or layout, I just set the appropriate images to null, and before the next render they will be regenerated.

You can do the same, just set the images to null in OnCreate() For your app, it seems to me you would want to create a bunch of differently coloured shapes. I would just draw them on the back-buffer in unique colours and use ReadPixels(), then test the mouse position against the appropriate element of the array.

The reason it works like this is because all sorts of hardware is being targeted, and we don't necessarily know it will be possible to write on the back buffer outside the render cycle.


GfK(Posted 2014) [#10]
Your issue is with the mojo framework, not with Monkey.
Po-tay-to, po-tar-to. Mojo is part of Monkey. I'm sure you'll retort that it isn't, but it came with it when I bought it, so it is.

The reason it works like this is because all sorts of hardware is being targeted, and we don't necessarily know it will be possible to write on the back buffer outside the render cycle.
You wouldn't even need to get into that sort of nonsense if we were given direct access to image data. Is there a valid reason why this cannot be done?


ziggy(Posted 2014) [#11]
What's happening is that you want to use the framework but still do stuff outside the standard way it works. Any framework is going to bite when you do that.
The real problem here is that there's no standard way of reading pixel information on any image.


Gerry Quinn(Posted 2014) [#12]
Well, you could always save images in a raw format and read them yourself...


GfK(Posted 2014) [#13]
You could, but three things about that:

1. it's hugely inconvenient to have to do it.
2. you're still wasting resources by storing the same data twice - once in the array, once in the image itself.
3. How do you save the image data when you don't have access to the image data?


Trez(Posted 2014) [#14]
I don't especially want it for collisions. I want to find the pixel within an image below the mouse pointer. So box collisions are unworkable here. The bottom line is, I need access to the raw image data in one form or another and it just seems impossible in Monkey's current state.


If you want to read the pixel below the mouse pointer why cant you just use ReadPixels ! the image must be rendered if its sitting under the mouse pointer. If you need to track an image then use a broad phase collision first like therevills as already recommended to identify the image the pixel is coming from. You can even use a lot of the code from this thread by therevills http://www.monkey-x.com/Community/posts.php?topic=3488.


GfK(Posted 2014) [#15]
Because in that case, the image I want to sample is not going to be the only image I've drawn, and there will still be no way of knowing if the pixel below the mouse was originally transparent/masked.


muddy_shoes(Posted 2014) [#16]
Frankly it's hard to see how to help you here as you seem focussed on expressing how you feel it should be easier rather than hearing how it can be done. If you don't wish to pre-process images outside of Monkey or dig into the specific platforms you want to target to write your own image access routines then drawing the images and reading the pixel data back in is pretty much what you'll have to do. Yes, you need to do that in a render loop but, having done exactly this, I don't see how that is an insurmountable problem. A bigger issue is how to deal with alpha values.


GfK(Posted 2014) [#17]
Frankly it's hard to see how to help you here as you seem focussed on expressing how you feel it should be easier rather than hearing how it can be done.
Yes it should be easier and it should be better - of course it should. The problem with "how it can be done", is that the solutions I'm being offered are not viable.

You're saying I should use raw image data instead of PNG format. Need I bring up the issue of download size for mobile devices/data limitations? There can be a colossal difference. For example, I have a 192x192 PNG image, which is 3.75KB. Storing that same image in raw data would take up 36KB - almost ten times the size.

You're also saying that it is perfectly reasonable to waste resources by having the image itself, then raw data standing on the sidelines for me to do the magic stuff with. Really? On already confined working area within certain mobiles? You simply cannot justify duplicating data unnecessarily like that when I've yet to see a valid reason for not having access to the image data itself, thus negating the requirement to do these God-awful work-arounds in the first place.


muddy_shoes(Posted 2014) [#18]
I would guess that mojo doesn't provide image data access mostly for two reasons:

1. Mark would have to find and wrap or write and support image readers for all formats on all targets.
2. HTML5 has security issues surrounding such accesses.

Does that solve your problem? I don't think it does.

Is memory usage a problem for your specific intention? I've no idea because you haven't explained what your usage is. Just talking about how large a compressed image file is versus an uncompressed file isn't exactly the whole story about how images use memory.


GfK(Posted 2014) [#19]
Is memory usage a problem for your specific intention? I've no idea because you haven't explained what your usage is

I don't have any intention/usage - just playing around with stuff, finding the limitations and considering the bigger picture if I were to commit to this, then hit all these problems way down the line when it would really become an issue.

Just talking about how large a compressed image file is versus an uncompressed file isn't exactly the whole story about how images use memory.
I wasn't talking about compressed vs uncompressed - I'm talking about the unacceptable requirement here to have a duplicate of the same data.

Mark would have to find and wrap or write and support image readers for all formats on all targets
Right.... and is he cracking on with that?

HTML5 has security issues surrounding such accesses
One problematic target hasn't mattered in the past.


muddy_shoes(Posted 2014) [#20]
I'm not here to speak for Mark and I'd be a very bad choice to do so. If you want to argue with Mark about mojo features you feel owed then the forum is not a great place to try to be heard.

>I wasn't talking about compressed vs uncompressed

Except that's exactly the argument you made by comparing png to raw. If you load a compressed image file do you believe it always remains compressed when you access the pixel data?

It's all a bit pointless though, isn't it? You don't have a plan in mind that you can describe but yet you somehow know that storing pixel data separately from your image files definitely isn't viable for your undefined application. I don't see how anyone is meant to approach your issues.


GfK(Posted 2014) [#21]
I don't want to argue with anybody - just putting my point of view across. Is that allowed?

If you load a compressed image file do you believe it always remains compressed when you access the pixel data?
*sigh*

The point is, and I've said this before so God knows why I'm having to say it again - it is senseless to have two sets of the same data in memory at the same time.

It's all a bit pointless though, isn't it? You don't have a plan in mind that you can describe but yet you somehow know that storing pixel data separately from your image files definitely isn't viable for your undefined application
I know it's a lousy, wasteful work-around, for reasons I've already stated numerous times.

Anyway, I've said my bit - you might have the time to keep going around in circles with this, but I really can't be bothered any more.


muddy_shoes(Posted 2014) [#22]
Actually I was hoping to provide you with a way of achieving what you want seeing as I've done some work in this area. Unfortunately a little circling was required to figure out that you don't want to do anything other than talk about how you'd prefer things to work and problems that may not be problems. Clearly I've been the one wasting your time here though. Sorry for that.


rIKmAN(Posted 2014) [#23]
Well that escalated quickly...

You two (GfK and muddy_shoes) are two of the better coders around here, and I'm 100% sure you could find an acceptable workaround if you decided that was what you were going to do.


ziggy(Posted 2014) [#24]
My suggestion would be to store the data only as raw data, and create the images at runtime using that data, and keep all streams alive so you can also read pixel information


therevills(Posted 2014) [#25]
2. HTML5 has security issues surrounding such accesses.

Muddy are you talking about accessing the pixel data of an image? If so, you can get it pretty easily and Mark actually does it for "tinting" the images via SetColor...

I think in most of the mojo targets, you can access pixel data if you want to extend Mojo yourself:

HTML5:
var imgData=tmpGC.getImageData( 0,0,sw,sh );

Android:
int pixel = bitmap.getPixel(x,y);



muddy_shoes(Posted 2014) [#26]
@therevills: HTML5 will throw an error if you try to access data in images that come from outside of the page domain. While this limitation could be defined in the mojo spec I'm speculating that their existence might have made Mark lean towards not supporting those operations. I seem to remember him mentioning the problems at one point early on. I could be wrong.

Of course you're right that mojo can be altered to allow access to pixel data. I mentioned the possibility above. It comes under stuff that GfK just doesn't want to do though.

@rIKmAN As I said, that's what I was hoping to do. Without a clear definition of the task it's pretty hard to provide a solution though. Throwing up suggestions to have them shot down on the basis of unstated knowledge as to why they'd be unworkable isn't particularly fulfilling. GfK has been given three broad options:

1. Pre-process images
2. Draw and read pixels
3. Alter mojo

Any of these can work. Based on what GfK has provided he wants to click on an screen full of images and know which one he's hit allowing for possible transparent edges and holes. That can be achieved via 1 or 2 by creating 1-bit per pixel collision maps based on alpha threshold and maintaining a z-order collision list for checking against image bounds. Would that be good enough for GfK? It seems not because it requires some more effort and some possible memory overhead over an imagined mojo that provides direct pixel data access.


Sensei(Posted 2014) [#27]
I find the problem is often, people new to Monkey have expectations that other programs like GS provides. If you can't be bothered to learn how to code and expect things to land in your lap in two clicks, Monkey is not the program for you.
There's always more than one way to skin a cat.
At the start, I found Monkey hard to use but over time I have improved and can do pretty much anything I need on it now (bar 3D stuff which isn't my interest anyway).

In any case, it's always worth programming something to see if it works. If it doesn't try another way. If all else fails, ask on here and some of the great programmers on here will offer an example or two. It's helped me plenty. No point crying things don't work if you're not going to give Monkey the time of day.

Just my two cents..


GfK(Posted 2014) [#28]
If you can't be bothered to learn how to code
OH MY GOD!!!!!! WHY DIDN'T I SEE IT BEFORE?!

You're right, I cannot be bothered to learn how to code! I am such a douche that I didn't even realise for the last two and a half decades that I can't code. HOW CAN THIS HAPPEN?

I've had published games since 1994 and at NO POINT as anybody ever mentioned this to me before - they just kept on BLINDLY giving me bags of cash month after month without even bothering to bring up the issue of my blatant inability.

I should be flogged. I should be put against a wall and shot. I should have my pants pulled down and my arse soundly THRASHED with a bunch of stinging nettles. I should be made to watch episodes of Neighbours.

I'm going away now to punch myself repeatedly about the face for being so stupid.

Thank you from the bottom of my heart for your words of wisdom, thank you so much. It is greatly appreciated. I'll completely gloss over the fact that I've probably been programming since your dad was in pre-school, because I'm clearly wrong and you're clearly right.

Colour me enlightened.


Sensei(Posted 2014) [#29]
Thank you for your entertaining response Gfk :)

I do apologize for my inability to see that you came across like a person that can't be arsed to give it a go, and then if it doesn't work, call for help. Again, my apologies :)

I would suggest that you should persevere with Monkey as it's a damn sight cheaper and better as a game dev tool than many others out there.
On the other hand, I'm sure you're more than capable of finding other tools that will do as you desire.

All the best mate.


GfK(Posted 2014) [#30]
I think I had a John Cleese moment.


Why0Why(Posted 2014) [#31]
Dave, as Sensei says, I think it will be worth your while to stick it out with Monkey. I know you are considering mobile. I think the desktop is still a more consistent path to making money, but I think being able to directly port something like CS2 over to android and ios would be a benefit(I know you have tried in the past without success.) I feel a game like that would do well with the proper marketing and play very well on a tablet.


rIKmAN(Posted 2014) [#32]
OH MY GOD!!!!!! WHY DIDN'T I SEE IT BEFORE?!
You're right, I cannot be bothered to learn how to code! I am such a douche that I didn't even realise for the last two and a half decades that I can't code. HOW CAN THIS HAPPEN?

I've had published games since 1994 and at NO POINT as anybody ever mentioned this to me before - they just kept on BLINDLY giving me bags of cash month after month without even bothering to bring up the issue of my blatant inability.

I should be flogged. I should be put against a wall and shot. I should have my pants pulled down and my arse soundly THRASHED with a bunch of stinging nettles. I should be made to watch episodes of Neighbours.

I'm going away now to punch myself repeatedly about the face for being so stupid.

Thank you from the bottom of my heart for your words of wisdom, thank you so much. It is greatly appreciated. I'll completely gloss over the fact that I've probably been programming since your dad was in pre-school, because I'm clearly wrong and you're clearly right.

Colour me enlightened.



Everything was going fine, but you had to go too far and bring Neighbours into the argument didn't you.....


Salmakis(Posted 2014) [#33]
I've had published games since 1994 and at NO POINT as anybody ever mentioned this to me before - they just kept on BLINDLY giving me bags of cash month after month without even bothering to bring up the issue of my blatant inability.


maybe this is exacly the Problem here, seems like you only want to use mechanics that you invented somewhere between 1994 and now, maybe they worked fine from then until now, and instead of thinking for a new idea or mechanic with the given tools from monkey to archieve your Goal, you tryhard to Remake the old one, even if monkey/mojo and also all other modern devtools offers way more interresting, faster and better ways to archieve this.

so dont blame monkey if you not able to archieve what you want to get with the given Tools, and if you are so pro, then just add the Feature you want by yourself, since the source is open.

if you want a pixmap class, just write one, or just write a custom Array / data buffer handle thingy wich only keeps the informations you Need, insteat of the whole 32bpp data. im pretty sure with a databuffer out of Shorts or even Bytes you can store all Infos you Need and even more, while saving some Memory.
on most cases/targets the texturedata of the Image are stored somewhere in the graphic Memory with some OpenGL stuff, it would be a waste of Memory to Keep every Image in normal Memory seperatly.


GfK(Posted 2014) [#34]
even if monkey/mojo and also all other modern devtools offers way more interresting, faster and better ways to archieve this.
Off you go, then - show me ONE METHOD of retrieving the pixel colour/alpha from within an Image, below a mouse-click.

It's extremely easy to say it - show me how to do it.


impixi(Posted 2014) [#35]
Here's a pixel reading/writing example here, for reference, as per my exchange with Gfk in this thread: http://www.blitzbasic.com/Community/posts.php?topic=103316



ReadPixels operates on the canvas, WritePixels on the Image. For Image-level pixel manipulation you need to retain the integer array used to load/create the image and use that for your operations.

EDIT: Updated the code so it fills the integer array from a loaded image file when necessary.


MonkeyPlotter(Posted 2014) [#36]
Nice piece of code ;)


DruggedBunny(Posted 2014) [#37]
That's pretty cool, impixi... with a bit of wrapping, it looks like it could become a [semi-?] automatically-loaded TPixmap-type of thing... hmm...


GfK(Posted 2014) [#38]
ReadPixels operates on the canvas, WritePixels on the Image.
Ooh, new words! What's a canvas?

[edit] Never mind.


impixi(Posted 2014) [#39]
"canvas" - I probably should use the term "render buffer", as that's what the docs use.

It's not a good situation when loading an image from a file. You need to render it first, then read the values from the "render buffer" into your array. But by doing so you lose the image's original alpha values. Would be so much nicer to have a ReadPixels method on the Image object. I'm investigating the Mojo source code now. Unfortunately, judging by the Javascript code for the HTML5 platform, it would not be as simple as you might think - at least for that platform. Unless I'm misunderstanding something - always a possibility. ;)


Later, I'll update my code so it fills the integer array from a file-loaded image when necessary.

EDIT: Updated the code in my previous post. Tested on MonkeyX Pro V81a. Works properly on Desktop target (GLFW 2 and GLFW 3) but breaks when trying to modify a pixel on the HTML5 target. No error given. Assuming it's a browser-related x-domain security violation or something like that (since it only happens on a loaded image, not a generated one) but the FireFox console tells me nothing...