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