模糊屏幕与iOS 7的快照API

我相信NDA已经下降了,所以我可以问这个问题。 我有一个UIView子类:

BlurView *blurredView = ((BlurView *)[self.view snapshotViewAfterScreenUpdates:NO]); blurredView.frame = self.view.frame; [self.view addSubview:blurredView]; 

到目前为止,它在捕获屏幕方面的工作,但现在我想模糊这个观点。 我究竟如何去做呢? 从我读过的东西中,我需要捕获视图的当前内容(上下文?!),并将其转换为CIImage(否),然后将CIGaussianBlur应用于视图并将其拖回视图。

我到底怎么做?

PS视图不是animation,所以它应该是性能明智的。

编辑:这是我迄今为止。 问题是我无法捕捉快照到UIImage,我得到一个黑屏。 但是,如果我直接添加视图作为子视图,我可以看到快照在那里。

 // Snapshot UIView *view = [self.view snapshotViewAfterScreenUpdates:NO]; // Convert to UIImage UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0); [view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); // Apply the UIImage to a UIImageView BlurView *blurredView = [[BlurView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; [self.view addSubview:blurredView]; blurredView.imageView.image = img; // Black screen -.- 

BlurView.m:

 - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code self.imageView = [[UIImageView alloc] init]; self.imageView.frame = CGRectMake(20, 20, 200, 200); [self addSubview:self.imageView]; } return self; } 

来自WWDC的示例代码ios_uiimageeffects

有一个名为UIImage+ImageEffectsUIImage类别

这是它的API:

 - (UIImage *)applyLightEffect; - (UIImage *)applyExtraLightEffect; - (UIImage *)applyDarkEffect; - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor; - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage; 

由于法律上的原因,我不能在这里展示实现,这里有一个演示项目。 应该很容易开始。

这个问题的一半没有得到答案,所以我认为值得补充。

UIScreen的问题

 - (UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates 

和UIView的

 - (UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets 

难道你不能从他们那里得到一个UIImage – “黑屏”的问题。

在iOS7中,Apple提供了第三个用于提取UIImages的API,这是UIView上的一个方法

 - (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates 

它不如snapshotView ,但与renderInContext相比并不差(在Apple提供的例子中,它比renderInContextrenderInContext ,比snapshotView慢三倍)

使用示例:

  UIGraphicsBeginImageContextWithOptions(image.size, NULL, 0); [view drawViewHierarchyInRect:rect]; UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

然后得到一个模糊的版本

  UIImage* lightImage = [newImage applyLightEffect]; 

其中applyLightEffect是被接受的答案中提到的苹果的UIImage+ImageEffects类别中的那些模糊类别方法之一(在接受的答案中UIImage+ImageEffects这个代码示例的链接不起作用,但是这一个会让你到正确的页面 :文件你想要的是iOS_UIImageEffects )。

主要参考WWDC2013会话226, 在iOS上实现使用UI

顺便说一句,在苹果的参考文档renderInContext暗示黑屏问题有一个有趣的笔记..

重要提示:此方法的OS X v10.5实现不支持整个Core Animation组合模型。 不呈现QCCompositionLayer,CAOpenGLLayer和QTMovieLayer图层。 此外,不使用3D变换的图层,也不绘制指定backgroundFilters,filters,compositingFilter或蒙版值的图层。 未来版本的OS X可能会添加对渲染这些图层和属性的支持。

这个笔记从10.5开始没有更新,所以我猜“未来的版本”可能还有一段时间了,我们可以添加新的CASnapshotLayer (或其他)到列表中。

总结如何使用代工厂的示例代码执行此操作,请使用以下代码:

我想模糊整个屏幕只是为了我的目的,所以我会使用主屏幕边界。

 CGRect screenCaptureRect = [UIScreen mainScreen].bounds; UIView *viewWhereYouWantToScreenCapture = [[UIApplication sharedApplication] keyWindow]; //screen capture code UIGraphicsBeginImageContextWithOptions(screenCaptureRect.size, NO, [UIScreen mainScreen].scale); [viewWhereYouWantToScreenCapture drawViewHierarchyInRect:screenCaptureRect afterScreenUpdates:NO]; UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //blur code UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0]; UIImage *blurredImage = [capturedImage applyBlurWithRadius:1.5 tintColor:tintColor saturationDeltaFactor:1.2 maskImage:nil]; //or use [capturedImage applyLightAffect] but I thought that was too much for me //use blurredImage in whatever way you so desire! 

屏幕截图部分的注释

UIGraphicsBeginImageContextWithOptions()第二个参数是不透明的。 它应该是NO除非你除了1之外没有任何alpha 。 如果您返回yes屏幕截图不会查看透明度值,所以它会更快,但可能是错误的。

UIGraphicsBeginImageContextWithOptions()第三个参数是比例。 可能要像我那样放置在设备的规模,以确定和区分视网膜和非视网膜。 但我没有真正testing这个,我认为0.0f也可以。

drawViewHierarchyInRect:afterScreenUpdates:注意你为屏幕更新返回BOOL 。 我试图在背景之前这样做,如果我没有把NO放到前台,那么应用程序会发生故障。 如果你不离开应用程序,你也许可以脱离YES

注意模糊

我在这里有一个非常轻的模糊。 更改blurRadius将使其变得模糊,并且可以更改色调颜色和alpha以制作各种其他效果。

你也需要添加模糊方法的类别工作…

如何添加UIImage + ImageEffects类别

您需要下载类别UIImage + ImageEffects模糊工作。 login后在此处下载: https : //developer.apple.com/downloads/index.action?name=WWDC%202013

search“UIImageEffects”,你会发现它。 只需拿出2个必要的文件,并将其添加到您的项目。 UIImage + ImageEffects.h和UIImage + ImageEffects.m。

此外,我必须在我的构build设置中启用模块,因为我有一个项目,而不是与xCode 5创build。要做到这一点去你的目标生成设置和search“模块”,并确保“启用模块”和“链接框架自动“都设置为是,否则您将有新类别的编译器错误。

祝你好运模糊!

检查WWDC 2013示例应用程序“快速运行”。

模糊是作为一个类别实现的。