Archive for February, 2009

Creating a UIImage from a CGLayer

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;
}

Safari-style iPhone Checkbox

I was finishing up work on an iPhone app earlier today and needed to add a check box to the interface. Interface Builder provides a “checkbox-ish” control that slides between “On” and “Off” states but it didn’t fit in well with the rest of the app. I needed a smaller one like the one that Mobile Safari provides for web forms.

It was pretty easy to create using a UIButton, but I spent a few minutes putting together images for the different button states. Click the link below to grab ‘em – and leave a comment if you find them useful!

iPhone Safari-Style Checkbox.zip