core image图像处理和分析技术,用于为core graphics, core video和image I/O框架提供图像操作。它涉及到的主要是3个角色类:
CIFilter: 可变类,用于代表某种特定的处理效果,需要接收至少一个输入并产生一个输出图像
CIImage: 不可变的图像类,可以通过合成数据,或者读取文件,也可以通过获取CIFilter对象的输出来得到CIImage对象
CIContext: 它是core image用来绘制CIFilter所产生的目标图像的地方的对象,这个上下文可以是基于CPU也可以是基于GPU
需要注意的是在第4步中,获取的outputimage只是一份"recipe"(实际是将原始图片处理成目标图片所需要进行的计算),只有在真正需要将目标图片渲染出来的时候(典型的是各Framework中用来在各上下文中将图片绘制出来的带render,drawimage,createimage字样的方法)才会进行最终的渲染,比如第5步中的操作
filter用于标识处理的属性,采用key-value的形式存储,key为常量,value为特定属性类型的值
创建core image上下文
contextWithOptions创建的上下文并没有实时性能,指定CPU还是GPU进行渲染可以使用kCIContextUseSoftwareRenderer属性设置不同的bool值,使用GPU渲染更快,但使用GPU需要先将结果image拷贝到CPU中并转换为比如UIImage之类的对象之后才能被显示出来。
EAGL context类型的CIContext支持实时渲染,且所渲染的图像一直留存在GPU中,通常先需要创建一个EAGL上下文:
EAGLContext *myEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
对于实时绘制,颜色逼真度通常不需要关注,同时也由于其会拖慢整个绘制的性能,可以通过将working color space设置为null以关闭颜色管理
NSDictionary *options = @{ kCIContextWorkingColorSpace : [NSNull null] };
CIContext *myContext = [CIContext contextWithEAGLContext:myEAGLContext options:options];
创建core image对象
hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];
iOS中,此时hueAdjust的各参数是初始化为默认值的,但OS X不是。hueAdjust有两个输入参数,图像和角度:角度指hue在HSV和HLS颜色空间中的位置,其值变化范围为0到2π,0代表红色,2/3π弧度代表绿色,4/3π代表蓝色。
[hueAdjust setValue: myCIImage forKey: kCIInputImageKey];
[hueAdjust setValue: @2.094f forKey: kCIInputAngleKey];
当然也可以将上述写法替换成
hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"] keysAndValues:
kCIInputImageKey, myCIImage,
kCIInputAngleKey, @2.094f,
nil];
值得提出的是,直到渲染才生成真正的像素可以选择最优的顺序进行计算,比如先上色再缩小图像会比先将图像缩小再上色更费计算。
将结果绘制到屏幕上:
[myContext drawImage:result inRect:destinationRect fromRect:contextRect];
维持线程安全
CIContext和CIImage是不可更改的对象,可在多线程之间共享,但CIFilter是可更改的,所以不可以在多线程之间共享,各线程自己应当创建自己的CIFilter对象。
串联filter
gloom filter通过将图像高亮的部分取消以使图像黯淡
CIFilter *gloom = [CIFilter filterWithName:@"CIGloom"];
[gloom setDefaults]; // 1
[gloom setValue: result forKey: kCIInputImageKey];
[gloom setValue: @25.0f forKey: kCIInputRadiusKey]; // 2
[gloom setValue: @0.75f forKey: kCIInputIntensityKey]; // 3
result = [gloom valueForKey: kCIOutputImageKey]; // 4
每2步中,输入半径指定了效果的程度,可在0到100之间变化,默认值为10
3 设置输入密度为0.75,它是一个标量值,在filter输出和原始图像之间指定了线性混合,变化区间为0~1.0, 默认值为1.0
bump distortion filter
CIBumpDistortion Filter在图像中指定点处创建一个凸起。
CIFilter *bumpDistortion = [CIFilter filterWithName:@"CIBumpDistortion"]; // 1
[bumpDistortion setDefaults]; // 2
[bumpDistortion setValue: result forKey: kCIInputImageKey];
[bumpDistortion setValue: [CIVector vectorWithX:200 Y:150]
forKey: kCIInputCenterKey]; // 3
[bumpDistortion setValue: @100.0f forKey: kCIInputRadiusKey]; // 4
[bumpDistortion setValue: @3.0f forKey: kCIInputScaleKey]; // 5
result = [bumpDistortion valueForKey: kCIOutputImageKey];
4 设置凸起半径为100像素
5 设置输入比例为3,输入比例指定了效果的方向和量,区间为-10~10,默认为-0.5,0代表没有效果,负值代表向外的凸起,正值代表向内的凸起。
切换效果
切换(transition)通常用在幻灯片的切换或者视频中场景的切换,切换效果通常会需要一段时间,并需要设置一个定时器,接下来就是介绍如何设置定时器
transition filter需要做如下的任务:
1 创建切换需要的ciimage
2 创建并调度一个定时器
3 创建一个CIContext对象
4 创建 CIFilter对象
5 在OS X 中,需要设置filter的默认值
6 设置filter参数
7 设置处理的源图片和目标图片
8 计算时间
9 应用filter
10 绘制结果
11 重复8-10步走到切换结束
与单纯的图片filter不同的是,切换filter需要在切换过程中的多个时间段内重复绘制效果
在初始的时候启动一个定时器,在drawRect中添加绘制过渡图像的方法,具体做法是以根据时间流逝的长度,取一个参数值,设置CICopyMachineTransition filter的kCIInputTimeKey,并将结果串联到CICrop filter中,将串联的结果绘制出来。同时在每次timeout的时候均setNeedsDisplay
具体可以参考core image program guide>processing images 相应部分
为视频添加Filter
core image和core video协同可以产生很多效果,比如可以使用一个颜色修正filter以修正水吸收红色比绿色和蓝色更快的问题。
具体可以参考core image program guide>processing images 相应部分