ReadPixels Offscreen

Monkey Forums/Monkey Programming/ReadPixels Offscreen

PoliteProgrammer(Posted 2012) [#1]
Hi all, I have a quick question regarding ReadPixels(). I am happily able to create an image on the fly using something like:
local img:Image = CreateImage(w,h)
local buffer:Int[] = New Int[w*h]
ReadPixels(buffer,0.0,0.0,w,h)
img.WritePixels(buffer,0.0,0.0,w,h)

But how do I create an image bigger than DeviceWidth()xDeviceHeight() using the same technique? My first attempt was to play with SetScissor(), but that didn't seem to do anything.

Does anyone have any advice? :)


AdamRedwoods(Posted 2012) [#2]
You cannot without external libraries because of the way Mojo works.


NoOdle(Posted 2012) [#3]
not strictly true you can write a work around.

CreateImage can create images larger than the screens width and height. You can only read the current screen rectangle using ReadPixels. To copy a larger area requires a trick:

To get a larger copy of the entire game field you would need to divide the world into screen rectangles and then render your world many times at that grid location x,y. Each time you read the pixels you would add them the to the created images stored pixel array.

Inserting the read pixels is easier than it sounds, only need to worry about correctly offsetting each row. This is done by incrementing the startIndex by width. This will now point to x, y + 1.
I posted some code that does similar:

http://www.monkeycoder.co.nz/Community/posts.php?topic=3495


PoliteProgrammer(Posted 2012) [#4]
Ah, so the idea is just to create the image piecewise and tack it all together? Thanks, just gave it a try and it works fine!

So, I guess this leads me to another question; I am using this sort of thing to construct a large, scrollable pre-rendered map for my game. This large image creation stuff therefore has to be done ONCE before loading a selected game level, but can't be done in OnCreate() because the levels are defined on-the-fly. Is there a way to get it to work on this stuff in the background while a simple, but dynamic 'loading' screen plays in the foreground?

In other words, I don't want to have a black screen for several seconds while it generates the map.


NoOdle(Posted 2012) [#5]
In other words, I don't want to have a black screen for several seconds while it generates the map.

Yea this is a problem, I overcame it in some of my projects by converting my images to text files containing pixel data. I loaded the pixel data into a created Image which meant I had access to the pixel data inside OnCreate bypassing the need for a special loading screen (which is not possible without hacking around under the hood).

It does require a bit of work to get it all working (making a tool to convert images to txt data, saving and loading) but it gives a huge amount of flexibility and control. I also compressed my data and managed to more than half the file size of the same image png format!


muddy_shoes(Posted 2012) [#6]
I also compressed my data and managed to more than half the file size of the same image png format!


You managed to get a reliable compression advantage of 50% over PNG via text representation and compression? Care to go into more detail? That's more than a little eyebrow raising unless there's something specific about the nature of your images that you're taking advantage of.


Shinkiro1(Posted 2012) [#7]
That would be really impressive.
I mean png does some really clever checking under the hood and then evaluates the best compression model to use, even replacing whole blocks of pixels with mathematical representations.


NoOdle(Posted 2012) [#8]
I was suprised, I finally opted for base64 as I use it for other parts of my framework and it is 40% smaller than the corresponding png file which is great. This is the case for the tests I have done which don't go above 128 px * 128 px. I was pretty surprised to see the smaller file size as well, almost expected them to be twice as big! (I was playing around with dynamically changing colour palettes to add more variety with less artwork!) The pngs were default settings saved from Photoshop so they may not be optimised at all which is why I'm seeing these results!