CGLayers are great for drawing – especially when things need to be drawn over and over again. Converting a CGLayer to a UIImage is another story, though. NetSketch uses CGLayers for the drawing canvas, but converts them to UIImages when you go to upload your drawing or email it to a friend. The code below shows how it’s done. The CGLayer is drawn into a bitmap CGContext of the same size, and then a CGImage is created around the CGContext. The CGImage can be turned into a UIImage, and you’re done!
Be sure to leave a comment if you find this function useful!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | UIImage* UIImageFromLayer(CGLayerRef layer) { // Create the bitmap context CGContextRef bitmapContext = NULL; void * bitmapData; int bitmapByteCount; int bitmapBytesPerRow; CGSize size = CGLayerGetSize(layer); // Declare the number of bytes per row. Each pixel in the bitmap in this // example is represented by 4 bytes; 8 bits each of red, green, blue, and // alpha. bitmapBytesPerRow = (size.width * 4); bitmapByteCount = (bitmapBytesPerRow * size.height); // Allocate memory for image data. This is the destination in memory // where any drawing to the bitmap context will be rendered. bitmapData = malloc( bitmapByteCount ); if (bitmapData == NULL) { return nil; } // Create the bitmap context. We want pre-multiplied ARGB, 8-bits // per component. Regardless of what the source image format is // (CMYK, Grayscale, and so on) it will be converted over to the format // specified here by CGBitmapContextCreate. bitmapContext = CGBitmapContextCreate (bitmapData, size.width, size.height,8,bitmapBytesPerRow, CGColorSpaceCreateDeviceRGB(),kCGImageAlphaNoneSkipFirst); if (bitmapContext == NULL) // error creating context return nil; CGContextScaleCTM(bitmapContext, 1, -1); CGContextTranslateCTM(bitmapContext, 0, -size.height); // Draw the image to the bitmap context. Once we draw, the memory // allocated for the context for rendering will then contain the // raw image data in the specified color space. CGContextDrawLayerAtPoint(bitmapContext, CGPointZero, layer); CGImageRef img = CGBitmapContextCreateImage(bitmapContext); UIImage* ui_img = [UIImage imageWithCGImage: img]; CGImageRelease(img); CGContextRelease(bitmapContext); free(bitmapData); return ui_img; } |