iOS-图像之CoreImage框架
1.coreImage的介绍
coreImage是IOS5中新加入的一个Objective-C的框架,提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析。iOS提供了很多强大的滤镜(Filter),其中IOS5中有48种,而到了最新的IOS6 Filter已经增加到了93种之多,并且这一数字会继续增加。这些Filter提供了各种各样的效果,并且还可以通过滤镜链将各种效果的Filter叠加起来,形成强大的自定义效果,如果你对该效果很满意,还可以子类化滤镜。
2.coreImage框架中的对象
2.1 CIImage
CIImage是CoreImage框架中最基本代表图像的对象,他不仅包含元图像数据,还包含作用在原图像上的滤镜链。这里我想特别强调的是CIImage和其他图像是不同的,在CIImage被CIContext渲染出来之前,他是依赖于滤镜链的,滤镜是不会更改CIImage中的图像数据。这个需要正确理解,不然会给你的程序造成错误。说到了CIImage的不同,就必须得提一下如何创建CIImage了,CIImage是不能直接有UIImage转化而来的,有以下几种创建CIImage的类方法(部分):
CIImage*image=[CIImage imageWithContentsOfURL:myURL];
CIImage*image=[CIImage imageWithData:myData];
CIImage*image=[CIImage imageWithCGImage:myCgimage];
CIImage*image=[CIImage imageWithCVPixelBuffer:CVBuffer];
2.2 CIFilter
1> CIFilter用来表示CoreImage提供的各种滤镜。滤镜使用键-值来设置输入值,一旦这些值设置好,CIFilter就可以用来生成新的CIImage输出图像了。
注意:
* 这里的输出的图像不会进行实际的图像渲染,他只包含一个对输入图像的引用以及需要应用与数据上的滤镜链。
* IOS永远在最佳的时间选择渲染图像。
2> 查询可用的滤镜种类:
[CIFilter filterNamesInCategory:kCICategoryBuiltIn];//搜索属于 kCICategoryBuiltIn类别的所有滤镜名字,返回一个数组;
[CIFilter filterNamesInCategories];//搜索所有可用的滤镜名称;
3> 查看filter的详细信息
调用[CIFilter attributes]会返回filter详细信息,下面我们以一个具体列子来看看他返回的信息。
下面是我程序返回的一个叫做CISepiaTone滤镜返回的详细信息:
2017-03-28 10:52:35.779 CIImage[1020:45742]{ CIAttributeFilterCategories = (//滤镜所示种类,通常一个滤镜可以属于几种
CICategoryColorEffect, //总类,这只是根据滤镜效果,作用来分类的
CICategoryVideo, //可以用种类名来搜索Fileter;
CICategoryInterlaced,
CICategoryNonSquarePixels,
CICategoryStillImage,
CICategoryBuiltIn
);
CIAttributeFilterDisplayName = "Sepia Tone";
CIAttributeFilterName = CISepiaTone; //滤镜的名称,通过该名称来
CIAttributeReferenceDocumentation = "http://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CISepiaTone"; // 相关API文档
//调用滤镜,具体见下面实例
inputImage = { //滤镜使用需要输入的参数,该
CIAttributeClass = CIImage; //参数类型为CIImage。
CIAttributeType = CIAttributeTypeImage;
};
inputIntensity = { //输入强度,参数的名称
CIAttributeClass = NSNumber; //类型
CIAttributeDefault = 1; //默认值
CIAttributeDescription = "The intensity of the sepia effect. A value of 1.0 creates a monochrome sepia image. A value of 0.0 has no effect on the image.";
CIAttributeIdentity = 0;
CIAttributeMax = 1; //最大值
CIAttributeMin = 0; //最小值
CIAttributeSliderMax = 1;
CIAttributeSliderMin = 0;
CIAttributeType = CIAttributeTypeScalar;
};
}
程序中使用CISepiaTone的代码为:
CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];
[filter setValue:inputImage forKey:@"inputImage"];
[filter setValue:[NSNumber numberWithFloat:0.8] forKey:@"inputIntensity"];
注意⚠️:
大家可以 [CIFilter filterNamesInCategories]返回所有的滤镜,并查看他们的参数来熟悉各个滤镜的使用方法。
2.3 CIContext
CIContext用来渲染CIImage,将作用在CIImage上的滤镜链应用到原始的图片数据中。CIContext可以是基于CPU的,也可以是基于GPU的。
* 这两种渲染的区别是:
使用CPU渲染的IOS会采用GCD来对图像进行渲染,这保证了CPU渲染在大部分情况下更可靠,比CPU渲染更容易使用,他可以在后台实现渲染过程;
使用GPU渲染的IOS会采用OpenGL ES2.0来渲染图像,这种方式CPU完全没有负担,应用程序的运行循环不会受到图像渲染的影响,而且他渲染比CPU渲染更快但是GPU渲染无法在后台运行。
* 对于如何选择更好的渲染方式,我认为应该视具体情况而定:
对于复杂的图像滤镜使用GPU更好,但是如果在处理视频并保存文件,或保存照片到照片库中时为避免程序退出对图片保存造成影响,这时应该使用CPU进行渲染。[CIContext contextWithOptions:] CPU或GPU都支持。要定义使用哪个,需要设置一个选项字典,增加键kCIContextUserSoftwareRenderer,并设置相应的布尔值。 默认情况是用CPU渲染的。
第一种:基于CPU的CIContext对象
CIContext *context = [CIContext contextWithOptions:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];//CPU渲染
第二种:基于GPU的CIContext对象
CIContext * ciContext =[CIContext contextWithOptions:nil];
第三种:基于OpenGL优化的CIContext对象。
EAGLContext * eagContent =[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
CIContext * context =[CIContext contextWithEAGLContext:eagContent];
渲染后的图片使用:
1.在imageView中使用:
CIContext *context = [CIContext context];
CIImage *ciimage = [filter outputImage];//获得处理过后的CIImage
CGImageRef cgimg = [context createCGImage:ciimage fromRect:[ciimage extent]];
UIImage *uiimage = [UIImage imageWithCGImage:cgimg scale:1.0f orientation:ui_orientation([ciimage properties])];
CGImageRelease(cgimg);
imageView.image = uiimage;
2.将图片保存到photoLibrary
CIImage *outputImage = [filter outputImage]; //filter 是滤镜。 方法表示获取到经过滤镜处理过的CIImage对象
CGImageRef cgimage = [cpu_context createCGImage:outputImage fromRect:[outputImage extent]];
//将图片保存到photo library
ALAssetsLibrary *library = [ALAssetsLibrary new];
[library writeImageToSavedPhotosAlbum:cgimage metadata:[outputImage properties] completionBlock:^(NSURL *assetURL NSError *error) {
CGImageRelease(cgimg);
}];
2.4 CIDetector和CIFeature
CIDetector用来分析CIImage,得到CIFeature。每个CIDetector都要用一个探测器来初始化,这个类型高数探测器要在图像中寻找什么特征。当一个CIDetector分析一张图片时,返回一个探测到的CIFeature的数组,如果CIDetector 被初始化为寻找面孔,那么返回的数组会被填上CIFaceFeature对象,每个CIFaceFeature都包含一个面部的CGrect引用(按照图像的坐标系),以及检测到的面孔的左眼,右眼,嘴部位置的CGPoint;
示例:
#pragma mark --人脸识别
+(BOOL)hasFace:(UIImage *)img content:(CIContext *)content
{
if (!img) {
return NO;
}
return ((NSArray *)[self featuresWithImage:img content:content])?YES:NO;
} +(NSArray *)featuresWithImage:(UIImage *)img content:(CIContext*)content
{
CIDetector * detector =[CIDetector detectorOfType:CIDetectorTypeFace context:content options:@{CIDetectorAccuracy:CIDetectorAccuracyHigh}];
CIImage * ciImage =[CIImage imageWithCGImage:img.CGImage];
NSArray * features =[detector featuresInImage:ciImage];
return features;
}
3. 注意事项
1> CoreImage在IOS上有很高的效率,但是滤镜和渲染操作也会对主线程造成影响。应该将CoreImage滤镜渲染操作放在后台线程执行,当这些操作介绍后在返回主线程进行界面的更新。
dispatch_async(
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^(void){
NSArray *filters;
CGImageRef cgImg = self.imageView.image.CGImage;
CIImage *coreImage = [CIImage imageWithCGImage:cgImg]; for(CIFilter *filter in filters){
[filter setValue:coreImage forKey:kCIInputImageKey];
coreImage = filter.outputImage;
} CGImageRef newImg = [self.imageContext createCGImage:coreImage
fromRect:[coreImage extent]]; dispatch_async(dispatch_get_main_queue(), ^(void){
self.imageView.image = [UIImage imageWithCGImage:newImg];
[self.adjustSpinner stopAnimating];
[sender setEnabled:YES];
});
});
上面这段代码,就是为了防止阻塞主线程,用GCD异步执行滤镜与渲染操作,在获取渲染后的照片以后,返回主线程进行界面的更新。
2> 不要重复应用滤镜,即使是同一个滤镜也不要应用两次,因为滤镜后输出照片包含滤镜链,在进行照片渲染是会将滤镜链效果叠加到原始数据上,这时会造成问题。比如,有一个CIImage,上面配置了强度为0.5的棕色滤镜,现在通过滑块将强度改为0.6,这个滤镜应该用在新的CIImage上,如果不是新的CIImage上,那么原来的CIImage中将包含强度为0.5和0.6的棕色滤镜,而我们只想0.6的棕色滤镜,这样就造成错误,这一点在编写程序的时候一定要切忌。
3> app中应用的滤镜太多,改变速率太快,如果是根据滑块来产生事件的话,一定要注意在使用滑条值前要首先判断更改的滤镜当前是否正在起作用,如果该滤镜正在生成新的渲染图片,则应该这次滑块的更新。这一点也是很重要的,弄的不好常常导致程序崩溃,出现内存泄露问题。
这些问题常常会导致程序的崩溃.
4. 总结
CoreImage处理图像的流程:
1:创建一个新的CIImage;
2:创建一个行的CIFIlter,并通过键-值设置各种输入值,这些值有些是有默认值的,有些没有默认值,需要编程者的设置;
3:在CIFilter中生成输出图像,如果存在滤镜链则将输出图像作为输入参数传入到下一个滤镜,跳回步骤2继续进行,如果到达滤镜末,则调用CIContext渲染CIImage对象。这个context可以是基于CPU或GPU的,基于CPU的产出CGImageRef对象,基于GPU的调用OpenGL ES在屏幕上画出结果,默认是基于CPU的。注意⚠️:
* 在使用CoreImage时,一定要记住CIImage对象在开始时不会操作图像数据,知道使用CIContext渲染图片是才会这么做。
* 还要记住最好在后台执行图像处理的操作,然后在主线程中修改界面。
iOS-图像之CoreImage框架的更多相关文章
- IOS 中的CoreImage框架
IOS 中的CoreImage框架(framework) - time4cnblogs 时间 2014-03-15 00:24:00 博客园-所有随笔区原文 http://www.cnblogs. ...
- IOS 中的CoreImage框架(framework)
http://www.cnblogs.com/try2do-neo/p/3601546.html coreimage framework 组成 apple 已经帮我们把image的处理分类好,来看看它 ...
- iOS超全开源框架、项目和学习资料汇总--数据库、缓存处理、图像浏览、摄像照相视频音频篇
iOS超全开源框架.项目和学习资料汇总--数据库.缓存处理.图像浏览.摄像照相视频音频篇 感谢:Ming_en_long 的分享 大神超赞的集合,http://www.jianshu.com/p/f3 ...
- iOS开发之CoreImage
CoreImage是iOS中的一个图像处理框架,提供了强大高效的图像处理功能,可以通过调用简单的API来使用框架所带的各种滤镜对图像进行处理. CoreImgae的三个重要组成部分:1.CIFiter ...
- iOS常用第三方开源框架和优秀开发者博客等
博客收藏iOS开发过程好的开源框架.开源项目.Xcode工具插件.Mac软件.文章等,会不断更新维护,希望对你们有帮助.如果有推荐或者建议,请到此处提交推荐或者联系我. 该文档已提交GitHub,点击 ...
- 【转】iOS超全开源框架、项目和学习资料汇总
iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...
- iOS 开发之照片框架详解(2)
一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...
- iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)
本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...
- iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)
转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...
随机推荐
- ios开发之--UIButton中imageView和titleLabel的位置调整
在使用UIButton时,有时候需要调整按钮内部的imageView和titleLabel的位置和尺寸.在默认情况下,按钮内部的imageView和titleLabel的显示效果是图片在左文字在右,然 ...
- 转载mysql数据库配置优化
网上有很多的文章教怎么配置MySQL服务器,但考虑到服务器硬件配置的不同,具体应用的差别,那些文章的做法只能作为初步设置参考,我们需要根据自己的情况进行配置优化,好的做法是MySQL服务器稳定运行了一 ...
- django学习笔记:AdminSite界面配置
(一)重定义字段顺序: 修改对应应用目录下的admin.py class PollAdmin(admin.ModelAdmin): fields = ['pub_date', 'questio ...
- hibernate sqlite jdbctemplate 待研究
http://my.oschina.net/lldy/blog/39058 hibernate sqlite http://foru ...
- DRBD架构详解(原创)
DRBD概述Distributed Replicated Block Device(DRBD)是一种基于软件的,无共享,复制的存储解决方案,在服务器之间的对块设备(硬盘,分区,逻辑卷等)进行镜像.DR ...
- es5.0 安装ik中文分词器 mac
es5.0集成ik中文分词器,网上资料很多,但是讲的有点乱,有的方法甚至不能正常运行此插件 特别注意的而是,es的版本一定要和ik插件的版本相对应: 1,下载ik 插件: https://github ...
- Lua学习笔记 入门的两个小程序
[Hello World]第一个Lua程序将遵循传统做法,打印一句“Hello World”: print("Hello World") [阶乘]下面的程序用于输出输入值对应的阶乘 ...
- Qt编写的RTSP播放器+视频监控(vlc版本)
几天写了个ffmpeg版本,今天特意抽空改写个vlc版本,之前vlc播放视频后,被接管了不能识别到鼠标,需要重新编译vlc源码得到支持鼠标消息的版本. /*** vlc视频播放类 作者:feiyang ...
- JS案例 - 基于vue的移动端长按手势
================================惯例碎碎念前言================================ 当时首先想到要做长按事件的时候,我想到的是vue内部的自 ...
- MAC升级node及npm
清除node.js的cache: sudo npm cache clean -f 安装 n 工具,这个工具是专门用来管理node.js版本的,别怀疑这个工具的名字,是他是他就是他,他的名字就是 &qu ...