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

  1. //
  2. // ImageFilter.h
  3. // CoreImageWapper
  4. //
  5. // Copyright (c) 2014年 Y.X. All rights reserved.
  6. //
  7.  
  8. #import <Foundation/Foundation.h>
  9. #import <CoreImage/CoreImage.h>
  10.  
  11. #pragma mark - 辅助内联函数
  12. NS_INLINE CIImage* CIImageFromImage(UIImage *image)
  13. {
  14. return [[CIImage alloc] initWithImage:image];
  15. }
  16.  
  17. #pragma mark - 定义的block
  18. typedef void(^ImageFilterConfigBlock_t)(CIFilter *filter);
  19.  
  20. @interface ImageFilter : NSObject
  21.  
  22. #pragma mark - 可读写属性
  23. @property (nonatomic, strong, readwrite) CIImage *inputCIImage; // 输入CIImage
  24. @property (nonatomic, strong, readwrite) NSString *filterName; // 滤镜名字
  25.  
  26. #pragma mark - 重写了getter方法,注意
  27. @property (nonatomic, strong, readonly) CIImage *outputCIImage; // 输出CIImage
  28. @property (nonatomic, assign, readonly) BOOL filterNameValid; // 滤镜名合法性
  29.  
  30. #pragma mark - 初始化方法
  31. - (instancetype)init;
  32. - (instancetype)initWithFilterName:(NSString *)filterName;
  33. - (instancetype)initWithFilterName:(NSString *)filterName inputCIImage:(CIImage *)inputCIImage;
  34.  
  35. #pragma mark - 配置
  36. - (void)configFilter:(ImageFilterConfigBlock_t)block;
  37.  
  38. @end
  1. //
  2. // ImageFilter.m
  3. // CoreImageWapper
  4. //
  5. // Copyright (c) 2014年 Y.X. All rights reserved.
  6. //
  7.  
  8. #import "ImageFilter.h"
  9.  
  10. NSArray *filterNameArray = nil;
  11.  
  12. @interface ImageFilter ()
  13.  
  14. @property (nonatomic, strong) CIFilter *filter;
  15.  
  16. @end
  17.  
  18. @implementation ImageFilter
  19.  
  20. @synthesize outputCIImage = _outputCIImage;
  21. @synthesize filterNameValid = _filterNameValid;
  22.  
  23. + (void)initialize
  24. {
  25. if (self == [ImageFilter class])
  26. {
  27. filterNameArray = [CIFilter filterNamesInCategory:kCICategoryBuiltIn];;
  28. }
  29. }
  30.  
  31. - (instancetype)init
  32. {
  33. return [self initWithFilterName:nil inputCIImage:nil];
  34. }
  35.  
  36. - (instancetype)initWithFilterName:(NSString *)filterName
  37. {
  38. return [self initWithFilterName:filterName inputCIImage:nil];
  39. }
  40.  
  41. - (instancetype)initWithFilterName:(NSString *)filterName inputCIImage:(CIImage *)inputCIImage
  42. {
  43. self = [super init];
  44. if (self)
  45. {
  46. self.filterName = filterName;
  47. self.inputCIImage = inputCIImage;
  48. }
  49. return self;
  50. }
  51.  
  52. -(CIImage *)outputCIImage
  53. {
  54. if (_filter)
  55. {
  56. return [_filter outputImage];
  57. }
  58. else
  59. {
  60. return nil;
  61. }
  62. }
  63.  
  64. - (void)configFilter:(ImageFilterConfigBlock_t)block
  65. {
  66. if (_filterName && _inputCIImage)
  67. {
  68. // 创建滤镜
  69. _filter = [CIFilter filterWithName:_filterName
  70. keysAndValues:kCIInputImageKey, _inputCIImage, nil];
  71.  
  72. // 设置滤镜
  73. block(_filter);
  74. }
  75.  
  76. block(nil);
  77. }
  78.  
  79. - (BOOL)filterNameValid
  80. {
  81. BOOL flag = NO;
  82.  
  83. if (_filterName)
  84. {
  85. for (NSString *name in filterNameArray)
  86. {
  87. if ([_filterName isEqualToString:name] == YES)
  88. {
  89. flag = YES;
  90. break;
  91. }
  92. }
  93. }
  94.  
  95. return flag;
  96. }
  97.  
  98. @end

ImageRender.h + ImageRender.m

  1. //
  2. // ImageRender.h
  3. // CoreImageWapper
  4. //
  5. // Copyright (c) 2014年 Y.X. All rights reserved.
  6. //
  7.  
  8. #import <Foundation/Foundation.h>
  9. #import "ImageFilter.h"
  10.  
  11. @interface ImageRender : NSObject
  12.  
  13. @property (nonatomic, strong) ImageFilter *imageFilter;
  14. @property (nonatomic, strong) UIImage *outputImage;
  15.  
  16. - (instancetype)init;
  17. - (instancetype)initWithImageFilter:(ImageFilter *)imageFilter;
  18. - (UIImage *)render;
  19.  
  20. @end
  1. //
  2. // ImageRender.m
  3. // CoreImageWapper
  4. //
  5. // Copyright (c) 2014年 Y.X. All rights reserved.
  6. //
  7.  
  8. #import "ImageRender.h"
  9.  
  10. @interface ImageRender ()
  11.  
  12. @property (nonatomic, strong) CIContext *context;
  13.  
  14. @end
  15.  
  16. @implementation ImageRender
  17.  
  18. - (instancetype)init
  19. {
  20. return [self initWithImageFilter:nil];
  21. }
  22.  
  23. - (instancetype)initWithImageFilter:(ImageFilter *)imageFilter
  24. {
  25. self = [super init];
  26. if (self)
  27. {
  28. // 基于GPU渲染
  29. self.context = [CIContext contextWithOptions:nil];
  30. self.imageFilter = imageFilter;
  31. }
  32. return self;
  33. }
  34.  
  35. - (UIImage *)render
  36. {
  37. if (_imageFilter)
  38. {
  39. CIImage *outputCIImage = [_imageFilter outputCIImage];
  40.  
  41. CGImageRef cgImage = [_context createCGImage:outputCIImage
  42. fromRect:[outputCIImage extent]];
  43.  
  44. self.outputImage = [UIImage imageWithCGImage:cgImage];
  45.  
  46. CGImageRelease(cgImage);
  47. }
  48.  
  49. return self.outputImage;
  50. }
  51.  
  52. @end

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

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

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.  
  5. ImageFilter *filter = [ImageFilter new];
  6. ImageRender *render = [ImageRender new];
  7.  
  8. filter.filterName = @"CIPixellate";
  9. filter.inputCIImage = CIImageFromImage([UIImage imageNamed:@"demo"]);
  10. [filter configFilter:^(CIFilter *filter) {
  11. [filter setValue:@
  12. forKey:@"inputScale"];
  13. }];
  14. render.imageFilter = filter;
  15.  
  16. UIImageView *imageView = [[UIImageView alloc] initWithImage:[render render]];
  17. [self.view addSubview:imageView];
  18. imageView.center = self.view.center;
  19.  
  20. _timer = [[GCDTimer alloc] initInQueue:[GCDQueue globalQueue]];
  21. [_timer event:^{
  22.  
  23. static int i = ;
  24.  
  25. [filter configFilter:^(CIFilter *filter) {
  26. [filter setValue:[NSNumber numberWithInt:(i++)% + ]
  27. forKey:@"inputScale"];
  28. }];
  29. render.imageFilter = filter;
  30.  
  31. [[GCDQueue mainQueue] execute:^{
  32. imageView.image = [render render];
  33. }];
  34.  
  35. } timeInterval:NSEC_PER_SEC/.f];
  36. [_timer start];
  37. }

  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4.  
  5. ImageFilter *filter = [ImageFilter new];
  6. ImageRender *render = [ImageRender new];
  7.  
  8. filter.filterName = @"CIHueAdjust";
  9. filter.inputCIImage = CIImageFromImage([UIImage imageNamed:@"demo"]);
  10. [filter configFilter:^(CIFilter *filter) {
  11. [filter setValue:@(3.14f)
  12. forKey:@"inputAngle"];
  13. }];
  14. render.imageFilter = filter;
  15.  
  16. UIImageView *imageView = [[UIImageView alloc] initWithImage:[render render]];
  17. [self.view addSubview:imageView];
  18. imageView.center = self.view.center;
  19.  
  20. _timer = [[GCDTimer alloc] initInQueue:[GCDQueue globalQueue]];
  21. [_timer event:^{
  22. static int i = ;
  23. [filter configFilter:^(CIFilter *filter) {
  24. [filter setValue:[NSNumber numberWithFloat:(i+=)%/.f]
  25. forKey:@"inputAngle"];
  26. }];
  27. render.imageFilter = filter;
  28. [[GCDQueue mainQueue] execute:^{
  29. imageView.image = [render render];
  30. }];
  31. } timeInterval:NSEC_PER_SEC/.f];
  32. [_timer start];
  33. }

附录:

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

封装CIImage实现实时渲染的更多相关文章

  1. 【原】实时渲染中常用的几种Rendering Path

    [原]实时渲染中常用的几种Rendering Path 本文转载请注明出处 —— polobymulberry-博客园 本文为我的图形学大作业的论文部分,介绍了一些Rendering Path,比较简 ...

  2. 利用GPU实现无尽草地的实时渲染

    0x00 前言 在游戏中展现一个写实的田园场景时,草地的渲染是必不可少的,而一提到高效率的渲染草地,很多人都会想起GPU Gems第七章 <Chapter 7. Rendering Countl ...

  3. 画面渲染:实时渲染(Real-time Rendering)、离线渲染(Offline Rendering)[转]

    实时渲染(Real-time Rendering) 实时渲染的本质就是图形数据的实时计算和输出.最典型的图形数据源是顶点.顶点包括了位置.法向.颜色.纹理坐标.顶点的权重等.在第一代渲染技术中(198 ...

  4. 如何实现最佳的跨平台游戏体验?Unity成亮解密实时渲染

    7月31日,2018云创大会游戏论坛在杭州国际博览中心103B圆满举行.本场游戏论坛聚焦探讨了可能对游戏行业发展有重大推动的新技术.新实践,如AR.区块链.安全.大数据等. Unity大中华区技术经理 ...

  5. 【实时渲染】实时3D渲染如何加速汽车线上体验应用推广

    在过去,一支优秀的广告片足以让消费者对一辆汽车产生兴趣.完美的底盘线条或引擎的轰鸣声便会让潜在买家跑到经销商那里试驾.现在,广告还是和往常一样,并没有失去其特性,但86%的买家在与销售交流之前会在网上 ...

  6. OpenGL-非实时渲染与实时混合使用(有图有真相)

    视频教程请关注 http://edu.csdn.net/lecturer/lecturer_detail?lecturer_id=440 一个朋友在问(我也曾经遇到过这样的事情),尤其是在地理信息上面 ...

  7. 【祥哥带你玩HoloLens开发】了解如何实现远程主机为HoloLens实时渲染

    今天有一个兄弟在群里讲到他们的项目模型比较大,单用HoloLens运行设备的性能无法满足需要,问道如何将渲染工作交给服务器来做,讲渲染结果传给HoloLens.正好刚刚看官方github的时候发现一个 ...

  8. 实时渲染基础(4)纹理(Texture)

    目录 纹理映射(Texture Mapping) 球形贴图(Spherical Map) 立方体贴图(Cube Map) 纹理走样问题 Mipmap 各向异性过滤(Ripmap) 纹理应用技术(Tex ...

  9. (笔记) RealTimeRender[实时渲染] C3

    @author: 白袍小道 转载表明,查看随缘 前言: 从历史上看,图形加速始于每个像素扫描线上的插值颜色重叠一个三角形,然后显示这些值.包括访问图像数据允许纹理应用于表面.添加硬件 插入和测试z深度 ...

随机推荐

  1. Core中使用Hangfire

    之前使用Quartz.Net,后来发现hangfire对Core的继承更加的好,而且自带管理后台,这就比前者好用太多了. 安装注册 安装 PM> Install-Package Hangfire ...

  2. Java的commons包的简介

    Jakarta Commons是Jakarta的一个子项目,目的是创建和维护独立于其他框架和产品的程序包(packages).Jakarta Commons项目源于重用,其中的程序包必须确保能够重用. ...

  3. Dubbo2.7源码分析-Dubbo是如何整合spring-framework的

    这篇文章是Dubbo源码分析的开端,与其说这篇文章是Dubbo源码分析,不如是spring源码分析,因为大部分都是在分析spring如何解析xml配置文件的,为了与后面的Dubbo源码分析保持一致,姑 ...

  4. [日常] PHP设置 include_path 配置选项

    动态设置php.ini中的include_path 配置选项: 两种方式set_include_path($new_include_path)ini_set('include_path',$new_i ...

  5. Linux root用户不能通过SSH连接的问题

    http://jingyan.baidu.com/article/fd8044fad48fc95031137a85.html 最近在虚拟机安装Ubuntu之后,通过普通ssh远程连接的时候明明输入了正 ...

  6. 高并发第六弹:线程封闭(ThreadLocal)

    当访问共享的可变数据时,通常需要使用同步.一种避免使用同步的方式就是不共享数据.如果仅在单线程内访问数据,就不需要同步.这种技术被称为线程封闭. 它其实就是把对象封装到一个线程里,只有一个线程能看到这 ...

  7. JVM之---Java源码编译机制

    Sun JDK中采用javac将Java源码编译为class文件,这个过程包含三个步骤:     1.分析和输入到符号表(Parse and Enter)    Parse过程所做的工作有词法和语法分 ...

  8. Centos7宽带连接

    网上大多教程都是虚拟机上实现宽带连接的,但是实际有差别 装完系统最头疼的就是宽带连接 转自:centos创建宽带连接-EnchanterBlue-ChinaUnix博客 http://blog.chi ...

  9. ASP.NET Core 2 学习笔记(十)视图

    ASP.NET Core MVC中的Views是负责网页显示,将数据一并渲染至UI包含HTML.CSS等.并能痛过Razor语法在*.cshtml中写渲染画面的程序逻辑.本篇将介绍ASP.NET Co ...

  10. JXU1NDRBJXU0RTJBJXU1MjJCJXU1NDI3

    U2FsdGVkX19f62S3+iSZxxJBADqNOfYV6/XumpnG7VwzMlQz7T7SaFsjyQx9d4PWAYQwtmgr4T9wDGKnKJCrR0veUEul6Uj4mEkN ...