https://github.com/YouXianMing

封装CIImage实现实时渲染

封装CIImage实现实时渲染

CIImage属于CoreImage里面的东东,用来渲染图片的,为什么要封装它呢?其实很简单,封装好之后使用更加方便.

如果直接使用CIImage渲染图片,使用的流程如下:

只要你仔细研究一下CIImage,你会发现,filter部分与context部分是彼此分离的,context只接受一个CIImage,其他的都不管,所以,这个地方,我们就把它拆分成两部分,一部分是filter,一部分是context.

注:context部分执行了CIImage的渲染工作,CIImage的outputImage方法只是封装了要被渲染的步骤而已.

@property(readonly, nonatomic) CIImage *outputImage
Description    
Returns a CIImage object that encapsulates the operations configured in the filter. (read-only)

ImageFilter.h + ImageFilter.m

//
//  ImageFilter.h
//  CoreImageWapper
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreImage/CoreImage.h>

#pragma mark - 辅助内联函数
NS_INLINE CIImage* CIImageFromImage(UIImage *image)
{
    return [[CIImage alloc] initWithImage:image];
}


#pragma mark - 定义的block
typedef void(^ImageFilterConfigBlock_t)(CIFilter *filter);

@interface ImageFilter : NSObject


#pragma mark - 可读写属性
@property (nonatomic, strong, readwrite) CIImage   *inputCIImage;    // 输入CIImage
@property (nonatomic, strong, readwrite) NSString  *filterName;      // 滤镜名字


#pragma mark - 重写了getter方法,注意
@property (nonatomic, strong, readonly)  CIImage   *outputCIImage;   // 输出CIImage
@property (nonatomic, assign, readonly)  BOOL       filterNameValid; // 滤镜名合法性


#pragma mark - 初始化方法
- (instancetype)init;
- (instancetype)initWithFilterName:(NSString *)filterName;
- (instancetype)initWithFilterName:(NSString *)filterName inputCIImage:(CIImage *)inputCIImage;


#pragma mark - 配置
- (void)configFilter:(ImageFilterConfigBlock_t)block;

@end
//
//  ImageFilter.m
//  CoreImageWapper
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "ImageFilter.h"

NSArray *filterNameArray = nil;

@interface ImageFilter ()

@property (nonatomic, strong) CIFilter   *filter;

@end

@implementation ImageFilter

@synthesize outputCIImage   = _outputCIImage;
@synthesize filterNameValid = _filterNameValid;

+ (void)initialize
{
    if (self == [ImageFilter class])
    {
        filterNameArray = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];;
    }
}

- (instancetype)init
{
    return [self initWithFilterName:nil inputCIImage:nil];
}

- (instancetype)initWithFilterName:(NSString *)filterName
{
    return [self initWithFilterName:filterName inputCIImage:nil];
}

- (instancetype)initWithFilterName:(NSString *)filterName inputCIImage:(CIImage *)inputCIImage
{
    self = [super init];
    if (self)
    {
        self.filterName   = filterName;
        self.inputCIImage = inputCIImage;
    }
    return self;
}

-(CIImage *)outputCIImage
{
    if (_filter)
    {
        return [_filter outputImage];
    }
    else
    {
        return nil;
    }
}

- (void)configFilter:(ImageFilterConfigBlock_t)block
{
    if (_filterName && _inputCIImage)
    {
        // 创建滤镜
        _filter = [CIFilter filterWithName:_filterName
                             keysAndValues:kCIInputImageKey, _inputCIImage, nil];
        
        // 设置滤镜
        block(_filter);
    }
    
    block(nil);
}

- (BOOL)filterNameValid
{
    BOOL flag = NO;
    
    if (_filterName)
    {
        for (NSString *name in filterNameArray)
        {
            if ([_filterName isEqualToString:name] == YES)
            {
                flag = YES;
                break;
            }
        }
    }
    
    return flag;
}

@end

ImageRender.h + ImageRender.m

//
//  ImageRender.h
//  CoreImageWapper
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ImageFilter.h"

@interface ImageRender : NSObject


@property (nonatomic, strong) ImageFilter  *imageFilter;
@property (nonatomic, strong) UIImage      *outputImage;


- (instancetype)init;
- (instancetype)initWithImageFilter:(ImageFilter *)imageFilter;
- (UIImage *)render;

@end
//
//  ImageRender.m
//  CoreImageWapper
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "ImageRender.h"

@interface ImageRender ()

@property (nonatomic, strong) CIContext    *context;

@end

@implementation ImageRender

- (instancetype)init
{
    return [self initWithImageFilter:nil];
}

- (instancetype)initWithImageFilter:(ImageFilter *)imageFilter
{
    self = [super init];
    if (self)
    {
        // 基于GPU渲染
        self.context     = [CIContext contextWithOptions:nil];
        self.imageFilter = imageFilter;
    }
    return self;
}

- (UIImage *)render
{
    if (_imageFilter)
    {
        CIImage *outputCIImage = [_imageFilter outputCIImage];
        
        CGImageRef cgImage = [_context createCGImage:outputCIImage
                                            fromRect:[outputCIImage extent]];
        
        self.outputImage = [UIImage imageWithCGImage:cgImage];
        
        CGImageRelease(cgImage);
    }
    
    return self.outputImage;
}

@end

现在,你可以这么使用了:)

好吧,来一个复杂的看看,即时渲染:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    ImageFilter *filter = [ImageFilter new];
    ImageRender *render = [ImageRender new];
    
    filter.filterName = @"CIPixellate";
    filter.inputCIImage = CIImageFromImage([UIImage imageNamed:@"demo"]);
    [filter configFilter:^(CIFilter *filter) {
        [filter setValue:@1
                  forKey:@"inputScale"];
    }];
    render.imageFilter = filter;
    
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[render render]];
    [self.view addSubview:imageView];
    imageView.center = self.view.center;
    
    _timer = [[GCDTimer alloc] initInQueue:[GCDQueue globalQueue]];
    [_timer event:^{
        
        static int i = 1;
        
        [filter configFilter:^(CIFilter *filter) {
            [filter setValue:[NSNumber numberWithInt:(i++)%10 + 1]
                      forKey:@"inputScale"];
        }];
        render.imageFilter = filter;
        
        [[GCDQueue mainQueue] execute:^{
            imageView.image = [render render];
        }];
        
    } timeInterval:NSEC_PER_SEC/10.f];
    [_timer start];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    ImageFilter *filter = [ImageFilter new];
    ImageRender *render = [ImageRender new];
    
    filter.filterName = @"CIHueAdjust";
    filter.inputCIImage = CIImageFromImage([UIImage imageNamed:@"demo"]);
    [filter configFilter:^(CIFilter *filter) {
        [filter setValue:@(3.14f)
                  forKey:@"inputAngle"];
    }];
    render.imageFilter = filter;

    UIImageView *imageView = [[UIImageView alloc] initWithImage:[render render]];
    [self.view addSubview:imageView];
    imageView.center = self.view.center;
    
    _timer = [[GCDTimer alloc] initInQueue:[GCDQueue globalQueue]];
    [_timer event:^{
        static int i = 0;
        [filter configFilter:^(CIFilter *filter) {
            [filter setValue:[NSNumber numberWithFloat:(i+=1)%314/100.f]
                      forKey:@"inputAngle"];
        }];
        render.imageFilter = filter;
        [[GCDQueue mainQueue] execute:^{
            imageView.image = [render render];
        }];
    } timeInterval:NSEC_PER_SEC/60.f];
    [_timer start];
}

附录:

https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/uid/TP40004346

https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/CoreImageFilterReference/Reference/reference.html

https://developer.apple.com/library/ios/documentation/GraphicsImaging/Conceptual/CoreImaging/CoreImage.pdf

http://www.rapidsnail.com/Tutorial/t/2012/112/30/22766/the-coreimage-ios.aspx

http://www.raywenderlich.com/zh-hans/24773/%E5%88%9D%E5%AD%A6ios6-%E4%B8%AD%E7%9A%84core-image%E6%8A%80%E6%9C%AF

http://my.safaribooksonline.com/book/video/9780321637031/chapter-15dot-secret-patches-core-image-filters-and-glsl-pushing-the-boundaries/ch15sec1lev5

http://stackoverflow.com/questions/17041669/creating-a-blurring-overlay-view/17041983#17041983

 

 

 

 

posted @ 2014-05-29 09:44  YouXianMing  阅读(1127)  评论(0编辑  收藏  举报