zoukankan      html  css  js  c++  java
  • 封装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

  • 相关阅读:
    SharePoint远程发布Solution
    SharePoint Web Part Error – The Specified Solution Was Not Found
    Visual Studio 2013启用AnkSVN
    Using LINQ to SharePoint
    SharePoint配置搜索服务和指定搜索范围
    SharePoint 站点集和子站点数据互相读取
    SharePoint Backup
    Bootstrap滚动监听
    探索 SharePoint 2013 Search功能
    C#利用iComparable接口实现List排序
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3757680.html
Copyright © 2011-2022 走看看