Ok, a bit late to the party. Apple officially approved the use of UIGetScreenImage().
After carefully considering the issue, Apple is now allowing applications to use the function UIGetScreenImage() to programmatically capture the current screen contents. The function prototype is as follows:
CGImageRef UIGetScreenImage(void);
https://devforums.apple.com/message/149553
How to caputure a view, ideally the live input of the camera? Unfortunaly there’s no clean and clear interface for that. Only the undocumented UIGetScreenCapture() call:
http://www.iphonedevsdk.com/forum/iphone-sdk-development/11219-screenshots-we-allowed-use-uigetscreenimage.html
http://stackoverflow.com/questions/1531815/takepicture-vs-uigetscreenimage
http://svn.saurik.com/repos/menes/trunk/iphonevnc/iPhoneVNC.mm
http://blogs.oreilly.com/iphone/2008/10/creating-a-full-screen-camera.html
But since UIGetScreenCapture() is an undocumented call (in 3.1), here are official ways to get the content of a view.
UIGraphicsGetImageFromCurrentImageContext();
http://icodeblog.com/2009/07/27/1188/
http://www.elrepositorio.com/?p=31
camera capture data pixel screen UIView
590Adding an UIAlertView
385Rotating an UIView
361Transparent Background of Custom Drawing Class
347UIImage → pixelData → UIImage Rountrip
The questions is rather simple: How to manipulate single pixels of an UIImage?
The answer is rather long; but includes a joyful trip into Quartz 2D Graphic land…
// load image, convert to CGImageRef
UIImage *c = [UIImage imageNamed:@"c.png"];
CGImageRef cRef = CGImageRetain(c.CGImage);
// png alpha to mask
NSData* pixelData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(cRef));
// image raw data
//NSData* pixelDataRep = UIImagePNGRepresentation(c);
// compressed png data
//NSLog(@"pixelData %i", [pixelData length]);
//NSLog(@"pixelDataRep %i", [pixelDataRep length]);
//NSLog(@"pixelDataRep equal to pixelData: %@", [pixelData isEqualToData:pixelDataRep] ? @"YES" : @"NO");
//UIImage* newImage = [UIImage imageWithData:pixelData];
//[newImage drawInRect:CGRectMake(10, 340, 65, 65)];
//NSLog(@"pixelData %@", pixelData);
unsigned char* pixelBytes = (unsigned char *)[pixelData bytes];
// return pointer to data
// step through char data
for(int i = 0; i < [pixelData length]; i += 4) {
// change accordingly
pixelBytes[i] = pixelBytes[i];
pixelBytes[i+1] = pixelBytes[i+1];
pixelBytes[i+2] = pixelBytes[i+2];
pixelBytes[i+3] = 255;
}
//1ms in Simulator , 5ms on iPhone 3GS , 65x65 pixel
// copy bytes in new NSData
NSData* newPixelData = [NSData dataWithBytes:pixelBytes length:[pixelData length]];
//NSLog(@"newPixelData %@", newPixelData);
//NSLog(@"newPixelData: %@", newPixelData ? @"ok" : @"nil");
//NSLog(@"newPixelData equal to pixelData: %@", [pixelData isEqualToData:newPixelData] ? @"YES" : @"NO");
// cast NSData as CFDataRef
CFDataRef imgData = (CFDataRef)pixelData;
//NSLog(@"CFDataGetLength %i", CFDataGetLength(imgData) );
// Make a data provider from CFData
CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData(imgData);
// testing... create data provider from file.... works
//NSString* imageFileName = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"c.png"];
//CGDataProviderRef imgDataProvider = CGDataProviderCreateWithFilename([imageFileName UTF8String]);
// does not work like that
// new image needs to get PNG properties
//CGImageRef throughCGImage = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);
// get PNG properties from cRef
size_t width = CGImageGetWidth(cRef);
size_t height = CGImageGetHeight(cRef);
size_t bitsPerComponent = CGImageGetBitsPerComponent(cRef);
size_t bitsPerPixel = CGImageGetBitsPerPixel(cRef);
size_t bytesPerRow = CGImageGetBytesPerRow(cRef);
CGColorSpaceRef colorSpace = CGImageGetColorSpace(cRef);
CGBitmapInfo info = CGImageGetBitmapInfo(cRef);
CGFloat *decode = NULL;
BOOL shouldInteroplate = NO;
CGColorRenderingIntent intent = CGImageGetRenderingIntent(cRef);
// cRef PNG properties + imgDataProvider's data
CGImageRef throughCGImage = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, info, imgDataProvider, decode, shouldInteroplate, intent);
CGDataProviderRelease(imgDataProvider);
//NSLog(@"c %i, throughCGImage: %i", CGImageGetHeight(cRef), CGImageGetHeight(throughCGImage) );
CGImageRelease(throughCGImage);
// make UIImage with CGImage
UIImage* newImage = [UIImage imageWithCGImage:throughCGImage];
//NSLog(@"newImage: %@", newImage);
// draw UIImage
[newImage drawInRect:CGRectMake(10, 340, 65, 65)];
References:
- http://iphoneincubator.com/blog/tag/cgimageref
- http://www.nixwire.com/getting-uiimage-to-work-with-nscoding-encodewithcoder/
- http://developer.apple.com/mac/library/qa/qa2007/qa1509.html
- http://stackoverflow.com/questions/1282830/uiimagepickercontroller-uiimage-memory-and-more
- http://lists.apple.com/archives/Quartz-dev/2008//Aug/msg00073.html
2D CGImageRef data NSData pixel pixel value Quartz UIImage
581Resizing an UIImage
569Layering one UIImage onto of another UIImage
564NSData to NSString and vice versa
355Programmatically capture UIView
338Accessing RGBA Pixel Data