创建模糊叠加视图

本文翻译自:Creating a blurring overlay view

In the Music app of the new iOS, we can see an album cover behind a view that blurs it. 在新iOS的音乐应用程序中,我们可以看到一个模糊背后的专辑封面。

How can something like that be accomplished? 如何才能完成这样的事情? I've read the documentation, but did not find anything there. 我已经阅读了文档,但没有找到任何内容。


#1楼

参考:https://stackoom.com/question/19VJd/创建模糊叠加视图


#2楼

Core Image 核心形象

Since that image in the screenshot is static, you could use CIGaussianBlur from Core Image (requires iOS 6). 由于屏幕截图中的图像是静态的,因此您可以使用Core Image中的CIGaussianBlur (需要iOS 6)。 Here is sample: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m 以下是示例: https//github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Mind you, this is slower than the other options on this page. 请注意,这比此页面上的其他选项慢。

#import <QuartzCore/QuartzCore.h>

- (UIImage*) blur:(UIImage*)theImage
{   
    // ***********If you need re-orienting (e.g. trying to blur a photo taken from the device camera front facing camera in portrait mode)
    // theImage = [self reOrientIfNeeded:theImage];

    // create our blurred image
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *inputImage = [CIImage imageWithCGImage:theImage.CGImage];

    // setting up Gaussian Blur (we could use one of many filters offered by Core Image)
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:inputImage forKey:kCIInputImageKey];
    [filter setValue:[NSNumber numberWithFloat:15.0f] forKey:@"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    // CIGaussianBlur has a tendency to shrink the image a little, 
    // this ensures it matches up exactly to the bounds of our original image
    CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];

    UIImage *returnImage = [UIImage imageWithCGImage:cgImage];//create a UIImage for this function to "return" so that ARC can manage the memory of the blur... ARC can't manage CGImageRefs so we need to release it before this function "returns" and ends.
    CGImageRelease(cgImage);//release CGImageRef because ARC doesn't manage this on its own.

    return returnImage;

    // *************** if you need scaling
    // return [[self class] scaleIfNeeded:cgImage];
}

+(UIImage*) scaleIfNeeded:(CGImageRef)cgimg {
    bool isRetina = [[[UIDevice currentDevice] systemVersion] intValue] >= 4 && [[UIScreen mainScreen] scale] == 2.0;
    if (isRetina) {
        return [UIImage imageWithCGImage:cgimg scale:2.0 orientation:UIImageOrientationUp];
    } else {
        return [UIImage imageWithCGImage:cgimg];
    }
}

- (UIImage*) reOrientIfNeeded:(UIImage*)theImage{

    if (theImage.imageOrientation != UIImageOrientationUp) {

        CGAffineTransform reOrient = CGAffineTransformIdentity;
        switch (theImage.imageOrientation) {
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, M_PI);
                break;
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformRotate(reOrient, M_PI_2);
                break;
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, 0, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, -M_PI_2);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationUpMirrored:
                break;
        }

        switch (theImage.imageOrientation) {
            case UIImageOrientationUpMirrored:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.height, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationDown:
            case UIImageOrientationLeft:
            case UIImageOrientationRight:
                break;
        }

        CGContextRef myContext = CGBitmapContextCreate(NULL, theImage.size.width, theImage.size.height, CGImageGetBitsPerComponent(theImage.CGImage), 0, CGImageGetColorSpace(theImage.CGImage), CGImageGetBitmapInfo(theImage.CGImage));

        CGContextConcatCTM(myContext, reOrient);

        switch (theImage.imageOrientation) {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.height,theImage.size.width), theImage.CGImage);
                break;

            default:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.width,theImage.size.height), theImage.CGImage);
                break;
        }

        CGImageRef CGImg = CGBitmapContextCreateImage(myContext);
        theImage = [UIImage imageWithCGImage:CGImg];

        CGImageRelease(CGImg);
        CGContextRelease(myContext);
    }

    return theImage;
}

Stack blur (Box + Gaussian) 堆栈模糊(Box + Gaussian)

  • StackBlur This implements a mix of Box and Gaussian blur. StackBlur这实现了Box和高斯模糊的混合。 7x faster than non accelerated gaussian, but not so ugly as box blur. 比非加速高斯快7倍,但不像盒子模糊那么难看。 See a demo in here (Java plugin version) or here (JavaScript version). 请参阅此处的演示(Java插件版本)或此处 (JavaScript版本)。 This algorithm is used in KDE and Camera+ and others. 该算法用于KDE和Camera +等。 It doesn't use the Accelerate Framework but it's fast. 它不使用Accelerate Framework,但速度很快。

Accelerate Framework 加速框架

  • In the session “Implementing Engaging UI on iOS” from WWDC 2013 Apple explains how to create a blurred background (at 14:30), and mentions a method applyLightEffect implemented in the sample code using Accelerate.framework. WWDC 2013的 “在iOS上实现引导UI”会议中,Apple解释了如何创建模糊背景(在14:30),并提到了使用Accelerate.framework在示例代码中实现的方法applyLightEffect

  • GPUImage uses OpenGL shaders to create dynamic blurs. GPUImage使用OpenGL着色器来创建动态模糊。 It has several types of blur: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. 它有几种类型的模糊:GPUImageBoxBlurFilter,GPUImageFastBlurFilter,GaussianSelectiveBlur,GPUImageGaussianBlurFilter。 There is even a GPUImageiOSBlurFilter that “should fully replicate the blur effect provided by iOS 7's control panel” ( tweet , article ). 甚至还有一个GPUImageiOSBlurFilter“应该完全复制iOS 7控制面板提供的模糊效果”( 推文文章 )。 The article is detailed and informative. 这篇文章详细而且内容丰富。

-(UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(NSInteger)blur {
        GPUImageFastBlurFilter *blurFilter = [GPUImageFastBlurFilter new];
        blurFilter.blurSize = blur;
        UIImage *result = [blurFilter imageByFilteringImage:image];
        return result;
    }

Other stuff 其他的东西

Andy Matuschak said on Twitter: “you know, a lot of the places where it looks like we're doing it in real time, it's static with clever tricks.” Andy Matuschak在推特上 :“你知道,很多地方看起来我们都是在实时做这件事,但这很聪明,技巧娴熟。”

At doubleencore.com they say “we've found that a 10 pt blur radius plus a 10 pt increase in saturation best mimics iOS 7's blur effect under most circumstances”. doubleencore.com,他们说“我们发现在大多数情况下,10点的模糊半径加上10点的饱和度增加最能模仿iOS 7的模糊效果”。

A peek at the private headers of Apple's SBFProceduralWallpaperView . 看看Apple的SBFProceduralWallpaperView的私人标题。

Finally, this isn't a real blur, but remember you can set rasterizationScale to get a pixelated image: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/ 最后,这不是真正的模糊,但请记住,您可以设置rasterizationScale来获取像素化图像: http//www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/


#3楼

I don't think I'm allowed to post the code, but the above post mentioning the WWDC sample code is correct. 我不认为我可以发布代码,但上面提到WWDC示例代码的帖子是正确的。 Here is the link: https://developer.apple.com/downloads/index.action?name=WWDC%202013 这是链接: https//developer.apple.com/downloads/index.action?name = WWDC%202020

The file you're looking for is the category on UIImage, and the method is applyLightEffect. 您要查找的文件是UIImage上的类别,方法是applyLightEffect。

As I noted above in a comment, the Apple Blur has saturation and other things going on besides blur. 正如我在评论中所提到的,Apple Blur除了模糊之外还有饱和度和其他事情。 A simple blur will not do... if you are looking to emulate their style. 一个简单的模糊不会...如果你想模仿他们的风格。


#4楼

Found this by accident, gives me really great (near duplicate with Apple's) results and uses the Acceleration framework. 偶然发现这个,给了我非常好的(与Apple的重复)结果,并使用Acceleration框架。 -- http://pastebin.com/6cs6hsyQ *Not written by me - http://pastebin.com/6cs6hsyQ *不是我写的


#5楼

I think the easiest solution to this is to override UIToolbar, which blurs everything behind it in iOS 7. It's quite sneaky, but it's very simple for you to implement, and fast! 我认为最简单的解决方案是覆盖UIToolbar,它在iOS 7中模糊了它背后的一切。它非常狡猾,但它实现起来非常简单,而且速度快!

You can do it with any view, just make it a subclass of UIToolbar instead of UIView . 您可以使用任何视图执行此操作,只需将其UIToolbar的子类而不是UIView You can even do it with a UIViewController 's view property, for example... 您甚至可以使用UIViewControllerview属性来执行此操作,例如...

1) create a new class that is a "Subclass of" UIViewController and check the box for "With XIB for user interface". 1)创建一个新类,它是UIViewController的“子类”,并选中“With XIB for user interface”框。

2) Select the View and go to the identity inspector in the right-hand panel (alt-command-3). 2)选择View并转到右侧面板中的身份检查器(alt-command-3)。 Change the "Class" to UIToolbar . 将“Class”更改为UIToolbar Now go to the attributes inspector (alt-command-4) and change the "Background" color to "Clear Color". 现在转到属性检查器(alt-command-4)并将“背景”颜色更改为“清除颜色”。

3) Add a subview to the main view and hook it up to an IBOutlet in your interface. 3)将子视图添加到主视图并将其连接到界面中的IBOutlet。 Call it backgroundColorView . 称之为backgroundColorView It will look something like this, as a private category in the implementation ( .m ) file. 它看起来像这样,作为实现( .m )文件中的私有类。

@interface BlurExampleViewController ()
@property (weak, nonatomic) IBOutlet UIView *backgroundColorView;
@end

4) Go to the view controller implementation ( .m ) file and change the -viewDidLoad method, to look as follows: 4)转到视图控制器实现( .m )文件并更改-viewDidLoad方法,如下所示:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.barStyle = UIBarStyleBlack; // this will give a black blur as in the original post
    self.backgroundColorView.opaque = NO;
    self.backgroundColorView.alpha = 0.5;
    self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];
}

This will give you a dark gray view, which blurs everything behind it. 这会给你一个深灰色的视图,模糊背后的一切。 No funny business, no slow core image blurring, using everything that is at your fingertips provided by the OS/SDK. 没有有趣的业务,没有缓慢的核心图像模糊,使用OS / SDK提供的触手可及的一切。

You can add this view controller's view to another view, as follows: 您可以将此视图控制器的视图添加到另一个视图,如下所示:

[self addChildViewController:self.blurViewController];
[self.view addSubview:self.blurViewController.view];
[self.blurViewController didMoveToParentViewController:self];

// animate the self.blurViewController into view

Let me know if anything is unclear, I'll be happy to help! 如果有什么不清楚,请告诉我,我很乐意提供帮助!


Edit 编辑

UIToolbar has been changed in 7.0.3 to give possibly-undesirable effect when using a coloured blur. UIToolbar在7.0.3中已更改,在使用彩色模糊时可能会产生不良影响。

We used to be able to set the colour using barTintColor , but if you were doing this before, you will need to set the alpha component to less than 1. Otherwise your UIToolbar will be completely opaque colour - with no blur. 我们曾经能够使用barTintColor设置颜色,但如果您之前这样做,则需要将alpha组件设置为小于1.否则您的UIToolbar将是完全不透明的颜色 - 没有模糊。

This can be achieved as follows: (bearing in mind self is a subclass of UIToolbar ) 这可以通过以下方式实现:(记住selfUIToolbar的子类)

UIColor *color = [UIColor blueColor]; // for example
self.barTintColor = [color colorWithAlphaComponent:0.5];

This will give a blue-ish tint to the blurred view. 这将为模糊的视图提供蓝色色调。


#6楼

You can use UIVisualEffectView to achieve this effect. 您可以使用UIVisualEffectView来实现此效果。 This is a native API that has been fine-tuned for performance and great battery life, plus it's easy to implement. 这是一个本机API,经过微调,性能和电池寿命长,而且易于实现。

Swift: 迅速:

//only apply the blur if the user hasn't disabled transparency effects
if !UIAccessibility.isReduceTransparencyEnabled {
    view.backgroundColor = .clear

    let blurEffect = UIBlurEffect(style: .dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    //always fill the view
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    view.backgroundColor = .black
}

Objective-C: Objective-C的:

//only apply the blur if the user hasn't disabled transparency effects
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    self.view.backgroundColor = [UIColor clearColor];

    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    //always fill the view
    blurEffectView.frame = self.view.bounds;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:blurEffectView]; //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    self.view.backgroundColor = [UIColor blackColor];
}

If you are presenting this view controller modally to blur the underlying content, you'll need to set the modal presentation style to Over Current Context and set the background color to clear to ensure the underlying view controller will remain visible once this is presented overtop. 如果您以模态方式呈现此视图控制器以模糊基础内容,则需要将模式演示文稿样式设置为“当前上下文”并将背景颜色设置为“清除”以确保基础视图控制器在显示为超出时保持可见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值