Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using CALayer's renderInContext: method with geometryFlipped

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]; 
like image 662
ndg Avatar asked Oct 21 '11 22:10

ndg


1 Answers

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];
like image 147
Martin Pilch Avatar answered Oct 16 '22 04:10

Martin Pilch