Using CALayer's renderInContext: method with geometryFlipped

2.6k views Asked by At

I have a CALayer (containerLayer) that I'm looking to convert to a NSBitmapImageRep before saving the data out as a flat file. containerLayer has its geometryFlipped property set to YES, and this seems to be causing issues. The PNG file that is ultimately generated renders the content correctly, but doesn't seem to takes the flipped geometry into account. I'm obviously looking for test.png to accurately represent the content shown to the left.

Attached below is a screenshot of the problem and the code I'm working with.

A visual example

- (NSBitmapImageRep *)exportToImageRep
{
    CGContextRef context = NULL;
    CGColorSpaceRef colorSpace;
    int bitmapByteCount;
    int bitmapBytesPerRow;

    int pixelsHigh = (int)[[self containerLayer] bounds].size.height;
    int pixelsWide = (int)[[self containerLayer] bounds].size.width;

    bitmapBytesPerRow = (pixelsWide * 4);
    bitmapByteCount = (bitmapBytesPerRow * pixelsHigh);

    colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    context = CGBitmapContextCreate (NULL,
                                     pixelsWide,
                                     pixelsHigh,
                                     8,
                                     bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaPremultipliedLast);
    if (context == NULL)
    {
        NSLog(@"Failed to create context.");
        return nil;
    }

    CGColorSpaceRelease(colorSpace);
    [[[self containerLayer] presentationLayer] renderInContext:context];    

    CGImageRef img = CGBitmapContextCreateImage(context);
    NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:img];
    CFRelease(img);

    return bitmap;    
}

For reference, here's the code that actually saves out the generated NSBitmapImageRep:

NSData *imageData = [imageRep representationUsingType:NSPNGFileType properties:nil];
[imageData writeToFile:@"test.png" atomically:NO]; 
1

There are 1 answers

0
Martin Pilch On BEST ANSWER

You need to flip the destination context BEFORE you render into it.

Update your code with this, I have just solved the same problem:

CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, pixelsHigh);
CGContextConcatCTM(context, flipVertical);
[[[self containerLayer] presentationLayer] renderInContext:context];