0

I would like to take the image that is on my iPad's screen and export it as a JPG, PNG or PDF file.

In simpler terms, the user created something on the screen, he clicks 'export to PNG' for example, and then a PNG file is created.

How do I go about doing that?

Sergey Katranuk
  • 1,162
  • 1
  • 13
  • 23

2 Answers2

1

If it is an UIImage that you are talking about - that does have build-in methods for writing it's contents to a file and for fetching the image as png or jpeg data stream. See the UIImage class reference for details.

AFAIK there is no bild-in function for exporting into PDF. You could of course create a PDF and draw the image into it. This is tutorial is easy to understand and it does include drawing an image: http://www.ioslearner.com/generate-pdf-programmatically-iphoneipad/

Edit in response to your comment. The response is too large for a comment:

I did a similar thing with a GL layer once. In your case it should be easier. How to get an UIImage from a view's layer is discussed here Convert UIView Layer to UIImage and here How to convert UIView as UIImage? . Once you have it stored in an UIImage see its reference here http://developer.apple.com/library/ios/#documentation/uikit/reference/UIImage_Class/Reference/Reference.html . It tells you that there are UIKit functions available (not methods as I said before) that convert UIImages to JPEG and PNG: UIImagePNGRepresentation and UIImageJPEGRepresentation that are documented here: http://developer.apple.com/library/ios/#documentation/uikit/reference/UIKitFunctionReference/Reference/reference.html#//apple_ref/c/func/UIImagePNGRepresentation . These functions return NSData objects.

NSData is documented here: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html It comes with metods to write the data to a file. writeToFile:atomically: for instance.

Here is an example. In my case I just needed a unique file name and decided to take a timestamp. You may want to use some more user friendly file name here.

// Use current time stamp for some unique photo ID
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *pathToDocuments=[paths objectAtIndex:0];  // this returns the path to the App's document directory
NSString *photoID = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]];  // this is just a time stamp. This is what you are most likely to do different. 
NSString *fileName = [NSString stringWithFormat:@"%@/%@.jpg", pathToDocuments, photoID]; // now you have a fully qualified path to a file within that part of the file system that belongs to your app. It will be overwritten if it exists. 

// Actually save the image (JPEG)
NSData *imgData = UIImageJPEGRepresentation(theImage, 1); // convert to jpeg - 1.0 represents 100%
[imgData writeToFile:fileName atomically:YES]; // actually save the data.
Community
  • 1
  • 1
Hermann Klecker
  • 14,039
  • 5
  • 48
  • 71
  • Thanks for the PDF tutorial, I can definitely use that. Now how do go about the JPG and PNG? – Sergey Katranuk Jan 13 '13 at 13:05
  • Whoa, that's a load of info. I didn't think it would be that complicated. Anyhow, thanks for the info, I'll gladly take a look at the code snippet if you have it. I'm fairly new to iOS development, but I think this feature will always be handy – Sergey Katranuk Jan 13 '13 at 13:25
1

I wrote this category for UIView, taken with some help from unremembered sources:

@interface UIView (Rendering)

+ (UIImage *)renderImageFromLayer:(CALayer *)layer withRect:(CGRect)frame;
- (UIImage *)renderImageWithRect:(CGRect)frame;

@end

@implementation UIView (Rendering)

+ (UIImage *)renderImageFromLayer:(CALayer *)layer withRect:(CGRect)frame
{
    // Create a new context of the desired size to render the image
    UIGraphicsBeginImageContextWithOptions(frame.size, YES, 1.0);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Translate it, to the desired position
    CGContextTranslateCTM(context, -frame.origin.x, -frame.origin.y);

    // Render the view as image
    [layer renderInContext:context];

    // Fetch the image
    UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();

    // Cleanup
    UIGraphicsEndImageContext();

    return renderedImage;
}

- (UIImage *)renderImageWithRect:(CGRect)frame
{
    return [UIView renderImageFromLayer:self.layer withRect:frame];
}

@end
Guy Kogus
  • 7,251
  • 1
  • 27
  • 32
  • Once you have the UIImage object, you can call `UIImageJPEGRepresentation` or `UIImagePNGRepresentation` to get the raw image data, then use that NSData object for whatever purpose you desire. – Guy Kogus Jan 13 '13 at 13:20
  • Hi Guy Kogus. Thanks for the provided code. I'm still new to iOS development, so I need some time understanding your example. Is there any possibility of a video tutorial on how to do this, somewhere out there? – Sergey Katranuk Jan 13 '13 at 13:26
  • I guess this is a good one. It is pretty much forward even if you are new to iOS. You are most probably new to objective-c too. If so the beginning needs some explanation. In Objective-C you can always extend a class and add new methods. That is what is happening here. He extends UIView and adds two methods. After doing that you can call them similar to any original method of any UIView object including subclasses. – Hermann Klecker Jan 13 '13 at 13:31
  • Upvote for the nice approach. Could you just explain why you designed `renderImageFromLayer` as a class method. Wouldn't it be more convenient having it as instance method that internally refers to self.layer rather than receiving the layer as parameter? – Hermann Klecker Jan 13 '13 at 13:33
  • So, I should place this code in the .h and .m files of my UIViewController and modify it to my needs for it work, right? Or did I get something wrong? – Sergey Katranuk Jan 13 '13 at 13:37
  • Hermann, I think this somehow answers my question. How can I do the same thing described above, BUT not as a class method ('cause I'm not really good with those yet) but as an instance method, instead? – Sergey Katranuk Jan 13 '13 at 13:42
  • I've included above an instance method as well as a class method, so that you can use whichever feels more appropriate. You can also call `[view renderImageWithRect:CGRectMake(0.0, 0.0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];` to get a view rendered in its full frame to an image. – Guy Kogus Jan 13 '13 at 14:17
  • Alright, now this sounds better. So, I can use the method you've written above, what kind of parameter does it return? A UIImage? – Sergey Katranuk Jan 13 '13 at 14:26
  • That's what the return type is claiming. – Guy Kogus Jan 13 '13 at 15:59
  • Gotcha. Awesome, thanks guys very much for your help! I'll get back with questions if any appear. – Sergey Katranuk Jan 13 '13 at 19:58