Question

Is it possible to convert a CATransform3D into a set of CIVectors in order to transform a UIImage with a CATransform3D?

I believe that is now finally possible to replace UIGetScreenImage()'s ability to flatten 3D transforms of UIView/CALayer into an image by traversing the view hierarchy and rendering individual images, and then applying the CATransform3D to the image that was created.

I started working with GPUImage, which does accept CATransform3Ds to apply to a UIImage and unfortunately had no luck. Attached is the code I was using, and links to the images that were produced.

Screenshot of Simulator

Image Produced

- (UIImage*)iterateLayerHierarchy:(CALayer*)layer
{
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(layer.frame.size.width,
                                                      layer.frame.size.height),
                                           NO,
                                           0.0);


    for (CALayer *sublayer in layer.sublayers)
    {
        UIImage* subImage;

        if (sublayer.sublayers.count > 1) {
            subImage = [self iterateLayerHierarchy:sublayer];
        } else {
            subImage = [UIView getImageFromLayer:sublayer];
        }
        CGRect imageRect;
        if (isRetina()) {
            imageRect = CGRectMake(sublayer.position.x-subImage.size.width/4,
                                   sublayer.position.y-subImage.size.height/4,
                                   subImage.size.width,
                                   subImage.size.height);
        }else{
            imageRect = CGRectMake(sublayer.position.x-subImage.size.width/2,
                                   sublayer.position.y-subImage.size.height/2,
                                   subImage.size.width,
                                   subImage.size.height);
        }
        [subImage drawInRect:imageRect];
        //sublayer.hidden = YES;
    }

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return img;
}


+ (UIImage*) getImageFromLayer:(CALayer *)layer
{
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(layer.bounds.size.width,
                                                      layer.bounds.size.height),
                                           NO,
                                           0.0);

    [layer renderInContext:UIGraphicsGetCurrentContext()];

    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    if (!CATransform3DEqualToTransform(layer.transform, CATransform3DIdentity))
    {
        GPUImageTransformFilter *transformFilter = [[GPUImageTransformFilter alloc] init];
        transformFilter.transform3D = layer.transform;
        img = [transformFilter imageByFilteringImage:img];
    }

    return img;
}
Was it helpful?

Solution

While not a direct answer to the question, as of iOS 7 there is no longer a need to solve this problem. "UIGetScreenImage()" has effectively been replaced by "drawViewHierarchyInRect:", which is able to capture both OpenGL layers and UIKit based views simultaneously.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top