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框架的更多相关文章

  1. IOS 中的CoreImage框架

    IOS 中的CoreImage框架(framework) - time4cnblogs 时间 2014-03-15 00:24:00  博客园-所有随笔区原文  http://www.cnblogs. ...

  2. IOS 中的CoreImage框架(framework)

    http://www.cnblogs.com/try2do-neo/p/3601546.html coreimage framework 组成 apple 已经帮我们把image的处理分类好,来看看它 ...

  3. iOS超全开源框架、项目和学习资料汇总--数据库、缓存处理、图像浏览、摄像照相视频音频篇

    iOS超全开源框架.项目和学习资料汇总--数据库.缓存处理.图像浏览.摄像照相视频音频篇 感谢:Ming_en_long 的分享 大神超赞的集合,http://www.jianshu.com/p/f3 ...

  4. iOS开发之CoreImage

    CoreImage是iOS中的一个图像处理框架,提供了强大高效的图像处理功能,可以通过调用简单的API来使用框架所带的各种滤镜对图像进行处理. CoreImgae的三个重要组成部分:1.CIFiter ...

  5. iOS常用第三方开源框架和优秀开发者博客等

    博客收藏iOS开发过程好的开源框架.开源项目.Xcode工具插件.Mac软件.文章等,会不断更新维护,希望对你们有帮助.如果有推荐或者建议,请到此处提交推荐或者联系我. 该文档已提交GitHub,点击 ...

  6. 【转】iOS超全开源框架、项目和学习资料汇总

    iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...

  7. iOS 开发之照片框架详解(2)

    一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...

  8. iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)

    本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...

  9. iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...

随机推荐

  1. 简单思考 如何用PHP输出本周的周三日期

    简单思考 如何用PHP输出本周的周三日期?比如今天2017-10-31 计算本周周三应该是2017-11-01 自己动脑筋想一想,然后给我留言或者评论

  2. iOS Ad hoc

    There's one situation in which you need an Ad Hoc profile, and that's when you want to test Push Not ...

  3. JSONP 劫持漏洞实例

    0x01 Jsonp简介 Jsonp(JSON with Padding) 是 json 的一种"使用模式",可以让网页从别的域名(网站)那获取资料,即跨域读取数据. 为什么我们从 ...

  4. nginx安装教程

    一.安装编译工具及库文件 yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel 二.首先要安装 PCRE ...

  5. c语言学习笔记---符号

    专题2.符号的技巧: 1) 注释符与转义符 vC语言中的接续符(\)是指示编译器行为的利器: 接续符的使用:编译器会将反斜杠剔除,嗯在反斜杠后面的字符自动解到前面的一行. 在接续单词时,反斜杠之后不能 ...

  6. 使用node中的iconv-lite实现对“gbk”格式的转码

    在window中,gbk和utf-8是最常见的两种格式,但是我们在显示的时候往往需要将GBK转换为UTF-8,我现在有一个同步读取文件的操作: const fs = require('fs'); co ...

  7. Android学习之SeekBar(控制wav音频的声音)

    使用SeekBar调节声音 SeekBar控件其实就是一个高级点的进度条,就像我们在听歌,看电影用的播放器上的进度条一样,是可以拖动的,可以改变进度的一个进度条控件! SeekBar常用属性: and ...

  8. linux源码编译安装php出现 cannot find -lltdl

    原因: 在编辑php时添加的“–with-mcrypt”选项造成. 解决方法: 1.如果不需要mcrypt,那么编辑php时去掉该选项,然后再make.make install. 2.如果需要mcry ...

  9. Glide加载图片缓存库出现——You cannot start a load for a destroyed activity

    请记住一句话:不要再非主线程里面使用Glide加载图片,如果真的使用了,请把context参数换成getApplicationContext.

  10. EXCEL数据匹配:The 'Microsoft.Jet.Oledb.4.0' provider is not registered on the local machin

    百度的处理结果: 作者:LisenYang http://blog.csdn.net/lisenyang/article/details/52106492 这篇博文里面说的,默认设置修改[启动32应用 ...