美文网首页
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