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. Linux wget 命令下载文件

    wget是Linux系统中用来下载文件的工具,其功能还是比较多的,能够下载单个文件,也可以分段下载,下面小编将针对wget命令的用法给大家做个实例介绍. 实例1 :下载单个文件 # wget http ...

  2. 使用CountDownLatch模拟高并发场景

    import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java ...

  3. Android开发-- The content of the adapter has changed but ListView did not receive a notification - With AsyncTask

    最近在联系开发DaysMatter时遇到一个问题: app中使用ListView来展示所有事件,每次添加完事件后使用下面代码来更新ListView. toDoListView.refreshDrawa ...

  4. Hashtable的应用

    一,哈希表(Hashtable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其 ...

  5. 客户端远程连接linux下mysql数据库授权

    mysql默认状态是只支持localhost连接,这样远程服务器都输入IP地址去连接你的服务器是不可以的,下面我来介绍怎么让mysql允许远程连接配置方法,有需要的朋友可参考.   方法一,直接利用p ...

  6. codeforces水题100道 第十七题 Codeforces Beta Round #25 (Div. 2 Only) A. IQ test (brute force)

    题目链接:http://www.codeforces.com/problemset/problem/25/A题意:在n个书中找到唯一一个奇偶性和其他n-1个数不同的数.C++代码: #include ...

  7. Material Design系列第三篇——Using the Material Theme

    Using the Material Theme This lesson teaches you to Customize the Color Palette Customize the Status ...

  8. jquery.gritter.js简介

    Gritter 是一个小型的 jQuery 消息通知插件,通知效果如下图所示: 参考网

  9. ubuntu apt 代理设置

    可以通过三种方法为apt-get设置http代理方法一这是一种临时的手段,如果您仅仅是暂时需要通过http代理使用apt-get,您可以使用这种方式.在使用apt-get之前,在终端中输入以下命令(根 ...

  10. android 线程间的通信

    (转自:http://www.cnblogs.com/allin/archive/2010/05/19/1738800.html) andriod提供了 Handler 和 Looper 来满足线程间 ...