“renderInContext:” and CATransform3D

2019-03-11 19:33发布

问题:

I have an view that have mutiples views inside it, and an image presentation (aka. 'cover flow') into that too... And I need to make a screenshot programatically !

Since docs says that "renderInContext:" will not render 3d animations :

"Important The Mac OS X v10.5 implementation of this method does not support the entire Core Animation composition model. QCCompositionLayer, CAOpenGLLayer, and QTMovieLayer layers are not rendered. Additionally, layers that use 3D transforms are not rendered, nor are layers that specify backgroundFilters, filters, compositingFilter, or a mask values. Future versions of Mac OS X may add support for rendering these layers and properties."

source: https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CALayer_class/Introduction/Introduction.html

I have searched a lot, and my 'best' solution (that is not good at all), is to create my own CGContext and record all CG animations into it. But I really do not want to do it, because I will need to re-write most of my animations codes and it will be very expensive for memory... I found other solutions (some of then unmakable) as use openGL or capture through AVSessions, but no one that can help me...

What are my options ? Any with that problem ?

Thanks for your time !

回答1:

have you actually tried it? I'm currently working on a project with several 3D transforms, and when I try to programmatically make this screenshot it works just fine :) Here is the code I use:

-(UIImage *)getScreenshot
{
    CGFloat scale = 1.0;
    if([[UIScreen mainScreen]respondsToSelector:@selector(scale)])
    {        
        CGFloat tmp = [[UIScreen mainScreen]scale];
        if (tmp > 1.5)
        {
            scale = 2.0;    
        }
    }      
    if(scale > 1.5)
    {
        UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, scale);
    } 
    else
    {
        UIGraphicsBeginImageContext(self.frame.size);
    }    
    //SELF HERE IS A UIVIEW
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];    
    UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return screenshot;
}


回答2:

I got it working with protocols.... I'm implementing a protocol in all UIViews classes that make 3D transforms. So when I request a screenshot, it make all subviews screenshot, and generate one UIImage.. Not so good for lots of views, but I'm doing in a few views.

#pragma mark - Protocol implementation 'TDITransitionCustomTransform'

//Conforms to "TDITransitionCustomTransform" protocol, return currrent image view state , by current layer

- (UIImage*)imageForCurrentState {

//Make print

UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);

[self.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

//return printed image

return screenShot;

}

I was thinking it may works now because I'm doing that render in the transformed view layer, which have being transformed it self... And it wasn't working because "renderInContext:" doesn't get layers of it subviews, may it possible ?

Anyone interest in a bit more code of this solution, can be found here . in the apple dev forum.

It may be a function bug, or it just not being design for this purpose ...



回答3:

May Be You can use Core Graphaic instead of CATransform3DMakeRotation :)

CGAffineTransform flip = CGAffineTransformMakeScale(1.0, -1.0);

Which get effet on the renderInContext