在开发中,有时候我们可能会做一些图片模糊的效果,来给APP添加色彩。自己看到一个APP的模糊效果,感觉很不错,所以就学了下如何来实现这样一个模糊效果,写下来方便自己回顾,有需要的童鞋也可以get下,还包含一个截屏功能哦~
先看效果图:
模糊前 模糊后
因为只是显示一个小功能,所以我都写在了ViewController文件里,要开发具备这个效果的App的童鞋最好单独抽出一个类来实现这个功能。
来看看代码,解释都写在注释里了。
#import "ViewController.h"
#import <Accelerate/Accelerate.h>
@interface ViewController ()
@property(nonatomic,strong)UIImageView *imageView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImageView *imageView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1"]];
imageView.frame=self.view.bounds;
self.imageView=imageView;
[self.view addSubview:imageView];
UIButton *blurBtn=[[UIButton alloc]init];
blurBtn.frame=CGRectMake(10, 64, 100, 30);
[blurBtn setTitle:@"按下变模糊" forState:UIControlStateNormal];
blurBtn.backgroundColor=[UIColor blackColor];
[blurBtn addTarget:self action:@selector(setBlurImageClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:blurBtn];
}
-(void)setBlurImageClick
{
UIImage *image=[self screenShot:self.view];
UIImage *imageBlur=[self blurryImage:image withBlurLevel:0.3f];
[self.imageView setImage:imageBlur];
}
/**
截图,返回一张截取的图片
这里的view为window窗口
*/
- (UIImage *) screenShot:(UIView *)window
{
CGSize size=window.bounds.size;
UIGraphicsBeginImageContextWithOptions(size, NO, 2.0);
[window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image=UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData=UIImageJPEGRepresentation(image, 0.75);
image=[UIImage imageWithData:imageData];
return image;
}
/**
返回一张模糊图片
使用vImage API进行模糊
需要导入头文件#import <Accelerate/Accelerate.h>
*/
- (UIImage *) blurryImage:(UIImage *)image withBlurLevel:(CGFloat)blur
{
if ((blur < 0.1f) || (blur > 2.0f)) {
blur=0.5f;
}
int boxSize=(int)(blur * 40);
boxSize=boxSize-(boxSize % 2)+1;
CGImageRef img=image.CGImage;
vImage_Buffer inBuffer,outBuffer;
vImage_Error error;
void *pixelBuffer;
CGDataProviderRef inProvider=CGImageGetDataProvider(img);
CFDataRef inBitmapData=CGDataProviderCopyData(inProvider);
inBuffer.width=CGImageGetWidth(img);
inBuffer.height=CGImageGetHeight(img);
inBuffer.rowBytes=CGImageGetBytesPerRow(img);
inBuffer.data=(void*)CFDataGetBytePtr(inBitmapData);
pixelBuffer=malloc(CGImageGetBytesPerRow(img)*CGImageGetHeight(img));
if (pixelBuffer==NULL) {
NSLog(@"No pixelbuffer");
}
outBuffer.data=pixelBuffer;
outBuffer.width=CGImageGetWidth(img);
outBuffer.height=CGImageGetHeight(img);
outBuffer.rowBytes=CGImageGetBytesPerRow(img);
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);
//vImageBoxConvolve_ARGB8888模糊算法函数
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);
}
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data, outBuffer.width, outBuffer.height, 8, outBuffer.rowBytes, colorSpace, CGImageGetBitmapInfo(image.CGImage));
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
free(pixelBuffer2);
CFRelease(inBitmapData);
CGColorSpaceRelease(colorSpace);
CGImageRelease(imageRef);
return returnImage;
}
/**
返回模糊图片
使用Core Image进行模糊
*/
//- (UIImage *)blurryImage:(UIImage *)image withBlurLevel:(CGFloat)blur
//{
// CIContext *context=[CIContext contextWithOptions:nil];
// CIImage *inputImage=[CIImage imageWithCGImage:image.CGImage];
// CIFilter *filter=[CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:kCIInputImageKey,inputImage,@"inputRadius", @(blur),nil];
//
// CIImage *outputImage=filter.outputImage;
//
// CGImageRef outImage=[context createCGImage:outputImage fromRect:[outputImage extent]];
// return [UIImage imageWithCGImage:outImage];
//}
@end
点击按钮,屏幕就会变模糊。
查资料时看到也可以使用Core Image来进行图片模糊,但是我试了下,感觉效果不是很好,可能是因为现在对Core Image还不熟,所以不太理解它的使用,等我进一步对它学习吧,知道的大神也可以指教下。注释掉的部分就是用Core Image来实现的,高斯模糊,有兴趣的童鞋可以试试看,我这里运行的效果感觉不是模糊效果。
本例中用的是vImage API进行模糊,注意不要忘记导入#import<Accelerate/Accelerate.h>头文件。