iOS 7'的模糊屏幕;s快照API

iOS 7'的模糊屏幕;s快照API,ios,objective-c,ios7,Ios,Objective C,Ios7,我相信保密协议已经失效了,所以我可以问这个问题。我有一个UIView子类: BlurView *blurredView = ((BlurView *)[self.view snapshotViewAfterScreenUpdates:NO]); blurredView.frame = self.view.frame; [self.view addSubview:blurredView]; 到目前为止,它在捕捉屏幕方面做了自己的工作,但现在我想模糊这个视图。我该怎么做呢?根据我所读到的内容,我需

我相信保密协议已经失效了,所以我可以问这个问题。我有一个UIView子类:

BlurView *blurredView = ((BlurView *)[self.view snapshotViewAfterScreenUpdates:NO]);
blurredView.frame = self.view.frame;
[self.view addSubview:blurredView];
到目前为止,它在捕捉屏幕方面做了自己的工作,但现在我想模糊这个视图。我该怎么做呢?根据我所读到的内容,我需要捕获视图的当前内容(上下文?!),并将其转换为CIImage(否?),然后对其应用CIGaussianBlur并将其绘制回视图

我该怎么做呢

另外,该视图未设置动画,因此在性能方面应该是正常的

编辑:这是我到目前为止的资料。问题是我无法将快照捕获到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 2013示例应用程序“使用快照运行”

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

来自WWDC的示例代码

有一个名为
UIImage+ImageEffects

以下是它的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中,苹果提供了第三个用于提取uiimage的API,这是UIView上的一种方法

- (BOOL)drawViewHierarchyInRect:(CGRect)rect 
             afterScreenUpdates:(BOOL)afterUpdates  
它的速度不如
snapshotView
,但与
RenderContext
相比还不错(在Apple提供的示例中,它比
RenderContext
快五倍,比
snapshotView
慢三倍)

示例用法:

 UIGraphicsBeginImageContextWithOptions(image.size, NULL, 0);
 [view drawViewHierarchyInRect:rect];
 UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
 UIGraphicsEndImageContext();  
然后得到一个模糊的版本

 UIImage* lightImage = [newImage applyLightEffect];  
其中,
applyLightEffect
是公认答案中提到的苹果
UIImage+ImageEffects
类别中的模糊分类方法之一(公认答案中指向此代码示例的诱人链接不起作用,但:您想要的文件是
iOS\u UIImageEffects

主要参考WWDC2013第226次会议,在iOS上实现引人入胜的UI

顺便说一句,苹果的参考文档中有一个有趣的注释,提示了黑屏问题

重要提示:此方法的OS X v10.5实现不支持整个核心动画合成模型。不渲染QCCompositionLayer、CAOPENGLayer和QTMovieLayer层。此外,不会渲染使用三维变换的层,也不会渲染指定背景过滤器、过滤器、合成过滤器或遮罩值的层。未来版本的OS X可能会添加对渲染这些层和属性的支持


注释自10.5版以来一直没有更新,因此我想“未来版本”可能还需要一段时间,我们可以将新的
CASnapshotLayer
(或其他)添加到列表中。

要总结如何使用foundry的示例代码,请使用以下内容:

我想稍微模糊整个屏幕,因此出于我的目的,我将使用主屏幕边界

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()
2参数为不透明。它应该是
NO
,除非您除了
1
之外没有任何
alpha
。如果返回yes,屏幕截图将不会查看透明度值,因此速度会更快,但可能会出错


UIGraphicsBeginImageContextWithOptions()
3个参数是刻度。我可能想像我一样把设备的刻度放进去,以确定和区分视网膜和非视网膜。但是我还没有真正测试过这个,我认为
0.0f
也可以

drawViewHierarchyInRect:AfterScreen更新:
注意屏幕更新返回的内容
BOOL
。我在背景设置之前就尝试过这样做,如果我不把
NO
放进去,当我回到前台时,应用程序会因为小故障而发疯。如果你不离开这个应用程序,你也许可以逃脱
是的

关于模糊的注意事项

我这里有一个非常模糊的地方。更改“模糊半径”(blurRadius)将使其更加模糊,您可以更改着色颜色和alpha以生成各种其他效果

此外,您还需要添加一个类别,使模糊方法能够工作

如何添加UIImage+ImageEffects类别

您需要下载UIImage+ImageEffects类别才能使模糊生效。登录后在此处下载:

搜索“UIImageEffects”,您将找到它。只需取出2个必要的文件并将它们添加到项目中。UIImage+ImageEffects.h和UIImage+ImageEffects.m

另外,我必须在构建设置中启用模块,因为我有一个项目不是用xCode 5创建的。要执行此操作,请转到您的目标构建设置并搜索“模块”,并确保“启用模块”和“自动链接框架”都设置为“是”,否则新类别将出现编译器错误


祝你好运

WWDC2013示例代码中有一个UIImageView类别。我签出了它,但它使用资产中的图像作为源,而我需要使用快照。我搞不懂,这只回答了我一半的问题。我仍然需要得到一个UIImage来应用这些效果,这个方法会给我一个黑色的图像:如果你只想要这个图像,就不需要快照API。只需在
self.view
上直接渲染图像,那么如果我不抓拍屏幕,从哪里获得图像呢?
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size,self.view.不透明,0.0)
然后
[self.view.layer renderInContext:UIGraphicsGetCurrentContext]
@NikolayDyankov我认为这永远不会奏效。我认为这不起作用(黑屏)的原因是snap返回的视图