劇情介紹
在iOS開發(fā)中夺脾,經(jīng)常會(huì)看到毛玻璃效果有鹿,也叫模糊效果鼓黔,比如系統(tǒng)的通知中心央勒,這個(gè)很時(shí)髦的效果增加了美觀性。
查看資料發(fā)現(xiàn)實(shí)現(xiàn)毛玻璃效果有很多種方式澳化,下面總結(jié)了其中幾種方式崔步。
靜態(tài)模糊效果
- 對(duì)于靜態(tài)的模糊效果,最直接的方式就是加載做好的模糊圖片
動(dòng)態(tài)模糊效果
- 蘋果原生控件:
UIVisualEffectView
- 蘋果原生API:Core Image 的濾鏡效果
- 蘋果原生API:vImage
- 使用第三方工具GPUImage
- 使用第三方工具FXBlurView
- ...
一缎谷、蘋果原生控件:UIVisualEffectView
實(shí)現(xiàn)模糊效果
-
UIVisualEffectView
是iOS8的新特性井濒,該控件主要用于為原有的控件增加模糊效果。 - 由于是iOS8的新特性列林,所以具有一定的局限性瑞你。
-
UIVisualEffectView
繼承自UIView,沒有繼承UIControl希痴,所以只能做靜態(tài)控件使用者甲。 - 控制
UIVisualEffectView
控件模糊效果的屬性時(shí)effect
只讀屬性,該屬性的類型是UIVisualEffect
,該類型有兩個(gè)子類:UIBlurEffect
和UIVibrancyEffect
润梯。 -
UIBlurEffect
允許應(yīng)用程序中動(dòng)態(tài)的創(chuàng)建實(shí)時(shí)的模糊效果过牙;UIVibrancyEffect
允許在模糊效果上“寫字”。 - Blur Style有三種效果:
-
UIBlurEffectStyleLight
:白色的模糊效果纺铭。 -
UIBlurEffectStyleExtraLight
:極亮的白色模糊效果寇钉。 -
UIBlurEffectStyleDark
:暗色的模糊效果。
-
- 可以通過(guò)在Interface Bulider中將
UIVibrancyEffect
控件直接拖入某個(gè)控件內(nèi)添加模糊效果舶赔,也可以通過(guò)純代碼的形式創(chuàng)建和添加扫倡。
// UIBlurEffectStyleLight模式
UIVisualEffectView *lightView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
lightView.frame = CGRectMake(40, 40, 300, 100);
[self.imageView addSubview:lightView];
// UIBlurEffectStyleExtraLight模式
UIVisualEffectView *extraLightView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]];
extraLightView.frame = CGRectMake(40, 160, 300, 100);
[self.imageView addSubview:extraLightView];
// UIBlurEffectStyleDark
UIVisualEffectView *darkView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
darkView.frame = CGRectMake(40, 280, 300, 100);
[self.imageView addSubview:darkView];
二、Core Image 的濾鏡效果實(shí)現(xiàn)模糊效果
- 在iOS5.0之后Core Image 的API提供了大量的濾鏡(Filter)效果。
- 利用Core Image 實(shí)現(xiàn)模糊效果非常簡(jiǎn)單撵溃,只需要10行左右的代碼就能搞定疚鲤。
- 使用Core Image 設(shè)置模糊之后,會(huì)在周圍產(chǎn)生白邊缘挑。
- 代碼中的
CIGaussianBlur
是一個(gè)濾鏡名稱集歇,更多的濾鏡可以參考蘋果濾鏡列表 -
Core Image
實(shí)現(xiàn)高斯模糊的原理是:將原來(lái)的圖片驚醒模糊處理返回渲染后的一整張圖片,比較消耗CPU性能语淘。
/**
* 使用Core Image進(jìn)行模糊
*/
- (UIImage *)blurryImage:(UIImage *)image withblurLevel:(CGFloat)blur{
// 1.創(chuàng)建CIImage
CIImage * ciImage = [[CIImage alloc]initWithImage:image];
// 2.添加濾鏡
CIFilter * blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
// 3.將圖片輸入到濾鏡中
[blurFilter setValue:ciImage forKey:kCIInputImageKey];
// 4.設(shè)置模糊值(不模糊為0诲宇,模糊最大為100)
[blurFilter setValue:[NSNumber numberWithFloat:blur] forKey:@"inputRadius"];
// 5.將處理好的圖片輸出
CIImage * outCiImage = [blurFilter valueForKey:kCIOutputImageKey];
// 6.生成圖片 CIContext(CIImage的操作句柄)nil表示默認(rèn)有CPU渲染圖片(如果讓GPU渲染提高效率,則應(yīng)設(shè)置contextWithOptions的字典數(shù)據(jù))
CIContext * context = [CIContext contextWithOptions:nil];
// 7.獲取CIImage句柄
CGImageRef outCGImage = [context createCGImage:outCiImage fromRect:[outCiImage extent]];
// 8.最終獲取到圖片
UIImage * blurImage = [UIImage imageWithCGImage:outCGImage];
// 9.釋放句柄
CGImageRelease(outCGImage);
return blurImage;
}
三惶翻、使用vImage
實(shí)現(xiàn)高斯模糊
-
vImage
屬于Accelerate.Framework
姑蓝,所以在使用是需要導(dǎo)入Accelerate
頭文件,導(dǎo)入頭文件代碼:#import <Accelerate/Accelerate.h>
-
Accelerate
主要用來(lái)做數(shù)圖像處理、字信號(hào)處理相關(guān)的向量吕粗、矩陣運(yùn)算的庫(kù)纺荧。 - 圖像可以認(rèn)為是由向量后者矩陣數(shù)據(jù)構(gòu)成的。
-
Accelerate
提供了搞笑的數(shù)學(xué)運(yùn)算API颅筋,所以能對(duì)圖像做各種各樣的處理宙暇。 -
Accelerate
實(shí)現(xiàn)高斯模糊的原理是:將原來(lái)的圖片驚醒模糊處理返回渲染后的一整張圖片,比較消耗CPU垃沦。 - 模糊算法使用的函數(shù)是:
vImageBoxConvolve_ARGB8888
代碼
(記得先導(dǎo)入頭文件#import <Accelerate/Accelerate.h>
)
/**
* 使用vImage實(shí)現(xiàn)模糊效果
*/
- (UIImage *)blurryImage:(UIImage *)image withblur:(CGFloat)blur{
if (blur < 0.f || blur > 1.0f) blur = 0.5f;
int boxSize = (int)(blur * 100);
boxSize -=(boxSize % 2) + 1;
// 圖像處理
CGImageRef img = image.CGImage;
// 輸入緩存 輸出緩存
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);
// 第三個(gè)中間的緩存區(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ù)上下文池充,處理過(guò)的圖片,重新組件
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
UIImage * outImage = [UIImage imageWithCGImage:imageRef];
//clean up
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
free(pixelBuffer2);
CFRelease(inBitmapData);
//CGColorSpaceRelease(colorSpace); //多余的釋放
// 釋放句柄
CGImageRelease(imageRef);
return outImage;
}
四缎讼、使用第三方工具GPUImage實(shí)現(xiàn)高斯模糊
-
GPUImage
一個(gè)基于GPU圖像和視頻處理的開源框架收夸,適用面廣。 -
GPUImage
同時(shí)支持objective-C和Swift血崭。 -
GPUImage
的github地址GPUImage -
GPUImage
可以直接導(dǎo)入本地卧惜,也可以使用使用pod導(dǎo)入。這是使用pod比較簡(jiǎn)單夹纫。 - 使用
GPUImage
實(shí)現(xiàn)高斯模糊的代碼非常簡(jiǎn)單.
/**
*使用GPUImage實(shí)現(xiàn)高斯模糊
*/
- (UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(CGFloat)blur{
GPUImageGaussianBlurFilter * blurFilter = [[GPUImageGaussianBlurFilter alloc]init];
blurFilter.blurRadiusInPixels = blur;
UIImage * blurImage = [blurFilter imageByFilteringImage:image];
return blurImage;
}
五咽瓷、 使用第三方工具FXBlurView實(shí)現(xiàn)高斯模糊
-
FXBlurView
是UIView的子類,支持iOS5.0及其以上 -
FXBlurView
的特點(diǎn)是簡(jiǎn)單和輕快舰讹,看源碼就知道幾行代碼就可以搞定茅姜。 -
FXBlurView
有兩種模式:static
靜態(tài)模糊,也就是只模糊一次月匣,就算背景圖片改變了模糊效果也不會(huì)改變钻洒;dynamic
動(dòng)態(tài)模糊奋姿,也就是會(huì)實(shí)時(shí)的對(duì)背景圖片進(jìn)行模糊,是會(huì)不斷變化的素标。 -
FXBlurView
同樣也可以通過(guò)pod導(dǎo)入称诗。 -
FXBlurView
的原理是在圖片上添加一個(gè)FXBlurView
的對(duì)象覆蓋原圖。
// 設(shè)置模糊效果
FXBlurView * blurView = [[FXBlurView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 200)];
blurView.backgroundColor = [UIColor whiteColor];
// 設(shè)置模式
blurView.dynamic = YES;
// 設(shè)置模糊半徑
blurView.blurRadius = 10.0;
demo后續(xù)上傳