Great link for working with lower level APIs: Quartz Programming
Some of the code below is based on examples from this book.
Note. This is not verified code, intended only for a starting point ....
- (NSBitmapImageRep*)convertImageRep:(NSBitmapImageRep*)startingImage{ CGImageRef anImage = [startingImage CGImage]; CGContextRef bitmapContext; CGRect ctxRect; size_t bytesPerRow, width, height; width = CGImageGetWidth(anImage); height = CGImageGetHeight(anImage); ctxRect = CGRectMake(0.0, 0.0, width, height); bytesPerRow = (width * 4 + 63) & ~63; bitmapData = calloc(bytesPerRow * height, 1); bitmapContext = createRGBBitmapContext(width, height, TRUE); CGContextDrawImage (bitmapContext, ctxRect, anImage);
Context Creation Function:
CGContextRef createRGBBitmapContext(size_t width, size_t height, Boolean needsTransparentBitmap) { CGContextRef context; size_t bytesPerRow; unsigned char *rasterData; //minimum bytes per row is 4 bytes per sample * number of samples bytesPerRow = width*4; //round up to nearest multiple of 16. bytesPerRow = COMPUTE_BEST_BYTES_PER_ROW(bytesPerRow); int bitsPerComponent = 2; // to get 256 colors (2xRGBA) //use function 'calloc' so memory is initialized to 0. rasterData = calloc(1, bytesPerRow * height); if(rasterData == NULL){ fprintf(stderr, "Couldn't allocate the needed amount of memory!\n"); return NULL; } // uses the generic calibrated RGB color space. context = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), (needsTransparentBitmap ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst) ); if(context == NULL){ free(rasterData); fprintf(stderr, "Couldn't create the context!\n"); return NULL; } //Either clear the rect or paint with opaque white, if(needsTransparentBitmap){ CGContextClearRect(context, CGRectMake(0, 0, width, height)); }else{ CGContextSaveGState(context); CGContextSetFillColorWithColor(context, getRGBOpaqueWhiteColor()); CGContextFillRect(context, CGRectMake(0, 0, width, height)); CGContextRestoreGState(context); } return context; }
Using:
NSBitmapImageRep *startingImage; // assumed to be previously set. NSBitmapImageRep *endingImageRep = [self convertImageRep:startingImage]; // Write out as data NSData *outputData = [endingImageRep representationUsingType:NSPNGFileType properties:nil]; // somePath is set elsewhere [outputData writeToFile:somePath atomically:YES];