Codec ░ NSData

564NSData to NSString and vice versa

From NSData to NSString:

NSString *s = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];

And the other way round:

NSData *d = [s dataUsingEncoding:NSUTF8StringEncoding]:

565Stripping Characters from an NSString 484Printing Selectors in NSLog 452Padding with Zeros (or other characters) 383String By Appending Path Component 381Zero-Padding

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

581Resizing an UIImage 569Layering one UIImage onto of another UIImage 564NSData to NSString and vice versa 355Programmatically capture UIView 338Accessing RGBA Pixel Data

338Accessing RGBA Pixel Data

NSData* pixelData = (NSData*) 
	CGDataProviderCopyData(CGImageGetDataProvider(c.CGImage));
unsigned char* pixelBytes = (unsigned char *)[pixelData bytes];
for(int i = 0; i < [pixelData length]; i += 4) {
		NSLog(@"pixelBytes[i] R:%i G:%i B:%i A:%i ", 
		(int)pixelBytes[i], 
		(int)pixelBytes[i+1], 
		(int)pixelBytes[i+2],
		(int)pixelBytes[i+3]);
		/*
		pixelBytes[i] = pixelBytes[i+3];
		pixelBytes[i+1] = pixelBytes[i+3];
		pixelBytes[i+2] = pixelBytes[i+3];
		pixelBytes[i+3] = 0;
		 */
    }
	NSData* newPixelData = [NSData dataWithBytes:pixelBytes length:[pixelData length]];
	UIImage* newImage = [UIImage imageWithData:newPixelData];

581Resizing an UIImage 569Layering one UIImage onto of another UIImage 564NSData to NSString and vice versa 361Transparent Background of Custom Drawing Class 347UIImage → pixelData → UIImage Rountrip

246writeToFile – quick file writing

Works with:

NSDictionary
NSArray
NSData
NSString

For more complicated purposes, NSOutputStream might be the best option, but for simply writing a date or even XML this might be the simplest and fasted way.

576NSDictionary and NSArray plist examples 565Stripping Characters from an NSString 564NSData to NSString and vice versa 484Printing Selectors in NSLog 452Padding with Zeros (or other characters)