使用GPUImage重新创建iOS 7玻璃效果

12

我正在尝试通过将图像效果应用于 MKMapView 的截图来在我的玻璃中使用iOS 7风格的玻璃效果。这是苹果提供的UIImage类别,是我使用的基准。该方法会使源图像变得无色,应用着色和模糊,并使用输入值进行大量模糊处理:

[image applyBlurWithRadius:10.0
                 tintColor:[UIColor colorWithRed:229/255.0f green:246/255.0f blue:255/255.0f alpha:0.33] 
     saturationDeltaFactor:0.66
                 maskImage:nil];

这产生了我想要的效果,但太慢了——在 iPhone 4上渲染需要 .3.5 秒。

输入图像描述

我想使用优秀的GPUImage,因为我的初步尝试大约快了 5-10 倍,但我似乎做不对。

GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:image];

GPUImageSaturationFilter *saturationFilter = [[GPUImageSaturationFilter alloc] init];
saturationFilter.saturation = 0.33; // 1.0 - 0.66;
[stillImageSource addTarget:saturationFilter];

GPUImageMonochromeFilter *monochromeFilter = [[GPUImageMonochromeFilter alloc] init];
[monochromeFilter setColor:(GPUVector4){229/255.0f, 246/255.0f, 1.0f, 0.33f}];
[monochromeFilter setIntensity:0.2];
[saturationFilter addTarget:monochromeFilter];

GPUImageFastBlurFilter *blurFilter = [[GPUImageFastBlurFilter alloc] init];
blurFilter.blurSize = 2;
blurFilter.blurPasses = 3;
[monochromeFilter addTarget:blurFilter];

[saturationFilter prepareForImageCapture];
[monochromeFilter prepareForImageCapture];

[stillImageSource processImage];
image = [blurFilter imageFromCurrentlyProcessedOutput];

这会生成一张接近但不完全相同的图片。

在此输入图片描述

模糊似乎不够深,但当我尝试将blurSize增加时,它变得像网格一样,几乎像万花筒。你可以通过放大第二幅图像来看到这个网格。我试图模仿的色调似乎只是把图像冲淡了,而不是像苹果的例子中那样叠加和融合。

我已经按照@BradLarson在另一个SO问题中的评论设置了滤镜。我是在错误地使用GPUImage滤镜以重现这种效果,还是只是设置它们时出了问题?


你试过 https://github.com/JagCesar/iOS-blur 吗?虽然它只在iOS7下工作,但非常棒。 - Tomas Camin
iOS-Blur不是一个可行的解决方案。你不知道苹果在幕后做了什么来使其工作,而且它在iOS 6上无法工作。 - coneybeare
1个回答

32

好的,我已经花了一些时间在这方面的工作上,最终实现了它。我刚刚将许多关于GPUImage模糊滤镜的更改整合到框架中,并且因此,我相信我已经制作出了一个类似于苹果在控制中心视图等场景使用的模糊效果的合理副本。

以前,我在框架中使用的模糊只使用一个预先计算的半径,并且影响它们的强度的唯一方法是调整它们从输入图像采样像素的间距。由于每个像素的采样数有限,将采样像素之间的间距的倍数大于1.5的情况开始引入严重的块状伪影。

我构建的新的高斯模糊实现将预先计算的高斯权重的性能优势与可以为高斯模糊使用任意半径(sigma)的能力相结合。它通过在需要不同半径的着色器时动态生成来实现这一点。它还通过使用硬件插值同时对每个样本点读取两个纹理元素来减少给定模糊半径所需的纹理采样数量。

新的GPUImageiOSBlurFilter将这个调整后的任意半径高斯模糊滤镜与一个颜色校正滤镜结合起来,该滤镜似乎复制了苹果对颜色进行模糊后的调整。我在我的答案这里添加了下面的比较,但它显示了左侧的控制中心视图中内置的苹果模糊和右侧的新的GPUImage模糊滤镜:

Apple's blur GPUImage's blur

作为提高性能的一种方式(苹果模糊似乎具有48的sigma值,每个像素需要采样相当大的区域),在高斯模糊之前使用4倍下采样,然后在之后使用4倍上采样。这将需要模糊的像素数量减少了16倍,并且将模糊sigma从48降低到12。使用此滤镜,iPhone 4S可以在大约30毫秒内模糊整个屏幕。

调整模糊效果是一回事。但苹果仍然没有提供一种快速获取视图背后图片内容的方法,所以这很可能会成为你快速变化内容的瓶颈。


1
所以我已经切换到GPUImageiOSBlurFilter,这使得我的渲染速度更快。我不用它进行实时模糊,但我需要它来模糊图像以在UITableViewCell中显示,因此必须快速和稳定。谢谢! - runmad
Brad,请你更新GPUImage的pod specs吗?旧的0.1.1规范中没有包含GPUImageiOSBlurFilter。谢谢! - Kyr Dunenkoff
@KyrDunenkoff - 我猜你是在提到CocoaPods吧?我并没有维护那里的任何东西,甚至自己也不使用CocoaPods,所以由负责人指向存储库中的最新构建。我只维护GitHub存储库。如果您想要最新的代码,我建议直接从GitHub拉取。 - Brad Larson
1
@BradLarson 嗨 Brad。我想知道为什么模糊处理总是有浅色背景?即使是对黑色图像进行模糊处理,最终也会得到灰色调的颜色。 - runmad
1
@runmad - 好的,你需要做的就是删除最后的颜色校正步骤(将GPUImageLuminanceRangeFilter与GPUImageiOSBlurFilter内部的passthrough GPUImageFilter交换),以获得模糊效果。GPUImageiOSBlurFilter并不复杂,因此很容易克隆和修改。我甚至可能会将模糊的下/上采样移动到主高斯模糊类中,使其更加简单。 - Brad Larson
显示剩余6条评论

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