Swift3.1动画之Core Image

图片来源于网络

前言:Core Image是一个强大的框架,可让您轻松地将过滤器应用于图像。您可以获得各种各样的效果,如修改活力,色调或曝光。它可以使用CPU或GPU来处理图像数据,并且速度非常快 - 足以实现视频帧的实时处理!
核心图像滤镜也可以链接在一起,以一次将多个效果应用于图像或视频帧。多个滤波器被组合成应用于图像的单个滤波器。与通过每个过滤器一次处理图像相比,这样做非常有效。

入门

在开始之前,让我们来讨论Core Image框架中的一些最重要的类:
CIContext。核心图像的所有处理都以CIContext完成。这与Core Graphics或OpenGL上下文有些相似。
CIImage。该类保存图像数据。它可以从UIImage,从图像文件或从像素数据创建。
CIFilter。CIFilter类有一个字典,用于定义它所代表的特定过滤器的属性。过滤器的例子是振动,颜色反转,裁剪等等。

基本图像过滤

通过简单地运行您的图像CIFilter并在屏幕上显示图像来开始。每次想要将CIFilter应用于图像时,有4个步骤:

1、创建一个CIImage对象。CIImage有几种初始化方法,包括:CIImage(CIImage(contentsOf: ),CIImage(data :),CIImage(CGImage :),CIImage(bitmapData:bytesPerRow:size:format:colorSpace :)等几个。最常用的是用CIImage(contentsOf: )
2、创建CIContext。CIContext可以是基于CPU或GPU的。CIContext初始化相对耗费资源,因此您可以重用它,而不是一遍又一遍地创建它。输出CIImage对象时,您将始终需要一个。
3、创建一个CIFilter。创建过滤器时,您可以配置依赖于您使用的过滤器的许多属性。
4、获取过滤器输出。过滤器为您提供输出图像作为CIImage - 您可以使用CIContext将其转换为UIImage,如下所示

  // 1
  let fileURL = Bundle.main.url(forResource: "beauty", withExtension: "jpg")
  // 2
  let beginImage = CIImage(contentsOf: fileURL!)
  // 3
  let filter = CIFilter (name: "CISepiaTone")
  filter?.setValue(beginImage, forKey: kCIInputImageKey)
  filter?.setValue(0.5, forKey: kCIInputIntensityKey)
  // 4
  let newImage = UIImage(ciImage: (filter?.outputImage)!)
  self.imageView.image = newImage;

我们先来看看这一节:

1、此行创建一个<code>NSURL</code>对象,该对象保存图像文件的路径。
2、接下来,使用<code>CIImage(contentsOf: )</code>构造函数创建您的CIImage。
3、接下来,您将创建您的<code>CIFilter</code>对象。<code>CIFilter</code>构造函数使用过滤器的名称,并指定该过滤器的键和值的字典。每个过滤器将有自己唯一的密钥和一组有效的值。所述<code>CISepiaTone</code>过滤器只需两个值:<code>KCIInputImageKey</code>(一个CIImage)和在0和1之间的<code>kCIInputIntensityKey</code> ,你给该值0.5。大多数过滤器具有默认值,如果没有提供值,将使用该值。一个例外是<code>CIImage</code>,这是必须提供的,因为没有默认。
4、将<code>CIImage</code>从过滤器中恢复与使用该<code>outputImage</code>属性一样简单。一旦输出<code>CIImage</code>,您将需要将其转换为<code>UIImage</code>。该<code>UIImage(ciImage:)</code>构造函数转换了<code>CIImage</code>到<code>UIImage</code>。一旦将其转换为<code>UIImage</code>,您只需将其显示在您之前添加的<code>imageView</code>中。

运行该项目,您将看到由深褐色滤镜过滤的图像。

置于上下文

在您继续了解之前,您应该了解一个优化。
我之前提到你需要一个CIContext应用CIFilter,但在上面的例子中没有提到这个对象。事实证明,<code>UIImage(ciImage:)code</code>构造函数为您做所有的工作。它创建CIContext并使用它来执行过滤图像的工作。这使得使用Core Image API非常简单。
有一个主要的缺点 - CIContext每次使用时都会创建一个新的。CIContext实例旨在可重用以提高性能。如果要使用滑块来更新过滤器值,就像在本教程中所做的那样,每次更改过滤器时都会创建一个新的CIContext将太慢了。
我们这样做是正确的。从viewDidLoad()添加的代码中删除步骤4 ,并将其替换为以下内容:

// 1
let context = CIContext(options:nil)

// 2
let cgimg = context.createCGImage(filter!.outputImage!, from: filter!.outputImage!.extent)

// 3
let newImage = UIImage(cgImage: cgimg!)
self.imageView.image = newImage;

再次,我们一起来看看这一节。
在这里,您设置CIContext对象并使用它来绘制CGImage。该CIContext(options:)构造采用指定的选项一个NSDictionary如色彩格式,或上下文是否应在CPU或GPU上运行。对于这个应用程序,默认值是好的,所以你传递为nil为该参数。
<code>createCGImage(outputImage:from:)</code>使用提供的CIImage在上下文中调用将返回一个新的CGImage实例。
接下来,您使用<code>UIImage(cgImage:)</code>构造函数从新创建的CGImage创建UIImage,而不是像以前一样直接从CIImage创建。注意,在完成它之后,不需要明确地释放CGImage,就像在Objective-C中一样。在Swift中,ARC可以自动释放Core Foundation对象。
构建和运行,并确保它像以前一样工作。
在这个例子中,自己处理CIContext的创建并没有太多的区别。但在下一节中,您将看到为什么这对于性能很重要,因为您实现了动态修改过滤器的功能!
更改过滤器值

下面增加滑块,每次滑块更改时,都需要使用不同的值重做图像过滤器。但是,您不想重做整个过程,这将是非常低效的,并且需要太长时间。您将需要更改类中的一些内容,以便您可以保留在viewDidLoad方法中创建的一些对象。
如果为了重新使用CIContext,而每次重新创建它程序将运行非常缓慢。
添加一些实例变量才能完成此任务。将以下三个属性添加到ViewController类中:

var context: CIContext!
var filter: CIFilter!
var beginImage: CIImage!

更改代码,因此<code>viewDidLoad()</code>使用这些属性,而不是声明新的局部变量,如下所示:

beginImage = CIImage(contentsOf: fileURL!)

filter = CIFilter (name: "CISepiaTone")
filter?.setValue(beginImage, forKey: kCIInputImageKey)
filter?.setValue(0.5, forKey: kCIInputIntensityKey)

let outputImage = filter.outputImage
context = CIContext(options:nil)

let cgimg = context.createCGImage(filter!.outputImage!, from: filter!.outputImage!.extent)

实现changeValue方法。在CIFilter字典中改变<code>inputIntensity</code>值。
一旦你改变了这个值,你需要重复几个步骤:

1、从CIFilter获取输出CIImage。
2、将CIImage转换为CGImage。
3、将CGImage转换为UIImage,并将其显示在图像视图中。

将创建一个方法<code>amountSliderValueChanged(sender :)</code>:

@IBAction func amountSliderValueChange(_ sender: UISlider) {
    let sliderValue = sender.value
    
    filter.setValue(sliderValue, forKey: kCIInputIntensityKey)
    let outputImage = filter.outputImage
    
    let cgimg = context.createCGImage(outputImage!, from: outputImage!.extent)
    
    let newImage = UIImage(cgImage: cgimg!)
    self.imageView.image = newImage
}
Core Image变化

老相片效果

在这个Demo中,会得到一个更精致的老照片效果,完成与棕褐色,一点噪音和一些晕影

func oldPhoto (img: CIImage, withAmount intensity: Float) -> CIImage {
    //1 CISepiaTone 棕褐色调
    let sepia = CIFilter(name: "CISepiaTone")
    sepia?.setValue(img, forKey: kCIInputImageKey)
    sepia?.setValue(intensity, forKey: "inputIntensity")
    
    //2 设置一个过滤器,创建一个随机噪声模式
    let random = CIFilter(name: "CIRandomGenerator")
    
    //3 改变随机噪声发生器的输出
    let lighten = CIFilter(name:"CIColorControls")
    lighten?.setValue(random?.outputImage, forKey:kCIInputImageKey)
    lighten?.setValue(1 - intensity, forKey:"inputBrightness")
    lighten?.setValue(0, forKey:"inputSaturation")
    
    //4 cropping(to rect: CGRect)输出CIImage并将其作用到所提供的rect
    let croppedImage = lighten?.outputImage?.cropping(to: beginImage.extent)
    
    //5 将棕褐色滤镜的输出与CIRandomGenerator滤镜的输出相结合。
    let composite = CIFilter(name:"CIHardLightBlendMode")
    composite?.setValue(sepia?.outputImage, forKey:kCIInputImageKey)
    composite?.setValue(croppedImage, forKey:kCIInputBackgroundImageKey)
    
    //6 合成输出上运行晕影滤镜(vignette filter),使照片的边缘变暗
    let vignette = CIFilter(name:"CIVignette")
    vignette?.setValue(composite?.outputImage, forKey:kCIInputImageKey)
    vignette?.setValue(intensity * 2, forKey:"inputIntensity")
    vignette?.setValue(intensity * 30, forKey:"inputRadius")
    
    //7 返回滤镜的输出
    return vignette!.outputImage!
}

效果图:

老照片.png

解析以上代码:
1、像在简单的场景中所做的一样,设置棕褐色滤镜。您在方法中传入浮点值以设置深色效果的强度。该值将由滑块提供。
2、设置一个过滤器,创建一个如下所示的随机噪声模式:


CIRandomGenerator

它不需要任何参数。您将使用这种噪音模式将纹理添加到最终的“旧照片”外观。
3、改变随机噪声发生器的输出。你想把它改成灰度,并减轻一点点,所以效果不那么戏剧化。您会注意到,输入图像键被设置为随机过滤器的outputImage属性。这是一个方便的方式来传递一个过滤器的输出作为下一个的输入。
4、 cropping(to rect: CGRect)输出CIImage并将其作用到所提供的rect。在这种情况下,您需要裁剪CIRandomGenerator过滤器的输出,因为它无限制地打砖块。如果您在某些时候没有裁剪,就会出现一个错误,表示过滤器具有“无限长度”。CIImages实际上并不包含图像数据,它们描述了创建它的“配方”。直到你在CIContext上调用一个方法来实际处理数据。
5、将棕褐色滤镜的输出与CIRandomGenerator滤镜的输出相结合。该过滤器执行与Photoshop图层中的“硬光”设置完全相同的操作。使用Core Image可以实现Photoshop中的大多数滤镜选项。
6、在此合成输出上运行晕影滤镜,使照片的边缘变暗。您正在使用滑块的值来设置此效果的半径和强度。
7、返回最后一个过滤器的输出。

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

推荐阅读更多精彩内容

  • Core Image是一个强大的框架,它能够让你轻松地对图像进行过滤。你能够通过修改图像的饱和度、色调或曝光率来获...
    木易林1阅读 1,121评论 0 1
  • 许多UIView的子类,如一个UIButton或一个UILabel,它们知道怎么绘制自己。迟早,你也将想要做一些自...
    shenzhenboy阅读 1,621评论 2 8
  • 前言 最近在研究 Core Image 自定义 Filter 相关内容,重新学习了 Core Image,对 Co...
    泥孩儿0107阅读 751评论 0 4
  • 原链接:http://www.csdn.net/article/2015-02-13/2823961-core-i...
    hament阅读 988评论 0 1
  • 望空楼而思忆,时三更而踌躇。笑笨鸟迟飞,本钝剑难鸣。心有沟壑万丈,胸无一点墨痕。哀矣! 日见雏鹰欲登千丈而飞,不集...
    小小小欧巴阅读 346评论 0 3