有没有人在iOS中使用CoreImage CICategoryTransition过滤器?

时间:2014-03-26 14:36:46

标签: ios objective-c core-image cifilter

Apple增加了一些" Transition" iOS 6中的核心图像过滤器(在CICategoryTransition类别中)。

是否有人知道示例项目如何使用它们来实际生成图像之间的实时转换?

到目前为止,我在iOS中使用CI过滤器的唯一方法是传入源CIImage,设置各种参数,然后向过滤器询问它的输出CIImage。

根据我的经验,这是相当慢的。 CICategoryTransition类别的过滤器具有时间属性。关于如何使用它的文档非常很薄,但我假设你将时间参数从0(转换开始)改为1.0(转换结束),并返回转换的图像指定的阶段。但是,我认为这不足以产生平滑动画所需的30 FPS。

1 个答案:

答案 0 :(得分:1)

我不同意文档" 很薄"。我从Core Image Programming Guide

得到了这一切

过渡过滤器需要执行以下任务:

  1. 创建用于的核心图像(CIImage对象) 过渡。

  2. 设置并安排计时器。

  3. 创建CIContext对象。

  4. 为过滤器创建一个CIFilter对象以应用于图像。

  5. 在OS X上,设置过滤器的默认值。

  6. 设置过滤器参数。

  7. 设置要处理的源图像和目标图像。

  8. 计算时间。

  9. 应用过滤器。

  10. 绘制结果。

  11. 重复步骤8-10,直到转换完成。

  12. 获取图像并设置计时器

    - (void)awakeFromNib {
    
    NSTimer    *timer;
    NSURL      *url;
    
    thumbnailWidth  = 340.0;
    thumbnailHeight = 240.0;
    
    url   = [NSURL fileURLWithPath: [[NSBundle mainBundle]
                    pathForResource: @"boots" ofType: @"jpg"]];
    [self setSourceImage: [CIImage imageWithContentsOfURL: url]];
    
    url   = [NSURL fileURLWithPath: [[NSBundle mainBundle]
                    pathForResource: @"skier" ofType: @"jpg"]];
    [self setTargetImage: [CIImage imageWithContentsOfURL: url]];
    
    timer = [NSTimer scheduledTimerWithTimeInterval: 1.0/30.0
                                             target: self
                                           selector: @selector(timerFired:)
                                           userInfo: nil
                                            repeats: YES];
    
    base = [NSDate timeIntervalSinceReferenceDate];
    [[NSRunLoop currentRunLoop] addTimer: timer
                                 forMode: NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] addTimer: timer
                                 forMode: NSEventTrackingRunLoopMode];
    }
    

    设置过渡过滤器

    - (void)setupTransition {
    CGFloat w = thumbnailWidth;
    CGFloat h = thumbnailHeight;
    
    CIVector *extent = [CIVector vectorWithX: 0  Y: 0  Z: w  W: h];
    
    transition  = [CIFilter filterWithName: @"CICopyMachineTransition"];
    // Set defaults on OS X; not necessary on iOS.
    [transition setDefaults];
    [transition setValue: extent forKey: kCIInputExtentKey];
    }
    

    复制机器转换效果的drawRect:方法

    - (void)drawRect: (NSRect)rectangle {
    CGRect  cg = CGRectMake(NSMinX(rectangle), NSMinY(rectangle),
                            NSWidth(rectangle), NSHeight(rectangle));
    
    CGFloat t = 0.4 * ([NSDate timeIntervalSinceReferenceDate] - base);
    if (context == nil) {
        context = [CIContext contextWithCGContext:
                        [[NSGraphicsContext currentContext] graphicsPort]
                                          options: nil];
    }
    if (transition == nil) {
        [self setupTransition];
    }
    [context drawImage: [self imageForTransition: t + 0.1]
                inRect: cg
              fromRect: cg];
    }
    

    应用过渡过滤器

    - (CIImage *)imageForTransition: (float)t {
    
    // Remove the if-else construct if you don't want the transition to loop
    if (fmodf(t, 2.0) < 1.0f) {
        [transition setValue: sourceImage  forKey: kCIInputImageKey];
        [transition setValue: targetImage  forKey: kCIInputTargetImageKey];
    } else {
        [transition setValue: targetImage  forKey: kCIInputImageKey];
        [transition setValue: sourceImage  forKey: kCIInputTargetImageKey];
    }
    
    [transition setValue: @( 0.5 * (1 - cos(fmodf(t, 1.0f) * M_PI)) )
                  forKey: kCIInputTimeKey];
    
    CIFilter  *crop = [CIFilter filterWithName: @"CICrop"
                                 keysAndValues:
                   kCIInputImageKey, [transition valueForKey: kCIOutputImageKey],
                   @"inputRectangle", [CIVector vectorWithX: 0  Y: 0
                                       Z: thumbnailWidth  W: thumbnailHeight],
                   nil];
    return [crop valueForKey: kCIOutputImageKey];
    }
    

    使用计时器更新显示

    - (void)timerFired: (id)sender {
    [self setNeedsDisplay: YES];
    }
    

    设置源图像和目标图像

    - (void)setSourceImage: (CIImage *)source {
    sourceImage = source;
    }
    
    - (void)setTargetImage: (CIImage *)target {
    targetImage = target;
    }
    

    我还建议查看以下项目示例CITransitionSelectorSample