前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Swift3.1动画之Core Image

Swift3.1动画之Core Image

作者头像
Dwyane
发布2018-05-22 17:43:53
1.5K0
发布2018-05-22 17:43:53
举报
文章被收录于专栏:技术总结

前言: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,如下所示

代码语言:javascript
复制
  // 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 ,并将其替换为以下内容:

代码语言:javascript
复制
// 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类中:

代码语言:javascript
复制
var context: CIContext!
var filter: CIFilter!
var beginImage: CIImage!

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

代码语言:javascript
复制
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>:

代码语言:javascript
复制
@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中,会得到一个更精致的老照片效果,完成与棕褐色,一点噪音和一些晕影

代码语言:javascript
复制
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、返回最后一个过滤器的输出。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.04.13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 入门
  • 基本图像过滤
  • 置于上下文
  • 老相片效果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档