IOS中模糊效果实现的几种方法(毛玻璃)(转载)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOS中模糊效果实现的几种方法(毛玻璃)(转载)相关的知识,希望对你有一定的参考价值。

在手机里面经常可以看到模糊效果,比如说控制中心。

那么这种效果怎么去实现的呢,一般有一下几种办法。

1.CoreImage

2.vImage(UIImageView+Effective)

3.GPUImage

4.UIVisualEfftiveView

下面来说说这几种方法的使用方法:

一、CoreImage

 1 - (void)test1 {
 2     //原始图片
 3     UIImage *originImage = [UIImage imageNamed:@"bg1.jpg"];
 4     //创建上下文
 5     CIContext *context = [CIContext contextWithOptions:nil];
 6     //将原始图片转换成CIImage
 7     CIImage *inputImage = [CIImage imageWithCGImage:originImage.CGImage];
 8     //创建滤镜
 9     CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
10     //设置滤镜的属性
11     [filter setValue:inputImage forKey:kCIInputImageKey];
12     //模糊半径
13     [filter setValue:@10.f forKey:@"inputRadius"];
14     //输出图片
15     CIImage *outputImage = [filter valueForKey:kCIOutputImageKey];
16     //转换成CGImage
17     CGImageRef ref = [context createCGImage:outputImage fromRect:[outputImage extent]];
18     //转换成UIImage
19     UIImage *newImage = [UIImage imageWithCGImage:ref];
20     //释放
21     CGImageRelease(ref);
22 }

二、vImage

vImage是苹果推出的库,是在Accelerate.framework中

Accelerate这个framework主要是用来做数字信号处理、图像处理相关的向量、矩阵运算的库。我们可以认为我们的图像都是由向量或者矩阵数据构成的,Accelerate里既然提供了高效的数学运算API,自然就能方便我们对图像做各种各样的处理。

基于vImage我们可以根据图像的处理原理直接做模糊效果,或者使用现有的工具。UIImage+ImageEffects是个很好的图像处理库,看名字也知道是对UIImage做的分类扩展。这个工具被广泛地使用着。

 1 @import UIKit;
 2  
 3 @interface UIImage (ImageEffects)
 4  
 5 #pragma mark - Blur Image
 6  
 7 /**
 8  *  Get blured image.
 9  *
10  *  @return Blured image.
11  */
12 - (UIImage *)blurImage;
13  
14 /**
15  *  Get the blured image masked by another image.
16  *
17  *  @param maskImage Image used for mask.
18  *
19  *  @return the Blured image.
20  */
21 - (UIImage *)blurImageWithMask:(UIImage *)maskImage;
22  
23 /**
24  *  Get blured image and you can set the blur radius.
25  *
26  *  @param radius Blur radius.
27  *
28  *  @return Blured image.
29  */
30 - (UIImage *)blurImageWithRadius:(CGFloat)radius;
31  
32 /**
33  *  Get blured image at specified frame.
34  *
35  *  @param frame The specified frame that you use to blur.
36  *
37  *  @return Blured image.
38  */
39 - (UIImage *)blurImageAtFrame:(CGRect)frame;
40  
41 #pragma mark - Grayscale Image
42  
43 /**
44  *  Get grayScale image.
45  *
46  *  @return GrayScaled image.
47  */
48 - (UIImage *)grayScale;
49  
50 #pragma mark - Some Useful Method
51  
52 /**
53  *  Scale image with fixed width.
54  *
55  *  @param width The fixed width you give.
56  *
57  *  @return Scaled image.
58  */
59 - (UIImage *)scaleWithFixedWidth:(CGFloat)width;
60  
61 /**
62  *  Scale image with fixed height.
63  *
64  *  @param height The fixed height you give.
65  *
66  *  @return Scaled image.
67  */
68 - (UIImage *)scaleWithFixedHeight:(CGFloat)height;
69  
70 /**
71  *  Get the image average color.
72  *
73  *  @return Average color from the image.
74  */
75 - (UIColor *)averageColor;
76  
77 /**
78  *  Get cropped image at specified frame.
79  *
80  *  @param frame The specified frame that you use to crop.
81  *
82  *  @return Cropped image
83  */
84 - (UIImage *)croppedImageAtFrame:(CGRect)frame;
85  
86 @end
  1 #import "UIImage+ImageEffects.h"
  2 #import <float.h>
  3 @import Accelerate;
  4  
  5 @implementation UIImage (ImageEffects)
  6  
  7  
  8 - (UIImage *)applyLightEffect{
  9     
 10     UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
 11     return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
 12 }
 13  
 14  
 15 - (UIImage *)applyExtraLightEffect {
 16     
 17     UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
 18     return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
 19 }
 20  
 21  
 22 - (UIImage *)applyDarkEffect {
 23     
 24     UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
 25     return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
 26 }
 27  
 28  
 29 - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor {
 30     
 31     const CGFloat EffectColorAlpha = 0.6;
 32     UIColor      *effectColor      = tintColor;
 33     int           componentCount   = (int)CGColorGetNumberOfComponents(tintColor.CGColor);
 34     
 35     if (componentCount == 2) {
 36         
 37         CGFloat b;
 38         if ([tintColor getWhite:&b alpha:NULL]) {
 39             
 40             effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
 41         }
 42         
 43     } else {
 44         
 45         CGFloat r, g, b;
 46         if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
 47             
 48             effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
 49         }
 50     }
 51     
 52     return [self applyBlurWithRadius:20 tintColor:effectColor saturationDeltaFactor:1.4 maskImage:nil];
 53 }
 54  
 55 - (UIImage *)blurImage {
 56     
 57     return [self applyBlurWithRadius:20
 58                            tintColor:[UIColor colorWithWhite:0 alpha:0.0]
 59                saturationDeltaFactor:1.4
 60                            maskImage:nil];
 61 }
 62  
 63 - (UIImage *)blurImageWithRadius:(CGFloat)radius {
 64     
 65     return [self applyBlurWithRadius:radius
 66                            tintColor:[UIColor colorWithWhite:0 alpha:0.0]
 67                saturationDeltaFactor:1.4
 68                            maskImage:nil];
 69 }
 70  
 71 - (UIImage *)blurImageWithMask:(UIImage *)maskImage {
 72     
 73     return [self applyBlurWithRadius:20
 74                            tintColor:[UIColor colorWithWhite:0 alpha:0.0]
 75                saturationDeltaFactor:1.4
 76                            maskImage:maskImage];
 77 }
 78  
 79 - (UIImage *)blurImageAtFrame:(CGRect)frame {
 80     
 81     return [self applyBlurWithRadius:20
 82                            tintColor:[UIColor colorWithWhite:0 alpha:0.0]
 83                saturationDeltaFactor:1.4
 84                            maskImage:nil
 85                              atFrame:frame];
 86 }
 87  
 88 - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage {
 89     
 90     // Check pre-conditions.
 91     if (self.size.width < 1 || self.size.height < 1) {
 92         
 93         NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
 94         return nil;
 95     }
 96     
 97     if (!self.CGImage) {
 98         
 99         NSLog (@"*** error: image must be backed by a CGImage: %@", self);
100         return nil;
101     }
102     
103     if (maskImage && !maskImage.CGImage) {
104         
105         NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
106         return nil;
107     }
108  
109     CGRect   imageRect   = { CGPointZero, self.size };
110     UIImage *effectImage = self;
111     
112     BOOL hasBlur             = blurRadius > __FLT_EPSILON__;
113     BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
114     if (hasBlur || hasSaturationChange) {
115         
116         UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
117         CGContextRef effectInContext = UIGraphicsGetCurrentContext();
118         CGContextScaleCTM(effectInContext, 1.0, -1.0);
119         CGContextTranslateCTM(effectInContext, 0, -self.size.height);
120         CGContextDrawImage(effectInContext, imageRect, self.CGImage);
121  
122         vImage_Buffer effectInBuffer;
123         effectInBuffer.data     = CGBitmapContextGetData(effectInContext);
124         effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);
125         effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);
126         effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
127     
128         UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
129         CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
130         vImage_Buffer effectOutBuffer;
131         effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);
132         effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);
133         effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);
134         effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
135  
136         if (hasBlur) {
137             
138             // A description of how to compute the box kernel width from the Gaussian
139             // radius (aka standard deviation) appears in the SVG spec:
140             // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
141             // 
142             // For larger values of ‘s‘ (s >= 2.0), an approximation can be used: Three
143             // successive box-blurs build a piece-wise quadratic convolution kernel, which
144             // approximates the Gaussian kernel to within roughly 3%.
145             //
146             // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
147             // 
148             // ... if d is odd, use three box-blurs of size ‘d‘, centered on the output pixel.
149             // 
150             CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
151             NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
152             if (radius % 2 != 1) {
153                 
154                 radius += 1; // force radius to be odd so that the three box-blur methodology works.
155             }
156             
157             vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend);
158             vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend);
159             vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend);
160         }
161         
162         BOOL effectImageBuffersAreSwapped = NO;
163         if (hasSaturationChange) {
164             
165             CGFloat s = saturationDeltaFactor;
166             CGFloat floatingPointSaturationMatrix[] = {
167                 0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
168                 0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
169                 0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
170                                   0,                    0,                    0,  1,
171             };
172             const int32_t divisor = 256;
173             NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
174             int16_t saturationMatrix[matrixSize];
175             
176             for (NSUInteger i = 0; i < matrixSize; ++i) {
177                 
178                 saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
179             }
180             
181             if (hasBlur) {
182                 
183                 vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
184                 effectImageBuffersAreSwapped = YES;
185                 
186             } else {
187                 
188                 vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
189             }
190         }
191         
192         if (!effectImageBuffersAreSwapped) {
193             
194             effectImage = UIGraphicsGetImageFromCurrentImageContext();
195         }
196         
197         UIGraphicsEndImageContext();
198  
199         if (effectImageBuffersAreSwapped) {
200             
201             effectImage = UIGraphicsGetImageFromCurrentImageContext();
202         }
203         
204         UIGraphicsEndImageContext();
205     }
206  
207     // Set up output context.
208     UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
209     CGContextRef outputContext = UIGraphicsGetCurrentContext();
210     CGContextScaleCTM(outputContext, 1.0, -1.0);
211     CGContextTranslateCTM(outputContext, 0, -self.size.height);
212  
213     // Draw base image.
214     CGContextDrawImage(outputContext, imageRect, self.CGImage);
215  
216     // Draw effect image.
217     if (hasBlur) {
218         
219         CGContextSaveGState(outputContext);
220         
221         if (maskImage) {
222             
223             CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
224         }
225         
226         CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
227         CGContextRestoreGState(outputContext);
228     }
229  
230     // Add in color tint.
231     if (tintColor) {
232         
233         CGContextSaveGState(outputContext);
234         CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
235         CGContextFillRect(outputContext, imageRect);
236         CGContextRestoreGState(outputContext);
237     }
238  
239     // Output image is ready.
240     UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
241     UIGraphicsEndImageContext();
242  
243     return outputImage;
244 }
245  
246 - (UIImage *)grayScale {
247     
248     int width  = self.size.width;
249     int height = self.size.height;
250     
251     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
252     
253     CGContextRef context = CGBitmapContextCreate(nil,
254                                                  width,
255                                                  height,
256                                                  8, // bits per component
257                                                  0,
258                                                  colorSpace,
259                                                  kCGBitmapByteOrderDefault);
260     
261     CGColorSpaceRelease(colorSpace);
262     
263     if (context == NULL) {
264         
265         return nil;
266     }
267     
268     CGContextDrawImage(context,
269                        CGRectMake(0, 0, width, height), self.CGImage);
270     CGImageRef image   = CGBitmapContextCreateImage(context);
271     UIImage *grayImage = [UIImage imageWithCGImage:image];
272     CFRelease(image);
273     CGContextRelease(context);
274     
275     return grayImage;
276 }
277  
278 - (UIImage *)scaleWithFixedWidth:(CGFloat)width {
279     
280     float newHeight = self.size.height * (width / self.size.width);
281     CGSize size     = CGSizeMake(width, newHeight);
282     UIGraphicsBeginImageContextWithOptions(size, NO, 0);
283     
284     CGContextRef context = UIGraphicsGetCurrentContext();
285     
286     CGContextTranslateCTM(context, 0.0, size.height);
287     CGContextScaleCTM(context, 1.0, -1.0);
288     
289     CGContextSetBlendMode(context, kCGBlendModeCopy);
290     CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);
291     
292     UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
293     
294     UIGraphicsEndImageContext();
295     
296     return imageOut;
297 }
298  
299 - (UIImage *)scaleWithFixedHeight:(CGFloat)height {
300     
301     float newWidth = self.size.width * (height / self.size.height);
302     CGSize size    = CGSizeMake(newWidth, height);
303     
304     UIGraphicsBeginImageContextWithOptions(size, NO, 0);
305     
306     CGContextRef context = UIGraphicsGetCurrentContext();
307     
308     CGContextTranslateCTM(context, 0.0, size.height);
309     CGContextScaleCTM(context, 1.0, -1.0);
310     
311     CGContextSetBlendMode(context, kCGBlendModeCopy);
312     CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);
313     
314     UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
315     
316     UIGraphicsEndImageContext();
317     
318     return imageOut;
319 }
320  
321 - (UIColor *)averageColor {
322     
323     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
324     unsigned char rgba[4];
325     CGContextRef context = CGBitmapContextCreate(rgba, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
326     
327     CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), self.CGImage);
328     CGColorSpaceRelease(colorSpace);
329     CGContextRelease(context);
330     
331     if(rgba[3] > 0) {
332         CGFloat alpha = ((CGFloat)rgba[3])/255.0;
333         CGFloat multiplier = alpha/255.0;
334         return [UIColor colorWithRed:((CGFloat)rgba[0])*multiplier
335                                green:((CGFloat)rgba[1])*multiplier
336                                 blue:((CGFloat)rgba[2])*multiplier
337                                alpha:alpha];
338     }
339     else {
340         return [UIColor colorWithRed:((CGFloat)rgba[0])/255.0
341                                green:((CGFloat)rgba[1])/255.0
342                                 blue:((CGFloat)rgba[2])/255.0
343                                alpha:((CGFloat)rgba[3])/255.0];
344     }
345 }
346  
347 - (UIImage *)croppedImageAtFrame:(CGRect)frame {
348     
349     frame = CGRectMake(frame.origin.x * self.scale,
350                        frame.origin.y * self.scale,
351                        frame.size.width * self.scale,
352                        frame.size.height * self.scale);
353     
354     CGImageRef sourceImageRef = [self CGImage];
355     CGImageRef newImageRef    = CGImageCreateWithImageInRect(sourceImageRef, frame);
356     UIImage   *newImage       = [UIImage imageWithCGImage:newImageRef scale:[self scale] orientation:[self imageOrientation]];
357     CGImageRelease(newImageRef);
358     return newImage;
359 }
360  
361 - (UIImage *)addImageToImage:(UIImage *)img atRect:(CGRect)cropRect {
362     
363     CGSize size = CGSizeMake(self.size.width, self.size.height);
364     UIGraphicsBeginImageContextWithOptions(size, NO, self.scale);
365     
366     CGPoint pointImg1 = CGPointMake(0,0);
367     [self drawAtPoint:pointImg1];
368     
369     CGPoint pointImg2 = cropRect.origin;
370     [img drawAtPoint: pointImg2];
371     
372     UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
373     UIGraphicsEndImageContext();
374     
375     return result;
376 }
377  
378 - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius
379                        tintColor:(UIColor *)tintColor
380            saturationDeltaFactor:(CGFloat)saturationDeltaFactor
381                        maskImage:(UIImage *)maskImage
382                          atFrame:(CGRect)frame
383 {
384     UIImage *blurredFrame = 385     [[self croppedImageAtFrame:frame] applyBlurWithRadius:blurRadius
386                                                 tintColor:tintColor
387                                     saturationDeltaFactor:saturationDeltaFactor
388                                                 maskImage:maskImage];
389     
390     return [self addImageToImage:blurredFrame atRect:frame];
391 }
392  
393 @end

使用方法很简单,如下所示:

 1 - (void)test2 {
 2     //原始图片
 3     UIImage *originImage = [UIImage imageNamed:@"bg1.jpg"];
 4     //整体模糊
 5     UIImage *newImage1 = [originImage blurImage];
 6     //局部模糊
 7     UIImage *newImage2 = [originImage blurImageAtFrame:CGRectMake(0, 100, 320, 200)];
 8     //设置模糊半径
 9     UIImage *newImage3 = [originImage blurImageWithRadius:10.f];
10 }

三、GPUImage

GPUImage框架如何导入,我之前的文章有说过了(戳我)。

使用起来也是很简单的:

 1 - (void)test3 {
 2     //创建滤镜
 3     GPUImageGaussianBlurFilter *filter = [[GPUImageGaussianBlurFilter alloc] init];
 4     //设置模糊半径
 5     filter.blurRadiusInPixels = 10.f;
 6     //原始图片
 7     UIImage *image = [UIImage imageNamed:@"bg1.jpg"];
 8     //模糊后的图片
 9     UIImage *newImage = [filter imageByFilteringImage:image];
10 }

四、UIVisualEffectView

注意:这个只能在ios8以上才能使用,并且可以动态的模糊哟~

效果图:

技术分享

- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化scrollView
    self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
    UIImageView *imgView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bg1.jpg"]];
    [self.scrollVi

以上是关于IOS中模糊效果实现的几种方法(毛玻璃)(转载)的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发探索-高斯模糊&毛玻璃效果

iOS 8 模糊视图(毛玻璃效果)的简单实现UIVisualEffectView

转css3实现ios7“毛玻璃”模糊效果

iOS 高斯模糊 毛玻璃效果

移动端UI设计越来越流行的高斯模糊(Gaussian blur)和毛玻璃效果(磨砂效果),如何使用Android RenderScript简单实现?

iOS View 模糊效果(毛玻璃)