美文网首页
iOS:AVFoundation视频-烟花、雪花效果

iOS:AVFoundation视频-烟花、雪花效果

作者: 豆浆油条cc | 来源:发表于2020-01-17 16:02 被阅读0次

直接上效果图:


Untitled.gif

为本地视频添加烟花、雪花效果。实际就是使用GIF、序列帧背景透明图片组,再用AVVideoCompositionCoreAnimationTool:

AVVideoCompositionCoreAnimationTool* animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:parentLayer];

创建parentLayer:
geometryFlipped:可以基于父层颠倒y轴坐标,因为CALayer是以左下角为原点的。

    CALayer *parentLayer = [CALayer layer];
    parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
    parentLayer.geometryFlipped = true;

加载gif的原理,是提取gif资源中的所有图片、图片时间节点,使用动画加到CALayer上

//从gif提取帧图片信息
-(void)getImagesWithGif:(NSURL *)gifPath resultBlock:(void(^)(NSArray<UIImage*>* images,CGFloat totalTime,NSArray* delayTimes))resultBlock{
        
    CGImageSourceRef gifSource = CGImageSourceCreateWithURL((CFURLRef)gifPath, NULL);
    size_t gifCount = CGImageSourceGetCount(gifSource);
    
    NSMutableArray *times = [NSMutableArray array];
    NSMutableArray *images = [NSMutableArray array];
    NSMutableArray *delayTimes = [NSMutableArray array];

    CGFloat totalTime = 0.0;
    CGFloat currentTime = 0.0;
    for (size_t i = 0; i< gifCount; i++) {
        
        CGImageRef imageRef = CGImageSourceCreateImageAtIndex(gifSource, i, NULL);
        [images addObject:(__bridge id _Nonnull)(imageRef)];
        
        //获取到的gif中帧信息
        NSDictionary *dict = (NSDictionary*)CFBridgingRelease(CGImageSourceCopyPropertiesAtIndex(gifSource, i, NULL));
        NSDictionary *gifDict = [dict valueForKey:(NSString*)kCGImagePropertyGIFDictionary];
        
        //持续时间
        CGFloat time = [[gifDict valueForKey:(NSString*)kCGImagePropertyGIFUnclampedDelayTime] floatValue];
        
        [delayTimes addObject:[NSNumber numberWithFloat:time]];
        //总时间
        totalTime = totalTime + time;
    }
    //图片占据时间点
    [delayTimes enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        NSNumber* number = [NSNumber numberWithFloat:[obj floatValue] + currentTime];
        [times addObject:number];
    }];
    
    resultBlock(images,totalTime,times);
}

创建动画:

//获取动画
- (void)addGifAnimationFromGifPath:(NSURL*)gifPath resultBlock:(void(^)(CAKeyframeAnimation* animation))resultBlock{
    
    [self getImagesWithGif:gifPath resultBlock:^(NSArray<UIImage *> *images, CGFloat totalTime, NSArray* delayTimes) {

        NSMutableArray *times = [NSMutableArray arrayWithCapacity:3];
        CGFloat currentTime = 0;
        NSInteger count = delayTimes.count;
        for (int i = 0; i < count; ++i) {
            [times addObject:[NSNumber numberWithFloat:(currentTime / totalTime)]];
            currentTime += [[delayTimes objectAtIndex:i] floatValue];
        }

        CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
        animation.keyTimes = times;//帧时间
        animation.values = images;//总图片
        animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        animation.duration = totalTime;
        animation.repeatCount = HUGE_VALF;
        animation.beginTime = AVCoreAnimationBeginTimeAtZero;
        animation.removedOnCompletion = NO;
        
        resultBlock(animation);
    }];
}

创建animationTool:

//获取animationTool
- (void)addAnimationLayerFromGif:(NSArray<NSURL*>*)gifPaths videoSize:(CGSize)videoSize resultBlock:(void(^)(AVVideoCompositionCoreAnimationTool* animationTool))resultBlock{
    
    CALayer *parentLayer = [CALayer layer];
    parentLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
    parentLayer.geometryFlipped = true;
    
    CALayer *videoLayer = [CALayer layer];
    videoLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
    
    [parentLayer addSublayer:videoLayer];
    
    [gifPaths enumerateObjectsUsingBlock:^(NSURL * _Nonnull gifPath, NSUInteger idx, BOOL * _Nonnull stop) {

        [self addGifAnimationFromGifPath:gifPath resultBlock:^(CAKeyframeAnimation *animation) {

            CALayer* gifLayer = [CALayer layer];
            gifLayer.frame = CGRectMake(0, 0, videoSize.width, videoSize.height);
            [gifLayer addAnimation:animation forKey:@"gif"];
            [parentLayer addSublayer:gifLayer];
            
            if (idx == gifPaths.count - 1) {
                //最后
                AVVideoCompositionCoreAnimationTool* animationTool = [AVVideoCompositionCoreAnimationTool videoCompositionCoreAnimationToolWithPostProcessingAsVideoLayer:videoLayer inLayer:
                                                                      ];
                resultBlock(animationTool);
            }
        }];
    }];
}

GitHub:
https://github.com/qw9685/addGif

相关文章

网友评论

      本文标题:iOS:AVFoundation视频-烟花、雪花效果

      本文链接:https://www.haomeiwen.com/subject/huoczctx.html