Core Image框架详细解析(四) —— Processing Images处理图像(一)

版本记录

版本号 时间
V1.0 2018.01.27

前言

Core Image是IOS5中新加入的一个框架,里面提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析。还提供了很多强大的滤镜,可以实现你想要的效果,下面我们就一起解析一下这个框架。感兴趣的可以参考上面几篇。
1. Core Image框架详细解析(一) —— 基本概览
2. Core Image框架详细解析(二) —— Core Image滤波器参考
3. Core Image框架详细解析(三) —— 关于Core Image

Overview

处理图像意味着应用滤波器 - 图像滤波器是一个逐像素检查输入图像的软件,在算法上应用一些效果来创建输出图像。 在Core Image中,图像处理依赖于CIFilterCIImage类,它们描述了过滤器及其输入和输出。 要应用过滤器并显示或导出结果,可以使用Core Image和其他系统框架之间的集成,或者使用CIContext类创建您自己的渲染工作流程。 本章介绍了使用这些类来应用过滤器和渲染结果的关键概念。

在应用程序中使用Core Image进行图像处理有很多方法。在本章中,Listing 1-1显示了一个基本的例子,并提供了进一步解释的指导。

// Listing 1-1  The basics of applying a filter to an image

import CoreImage
 
let context = CIContext()                                           // 1
 
let filter = CIFilter(name: "CISepiaTone")!                         // 2
filter.setValue(0.8, forKey: kCIInputIntensityKey)
let image = CIImage(contentsOfURL: myURL)                           // 3
filter.setValue(image, forKey: kCIInputImageKey)
let result = filter.outputImage!                                    // 4
let cgImage = context.createCGImage(result, from: result.extent)    // 5

这里就是代码做的事情:

    1. 创建一个CIContext对象(使用默认选项)。你并不总是需要你自己的Core Image context - 通常你可以与其他管理渲染的系统框架集成。创建自己的上下文可以更精确地控制渲染过程和渲染过程中涉及的资源。上下文是重量级的对象,所以如果你真的创建了一个,那么尽可能早地做,并且每次需要处理图片时都要重新使用它。 (请参阅Building Your Own Workflow with a Core Image Context。)
    1. 实例化表示要应用的过滤器的CIFilter对象,并为其参数提供值。 (请参阅Filters Describe Image Processing Effects。)
    1. 创建一个表示要处理的图像的CIImage对象,并将其作为输入图像参数提供给过滤器。从URL中读取图像数据只是创建图像对象的许多方法之一。 (请参阅Images are the Input and Output of Filters。)
    1. 获取表示过滤器输出的CIImage对象。此时过滤器尚未执行 - 图像对象是一个“recipe”,指定如何使用指定的滤镜,参数和输入创建图像。Core Image仅在请求渲染时才执行此recipe。 (请参阅Images are the Input and Output of Filters。)
    1. 将输出图像渲染为可以显示或保存到文件的Core Graphics图像。 (请参阅Building Your Own Workflow with a Core Image Context。)

Images are the Input and Output of Filters - 图像是过滤器的输入和输出

Core Image过滤器处理和生成Core Image图像。 CIImage实例是表示图像的不可变对象。 这些对象不直接表示图像位图数据 - 而是一个CIImage对象是用于生成图像的“recipe”。 一个“recipe”可能会要求从文件加载图像; 另一个可能表示来自过滤器的输出,或来自过滤器链的输出。 Core Image只有在您要求显示或输出图像时才执行这些“recipe”

要应用滤镜,请创建一个或多个代表要由滤镜处理的图像的CIImage对象,并将其分配给滤镜的输入参数(如kCIInputImageKey)。 您几乎可以从任何图像数据源创建一个Core Image图像对象,其中包括:

  • 引用要加载的图像文件的URL或包含图像文件数据的NSData对象
  • Quartz2D,UIKit或AppKit图像表示(CGImageRefUIImageNSBitmapImageRep对象)
  • Metal,OpenGL或OpenGL ES纹理
  • CoreVideo图像或像素缓冲区(CVImageBufferRefCVPixelBufferRef
  • 在进程之间共享图像数据的IOSurfaceRef对象
  • 内存中的图像位图数据(指向此类数据的指针或按需提供数据的CIImageProvider对象)

有关创建CIImage对象的完整列表,请参阅CIImage Class Reference

由于CIImage对象描述如何生成图像(而不是包含图像数据),因此它也可以表示过滤器输出。在访问CIFilter对象的outputImage属性时,Core Image仅会标识并存储执行过滤器所需的步骤。这些步骤只有在您要求显示或输出图像时才会执行。您可以使用CIContextrenderdraw方法之一(请参阅Building Your Own Workflow with a Core Image Context)显式地请求渲染,也可以使用与Core Image一起工作的许多系统框架之一显示图像来隐式的请求渲染(请参阅Integrating with Other Frameworks)。

推迟处理,直到渲染时间使Core Image快速高效。在渲染时,Core Image可以查看是否需要将多个过滤器应用于图像。如果是这样,它自动连接多个“recipes”,并组织它们以消除冗余操作,使每个像素只处理一次,而不是多次。


Filters Describe Image Processing Effects - 过滤器描述图像处理效果

CIFilter类的一个实例是一个表示图像处理效果的可变对象以及控制该效果行为的任何参数。要使用过滤器,您可以创建CIFilter对象,设置其输入参数,然后访问其输出图像(请参阅 Images are the Input and Output of Filters)。调用filterWithName:初始化器来使用系统已知的过滤器的名称实例化一个过滤器对象(请参阅Querying the System for FiltersCore Image Filter Reference)。

大多数过滤器都有一个或多个输入参数,可以控制处理过程的方式。每个输入参数都有一个属性类,用于指定其数据类型,如NSNumber。输入参数可以选择性地包含其他属性,例如默认值,允许的最小值和最大值,参数的显示名称以及CIFilter Class Reference中描述的其他属性。例如,CIColorMonochrome滤镜具有三个输入参数 - 要处理的图像,单色和颜色强度。

过滤器参数被定义为键值对,要使用参数,通常使用valueForKey:setValue:forKey:方法或基于键值编码(如Core Animation)的其他功能。key是标识属性的常数,值是与key相关的设置。Core Image属性值通常使用下面Attribute value data types表中列出的数据类型之一

重要:CIFilter objects are mutable, so you cannot safely share them between different threads. Each thread must create its own CIFilter objects. However, a filter’s input and output CIImage objects are immutable, and thus safe to pass between threads. CIFilter对象是可变的,所以你不能在不同的线程之间安全地共享它们。 每个线程都必须创建自己的CIFilter对象。 但是,过滤器的输入和输出CIImage对象是不可变的,因此在线程之间传递是安全的。

1. Chaining Filters for Complex Effects - 复杂效果的链式滤波器

每个Core Image过滤器都会生成一个输出CIImage对象,因此您可以将此对象用作另一个过滤器的输入。 例如,图1-1中所示的过滤器序列将颜色效果应用于图像,然后添加发光效果,最后从结果中裁剪出一部分。

Figure 1-1 Construct a filter chain by connecting filter inputs and outputs

Core Image优化过滤器链的应用,如这一个,以快速和高效地呈现结果。 链中的每个CIImage对象都不是完全渲染的图像,而仅仅是渲染的“recipe”。 Core Image不需要单独执行每个滤镜,浪费时间和内存渲染永远不会看到的中间像素缓冲区。 相反,Core Image将过滤器组合成一个单一的操作,甚至可以重新组织过滤器,当以不同的顺序应用它们时会更有效地产生相同的结果。 图1-2显示了从图1-1中示例过滤器链的更准确的解释。

Figure 1-2 Core Image optimizes a filter chain to a single operation

请注意,在图1-2中,裁剪操作已从最后一个移到第一个。 该过滤器会导致原始图像的大部分区域被从最终输出中剪切掉。 因此,不需要应用颜色并将锐化滤镜添加到这些像素。 通过首先执行裁剪,Core Image可以确保昂贵的图像处理操作仅适用于在最终输出中可见的像素。

Listing 1-2显示了如何设置如上所示的过滤器链

// Listing 1-2  Creating a filter chain

func applyFilterChain(to image: CIImage) -> CIImage {
    // The CIPhotoEffectInstant filter takes only an input image
    let colorFilter = CIFilter(name: "CIPhotoEffectProcess", withInputParameters:
        [kCIInputImageKey: image])!
    
    // Pass the result of the color filter into the Bloom filter
    // and set its parameters for a glowy effect.
    let bloomImage = colorFilter.outputImage!.applyingFilter("CIBloom",
                                                             withInputParameters: [
                                                                kCIInputRadiusKey: 10.0,
                                                                kCIInputIntensityKey: 1.0
        ])
    
    // imageByCroppingToRect is a convenience method for
    // creating the CICrop filter and accessing its outputImage.
    let cropRect = CGRect(x: 350, y: 350, width: 150, height: 150)
    let croppedImage = bloomImage.cropping(to: cropRect)
    
    return croppedImage
}

Listing 1-2还显示了一些用于配置过滤器和访问结果的便利方法。总之,您可以使用这些方法中的任何一种来单独或作为过滤器链的一部分应用过滤器:

  • 使用filterWithName:初始化器创建CIFilter实例,使用·setValue:forKey:·方法(包括要处理图像的·kCIInputImageKey·)设置参数,并使用·outputImage·属性访问输出图像。 (请参阅Listing 1-1。)

  • 一次调用filterWithName:withInputParameters: 初始化器创建一个CIFilter实例并设置其参数(包括输入图像),然后使用outputImage属性访问输出。 (请参阅Listing 1-2中的colorFilter示例。)

  • 通过使用imageByApplyingFilter:withInputParameters:方法应用于CIImage对象,而不创建CIFilter实例来应用过滤器。 (请参阅Listing 1-2中的bloomImage示例。)

  • 对于某些常用的滤镜操作(例如cropping, clamping, 和 applying coordinate transforms),请使用Creating an Image by Modifying an Existing Image中列出的其他CIImage实例方法。 (请参阅Listing 1-2中的croppedImage示例。)

2. Using Special Filter Types for More Options - 使用特殊的过滤器类型获得更多的选择

大多数内置的Core Image过滤器在主要输入图像上运行(也可能有会影响处理的附加输入图像)并创建单个输出图像。 但还有其他几种可用于创建有趣效果的类型,或者与其他过滤器结合使用以生成更复杂的工作流程。

  • 合成(或混合)滤镜根据预设的公式组合两个图像。 例如:
    • CISourceInCompositing过滤器组合图像,使得只有输入图像中不透明的区域在输出图像中才可见。
    • CIMultiplyBlendMode滤镜将两个图像的像素颜色相乘,产生一个黑暗的输出图像。

有关合成过滤器的完整列表,请查询CICategoryCompositeOperation类别。

Note: You can arrange input images before compositing them by applying geometry adjustments to each. See the CICategoryGeometryAdjustment filter category or the imageByApplyingTransform: method. 注意:您可以在合成之前安排输入图像,方法是对每个图像应用几何调整。 请参阅CICategoryGeometryAdjustment筛选器类别或imageByApplyingTransform:方法。

  • generator滤波器不输入任何输入图像。相反,这些过滤器使用其他输入参数从头创建一个新的图像。一些generator产生的输出可以独立使用,另一些发生器可以组合在滤波器链中产生更有趣的图像。内置Core Image过滤器中的一些示例包括:

要查找生成器过滤器,请查询CICategoryGeneratorCICategoryGradient类别。

  • reduction过滤器对输入图像进行操作,但是不是以传统意义来创建输出图像,而是其输出描述关于输入图像的信息。 例如:
    • CIAreaMaximum滤镜输出表示图像指定区域中所有像素颜色中最亮的单个颜色值。
    • CIAreaHistogram过滤器输出关于图像的指定区域中的每个强度值的像素数目的信息。

所有Core Image过滤器都必须生成一个CIImage对象作为输出,所以由reduction生成的信息仍然是一个图像。 但是,通常不显示这些图像,而是从单像素或单行图像中读取颜色值,或将其用作其他滤镜的输入。

有关reduction过滤器的完整列表,请查询CICategoryReduction类别。

  • 一个transition过滤器需要两个输入图像,并根据一个独立的变量来改变它们之间的输出 - 通常这个变量是时间,所以你可以使用transition过滤器来创建一个动画,从一个图像开始,在另一个图像上结束, 从一个到另一个使用有趣的视觉效果。 Core Image提供了几个内置的transition过滤器,包括:
    • CIDissolveTransition过滤器产生一个简单的交叉消解,从一个图像渐变到另一个。
    • CICopyMachineTransition过滤器模拟复印机,在一幅图像上划过一道明亮的光线,以显示另一幅图像。

有关transition过滤器的完整列表,请查询CICategoryTransition类别。

后记

本篇已结束,后面更精彩~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容