封装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:@
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 = ; [filter configFilter:^(CIFilter *filter) {
[filter setValue:[NSNumber numberWithInt:(i++)% + ]
forKey:@"inputScale"];
}];
render.imageFilter = filter; [[GCDQueue mainQueue] execute:^{
imageView.image = [render render];
}]; } timeInterval:NSEC_PER_SEC/.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 = ;
[filter configFilter:^(CIFilter *filter) {
[filter setValue:[NSNumber numberWithFloat:(i+=)%/.f]
forKey:@"inputAngle"];
}];
render.imageFilter = filter;
[[GCDQueue mainQueue] execute:^{
imageView.image = [render render];
}];
} timeInterval:NSEC_PER_SEC/.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
封装CIImage实现实时渲染的更多相关文章
- 【原】实时渲染中常用的几种Rendering Path
[原]实时渲染中常用的几种Rendering Path 本文转载请注明出处 —— polobymulberry-博客园 本文为我的图形学大作业的论文部分,介绍了一些Rendering Path,比较简 ...
- 利用GPU实现无尽草地的实时渲染
0x00 前言 在游戏中展现一个写实的田园场景时,草地的渲染是必不可少的,而一提到高效率的渲染草地,很多人都会想起GPU Gems第七章 <Chapter 7. Rendering Countl ...
- 画面渲染:实时渲染(Real-time Rendering)、离线渲染(Offline Rendering)[转]
实时渲染(Real-time Rendering) 实时渲染的本质就是图形数据的实时计算和输出.最典型的图形数据源是顶点.顶点包括了位置.法向.颜色.纹理坐标.顶点的权重等.在第一代渲染技术中(198 ...
- 如何实现最佳的跨平台游戏体验?Unity成亮解密实时渲染
7月31日,2018云创大会游戏论坛在杭州国际博览中心103B圆满举行.本场游戏论坛聚焦探讨了可能对游戏行业发展有重大推动的新技术.新实践,如AR.区块链.安全.大数据等. Unity大中华区技术经理 ...
- 【实时渲染】实时3D渲染如何加速汽车线上体验应用推广
在过去,一支优秀的广告片足以让消费者对一辆汽车产生兴趣.完美的底盘线条或引擎的轰鸣声便会让潜在买家跑到经销商那里试驾.现在,广告还是和往常一样,并没有失去其特性,但86%的买家在与销售交流之前会在网上 ...
- OpenGL-非实时渲染与实时混合使用(有图有真相)
视频教程请关注 http://edu.csdn.net/lecturer/lecturer_detail?lecturer_id=440 一个朋友在问(我也曾经遇到过这样的事情),尤其是在地理信息上面 ...
- 【祥哥带你玩HoloLens开发】了解如何实现远程主机为HoloLens实时渲染
今天有一个兄弟在群里讲到他们的项目模型比较大,单用HoloLens运行设备的性能无法满足需要,问道如何将渲染工作交给服务器来做,讲渲染结果传给HoloLens.正好刚刚看官方github的时候发现一个 ...
- 实时渲染基础(4)纹理(Texture)
目录 纹理映射(Texture Mapping) 球形贴图(Spherical Map) 立方体贴图(Cube Map) 纹理走样问题 Mipmap 各向异性过滤(Ripmap) 纹理应用技术(Tex ...
- (笔记) RealTimeRender[实时渲染] C3
@author: 白袍小道 转载表明,查看随缘 前言: 从历史上看,图形加速始于每个像素扫描线上的插值颜色重叠一个三角形,然后显示这些值.包括访问图像数据允许纹理应用于表面.添加硬件 插入和测试z深度 ...
随机推荐
- Hadoop网站日志数据清洗——正则表达式实现
周旭龙前辈的Hadoop学习笔记—网站日志分析项目案例简明.经典,业已成为高校大数据相关专业的实验项目.上周博主也完成了这个实验,不同于周前辈使用特殊符号切割字符串得到数据的做法,博主使用了正则表达式 ...
- python 笔记-转
python笔记 Python 学习笔记 - 14.技巧(Tips) Python 学习笔记 - 13.异常(Exception) Python 学习笔记 - 12.流程控制(Contro ...
- 初学者使用MySQL_Workbench 6.0CE创建数据库和表,以及在表中插入数据。
标签: mysqlworkbench数据库 2013-10-09 20:17 19225人阅读 评论(14) 收藏 举报 分类: mysql(1) 版权声明:本文为博主原创文章,未经博主允许不得转 ...
- CLR via C# 读书笔记-26.线程基础
前言 这俩个月没怎么写文章做记录分享,一直在忙项目上线的事情,但是学习这件事情,停下来就感觉难受,clr线程这章也是反复看了好多遍,书读百遍其义自见,今天我们来聊下线程基础 1.进程是什么,以及线程起 ...
- 什么是memcached?
缓存是一种常驻与内存的内存数据库,内存的读取速度远远快于程序在磁盘读取数据的速度.我们在设计程序的时候常常会考虑使用缓存,将经常访问的数据放到内存上面这样可以提高访问数据的速度,同时可以降低磁盘或数据 ...
- An internal error occurred during: "Updating status for Tomcat v7.0 Server at localhost..."
tomcat启动maven工程的时候提示如下错误信息: An internal error occurred during: "Updating status for Tomcat v7.0 ...
- mybatis-plus的集成与使用
Mybatis-Plus: Mybatis-Plus(简称MP)是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发.提高效率而生. 官方网站:http://m ...
- mybatis循环生成前后缀:mapper.xml的<trim></trim>
*在mapper.xml中<trim prefix="(" suffix=")" suffixOverrides="," prefix ...
- Chrome浏览器取消INPUT自动记忆下拉框
项目中有一个搜索框,每次聚焦就会出现如下图自动记忆框,遮挡了项目的搜索列表 差了很多资料想要去掉它,最后发现在input上加上autocomplete="off"就可以了!
- 润乾报表如何使用Echarts
1. 润乾报表中使用Echarts统计图的步骤 2. 报表中添加echarts2统计图 选中需要设为统计图的单元格,点击 报表-第三方图形 菜单项,或者右键菜单-第三方图形,在图形编 ...