Search code examples
objective-crenderscalingcatiledlayer

Render large CATiledLayer into smaller area


I have a CATiledLayer of size 4096 x 4096 which I want to render into a PNG of size 1024 x 1024

this isnt doing it...

-(NSData *)createPNGFormat
{
    UIGraphicsBeginImageContext(CGSizeMake(1024, 1024));
    tiledLayer.transform = CATransform3DMakeScale(0.25, 0.25, 1.0);
    [tiledLayer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return UIImagePNGRepresentation(image);     

}

Any ideas on how to do this?


Solution

  • [First Hack] Brute Force , Render tile by tile. This works (slowly)

    -(UIImage *)renderTileX:(NSInteger)xpos tileY:(NSInteger)ypos scale:(CGFloat)ascale
    {
        CGSize tiledsize = tiledLayer.tileSize;
        CGRect tiledframe = tiledLayer.bounds;
        CALayer *container = [CALayer layer];
        container.frame = CGRectMake(0, 0, tiledsize.width,tiledsize.height);
        UIGraphicsBeginImageContext(tiledsize);
        [container addSublayer:tiledLayer];
        tiledLayer.frame = CGRectMake(-tiledsize.width*xpos,-tiledsize.height*ypos, tiledframe.size.width, tiledframe.size.height);
        [container renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        [tiledLayer removeFromSuperlayer];
    
        CGFloat fsize = tiledsize.width*ascale;
        CGRect apicrect = CGRectMake(0,0,fsize,fsize);
    
        UIGraphicsBeginImageContext(apicrect.size);
        [image drawInRect:apicrect];
        UIImage *thumb = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return thumb;   
    
    
    }
    
    
    -(UIImage *)renderTiledLayer
    {
    
        UIGraphicsBeginImageContext(CGSizeMake(1024, 1024));
    
        for (NSInteger x = 0 ; x<4; x++) {
            for (NSInteger y = 0; y < 4; y++) {
                NSLog(@"render %d:%d",x,y);
                UIImage *tile = [self renderTileX:x tileY:y scale:0.25];
                [tile drawAtPoint:CGPointMake(x*256, y*256)];
            }
        }
        UIImage *fimage = UIGraphicsGetImageFromCurrentImageContext();
    
        UIGraphicsEndImageContext();
    
    
        return fimage;      
    }
    

    [Using the Google...] The better way

    -(UIImage *)createThumb
    {
    
        UIGraphicsBeginImageContext(CGSizeMake(1024, 1024));
        CGContextScaleCTM(UIGraphicsGetCurrentContext(), 0.25, 0.25);
        [tiledLayer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *fimage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return fimage;  
    }