SDWebImage(一) GIF播放

工作的时候,需要播放某几帧有延时的GIF,才发现工程中接入的SDWebImage(V3.8)不支持这个功能。


某一些帧有明显延时 (网络图片,侵删)

为了解决这个问题,查了一些资料,看了SDWebImage源码,所以做个记录:在4.0之前,SDWebImage自带GIF播放效果,不需要特殊处理;从4.0开始,SDWebImage集成FLAnimatedImageView来播放GIF。

V4.0之前

SDWebImage源码里面,对于获取到的图片信息(二进制数据),如果判定为GIF,就换成GIF图:

+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
    if (!data) {
        return nil;
    }
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    size_t count = CGImageSourceGetCount(source);
    UIImage *animatedImage;
    if (count <= 1) {
        animatedImage = [[UIImage alloc] initWithData:data];
    }
    else {
        NSMutableArray *images = [NSMutableArray array];
        NSTimeInterval duration = 0.0f;
        for (size_t i = 0; i < count; i++) {
            CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
            if (!image) {
                continue;
            }
            //获取每一帧的展示时长,并相加,得到整个GIF的时长
            duration += [self sd_frameDurationAtIndex:i source:source]; 
            [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
            CGImageRelease(image);
        }
        if (!duration) {
            duration = (1.0f / 10.0f) * count;
        }
        animatedImage = [UIImage animatedImageWithImages:images duration:duration];
    }
    CFRelease(source);
    return animatedImage;
}

如上所示,整个GIF的duration是每一帧的展示时长相加之和,从而导致最终每一帧展示的时长是一样的。对于普通的GIF,可以满足需求,但是对于那些某一帧需要特别停顿较长时间的GIF,就满足不了需求。

不过,这个版本中,SDWebImage外露的下载GIF和普通图片(png、JPG等)的接口是一致的。所以,使用者不用区分需要下载的是GIF还是普通图片,使用统一的接口下载即可。

V4.0及以上

从4.0开始,SDWebImage集成了FLAnimatedImageView,并且新建了一个FLAnimatedImageView的分类,专门用于播放GIF:


FLAnimatedImageView的分类

如果想要下载的是GIF,那么对应的UIImageView必须FLAnimatedImageView的对象,并且使用FLAnimatedImageView+WebCache提供的接口:

    FLAnimatedImageView *imageView = [[FLAnimatedImageView alloc] init];
    imageView.frame = CGRectMake(100, 300, 38, 38);
    [imageView sd_setImageWithURL:[NSURL URLWithString:@"https://www.xxx.com/xxx.gif"] placeholderImage:nil options:SDWebImageRefreshCached];
    [self.view addSubview:imageView];

而且,FLAnimatedImageView里面,使用了CADisplayLink作为计时器来播放GIF,从而可以达到每一帧时长都不同的效果。

分析

个人觉得,4.0之所以集成FLAnimatedImageView,主要就是为了可以播放每一帧的展示时长会不同的GIF。

你可能感兴趣的:(SDWebImage(一) GIF播放)