封装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