1. 程式人生 > >新部落格地址:blog.songchunmin.com

新部落格地址:blog.songchunmin.com

0. Core Image

作為設計和體驗方面的領導者,蘋果自己對圖片效果和圖片處理的支援一定是非常好的,在iOS平臺上,5.0之後就出現了Core Image的API。Core Image的API被放在CoreImage.framework庫中。

在iOS和OS X平臺上,Core Image都提供了大量的濾鏡(Filter),這也是Core Image庫中比較核心的東西之一。按照官方文件記載,在OS X上有120多種Filter,而在iOS上也有90多。

下面是一段Core Image做模糊的示例程式碼:

1 2 3 4 5 6 7 8 CIContext *context = [CIContext contextWithOptions:nil];
CIImage *image = [CIImage imageWithContentsOfURL:imageURL]; CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"]; [filter setValue:image forKey:kCIInputImageKey]; [filter setValue:@2.0f forKey: @"inputRadius"]; CIImage *result = [filter valueForKey:kCIOutputImageKey]; CGImageRef outImage = [context createCGImage: result fromRect:[result extent]];
UIImage * blurImage = [UIImage imageWithCGImage:outImage];

這裡可以看到,Core Image為了做得比較靈活,Filter都是按字串的名字去建立的,比如高斯模糊濾鏡就是“CIGaussianBlur”,這裡有一個官方列表可以參看。

除了這裡提到的多種Filter之外,Core Image還提供了CIDetector等類,可以支援人臉識別等,在OS X上Core Image也做了更多支援。

1. GPUImage

除了蘋果官方提供的之外,第三方也有這方面圖片處理的工具。一個叫Brad Larson的老兄就搞了一套叫做

GPUImage的開源庫。同樣的,裡面提供了很多Filter。

同樣是做高斯模糊,用GPUImage可以這樣:

1 2 3 4 GPUImageGaussianBlurFilter * blurFilter = [[GPUImageGaussianBlurFilter alloc] init]; blurFilter.blurRadiusInPixels = 2.0; UIImage * image = [UIImage imageNamed:@"xxx"]; UIImage *blurredImage = [blurFilter imageByFilteringImage:image];

至少看起來,程式碼上比使用Core Image的情況簡單得多。

2. vImage

其實,說完上面的Core Image和GPUImage,很多情況下就已經足夠用了。下面我們再來看一個,那就是vImage。vImage也是蘋果推出的庫,在Accelerate.framework中。

Accelerate這個framework主要是用來做數字訊號處理、影象處理相關的向量、矩陣運算的庫。我們可以認為我們的影象都是由向量或者矩陣資料構成的,Accelerate裡既然提供了高效的數學運算API,自然就能方便我們對影象做各種各樣的處理。

基於vImage我們可以根據影象的處理原理直接做模糊效果,或者使用現有的工具。UIImage+ImageEffects是個很好的影象處理庫,看名字也知道是對UIImage做的分類擴充套件。這個工具被廣泛地使用著。

3. UIVisualEffectView(iOS8系統之後使用,有即時效果)

在iOS 8後,蘋果開放了不少建立特效的介面,其中就包括建立毛玻璃(blur)的介面。

通常要想建立一個特殊效果(如blur效果),可以建立一個UIVisualEffectView檢視物件,這個物件提供了一種簡單的方式來實現複雜的視覺效果。這個可以把這個物件看作是效果的一個容器,實際的效果會影響到該檢視物件底下的內容,或者是新增到該檢視物件的contentView中的內容。

我們舉個例子來看看如果使用UIVisualEffectView:

let bgView: UIImageView = UIImageView(image: UIImage(named: "visual"))
bgView.frame = self.view.bounds
self.view.addSubview(bgView)
let blurEffect: UIBlurEffect = UIBlurEffect(style: .Light)
let blurView: UIVisualEffectView = UIVisualEffectView(effect: blurEffect)
blurView.frame = CGRectMake(50.0, 50.0, self.view.frame.width - 100.0, 200.0)
self.view.addSubview(blurView)

這段程式碼是在當前檢視控制器上添加了一個UIImageView作為背景圖。然後在檢視的一小部分中使用了blur效果。

我們可以看到UIVisualEffectView還是非常簡單的。需要注意是的,不應該直接新增子檢視到UIVisualEffectView檢視中,而是應該新增到UIVisualEffectView物件的contentView中。

另外,儘量避免將UIVisualEffectView物件的alpha值設定為小於1.0的值,因為建立半透明的檢視會導致系統在離屏渲染時去對UIVisualEffectView物件及所有的相關的子檢視做混合操作。這不但消耗CPU/GPU,也可能會導致許多效果顯示不正確或者根本不顯示。

我們在上面看到,初始化一個UIVisualEffectView物件的方法是UIVisualEffectView(effect: blurEffect),其定義如下:

init(effect effect: UIVisualEffect)

這個方法的引數是一個UIVisualEffect物件。我們檢視官方文件,可以看到在UIKit中,定義了幾個專門用來建立視覺特效的,它們分別是UIVisualEffect、UIBlurEffect和UIVibrancyEffect。它們的繼承層次如下所示:

NSObject
| -- UIVisualEffect
    | -- UIBlurEffect
    | -- UIVibrancyEffect

UIVisualEffect是一個繼承自NSObject的建立視覺效果的基類,然而這個類除了繼承自NSObject的屬性和方法外,沒有提供任何新的屬性和方法。其主要目的是用於初始化UIVisualEffectView,在這個初始化方法中可以傳入UIBlurEffect或者UIVibrancyEffect物件。

一個UIBlurEffect物件用於將blur(毛玻璃)效果應用於UIVisualEffectView檢視下面的內容。如上面的示例所示。不過,這個物件的效果並不影響UIVisualEffectView物件的contentView中的內容。

UIBlurEffect主要定義了三種效果,這些效果由列舉UIBlurEffectStyle來確定,該列舉的定義如下:

enum UIBlurEffectStyle : Int {
    case ExtraLight
    case Light
    case Dark
}

其主要是根據色調(hue)來確定特效檢視與底部檢視的混合。

與UIBlurEffect不同的是,UIVibrancyEffect主要用於放大和調整UIVisualEffectView檢視下面的內容的顏色,同時讓UIVisualEffectView的contentView中的內容看起來更加生動。通常UIVibrancyEffect物件是與UIBlurEffect一起使用,主要用於處理在UIBlurEffect特效上的一些顯示效果。接上面的程式碼,我們看看在blur的檢視上新增一些新的特效,如下程式碼所示:

let vibrancyView: UIVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(forBlurEffect: blurEffect))
vibrancyView.setTranslatesAutoresizingMaskIntoConstraints(false)
blurView.contentView.addSubview(vibrancyView)
var label: UILabel = UILabel()
label.setTranslatesAutoresizingMaskIntoConstraints(false)
label.text = "Vibrancy Effect"
label.font = UIFont(name: "HelveticaNeue-Bold", size: 30)
label.textAlignment = .Center
label.textColor = UIColor.whiteColor()
vibrancyView.contentView.addSubview(label)

vibrancy特效是取決於顏色值的。所有新增到contentView的子檢視都必須實現tintColorDidChange方法並更新自己。需要注意的是,我們使用UIVibrancyEffect(forBlurEffect:)方法建立UIVibrancyEffect時,引數blurEffect必須是我們想加效果的那個blurEffect,否則可能不是我們想要的效果。

另外,UIVibrancyEffect還提供了一個類方法notificationCenterVibrancyEffect,其宣告如下:

class func notificationCenterVibrancyEffect() -> UIVibrancyEffect!

這個方法建立一個用於通知中心的Today擴充套件的vibrancy特效。