如何制作类似iOS 7模糊视图的效果?

219

我正在尝试复制苹果公开发布的iOS 7示例屏幕中的模糊背景:

iOS 7 Control Center screenshot

这个问题建议对下面的内容应用CI滤镜,但这是一种完全不同的方法。显然,iOS 7没有捕获下面视图的内容,原因有很多:

  1. 进行一些粗略的测试,捕获下面视图的屏幕截图并应用足够大的CIGaussianBlur滤镜来模拟iOS 7的模糊样式需要1-2秒,即使在模拟器上也是如此。
  2. iOS 7的模糊视图可以在动态视图(例如视频或动画)上进行模糊处理,而且没有明显的延迟。

有人能假设他们可能使用哪些框架来创建这种效果,并且是否可以使用当前公共API创建类似的效果吗?

编辑:(来自评论)我们不确切知道苹果是如何做到的,但是我们可以做出一些基本假设吗?我们可以假设他们正在使用硬件,是吗?

该效果是否包含在每个视图中,以使效果实际上不知道其背后的内容?或必须根据模糊处理的工作方式考虑模糊处理后面的内容?

如果效果后面的内容相关,我们可以假设Apple正在接收下方内容的“馈送”并不断使用模糊渲染它们吗?


我认为苹果公司正在使用纯GL来渲染主屏幕。我怀疑他们是否会使用UIView等抽象层来降低性能,因为这是操作系统的关键部分。 - Dave
正如我在这里的答案评论中所指出的:https://dev59.com/kWQn5IYBdhLWcg3wLkkd#17048668 他们编写了操作系统,因此当然可以加速访问当前视图下面组合层的内容。我们可以在私有IOSurface API中看到他们可能正在使用的一些内容:https://dev59.com/vWzXa4cB1Zd3GeqPXL8_ 。如果高斯模糊具有固定半径,甚至使用像积分图像这样的有趣优化,那么它们可以比广义高斯模糊情况快得多。 - Brad Larson
@BradLarson - 转述一下杰西卡·辛普森的话...我不知道所有这些意味着什么,但听起来很酷!但是说真的,你是在说可以使用部分透明的视图和模糊滤镜将其覆盖在另一个视图上以实现这种效果吗? - sangony
https://dev59.com/x2Qn5IYBdhLWcg3wLkgd#25706250 对我来说第一次尝试就完美地运行了,并且非常简洁。 - Ben Wheeler
12个回答

134

为什么要费力复制效果?只需在您的视图后面绘制一个UIToolbar。

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];

8
我不同意crizzwald的观点。我认为这并不是对于Apple预期行动规则的一个好解释。 - Andrew Johnson
118
本周我在苹果技术交流实验室向一位Apple UIKit 工程师咨询了这种做法。虽然他肯定不会认可这种方式,但他承认需要这种效果,而且也没有真正的公共API可以使用,他说这种方法是目前最小毒瘤的选择,并且按此书写是相当安全的。具体来说,他说不要尝试对工具栏/视图的frame或者transform执行任何动画,否则会出现问题。他还强烈建议就此提出Radar错误报告,以内部构建案例并获得真正的公共API以实现该效果! - smileyborg
44
有趣...看起来账号 @user2342340 是专门为匿名回答这个问题而创建的。让你想知道是否这不是某个比我们更了解这些事情的人发布的非官方帖子 :) - smileyborg
4
在运行iOS 7的iPhone 4上,这并不起作用。这可能是因为在iPhone 4上,由于GPU功率过低,系统没有向其UITabBar添加通常的模糊效果。 - Ayush Goel
2
如何使它不是白色的?如果我更改工具栏的背景颜色,它就不会显示模糊。 - Nikita P
显示剩余6条评论

64

苹果在WWDC上发布了一个UIImage类别的代码,其中包括此功能。如果您拥有开发人员帐户,可以通过访问此链接获取UIImage类别(以及其余示例代码):https://developer.apple.com/wwdc/schedule/,然后浏览第226节并单击详情。我还没有尝试过它,但我认为在iOS6上该效果会慢很多,iOS7有一些增强功能能够更快地抓取作为输入到模糊中所使用的初始屏幕截图。

直接链接:https://developer.apple.com/downloads/download.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip


1
我看到了视频,可以观看,但是找不到下载示例代码的地方! - Nathan H
与简单的背景透明度变化相比,我没有看到太大的区别;也许是因为我正在显示视频,它们只需要更多的模糊效果... - Ja͢ck

37

实际上,我敢打赌这应该是相当容易实现的。它可能不会像苹果那样操作或外观完全一样,但可以非常接近。

首先,您需要确定将要呈现的UIView的CGRect。一旦您确定了,您只需要获取UI的部分图像,以便可以进行模糊处理。例如:

- (UIImage*)getBlurredImage {
    // You will want to calculate this in code based on the view you will be presenting.
    CGSize size = CGSizeMake(200,200);

    UIGraphicsBeginImageContext(size);
    [view drawViewHierarchyInRect:(CGRect){CGPointZero, w, h} afterScreenUpdates:YES]; // view is the view you are grabbing the screen shot of. The view that is to be blurred.
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // Gaussian Blur
    image = [image applyLightEffect];

    // Box Blur
    // image = [image boxblurImageWithBlur:0.2f];

    return image;
}

高斯模糊 - 推荐使用

使用苹果提供的UIImage+ImageEffects类别,下载链接在这里,您将获得一个看起来非常像iOS 7中的模糊的高斯模糊。

方框模糊

您也可以使用以下boxBlurImageWithBlur: UIImage类别进行方框模糊。这是基于一种算法,您可以在这里找到。

@implementation UIImage (Blur)

-(UIImage *)boxblurImageWithBlur:(CGFloat)blur {
    if (blur < 0.f || blur > 1.f) {
        blur = 0.5f;
    }
    int boxSize = (int)(blur * 50);
    boxSize = boxSize - (boxSize % 2) + 1;

    CGImageRef img = self.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);

    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);

    if (error) {
        NSLog(@"JFDepthView: error from convolution %ld", error);
    }

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
                                         outBuffer.width,
                                         outBuffer.height,
                                         8,
                                         outBuffer.rowBytes,
                                         colorSpace,
                                         kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];

    //clean up
    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);

    free(pixelBuffer);
    CFRelease(inBitmapData);

    CGImageRelease(imageRef);

    return returnImage;
}

@end

现在,您正在计算要模糊的屏幕区域,将其传递到模糊类别中,并接收到一张已经模糊的UIImage图片返回。现在唯一剩下的就是将该模糊图像设置为您将要呈现的视图的背景。就像我说的那样,这不会完全匹配苹果所做的,但它应该看起来相当酷。

希望能对您有所帮助。


看起来模糊图像的蓝色和红色颜色被交换了。 - Henry
看起来有人使用了你的代码创建了这个项目:https://github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/Classes/UIImage%2BBoxBlur.m,但不幸的是,没有署名,并且他们在顶部添加了一个“保留所有权利”的版权声明。 - Mark Erdmann
@Mark,谢谢你提醒我。然而,这个模糊算法不是我自己的。我在我的帖子中已经提到了我从哪里得到它。正如我的帖子中所说:“这是基于一个算法,你可以在这里找到。”并附有链接http://indieambitions.com/idevblogaday/perform-blur-vimage-accelerate-framework-tutorial/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3a%20IndieAmbitions%20%28Indie%20Ambitions%29 我一定会给这个人发一条消息,让他们知道他们缺少归属。谢谢。 - Jeremy Fox
@MarkErdmann,请查看您在Xcode中的文件。它有“保留所有权利”。这是Xcode添加的通用内容。此外,作者还添加了一个license.md文件,说明其已获得MIT许可证授权。 - Andrew
不要使用renderInContext,而是使用新的drawViewHierarchyInRect:snapshotView:。WWDC演讲216“在iOS7上实现引人入胜的用户界面”声称有5-15倍的性能提升。 - bcattle
@bcattle 谢谢,我已经编辑了答案并添加了 drawViewHierarchyInRect:afterScreenUpdates: - Jeremy Fox

24

iOS8回答了这些问题。

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

或者Swift:

init(effect effect: UIVisualEffect)


我猜在iOS 9发布之前,这个解决方案基本上是无用的。大多数应用程序仍然支持iOS 7,而此解决方案不支持它。 - Dmitry Sobolev
没错,你现在可以使用这个东西:https://github.com/nicklockwood/FXBlurView - Adam Waite
我使用Xcode 6工具链和iOS8实现了这个功能,效果非常好。我尝试使用CPU实现,但是与这种方法相比明显运行速度较慢。 - Jon
为什么要编写代码,当Xcode已经在Storyboard中提供了所有功能!感谢@AdamWaite - Mihir Oza

20

我刚刚编写了一个UIView的子类,它可以在任何自定义视图上实现本机iOS 7模糊效果。它使用UIToolbar以一种安全的方式来更改其框架、边界、颜色和透明度,并具有实时动画。

如果您注意到任何问题,请告诉我。

https://github.com/ivoleko/ILTranslucentView

ILTranslucentView examples


我尝试了其他一些方法(比如自己添加UIToolbar,或者使用苹果的UIImage+ImageEffects.h类别);你的解决方案是最好和最简单的。谢谢! - Yunus Nedim Mehel
4
它对新的 iOS 7.0.3 下载的兼容性如何?使用此技术的其他分类不再正确呈现 :[ - esreli
@achi,我没有注意到iOS 7.0.3存在任何问题。 - Ivo Leko
你知道是否有任何使用你的方法进行动画并被苹果接受的应用程序吗? - Brad G
大家好。是的,使用这个类的应用将会被苹果批准! - Ivo Leko

10

有传言称,苹果工程师声称为了使其性能更好,他们正在直接从GPU缓冲区中读取数据,这会引起安全问题,这就是为什么目前没有公开的API可以实现这一功能。


6
如果这是真的,那么那绝对是有史以来最糟糕的解决方案。 - cutsoy
2
iOS 7中的模糊效果已经被移除。 - Code Guru
3
只有在性能出现问题的设备上才会移除它。 - Cody C
24
这篇帖子是谣言的源头吗? :) - Jano
11
那个传闻很可能是无稽之谈。在iOS上,OpenGL ES 2.0可以让你读取和写入帧缓存而不会有任何安全风险。模糊效果是使用GLSL着色器实现的,这也是为什么它运行得很快的原因。 - bentford

7
这是一个解决方案,你可以在WWDC的视频中看到。首先,你需要进行高斯模糊处理,所以你需要添加一个新的.m和.h文件,其中包含我写在下面的代码。然后你需要截屏,并使用所需的效果将其添加到你的视图中。接着,你的UITable UIView或其他控件必须透明,你可以根据需要调整applyBlurWithRadius,以实现所需的效果。这个调用适用于任何UIImage。
最终,模糊的图片将成为背景,上面的所有控件都必须透明。
为了使它工作,你需要添加以下库:
Acelerate.framework、UIKit.framework和CoreGraphics.framework。
希望你喜欢它。
祝你编程愉快。
    //Screen capture.
    UIGraphicsBeginImageContext(self.view.bounds.size);

    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(c, 0, 0);
    [self.view.layer renderInContext:c];

    UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext();
    viewImage = [viewImage applyLightEffect];

    UIGraphicsEndImageContext();

    //.h FILE
    #import <UIKit/UIKit.h>

    @interface UIImage (ImageEffects)

   - (UIImage *)applyLightEffect;
   - (UIImage *)applyExtraLightEffect;
   - (UIImage *)applyDarkEffect;
   - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;

   - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;

   @end

    //.m FILE
    #import "cGaussianEffect.h"
    #import <Accelerate/Accelerate.h>
    #import <float.h>


     @implementation UIImage (ImageEffects)


    - (UIImage *)applyLightEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyExtraLightEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyDarkEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
    {
        const CGFloat EffectColorAlpha = 0.6;
        UIColor *effectColor = tintColor;
        int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
        if (componentCount == 2) {
            CGFloat b;
            if ([tintColor getWhite:&b alpha:NULL]) {
                effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
            }
        }
        else {
            CGFloat r, g, b;
            if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
                effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
            }
        }
        return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
    }


    - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
    {
        if (self.size.width < 1 || self.size.height < 1) {
            NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
            return nil;
        }
        if (!self.CGImage) {
            NSLog (@"*** error: image must be backed by a CGImage: %@", self);
            return nil;
        }
        if (maskImage && !maskImage.CGImage) {
            NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
            return nil;
        }

        CGRect imageRect = { CGPointZero, self.size };
        UIImage *effectImage = self;

        BOOL hasBlur = blurRadius > __FLT_EPSILON__;
        BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
        if (hasBlur || hasSaturationChange) {
            UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
            CGContextRef effectInContext = UIGraphicsGetCurrentContext();
            CGContextScaleCTM(effectInContext, 1.0, -1.0);
            CGContextTranslateCTM(effectInContext, 0, -self.size.height);
            CGContextDrawImage(effectInContext, imageRect, self.CGImage);

            vImage_Buffer effectInBuffer;
            effectInBuffer.data     = CGBitmapContextGetData(effectInContext);
            effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);
            effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);
            effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);

            UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
            CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
            vImage_Buffer effectOutBuffer;
            effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);
            effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);
            effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);
            effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);

            if (hasBlur) {
                CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
                NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
                if (radius % 2 != 1) {
                    radius += 1;
                }
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
                vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
            }
            BOOL effectImageBuffersAreSwapped = NO;
            if (hasSaturationChange) {
                CGFloat s = saturationDeltaFactor;
                CGFloat floatingPointSaturationMatrix[] = {
                    0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
                    0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
                    0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
                                  0,                    0,                    0,  1,
                };
                const int32_t divisor = 256;
                NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
                int16_t saturationMatrix[matrixSize];
                for (NSUInteger i = 0; i < matrixSize; ++i) {
                    saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
                }
                if (hasBlur) {
                    vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
                    effectImageBuffersAreSwapped = YES;
                }
                else {
                    vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
                }
            }
            if (!effectImageBuffersAreSwapped)
                effectImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            if (effectImageBuffersAreSwapped)
                effectImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        }

        UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
        CGContextRef outputContext = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(outputContext, 1.0, -1.0);
        CGContextTranslateCTM(outputContext, 0, -self.size.height);

        CGContextDrawImage(outputContext, imageRect, self.CGImage);

        if (hasBlur) {
            CGContextSaveGState(outputContext);
            if (maskImage) {
                CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
            }
            CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
            CGContextRestoreGState(outputContext);
        }

        if (tintColor) {
            CGContextSaveGState(outputContext);
            CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
            CGContextFillRect(outputContext, imageRect);
            CGContextRestoreGState(outputContext);
        }

        UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return outputImage;
    }

7
您可以从此页面中的苹果DEMO找到解决方案: WWDC 2013,查找并下载UIImageEffects示例代码。
然后使用@Jeremy Fox的代码,我对其进行了修改。
- (UIImage*)getDarkBlurredImageWithTargetView:(UIView *)targetView
{
    CGSize size = targetView.frame.size;

    UIGraphicsBeginImageContext(size);
    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(c, 0, 0);
    [targetView.layer renderInContext:c]; // view is the view you are grabbing the screen shot of. The view that is to be blurred.
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return [image applyDarkEffect];
}

希望这能对你有所帮助。


7
这是一种非常简单的方法:https://github.com/JagCesar/iOS-blur。只需复制UIToolbar层,AMBlurView会为您处理。好吧,它没有控制中心那么模糊,但已经足够模糊了。 请注意,iOS7受NDA保护。

6
每个响应都使用 vImageBoxConvolve_ARGB8888 函数,这个函数非常慢,如果性能不是高优先级要求,那么这没问题,但如果您在两个视图控制器之间进行过渡(例如),这种方法意味着超过1秒或更长时间,这对您的应用程序用户体验非常不好。
如果您喜欢将所有图像处理交给GPU(而且您应该这样做),您可以获得更好的效果,也可以获得约50ms左右的时间(假设第一种方法需要1秒的时间),所以让我们开始吧。
首先下载 GPUImage 框架(BSD 许可证)here
接下来,从 GPUImage 添加以下类(.m 和 .h)(我不确定这些是否仅适用于模糊效果)。
  • GPUImage.h
  • GPUImageAlphaBlendFilter
  • GPUImageFilter
  • GPUImageFilterGroup
  • GPUImageGaussianBlurPositionFilter
  • GPUImageGaussianSelectiveBlurFilter
  • GPUImageLuminanceRangeFilter
  • GPUImageOutput
  • GPUImageTwoInputFilter
  • GLProgram
  • GPUImageBoxBlurFilter
  • GPUImageGaussianBlurFilter
  • GPUImageiOSBlurFilter
  • GPUImageSaturationFilter
  • GPUImageSolidColorGenerator
  • GPUImageTwoPassFilter
  • GPUImageTwoPassTextureSamplingFilter

  • iOS/GPUImage-Prefix.pch

  • iOS/GPUImageContext
  • iOS/GPUImageMovieWriter
  • iOS/GPUImagePicture
  • iOS/GPUImageView

接下来,在UIImage上创建一个分类,将模糊效果添加到现有的UIImage中:

#import "UIImage+Utils.h"

#import "GPUImagePicture.h"
#import "GPUImageSolidColorGenerator.h"
#import "GPUImageAlphaBlendFilter.h"
#import "GPUImageBoxBlurFilter.h"

@implementation UIImage (Utils)

- (UIImage*) GPUBlurredImage
{
    GPUImagePicture *source =[[GPUImagePicture alloc] initWithImage:self];

    CGSize size = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale);

    GPUImageBoxBlurFilter *blur = [[GPUImageBoxBlurFilter alloc] init];
    [blur setBlurRadiusInPixels:4.0f];
    [blur setBlurPasses:2.0f];
    [blur forceProcessingAtSize:size];
    [source addTarget:blur];

    GPUImageSolidColorGenerator * white = [[GPUImageSolidColorGenerator alloc] init];

    [white setColorRed:1.0f green:1.0f blue:1.0f alpha:0.1f];
    [white forceProcessingAtSize:size];

    GPUImageAlphaBlendFilter * blend = [[GPUImageAlphaBlendFilter alloc] init];
    blend.mix = 0.9f;

    [blur addTarget:blend];
    [white addTarget:blend];

    [blend forceProcessingAtSize:size];
    [source processImage];

    return [blend imageFromCurrentlyProcessedOutput];
}

@end

最后,将以下框架添加到您的项目中:

AVFoundation CoreMedia CoreVideo OpenGLES

是的,享受这种更快的方法吧 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接