Screen Capture using UIGetScreenImage

Editor’s Note: I read today (7/22/2010) that Apple is no longer approving applications using UIGetScreenImage. I haven’t been able to find an official Apple announcement on this – however, please give this consideration before using this method in your apps.

As talked about on TUAW, among other popular blogs, Apple has opened up the API to allow applications to capture the screen contents. So what’s the excitement all about? Read on, as this method opens up some interesting possibilities…

One of the unique opportunities is capturing screen contents while the camera is active, think augmented reality. One example of this idea in action is Sudoku Grab created by Chris Greening. The application allows the user to point the camera to a Sudoko board wherein the app will recognize the board, process the information and (optionally) show the solution. It’s not so much about solving the game that’s interesting as is the idea of using UIGetScreenImage() as a means to make this happen.

Setting up the User Interface

So let’s look at how to call UIGetScreenImage() to capture screen contents. This app consists of one primary view controller, the initialization is shown below.

- (id)init
  if (self = [super init]) 
    self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease];
		self.view.backgroundColor = [UIColor grayColor];
    // Button to activate camera
    button = [[UIButton alloc] initWithFrame:CGRectMake(80, 55, 162, 53)];    
    [button setBackgroundImage:[UIImage imageNamed:@"Camera.png"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];      
    [self.view addSubview:button];
    [button release];
  return self;  

This simple UI presents nothing more than one button, which when pressed will call a method to activate UIGetScreenImage() to capture the screen.

Calling UIGetScreenImage()

Before we can call UIGetScreenImage(), it’s good practice to define the method somewhere within our code. This will keep the compiler from generating the warning: implicit declaration of function ‘UIGetScreenImage.’ The next steps involve capturing the screen and creating a UIImage object.

// Define at top of implementation file
CGImageRef UIGetScreenImage(void);
- (void)buttonPressed:(UIButton *)button
  // Capture screen here...
  CGImageRef screen = UIGetScreenImage();
  UIImage* image = [UIImage imageWithCGImage:screen];
  // Save the captured image to photo album
  UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
Saving Captured Image to Photo Album

If you look at the last line of code above, this will initiate a request to write the image to the Photo Album. The code below shows the method that is called once the save is completed, in this example I display a message indicating success or failure.

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
  UIAlertView *alert;
  // Unable to save the image  
  if (error)
    alert = [[UIAlertView alloc] initWithTitle:@"Error" 
                            message:@"Unable to save image to Photo Album." 
                            delegate:self cancelButtonTitle:@"Ok" 
  else // All is well
    alert = [[UIAlertView alloc] initWithTitle:@"Success" 
                            message:@"Image saved to Photo Album." 
                            delegate:self cancelButtonTitle:@"Ok" 
  [alert show];
  [alert release];
Simulator Support

From what I can tell, UIGetScreenImage() is not supported on the simulator, you’ll need to load the app on a device to see how this works.

UIGetScreenImage Source Code Example

Here is a link to download the Xcode project for UIGetScreenImage Source.

  1. Yeah, Apple has confirmed that they will allow apps using UIGetScreenImage in the App store, but that’s subject to change, as the API itself might change.

    Anyhow – using UIGetScreenImage to capture the screen is pretty awesome in many cases – for example to render UIView’s contents when there’s transformations applied to some of its subviews – I’ve seen this question popup many times in dev forums. It seems the only solution is to call UIGetScreenImage, since the API which renders UIView context is not considering the transformations applied

    Nice overview, enjoying everything from your feed,

  2. If they are going to be opening up a lot of private APIs and later converting them to public, it might be a good idea to create something like a PrivateAPI class to provide wrappers for these functions. That way when they change from private to public you only have to change one line of code and you know exactly where you will find it. Of course that will be easier to do when it’s a loose function like this one rather than an object method, but some sort of encapsulation would be smart.

    On the topic of private API use, do you know whether Apple would pick up on the inclusion of one if it were in the code as text but, for example, excluded from the build using a #define?

    I used to work with Chris Greening. Very smart guy.

  3. I am using the same code snippet in an application to save screenshot in the photo album but I have the following issue:
    All thumnail in photoalbum are empty (black) even if teh picture itself is correct.
    Are you encountering the same issue?

    • AP, the images appear when in the photo album when I run the code. I would recommend trying various OS versions to see if that makes any difference.

  4. Hi John,

    indeed Apple has banned again the UIGetScreenImage API. Very frustrating for all the devs that actually used it and now need to remove that functionality from their apps (like me). Apple has also sent out an email to the apps who have been known to use that API that they’ll have to remove the code and release an app update.


Comments are closed.