iOS實現(xiàn)模糊效果的幾種方法

iOS7后,半透明模糊效果得到了廣泛的使用遗菠,所以iOS開發(fā)過程中經(jīng)常需要用到半透明模糊效果联喘,本文對比列舉幾種實現(xiàn)半透明模糊效果的方法,包括Core Image辙纬、vImage豁遭、BlurEffect,第三方庫FXBlurView贺拣、GPUImage等蓖谢。

一捂蕴、蘋果原生API

1、Core Image

Core Image 是蘋果用來簡化圖片處理的框架闪幽;在 iOS 平臺上啥辨,5.0 之后就出現(xiàn)了 Core Image 的 API。Core Image 的 API 被放在 CoreImage.framework 庫中盯腌。不過直到iOS6.0才開始支持模糊委可。這個API調(diào)用起來很方便簡潔。

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

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

- (UIImage *)blurryImage:(UIImage *)image withMaskImage:(UIImage *)maskImage blurLevel:(CGFloat)blur {
    
    // 創(chuàng)建屬性
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    
    // 濾鏡效果 高斯模糊
//    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
//    [filter setValue:cimage forKey:kCIInputImageKey];
//    // 指定模糊值 默認(rèn)為10, 范圍為0-100
//    [filter setValue:[NSNumber numberWithFloat:blur] forKey:@"inputRadius"];
    
    /**
     *  濾鏡效果 VariableBlur
     *  此濾鏡模糊圖像具有可變模糊半徑客们。你提供和目標(biāo)圖像相同大小的灰度圖像為它指定模糊半徑
     *  白色的區(qū)域模糊度最高,黑色區(qū)域則沒有模糊材诽。
     */
    CIFilter *filter = [CIFilter filterWithName:@"CIMaskedVariableBlur"];
    // 指定過濾照片
    [filter setValue:ciImage forKey:kCIInputImageKey];
    CIImage *mask = [CIImage imageWithCGImage:maskImage.CGImage] ;
    // 指定 mask image
    [filter setValue:mask forKey:@"inputMask"];
    // 指定模糊值  默認(rèn)為10, 范圍為0-100
    [filter setValue:[NSNumber numberWithFloat:blur] forKey: @"inputRadius"];
    
    // 生成圖片
    CIContext *context = [CIContext contextWithOptions:nil];
    // 創(chuàng)建輸出
    CIImage *result = [filter valueForKey:kCIOutputImageKey];
    
    // 下面這一行的代碼耗費(fèi)時間內(nèi)存最多,可以開辟線程處理然后回調(diào)主線程給imageView賦值
    //result.extent 指原來的大小size
//    NSLog(@"%@",NSStringFromCGRect(result.extent));
//    CGImageRef outImage = [context createCGImage: result fromRect: result.extent];
    
    CGImageRef outImage = [context createCGImage: result fromRect:CGRectMake(0, 0, 320.0 * 2, 334.0 * 2)];
    UIImage * blurImage = [UIImage imageWithCGImage:outImage];
    
    return blurImage;
}
coreImage.png

更多的濾鏡效果可以參見這個 Filter官方列表

2底挫、vImage

vImage 也是蘋果推出的庫,在 Accelerate.framework 中脸侥。

Accelerate這個framework主要是用來做數(shù)字信號處理建邓、圖像處理相關(guān)的向量、矩陣運(yùn)算的庫睁枕。我們可以認(rèn)為我們的圖像都是由向量或者矩陣數(shù)據(jù)構(gòu)成的官边,Accelerate里既然提供了高效的數(shù)學(xué)運(yùn)算API,自然就能方便我們對圖像做各種各樣的處理外遇。

基于vImage我們可以根據(jù)圖像的處理原理直接做模糊效果注簿,或者使用現(xiàn)有的工具。UIImage+ImageEffects是個很好的圖像處理庫跳仿,看名字也知道是對UIImage做的分類擴(kuò)展诡渴。這個工具被廣泛地使用著,后面會做介紹菲语。

下面是一段使用 vImage 實現(xiàn)模糊效果的代碼:

// 添加通用模糊效果
// image是圖片妄辩,blur是模糊度
- (UIImage *)blurryImage:(UIImage *)image withBlurLevel:(CGFloat)blur
{
    if (image==nil)
    {
        NSLog(@"error:為圖片添加模糊效果時,未能獲取原始圖片");
        return nil;
    }
    //模糊度,
    if (blur < 0.025f) {
        blur = 0.025f;
    } else if (blur > 1.0f) {
        blur = 1.0f;
    }
    
    //boxSize必須大于0
    int boxSize = (int)(blur * 100);
    boxSize -= (boxSize % 2) + 1;
    NSLog(@"boxSize:%i",boxSize);
    //圖像處理
    CGImageRef img = image.CGImage;
    //需要引入#import <Accelerate/Accelerate.h>
    
    //圖像緩存,輸入緩存山上,輸出緩存
    vImage_Buffer inBuffer, outBuffer;
    vImage_Error error;
    //像素緩存
    void *pixelBuffer;
    
    //數(shù)據(jù)源提供者恩袱,Defines an opaque type that supplies Quartz with data.
    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    // provider’s data.
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
    
    //寬,高胶哲,字節(jié)/行畔塔,data
    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);
    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
    
    //像數(shù)緩存,字節(jié)行*圖片高
    pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);
    // 第三個中間的緩存區(qū),抗鋸齒的效果
    void *pixelBuffer2 = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
    vImage_Buffer outBuffer2;
    outBuffer2.data = pixelBuffer2;
    outBuffer2.width = CGImageGetWidth(img);
    outBuffer2.height = CGImageGetHeight(img);
    outBuffer2.rowBytes = CGImageGetBytesPerRow(img);
    //Convolves a region of interest within an ARGB8888 source image by an implicit M x N kernel that has the effect of a box filter.
    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer2, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
    error = vImageBoxConvolve_ARGB8888(&outBuffer2, &inBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
    if (error) {
        NSLog(@"error from convolution %ld", error);
    }
    //    NSLog(@"字節(jié)組成部分:%zu",CGImageGetBitsPerComponent(img));
    //顏色空間DeviceRGB
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    //用圖片創(chuàng)建上下文,CGImageGetBitsPerComponent(img),7,8
    CGContextRef ctx = CGBitmapContextCreate(
                                             outBuffer.data,
                                             outBuffer.width,
                                             outBuffer.height,
                                             8,
                                             outBuffer.rowBytes,
                                             colorSpace,
                                             CGImageGetBitmapInfo(image.CGImage));
    
    //根據(jù)上下文,處理過的圖片澈吨,重新組件
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
    //clean up
    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);
    free(pixelBuffer);
    free(pixelBuffer2);
    CFRelease(inBitmapData);
    //CGColorSpaceRelease(colorSpace);   //多余的釋放
    CGImageRelease(imageRef);
    return returnImage;
}
vImage.png

3把敢、UIVisualEffectView

UIVisualEffectView只支持iOS 8以后的設(shè)備,所以有一定的局限性谅辣,但是使用起來非常簡單修赞,并且能通過代碼或 storyboard 實現(xiàn)模糊效果,下面是一段實現(xiàn)模糊效果的示例代碼桑阶,其中 effectWithStyle 有 Light柏副、ExtraLight、dark 三種蚣录,如下:

UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
effectView.frame = self.view.frame;
[self.view addSubview:effectView];
blurEffect.png

實現(xiàn)中間透明文字效果的代碼為:

- (void)configBlurEffect{
    
    // 原始圖片 self.imageView
    // 為了更好的看到UIVisualEffectView的即時渲染效果添加平移手勢 此處通過 storyBoard 添加
//    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
//    [self.imageView addGestureRecognizer:pan];
    
    // 創(chuàng)建模糊View
    UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
    effectView.layer.cornerRadius = 10.0f;
    effectView.layer.masksToBounds = YES;
    effectView.frame = CGRectMake(80, 300, 160, 80);
    [self.view addSubview:effectView];
    
    
    UILabel *label = [[UILabel alloc] initWithFrame:effectView.bounds];
    label.text = @"Blur Effect";
    label.textAlignment = NSTextAlignmentCenter;
    label.font = [UIFont systemFontOfSize:20];
    //    [effectView.contentView addSubview:label];
    // 在創(chuàng)建的模糊View的上面再添加一個子模糊View
    UIVisualEffectView *subEffectView = [[UIVisualEffectView alloc] initWithEffect:[UIVibrancyEffect effectForBlurEffect:(UIBlurEffect *)effectView.effect]];
    
    subEffectView.frame = effectView.bounds;
    
    [effectView.contentView addSubview:subEffectView];
    
    [subEffectView.contentView addSubview:label];
}

- (IBAction)panGesture:(UIPanGestureRecognizer *)sender {
    
    CGPoint point = [sender translationInView:sender.view];
    sender.view.center = CGPointMake(sender.view.center.x + point.x,
                                      sender.view.center.y + point.y);
    [sender setTranslation:CGPointZero inView:sender.view];

}

二割择、第三方庫/工具

1、FXBlurView

FXBlurView 是一個UIView的子類萎河,效果和iOS7的背景實時模糊效果一樣荔泳,但是支持到了 iOS 5.0。

FXBlurView 有兩種模式虐杯,一種是 static 靜態(tài)模糊:也就是只模糊一次玛歌,后面即使背景圖片變化了,模糊效果也不會變化擎椰;另外就是 dynamic 動態(tài)模糊:這會實時的對背景圖片進(jìn)行模糊支子,是會不斷變化的。

FXBlurView 的使用非常簡單达舒,看一下它的源碼就明白了译荞,一個示例代碼如下:

FXBlurView *blurView = [[FXBlurView alloc] init];
[blurView setFrame:CGRectMake(40.0, 60.0, 240.0, 240.0)];
[blurView setBackgroundColor:[UIColor whiteColor]];
//設(shè)置模式
self.blurView.dynamic = YES;
//設(shè)置模糊半徑
self.blurView.blurRadius = 10.0;
FXBlurView.png

2、GPUImage

GPUImage 是一個基于GPU圖像和視頻處理開源的iOS framework休弃,適用面很廣吞歼。

順便說一下 GPUImage 的一種使用方法:

  1. 在 github 上 clone 源碼
  2. 將它的 framework 整個文件夾拷貝到你的工程文件夾下
  3. 將 framework 下的 GPUImage.xcodeproj 文件拖到你的 Xcode project 中
  4. 到工程的 target 的 Build Phases 界面,添加 GPUImage 到 Target Dependencies
  5. 繼續(xù)將 libGPUImage.a 添加到Build Phases 界面的 Link Binary With Libraries
  6. Link Binary With Libraries 繼續(xù)添加 GPUImage 的支持庫:
    • CoreMedia
    • CoreVideo
    • OpenGLES
    • AVFoundation
    • QuartzCore
  7. 最后塔猾,到工程的 Build Settings 設(shè)置 Header Search Paths篙骡,搜索 Header Search Paths 后在 Header Search Paths 一欄添加 framework 的頭文件路徑,不想手動輸入可以將 framework 文件夾拖入即可自動生成路徑丈甸,然后將后面的選項設(shè)置為 recursive
  8. 在工程使用 #import "GPUImage.h" 即可開始使用了
HeaderSearchPaths.png

如果要使用 GPUImage 實現(xiàn)高斯模糊糯俗,則非常簡單,代碼如下:

- (UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(CGFloat)blur {

    // 高斯模糊
    GPUImageGaussianBlurFilter * blurFilter = [[GPUImageGaussianBlurFilter alloc] init];
    blurFilter.blurRadiusInPixels = blur;
    UIImage *blurredImage = [blurFilter imageByFilteringImage:image];
    
    return blurredImage;
}
GPUImage.png

3睦擂、UIImage+ImageEffects

Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.

摘要:這是UIImage的category得湘,增加方法來對圖像進(jìn)行模糊和著色效果。這就是你想要的如何有效利用 vImage實現(xiàn)模糊效果的代碼

UIImage+ImageEffects 的模糊效果非常美觀顿仇,對 UIImage+ImageEffects 進(jìn)行修改后可以對圖片進(jìn)行局模糊;

UIImage+ImageEffects 提供了很多方法可以使用淘正,常用的幾個方法使用示例如下:

// 通用模糊摆马,默認(rèn)模糊半徑為20.0
self.blurView.image = [[UIImage imageNamed:@"WID-small"] blurImage];
// 局部模糊
self.partBlurView.image = [[UIImage imageNamed:@"WID-small"] blurImageAtFrame:CGRectMake(0.0, 0.0, 155.0*2 , 235.0*4.0)];
// 灰度銳化圖
self.grayScaleView.image = [[UIImage imageNamed:@"WID-small"] grayScale];
UIImage+ImageEffects.png

后續(xù)若又發(fā)現(xiàn)好用的實現(xiàn)模糊效果的方法再更新吧

附上代碼的github地址 BlurViewExample

推薦閱讀:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鸿吆,隨后出現(xiàn)的幾起案子囤采,更是在濱河造成了極大的恐慌,老刑警劉巖惩淳,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蕉毯,死亡現(xiàn)場離奇詭異,居然都是意外死亡思犁,警方通過查閱死者的電腦和手機(jī)代虾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來激蹲,“玉大人棉磨,你說我怎么就攤上這事⊥信唬” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵频敛,是天一觀的道長项郊。 經(jīng)常有香客問我,道長斟赚,這世上最難降的妖魔是什么着降? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮拗军,結(jié)果婚禮上任洞,老公的妹妹穿的比我還像新娘。我一直安慰自己发侵,他們只是感情好交掏,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刃鳄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上捍岳,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天紧帕,我揣著相機(jī)與錄音,去河邊找鬼愉烙。 笑死讨盒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的步责。 我是一名探鬼主播返顺,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼禀苦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了创南?” 一聲冷哼從身側(cè)響起伦忠,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎稿辙,沒想到半個月后昆码,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邻储,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年赋咽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吨娜。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡脓匿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宦赠,到底是詐尸還是另有隱情陪毡,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布勾扭,位于F島的核電站毡琉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏妙色。R本人自食惡果不足惜桅滋,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望身辨。 院中可真熱鬧丐谋,春花似錦、人聲如沸煌珊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽定庵。三九已至萧落,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洗贰,已是汗流浹背找岖。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留敛滋,地道東北人许布。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像绎晃,于是被迫代替她去往敵國和親蜜唾。 傳聞我的和親對象是個殘疾皇子杂曲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Swift版本點擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 25,374評論 7 249
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫颖榜、插件棚饵、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評論 4 62
  • 潛能拼圖這一塊,是考察人間的這個游戲到底有什么功課要做的… 人間有很多功課掩完,每個人的具體呈現(xiàn)都不同噪漾! 搞清楚潛能,...
    建設(shè)現(xiàn)代生活閱讀 279評論 0 0
  • 我們兩家離得不遠(yuǎn)且蓬,他比我大三歲欣硼,但并不記得小時候和他有什么交集,他和我哥哥年齡相仿恶阴,也并不記得他們曾是玩伴诈胜。知道有...
    朝飲木蘭之墜露兮Y閱讀 164評論 0 0
  • 1. 辭職的第三天夜里,出去跟朋友嗨皮到后半夜冯事。 我都不知道幾點回的家焦匈,我在距離家里還有一站地的時候,提前下的車桅咆。...
    87b2ca3db634閱讀 332評論 2 4