
核心映像框架的力量
Core Image是一种图像处理和分析技术,旨在为iOS和OS X中的静止图像和视频图像提供近乎实时的处理。Apple制作了一些出色的预制照片效果,您可以轻松地将它们用于摄影应用程序。名称,例如“即时”,“过程”,“棕褐色”,“色调”等。
核心图片参考
iOS开发人员库在Core Image Reference Collection中很好地解释了Core Image图像处理。
我建议您也查看“ 核心图像过滤器参考”页面,以获取可用CIFilter
的完整列表。 请注意,并非所有这些都与iOS兼容; 其中一些仅适用于OSX。
我们将使用以下核心图像过滤器:
-
CIPhotoEffectChrome
-
CISepiaTone
-
CIPhotoEffectTransfer
-
CIPhotoEffectTonal
-
CIPhotoEffectProcess
-
CIPhotoEffectNoir
-
CIPhotoEffectInstant
-
CIPhotoEffectFade
注意: 本教程是使用Xcode 7.3和Swift 2.2编写的,并且将Deployment Target设置为8.0,因此您的应用程序也可以在较旧的设备上运行。
让我们开始吧!
创建一个项目并添加视图
打开Xcode并创建一个新项目iOS Single View Application 。 选择“ Swift”作为语言,选择“ 通用”作为设备。 在Storyboard中,您将获得一个空白的UIViewController
以及两个.swift文件: ViewController.swift和AppDelegate.swift 。
在情节提要中选择控制器,然后在右侧面板的“ 模拟度量”下将其大小设置为iPhone 3.5英寸 。 这将帮助您调整屏幕尺寸最小的Apple设备iPhone 4S的视图。

在本教程中,我们将不使用“自动布局”,因为它会弄乱iPad和iPad Pro等大型设备上的布局。 通过选择File Inspector禁用它,然后取消选中Use Auto Layout 。 然后从弹出窗口中单击“ 禁用尺寸类别”按钮。

现在,从Web或Mac中找到JPEG图像,并将其拖到“项目”导航器面板中的Assets.xcassets文件夹下。 我们将其用作示例图像,可以将其应用到过滤器中。 将此文件命名为picture.jpg ; 我们稍后将在代码中将其命名。
您将不得不将一些其他视图拖到控制器中。 选择Xcode右下角的对象库,然后将UIView
拖动到屏幕中央。 将视图尺寸调整为320 x 320 px,并将其水平居中。
现在,通过在对象库中找到两个UIImageView
并将其拖到主UIView
,将它们添加到Storyboard中。 调整这些图像视图的大小以填充该主视图(稍后我们将介绍如何设置其自动调整大小属性)。 使用“属性”检查器面板将picture.jpg分配给第一个图像视图。

接下来,将UIScrollView
拖到屏幕底部,并设置其宽度以适合控制器的宽度。 您还可以将UILabel
添加到控制器的顶部,并将其文本设置为Filters 。 这将是您的应用程序的标题。
最后,将UIButton
添加到屏幕的左上角,并使其标题为Save 。
设置自动调整大小和布局视图
尺寸检查器 通过单击屏幕右上角的小尺子图标可以显示面板。 现在执行此操作,然后通过选择UIButton开始编辑视图大小。 大小检查器将在屏幕上显示其x和y坐标(请记住,x在屏幕左侧为0,y在顶部为0)。 将宽度和高度设置为44像素。
设置按钮的自动调整大小蒙版以附加到屏幕的顶部和左侧。
现在,一个一个地选择所有其他视图,并如下调整其大小和位置:

该应用程序标题的宽度为320像素,高度为44像素,并附在屏幕顶部。

每个图像视图的宽度和高度均为320像素。

最后,滚动视图(用于过滤器选项)的宽度为320像素,高度为80像素。
在.swift文件中声明视图
Xcode最好的功能之一是可以将工作空间分为两部分,并在一侧提供Storyboard,在另一侧提供Swift文件。 为了做到这一点,您必须单击Xcode窗口右上角的Assistant Editor图标:

如果在Storyboard中选择了ViewController
,则右侧部分将自动显示其相对的.swift文件。 如果没有发生这种情况,您可以尝试单击swift文件顶部的水平菜单,然后将Manual切换为Automatic :

现在,让我们将一些视图附加到ViewController.swift文件。 在“ 文档大纲”面板中,选择包含两个UIImageView
的UIView
,按住Control (或鼠标右键),然后将鼠标指针拖到下面以获取视图控制器的类声明。
释放鼠标按钮,将出现一个弹出窗口。 键入名称UIView
- containerView -and点击连接按钮。
您刚刚向.swift文件中添加了UIView
类型的IBOutlet
声明。 对其他图像视图执行相同的操作:将蓝线拖到您要声明的每个实例下方,并将第一个命名为originalImage
和第二个imageToFilter
。 确保originalImage
是带有picture.jpg作为图像的图像。
然后连接UIScrollView
并将其命名为filtersScrollView
。 这将存储用于将滤镜应用于图片的所有按钮。
稍后我们将UIButton
声明为IBAction
。 此按钮将使我们能够将过滤后的图像保存到设备的照片库中。
让我们编码!
创建一组核心图像滤镜
在Swift中,您可以通过简单地将全局变量放在class
声明之外来声明全局变量,在本例中为:
class ViewController: UIViewController {
我们需要创建一个CIFilter
名称数组:
var CIFilterNames = [
"CIPhotoEffectChrome",
"CIPhotoEffectFade",
"CIPhotoEffectInstant",
"CIPhotoEffectNoir",
"CIPhotoEffectProcess",
"CIPhotoEffectTonal",
"CIPhotoEffectTransfer",
"CISepiaTone"
]
如本教程开头所述,我们必须使用原始的Core Image过滤器名称,以便我们的应用程序能够识别它们。 我们将这些过滤器分配给稍后创建的按钮,这些按钮会将过滤器应用于我们的图像。
隐藏状态栏
在大多数情况下,您可能希望从屏幕上隐藏状态栏。 从Xcode 7.0开始,不再可以在Info.plist中设置状态栏的hidden属性,因此必须在viewDidLoad()
上方添加此方法:
override func prefersStatusBarHidden() -> Bool {
return true
}
创建过滤器按钮
viewDidLoad()
方法是Xcode每次向您的项目添加.swift文件时创建的默认实例; 当屏幕及其所有视图加载时,将调用它。 如果您想在发生之前执行某些操作,则可以使用viewDidAppear()
或viewWillAppear()
方法,但是我们不需要这样做。 因此,让我们在super.viewDidLoad()
下面添加一些CGFloat
类型的变量:
override func viewDidLoad() {
super.viewDidLoad()
var xCoord: CGFloat = 5
let yCoord: CGFloat = 5
let buttonWidth:CGFloat = 70
let buttonHeight: CGFloat = 70
let gapBetweenButtons: CGFloat = 5
需要这些值才能在我们的filtersScrollView
内放置一行按钮。 如您在上面的代码中看到的, xCoord
是将放置按钮的X位置, yCoord
是Y位置, buttonWidth
和buttonHeight
是其大小, gapBetweenButtons
是每个按钮之间的间隔。
现在,我们需要使用for
循环实际创建按钮,该循环将复制自定义UIButton
并将其基于上述值放置到filtersScrollView
。
将此代码放在这些CGFloat
实例的正下方:
var itemCount = 0
for i in 0..<CIFilterNames.count {
itemCount = i
// Button properties
let filterButton = UIButton(type: .Custom)
filterButton.frame = CGRectMake(xCoord, yCoord, buttonWidth, buttonHeight)
filterButton.tag = itemCount
filterButton.addTarget(self, action: #selector(ViewController.filterButtonTapped(_:)), forControlEvents: .TouchUpInside)
filterButton.layer.cornerRadius = 6
filterButton.clipsToBounds = true
// CODE FOR FILTERS WILL BE ADDED HERE...
让我们看看这段代码会发生什么。 itemCount
是一个变量,稍后我们将使用它来将过滤器按钮添加为filtersScrollView
子视图。 您可能会注意到,我们已经使用var
前缀声明了此变量。 那是因为它将被for
循环修改。 如果要在Swift中声明常量,请使用let
前缀,就像我们对filterButton
所做的filterButton
。
使用Swift 2.2的新for
循环语法,我们不再需要编写i++
。 循环将通过从0计数到CIFilterNames
数组的元素数量自动使i
增加。
在该for
循环内,我们创建一个自定义按钮,设置其CGRect
值,为其分配标签,然后向其添加目标操作,该操作将调用稍后将介绍的函数: filterButtonTapped()
。
为了使我们的按钮看起来带有圆角,我们使用layer
属性并将其角半径设置为6。然后我们将图像裁剪为包含在其边界内,否则它将覆盖圆角。
将图像添加到按钮并应用过滤器
必须在上一个注释的下方添加下一个代码段:
// Create filters for each button
let ciContext = CIContext(options: nil)
let coreImage = CIImage(image: originalImage.image!)
let filter = CIFilter(name: "\(CIFilterNames[i])" )
filter!.setDefaults()
filter!.setValue(coreImage, forKey: kCIInputImageKey)
let filteredImageData = filter!.valueForKey(kCIOutputImageKey) as! CIImage
let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent)
let imageForButton = UIImage(CGImage: filteredImageRef);
在这里,我们初始化CIContext
和CIImage
以使Core Image在每个按钮将显示的originalImage
( picture.jpg )上工作。 然后,我们初始化一个CIFilter
类型的过滤器变量,该按钮将由每个按钮通过基于CIFilterNames
数组的for
循环CIFilterNames
。
我们的filter
实例需要设置其默认状态,然后它成为图像的输入键。 然后,我们从该对象及其图像引用创建数据对象,我们将使用它们立即创建一个UIImage
并将其附加到按钮。
由于我们在本教程中选择的滤镜是Apple预先制成的,因此我们不需要应用任何其他值(例如强度,颜色等)。 如果要获取有关其他CIFilters
信息,则可以查看“ 核心图像过滤器参考”页面。
在本节的最后一行,我们最终设置了我们先前创建的按钮的背景图像。
// Assign filtered image to the button
filterButton.setBackgroundImage(imageForButton, forState: .Normal)
将按钮添加到ScrollView
只需几行即可完成我们的viewDidLoad()
方法:
// Add Buttons in the Scroll View
xCoord += buttonWidth + gapBetweenButtons
filtersScrollView.addSubview(filterButton)
} // END FOR LOOP
// Resize Scroll View
filtersScrollView.contentSize = CGSizeMake(buttonWidth * CGFloat(itemCount+2), yCoord)
} // END viewDidload()
我们将基于按钮的位置以及它们之间应保持的宽度和间隔将按钮作为子视图添加到filtersScrollView
。 然后最后我们关闭for
循环。
最后,我们必须设置ScrollView
的contentSize
以适合所有按钮。 在这里,我们最终使用先前声明的itemCount
变量,将其转换为CGFloat
(因为CGSizeMake
它不接受Int
值)。
筛选器按钮动作
仅需几行代码,我们就快完成了!
在ViewController
类的viewDidLoad()
外部,创建filterButtonTapper()
函数。 每次您点击我们之前生成的按钮之一时,就会调用此方法。
func filterButtonTapped(sender: UIButton) {
let button = sender as UIButton
imageToFilter.image = button.backgroundImageForState(UIControlState.Normal)
}
我们需要首先创建UIButton
的实例,然后基于该按钮的背景图像设置imageToFilter
的图像,该图像已经被放置在viewDidLoad()
的代码过滤了。
确保名为imageToFilter
的UIImageView
覆盖originalImage
,如下所示,否则该应用程序将不会向您显示已处理的图像,因为原始图像会将其隐藏。

保存处理后的图片
我们已经到了本教程的结尾,并且在.swift文件中仅添加了一个功能。 那是我们先前放在情节提要中的“保存”按钮。 按住Control和鼠标按钮,将UIButton
的蓝线拖到班级中的空白处,释放鼠标按钮,将显示一个新的弹出窗口。 在这里,您必须将“ 连接”类型更改为“动作”,并输入方法的名称(在本例中为savePicButton
,然后单击“ 连接”按钮。

这次您已经创建了一个IBAction
这是必须放置在其中的代码:
// Save the image into camera roll
UIImageWriteToSavedPhotosAlbum(imageToFilter.image!, nil, nil, nil)
let alert = UIAlertView(title: "Filters",
message: "Your image has been saved to Photo Library",
delegate: nil,
cancelButtonTitle: "OK")
alert.show()
第一行只是将包含在imageToFilter
的图像直接保存在设备或iOS Simulator的照片库中。 然后,我们触发一个简单的UIAlertView
,以确认该操作已完成。
好的,让我们运行我们的应用程序,看看如果点击底部的按钮会发生什么。 如果您正确完成了所有操作,则您的应用应如下所示:



翻译自: https://code.tutsplus.com/tutorials/ios-sdk-apply-photo-filters-with-core-image-in-swift--cms-27142