CATiledLayer显示超大图片的解决方案

 

先对图片进行了裁剪 -> 很多小图片, 然后再根据显示 进行绘制

 

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self cutImageAndSave];
    [self addTiledLayer];
    
}

/**
 *  平铺layer 可用于展示大图
 *  展示大图时可能会引起卡顿(阻塞主线程),将大图切分成小图,然后用到他们(需要展示)的时候再加载(读取)
 */
- (void)addTiledLayer{
    //BingWallpaper-2015-11-22.jpg
    UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:self.view.bounds];
    [self.view addSubview:scrollView];
    
    //    UIImage *image = [UIImage imageNamed:@"BingWallpaper-2015-11-22.jpg"];
    
    CATiledLayer *tiledLayer = [CATiledLayer layer];
    //layer->像素 和 点 的概念不同 一个点是[UIScreen mainScreen].scale个像素
    //    CGFloat screenScale = [UIScreen mainScreen].scale;
    //    tiledLayer.contentsScale = screenScale;
    tiledLayer.frame = CGRectMake(0, 0, 1920, 1200);//image.size.width, image.size.height);
    tiledLayer.delegate = self;
    
    _tiledLayer = tiledLayer;
    
    scrollView.contentSize = tiledLayer.frame.size;
    //CGSizeMake(image.size.width / screenScale, image.size.height / screenScale);
    [scrollView.layer addSublayer:tiledLayer];
    [tiledLayer setNeedsDisplay];
}

/** 切图并保存到沙盒中 */
- (void)cutImageAndSave{
    NSString *filePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    NSString *imageName = [NSString stringWithFormat:@"%@/test-00-00.png",filePath];
    UIImage *tileImage = [UIImage imageWithContentsOfFile:imageName];
    NSLog(@"%@",imageName);
    if (tileImage) return;
    
    UIImage *image = [UIImage imageNamed:@"test-00-00.png"];
    UIImageView *imageView = [[UIImageView alloc]initWithImage:image];
    //    [self.view addSubview:imageView];
    CGFloat WH = 256;
    CGSize size = image.size;
    
    //ceil 向上取整
    NSInteger rows = ceil(size.height / WH);
    NSInteger cols = ceil(size.width / WH);
    
    for (NSInteger y = 0; y < rows; ++y) {
        for (NSInteger x = 0; x < cols; ++x) {
            UIImage *subImage = [self captureView:imageView frame:CGRectMake(x*WH, y*WH, WH, WH)];
            NSString *path = [NSString stringWithFormat:@"%@/test-%02ld-%02ld.png",filePath,x,y];
            [UIImagePNGRepresentation(subImage) writeToFile:path atomically:YES];
        }
    }
}


/** 切图 */
- (UIImage*)captureView:(UIView *)theView frame:(CGRect)fra{
    //开启图形上下文 将heView的所有内容渲染到图形上下文中
    UIGraphicsBeginImageContext(theView.frame.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [theView.layer renderInContext:context];
    
    //获取图片
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    CGImageRef ref = CGImageCreateWithImageInRect(img.CGImage, fra);
    UIImage *i = [UIImage imageWithCGImage:ref];
    CGImageRelease(ref);
    
    return i;
}

/**
 *  加载图片
 *  CALayerDelegate
 *  支持多线程绘制,-drawLayer:inContext:方法可以在多个线程中同时地并发调用
 *  所以请小心谨慎地确保你在这个方法中实现的绘制代码是线程安全的.(不懂哎)
 */
- (void)drawLayer:(CATiledLayer *)layer inContext:(CGContextRef)ctx{
    
    //获取图形上下文的位置与大小
    CGRect bounds = CGContextGetClipBoundingBox(ctx);
    //floor 向下取整
    NSInteger x = floor(bounds.origin.x / layer.tileSize.width);
    // * [UIScreen mainScreen].scale);
    NSInteger y = floor(bounds.origin.y / layer.tileSize.height);
    // * [UIScreen mainScreen].scale);
    
    //load tile image
    NSString *filePath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
    NSString *imageName = [NSString stringWithFormat:@"%@/test-%02ld-%02ld.png",filePath,x,y];
    UIImage *tileImage = [UIImage imageWithContentsOfFile:imageName];
    
    UIGraphicsPushContext(ctx);
    //绘制
    
    [tileImage drawInRect:bounds];
    UIGraphicsPopContext();
}

 

转载于:https://www.cnblogs.com/daxueshan/p/11189891.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值