我试图复制苹果公开发布的iOS 7示例屏幕上的模糊背景:

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

做一些粗略的测试,截取以下视图的截图,并应用CIGaussianBlur过滤器,使用足够大的半径来模拟iOS 7的模糊风格,即使在模拟器上也需要1-2秒。 iOS 7的模糊视图能够模糊动态视图,比如视频或动画,没有明显的延迟。

有没有人可以假设他们可以使用什么框架来创建这种效果,以及是否有可能使用当前的公共api创建类似的效果?

编辑:(来自评论)我们不知道苹果是怎么做的,但我们能做出一些基本的假设吗?我们可以假设他们在使用硬件,对吧?

效果是否在每个视图中都是自包含的,以至于效果实际上不知道它背后是什么?或者,基于模糊的工作原理,模糊背后的内容必须被考虑进去?

如果效果背后的内容是相关的,我们是否可以假设苹果正在接收以下内容的“feed”,并不断地以模糊的方式渲染它们?


当前回答

Apple released code at WWDC as a category on UIImage that includes this functionality, if you have a developer account you can grab the UIImage category (and the rest of the sample code) by going to this link: https://developer.apple.com/wwdc/schedule/ and browsing for section 226 and clicking on details. I haven't played around with it yet but I think the effect will be a lot slower on iOS 6, there are some enhancements to iOS 7 that make grabbing the initial screen shot that is used as input to the blur a lot faster.

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

其他回答

Apple released code at WWDC as a category on UIImage that includes this functionality, if you have a developer account you can grab the UIImage category (and the rest of the sample code) by going to this link: https://developer.apple.com/wwdc/schedule/ and browsing for section 226 and clicking on details. I haven't played around with it yet but I think the effect will be a lot slower on iOS 6, there are some enhancements to iOS 7 that make grabbing the initial screen shot that is used as input to the blur a lot faster.

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

您可以尝试使用我的自定义视图,它具有模糊背景的功能。它通过假装拍摄背景快照并模糊它来做到这一点,就像苹果的WWDC代码中那样。使用起来很简单。

我还做了一些改进,在不损失性能的情况下伪造动态模糊。我的视图的背景是一个scrollView,它与视图一起滚动,从而为父视图的其余部分提供了模糊效果。

请参阅我的GitHub上的示例和代码

事实上,我敢打赌这很容易实现。它的运作方式或外观可能不会完全像苹果,但可能非常接近。

首先,你需要确定你要呈现的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 Category,你会得到一个高斯模糊,看起来很像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,现在剩下的就是将这个模糊的图像设置为你将呈现的视图的背景。就像我说的,这将不是一个完美的匹配苹果正在做的,但它仍然看起来很酷。

希望能有所帮助。

这里有一个非常简单的方法:https://github.com/JagCesar/iOS-blur

只要复制UIToolbar的图层就完成了,AMBlurView为你做了。 好吧,它没有控制中心那么模糊,但已经足够模糊了。

记住,iOS7是保密协议。

这里的每个响应都使用vImageBoxConvolve_ARGB8888,这个函数真的非常非常慢,如果性能不是一个高优先级的要求,这是很好的,但如果你使用这个在两个视图控制器之间转换(例如),这种方法意味着时间超过1秒或更多,这对你的应用程序的用户体验是非常糟糕的。

如果你更喜欢把所有的图像处理都留给GPU(你应该),你可以得到更好的效果,也可以得到50毫秒的惊人时间(假设你在第一个方法中有1秒的时间),所以,让我们这样做吧。

首先下载GPUImage框架(BSD许可)。

接下来,添加以下类(。m和.h)从gpu图像(我不确定这些是最低需要的模糊效果)

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 opengl

是的,这种更快的方法很有趣;)