iDevGames Forums
Taking Pictures of Game State inside an app - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: iPhone, iPad & iPod Game Development (/forum-11.html)
+--- Thread: Taking Pictures of Game State inside an app (/thread-643.html)



Taking Pictures of Game State inside an app - Bersaelor - Oct 27, 2009 02:23 PM

Is there an way (or a even an API) for making a Picture of the Current State of a Game?

It's 3D in OpenGL ES and the idea is to make a Screenshot of the current game, shrink it and put it next to the Entry in the "saved games" tableview.


Taking Pictures of Game State inside an app - iamflimflam1 - Oct 27, 2009 05:16 PM

Bersaelor Wrote:Is there an way (or a even an API) for making a Picture of the Current State of a Game?

It's 3D in OpenGL ES and the idea is to make a Screenshot of the current game, shrink it and put it next to the Entry in the "saved games" tableview.

There is an undocumented call UIScreenGetImage - unfortunately Apple seem to have clamped down on using this recently.

Your best option is to use glReadPixels to get the screen contents and then use something along the following lines:

Code:
    CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
    CGContextRef context=CGBitmapContextCreate(imgData, width, height, 8, width*sizeof(uint32_t), colorSpace, kCGBitmapByteOrder32Little|kCGImageAlphaNoneSkipLast);
    CGImageRef image=CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    UIImage *resultUIImage=[UIImage imageWithCGImage:image];
    CGImageRelease(image);

Where imgData points to pixel data.


Taking Pictures of Game State inside an app - Bersaelor - Oct 30, 2009 05:47 AM

Well I did:
Code:
void* pxlData;
glReadPixels(1, 1, 300, 300, GL_RGB, GL_UNSIGNED_BYTE, pxlData);
                    
CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceRGB();
CGContextRef context=CGBitmapContextCreate(pxlData, 300, 300, 8, 300*sizeof(uint32_t), colorSpace, kCGImageAlphaNoneSkipLast);
CGImageRef image=CGBitmapContextCreateImage(context);
UIImage *resultUIImage=[UIImage imageWithCGImage:image];
                    
NSData *imageData = UIImagePNGRepresentation(resultUIImage);
NSLog(@"ImageData has size: %i Bytes",imageData.length);
[imageData writeToFile:@"test.png" atomically:YES];

But the result isn't very satisfiing:
[Image: testlh.png]

I believe I got the Data Amount per Pixel wrong, I mean GL_RGB tells OpenGl to represent the pixel as RGB and kCGImageAlphaNoneSkipLast means RGB without Alpha too, right?
Is GL_UNSIGNED_BYTE right when I say "8" Bytes in CGBitmapCOntextCreate?


Taking Pictures of Game State inside an app - Skorche - Oct 30, 2009 06:21 AM

I'm surprised that didn't crash. You need more than just a pointer to write the data into. What you gave it was a pointer to some random place to write data into. You need to initialize your pixel data pointer from a call to malloc or similar with enough room to copy all the pixel data.


Taking Pictures of Game State inside an app - Bersaelor - Oct 30, 2009 07:42 AM

Sorry, what was I thinking!

Anyway that and a change to RGBA in "glReadPixels(1, 1, 300, 300, GL_RGB, GL_UNSIGNED_BYTE, pxlData);" seemed to work.

Now the Picture is mirrored, turned by 90º and I'd like it to shrink to about 1/3rd.

Since you helped me so nicely till now, I figured I can just ask another question Wink
I didn't find anything about resizing or Mirroring an UIImage or CGImageRef in the Documentation.
Do I have to program this myself or is there a nice official way how to edit those Images (the action happens quiet often so I'd like it to be fast)?

EDIT: Resizing was easy, I got that. Though for mirroring I still have to look.


Taking Pictures of Game State inside an app - kshep - Oct 30, 2009 09:48 AM

There is another way you can try. Using this method you can actually get a UIImage of any UIView. Look at the sample code on the iPhone dev portal for the Elements app. It uses the function that turns a UIView into a UIImage for generating the mirror image of the element placard. I used this same method in a game to allow the user to take a screenshot and send it to a friend.


Taking Pictures of Game State inside an app - iamflimflam1 - Nov 1, 2009 02:02 PM

Bersaelor Wrote:Sorry, what was I thinking!

Anyway that and a change to RGBA in "glReadPixels(1, 1, 300, 300, GL_RGB, GL_UNSIGNED_BYTE, pxlData);" seemed to work.

Now the Picture is mirrored, turned by 90º and I'd like it to shrink to about 1/3rd.

Since you helped me so nicely till now, I figured I can just ask another question Wink
I didn't find anything about resizing or Mirroring an UIImage or CGImageRef in the Documentation.
Do I have to program this myself or is there a nice official way how to edit those Images (the action happens quiet often so I'd like it to be fast)?

EDIT: Resizing was easy, I got that. Though for mirroring I still have to look.

Easiest way I can think of would be to use UIGraphicsBeginImageContext then use UIGraphicsGetCurrentContext to get the CGContextRef

You should then be able to setup a transform on the context to rotate, mirror and shrink. Then draw the image into the context and call UIGraphicsGetImageFromCurrentImageContext to get the result back.

To mirror CGContextTranslateCTM to move accross by the width of the image and then CGContextScaleCTM(-1.0f, 1.0f).

To rotate CGContextRotateCTM.

You'll have to play around with these to get exactly what you want.

Or you can do it all yourself by moving the bytes around - this might actually be reasonably fast.


Taking Pictures of Game State inside an app - Bersaelor - Nov 3, 2009 05:07 AM

Well some of the parts you mentioned I already found myself, but thank you for the explanation Smile

I got my Picture Saving and Game Resuming working now!