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的类方法:

[cpp] view plaincopy
  1. 1.CIImage*image=[CIImage imageWithContentsOfURL:myURL];
  2. 2.CIImage*image=[CIImage imageWithData:myData];
  3. 3.CIImage*image=[CIImage imageWithCGImage:myCgimage];
  4. 4.CIImage*image=[CIImage imageWithCVPixelBuffer:CVBuffer];

2.2 CIFilter

CIFilter用来表示CoreImage提供的各种滤镜。滤镜使用键-值来设置输入值,一旦这些值设置好,CIFilter就可以用来生成新的CIImage输出图像了。记住,这里的输出的图像不会进行实际的图像渲染,他只包含一个对输入图像的引用以及需要应用与数据上的滤镜链。IOS永远在最佳的时间选择渲染图像。

CIFilter提供了一个简单的方法查询可用的滤镜种类:[CIFilterfilterNamesInCategory:kCICategoryBuiltIn];//搜索属于 kCICategoryBuiltIn类别的所有滤镜名字,返回一个数组;

[CIFilterfilterNamesInCategories];//搜索所有可用的滤镜名称;

调用[CIFilter attributes]会返回filter详细信息,下面我们以一个具体列子来看看他返回的信息。

下面是我程序返回的一个叫做CISepiaTone滤镜返回的详细信息:

[cpp] view plaincopy
  1. 2012-09-18 16:17:09.155 SZFYKJHomeWorkVersion1[2836:f803] {
  2. CIAttributeFilterCategories =     (//滤镜所示种类,通常一个滤镜可以属于几种
  3. CICategoryColorEffect,       //总类,这只是根据滤镜效果,作用来分类的
  4. CICategoryVideo,             //可以用种类名来搜索Fileter;
  5. CICategoryInterlaced,
  6. CICategoryNonSquarePixels,
  7. CICategoryStillImage,
  8. CICategoryBuiltIn
  9. );
  10. CIAttributeFilterDisplayName = "Sepia Tone";
  11. CIAttributeFilterName = CISepiaTone;        //滤镜的名称,通过该名称来
  12. //调用滤镜,具体见下面实例
  13. inputImage =     {                 //滤镜使用需要输入的参数,该
  14. CIAttributeClass = CIImage;     //参数类型为CIImage。
  15. CIAttributeType = CIAttributeTypeImage;
  16. };
  17. inputIntensity =     {              //输入强度,参数的名称
  18. CIAttributeClass = NSNumber;        //类型
  19. CIAttributeDefault = 1;         //默认值
  20. CIAttributeIdentity = 0;
  21. CIAttributeMax = 1;             //最大值
  22. CIAttributeMin = 0;             //最小值
  23. CIAttributeSliderMax = 1;
  24. CIAttributeSliderMin = 0;
  25. CIAttributeType = CIAttributeTypeScalar;
  26. };
  27. }
  28. 程序中使用CISepiaTone的代码为:CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone"];
  29. [filter setValue:inputImage forKey:@"inputImage"];
  30. [filter setValue:[NSNumber numberWithFloat:0.8] forKey:@"inputIntensity"];

大家可以 [CIFilterfilterNamesInCategories]返回所有的滤镜,并查看他们的参数来熟悉各个滤镜的使用方法。

2.3 CIContext

CIContext用来渲染CIImage,将作用在CIImage上的滤镜链应用到原始的图片数据中。CIContext可以是基于CPU的,也可以是基于GPU的,这两种渲染的区别是:使用CPU渲染的IOS会采用GCD来对图像进行渲染,这保证了CPU渲染在大部分情况下更可靠,比CPU渲染更容易使用,他可以在后台实现渲染过程;而GPU渲染方式使用OpenGL ES2.0来渲染图像,这种方式CPU完全没有负担,应用程序的运行循环不会受到图像渲染的影响,而且他渲染比CPU渲染更快但是GPU渲染无法在后台运行。

对于如何选择更好的渲染方式,我认为应该视具体情况而定:对于复杂的图像滤镜使用 GPU 更好,但是如果在处理视频并保存文件,或保存照片到照片库中时为避免程序退出对图片保存造成影响,这时应该使用 CPU 进行渲染。默认情况是用 CPU 渲染的。

[cpp] view plaincopy
  1. CIContext *context = [CIContext contextWithOptions:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];//CPU渲染

渲染后的图片使用:

1.在imageView中使用:

[cpp] view plaincopy
  1. // Create the CIContext to render into
  2. CIContext *context = [CIContext context];
  3. // Get outputImage from the last filter in chain
  4. CIImage *ciimage = [filter outputImage];
  5. // Render the CIImage into a CGImageRef
  6. CGImageRef cgimg = [context createCGImage:ciimage fromRect:[ciimage extent]];
  7. // Create a UIImage from the CGImageRef
  8. UIImage *uiimage = [UIImage imageWithCGImage:cgimg scale:1.0f
  9. orientation:ui_orientation([ciimage properties])];
  10. CGImageRelease(cgimg);
  11. // Use the UIImage in an UIImageView
  12. imageView.image = uiimage;

2.将图片保存到photoLibrary

[cpp] view plaincopy
  1. // Create a CGImage from the CIImage
  2. CIImage *outputImage = [filter outputImage];
  3. CGImageRef cgimage = [cpu_context createCGImage:outputImage
  4. fromRect:[outputImage extent]];
  5. // Add the CGImage to the photo library
  6. ALAssetsLibrary *library = [ALAssetsLibrary new];
  7. [library writeImageToSavedPhotosAlbum:cgimage
  8. metadata:[outputImage properties]
  9. completionBlock:^(NSURL *assetURL NSError *error) {
  10. CGImageRelease(cgimg);
  11. }];

2.4 CIDetector和CIFeature

CIDetector用来分析CIImage,得到CIFeature。每个CIDetector都要用一个探测器来初始化,这个类型高数探测器要在图像中寻找什么特征。

当一个CIDetector分析一张图片时,返回一个探测到的CIFeature的数组,如果CIDetector 被初始化为寻找面孔,那么返回的数组会被填上CIFaceFeature对象,每个CIFaceFeature都包含一个面部的CGrect引用(按照图像的坐标系),以及检测到的面孔的左眼,右眼,嘴部位置的CGPoint;

[cpp] view plaincopy
  1. CIDetector *faceDetector = [CIDetector
  2. detectorOfType:CIDetectorTypeFace
  3. context:self.imageContext
  4. options:options];
  5. NSArray *faces = [faceDetector featuresInImage:coreImage
  6. options:nil];
  7. for(CIFaceFeature *face in faces){
  8. coreImage = [CIFilter filterWithName:@"CISourceOverCompositing"
  9. keysAndValues:kCIInputImageKey, [self makeBoxForFace:face],
  10. kCIInputBackgroundImageKey, coreImage, nil].outputImage;
  11. }

3 注意事项

 

1 CoreImage在IOS上有很高的效率,但是滤镜和渲染操作也会对主线程造成影响。应该将CoreImage滤镜渲染操作放在后台线程执行,当这些操作介绍后在返回主线程进行界面的更新。

[cpp] view plaincopy
  1. dispatch_async(
  2. dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
  3. ^(void){
  4. //CGImageRef cgImage = [self autoAdjustImage];
  5. NSArray *filters;
  6. // Create Core Image
  7. CGImageRef cgImg = self.imageView.image.CGImage;
  8. CIImage *coreImage = [CIImage imageWithCGImage:cgImg];
  9. // Iterate through all of our filters and apply
  10. // them to the CIImage
  11. for(CIFilter *filter in filters){
  12. [filter setValue:coreImage forKey:kCIInputImageKey];
  13. coreImage = filter.outputImage;
  14. }
  15. // Create a new CGImageRef by rendering through CIContext
  16. // This won't slow down main thread since we're in a background
  17. // dispatch queue
  18. CGImageRef newImg = [self.imageContext createCGImage:coreImage
  19. fromRect:[coreImage extent]];
  20. dispatch_async(dispatch_get_main_queue(), ^(void){
  21. // Update our image view on the main thread
  22. // You can also perform any other UI updates needed
  23. // here such as hidding activity spinners
  24. self.imageView.image = [UIImage imageWithCGImage:newImg];
  25. [self.adjustSpinner stopAnimating];
  26. [sender setEnabled:YES];
  27. });
  28. });

上面这段代码,就是为了防止阻塞主线程,用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渲染图片是才会这么做。还要记住最好在后台执行图像处理的操作,然后在主线程中修改界面。

大家有机会可以参考一下IOS5核心框架中的CoreImage章节和AVFoundation章节,下面在贴一个书本中的列子的连接,我认为很有助理解。http://ioscoreframeworks.com/download/。

另外也可以参考下wwdc上面的视频Session510-Getting Started with Core Image和Session 511 -  Core Image Techniques.mov。

iOS框架介绍之coreImage相关推荐

  1. 《企业级ios应用开发实战》一2.2 iOS框架介绍

    2.2 iOS框架介绍 iOS衍生自Mac OS X的成熟内核,但iOS操作系统更紧凑和高效,支持iPhone和iPod Touch的硬件.iOS继承了Mac OS X的风格,包括:统一的OS X 内 ...

  2. 一个iOS 框架介绍:MKNetworkKit

    2019独角兽企业重金招聘Python工程师标准>>> ASIHTTPRequest (作者:BenCopsey) 是一个使用简单,可用于各种从简单到复杂的 HTTP 请求,或者可用 ...

  3. iOS框架介绍--EF字头

    1.EventKit 2.EventKitUI 3.ExternalAccessory 4.Foundation

  4. iOS框架介绍——M字头

    1.MapKit 2.MediaAccessibility 3.MediaPlayer 4.MediaToolbox 5.MessageUI 6.Metal 7.MobileCoreServices ...

  5. iOS 常用框架介绍

    iOS框架介绍      Cocoa Touch GameKit  实现对游戏中心的支持,让用户能够在线共享他们的游戏相关的信息  iOS设备之间蓝牙数据传输   从iOS7开始过期   局域网游戏 ...

  6. mPaaS iOS框架笔记0-mPaaS iOS 框架初探(以MPH5Demo_plugin为例)

    1. mPaaS iOS 框架介绍 mPaaS iOS 框架源自支付宝客户端的开发框架,基于 Framework 的设计思想: 1.将业务隔离成相对独立的模块 2.着力追求模块与模块之间高內聚.低耦合 ...

  7. iOS流媒体直播整个框架介绍(HLS、RTSP)

    iOS流媒体直播整个框架介绍(HLS.RTSP) 目录技术文章2016年7月17日 一.HTTP(WebService) 基于HTTP的渐进下载Progressive Download流媒体播放仅是在 ...

  8. iOS 内购StoreKit 框架介绍

    StoreKit 框架介绍 一.StoreKit 能做什么? In-App Purchase 提供和促进内容和服务的应用内购买. Apple Music 检查用户的Apple Music功能并提供订阅 ...

  9. iOS黑科技之(CoreImage)静态人脸识别(一)

    iOS黑科技之(CoreImage)静态人脸识别(一) 人脸识别原理简介:每一张图片都是由每一个像素点组成,而每一个像素点中又有对应的颜色值(如RGB),人的面部特征中,不同的五官,颜色值肯定存在差异 ...

最新文章

  1. Pandownload惊喜复活!下载速度惊人!
  2. 第5章 用户身份与文件权限
  3. oracle误删表空间 无法关闭,oracle 误删表空间文件启动不了数据库的解决办法
  4. 开发加速使用maven国内源,感谢阿里技术团队,良心团队!
  5. 洛谷 1351 联合权值——树形dp
  6. Java SE 11(18.9)中的API更新
  7. 在 Linux 中使用动态磁盘
  8. C语言 | 内存对齐03 - 内存对齐的公式
  9. 你已经是一个成熟的码农了,这些思维习惯你要有!
  10. 查找下载外文文献,这个网站比知网好用多了,经过对比后,五星推荐给大家!
  11. 系统分析员要了解什么知识?
  12. 2021 HW —— 简单过程-致远OA
  13. 视觉3d中五折幕的震撼这就是沉浸式屏幕
  14. 银心科技与黑萤科技达成战略合作,联合构建区块链数据库存储生态至高点
  15. java RSA生成公钥对象和私钥对象
  16. (2021 ICCV)Specificity-preserving RGB-D Saliency Detection(A类)
  17. 巧用win7搜索功能
  18. 本周最新文献速递20220515
  19. Elastic Search一些用法
  20. 计算机网络——01网络模型

热门文章

  1. linux远程升级运行程序,运用RedHat的Kickstart升级Linux系统方法
  2. mysql innodb启动失败_mysql启动失败
  3. python怎么赋值int_int对象不支持项赋值
  4. javascript---001-运行原理01_前端三大技术_JS重要性_Atwood定律_JS应用_JS让人迷惑_TypeScript会取代JS吗_JS是一门编程语言_浏览器工作原理_浏览器内核
  5. 用c语言实现蚂蚁算法,rsa算法的c语言实现
  6. kettle java 变量传递_kettle的jdk1.7环境变量配置
  7. python的类作用_python——类中的self到底的作用及三个应用场景
  8. pmp知识点详解-项目大牛整理_PMP第七章:项目成本管理(1)项目管理核心知识点...
  9. integer是值传递还是引用传递_值传递与引用传递
  10. P4016 负载平衡问题(最小费用最大流)