版本记录
版本号 | 时间 |
---|---|
V1.0 | 2018.01.27 |
前言
Core Image是IOS5中新加入的一个框架,里面提供了强大高效的图像处理功能,用来对基于像素的图像进行操作与分析。还提供了很多强大的滤镜,可以实现你想要的效果,下面我们就一起解析一下这个框架。感兴趣的可以参考上面几篇。
1. Core Image框架详细解析(一) —— 基本概览
2. Core Image框架详细解析(二) —— Core Image滤波器参考
3. Core Image框架详细解析(三) —— 关于Core Image
Overview
处理图像意味着应用滤波器 - 图像滤波器是一个逐像素检查输入图像的软件,在算法上应用一些效果来创建输出图像。 在Core Image中,图像处理依赖于CIFilter和CIImage类,它们描述了过滤器及其输入和输出。 要应用过滤器并显示或导出结果,可以使用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
这里就是代码做的事情:
-
- 创建一个CIContext对象(使用默认选项)。你并不总是需要你自己的
Core Image context
- 通常你可以与其他管理渲染的系统框架集成。创建自己的上下文可以更精确地控制渲染过程和渲染过程中涉及的资源。上下文是重量级的对象,所以如果你真的创建了一个,那么尽可能早地做,并且每次需要处理图片时都要重新使用它。 (请参阅Building Your Own Workflow with a Core Image Context。)
- 创建一个CIContext对象(使用默认选项)。你并不总是需要你自己的
-
- 实例化表示要应用的过滤器的CIFilter对象,并为其参数提供值。 (请参阅Filters Describe Image Processing Effects。)
-
- 创建一个表示要处理的图像的CIImage对象,并将其作为输入图像参数提供给过滤器。从URL中读取图像数据只是创建图像对象的许多方法之一。 (请参阅Images are the Input and Output of Filters。)
-
- 获取表示过滤器输出的CIImage对象。此时过滤器尚未执行 - 图像对象是一个
“recipe”
,指定如何使用指定的滤镜,参数和输入创建图像。Core Image仅在请求渲染时才执行此recipe。 (请参阅Images are the Input and Output of Filters。)
- 获取表示过滤器输出的CIImage对象。此时过滤器尚未执行 - 图像对象是一个
-
- 将输出图像渲染为可以显示或保存到文件的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图像表示(CGImageRef,UIImage或NSBitmapImageRep对象)
- Metal,OpenGL或OpenGL ES纹理
- CoreVideo图像或像素缓冲区(CVImageBufferRef或 CVPixelBufferRef)
- 在进程之间共享图像数据的IOSurfaceRef对象
- 内存中的图像位图数据(指向此类数据的指针或按需提供数据的
CIImageProvider
对象)
有关创建CIImage对象的完整列表,请参阅CIImage Class Reference。
由于CIImage对象描述如何生成图像(而不是包含图像数据),因此它也可以表示过滤器输出。在访问CIFilter对象的outputImage属性时,Core Image仅会标识并存储执行过滤器所需的步骤。这些步骤只有在您要求显示或输出图像时才会执行。您可以使用CIContextrender
或draw
方法之一(请参阅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 Filters或Core 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中所示的过滤器序列将颜色效果应用于图像,然后添加发光效果,最后从结果中裁剪出一部分。
Core Image优化过滤器链的应用,如这一个,以快速和高效地呈现结果。 链中的每个CIImage对象都不是完全渲染的图像,而仅仅是渲染的“recipe”。 Core Image不需要单独执行每个滤镜,浪费时间和内存渲染永远不会看到的中间像素缓冲区。 相反,Core Image将过滤器组合成一个单一的操作,甚至可以重新组织过滤器,当以不同的顺序应用它们时会更有效地产生相同的结果。 图1-2显示了从图1-1中示例过滤器链的更准确的解释。
请注意,在图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
过滤器中的一些示例包括:- 像CIQRCodeGenerator和CICode128BarcodeGenerator这样的过滤器会生成对指定的输入数据进行编码的条形码图像。
- 像CIConstantColorGenerator,CICheckerboardGenerator和CILinearGradient这样的过滤器可以从指定的颜色生成简单的过程图像。您可以将这些滤镜与其他滤镜结合使用以获得有趣的效果,例如,CIRadialGradient滤镜可以创建用于CIMaskedVariableBlur滤镜的遮罩。
- 像CILenticularHaloGenerator和CISunbeamsGenerator这样的过滤器可以创建独立的视觉效果 - 将这些与合成过滤器结合使用,为图像添加特殊效果。
要查找生成器过滤器,请查询CICategoryGenerator和CICategoryGradient类别。
-
reduction
过滤器对输入图像进行操作,但是不是以传统意义来创建输出图像,而是其输出描述关于输入图像的信息。 例如:- CIAreaMaximum滤镜输出表示图像指定区域中所有像素颜色中最亮的单个颜色值。
- CIAreaHistogram过滤器输出关于图像的指定区域中的每个强度值的像素数目的信息。
所有Core Image过滤器都必须生成一个CIImage对象作为输出,所以由reduction
生成的信息仍然是一个图像。 但是,通常不显示这些图像,而是从单像素或单行图像中读取颜色值,或将其用作其他滤镜的输入。
有关reduction
过滤器的完整列表,请查询CICategoryReduction类别。
- 一个
transition
过滤器需要两个输入图像,并根据一个独立的变量来改变它们之间的输出 - 通常这个变量是时间,所以你可以使用transition
过滤器来创建一个动画,从一个图像开始,在另一个图像上结束, 从一个到另一个使用有趣的视觉效果。 Core Image提供了几个内置的transition
过滤器,包括:- CIDissolveTransition过滤器产生一个简单的交叉消解,从一个图像渐变到另一个。
- CICopyMachineTransition过滤器模拟复印机,在一幅图像上划过一道明亮的光线,以显示另一幅图像。
有关transition
过滤器的完整列表,请查询CICategoryTransition类别。
后记
本篇已结束,后面更精彩~~~