使用GPUImage重现iOS 7玻璃效果

10 浏览
0 Comments

使用GPUImage重现iOS 7玻璃效果

我正在尝试使用iOS 7风格的玻璃效果,通过对MKMapView的屏幕截图应用图像效果来实现。这是苹果提供的一种基准方法,它将源图像去色,应用色调,并使用输入值进行模糊处理:

[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上需要0.3到0.5秒的渲染时间。

enter image description here

我想使用出色的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];

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

enter image description here

模糊度似乎不够深,但是当我尝试增加blurSize时,它变得像一个万花筒一样的网格状。通过放大第二张图片,你实际上可以看到这个网格。我尝试模仿的色调似乎只是将图像冲淡,而不是叠加和混合,这是我认为苹果示例所做的。

我尝试按照@BradLarson在另一个SO问题中的评论设置滤镜。我是在使用错误的GPUImage滤镜来复现这个效果,还是我设置有问题?

0
0 Comments

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

问题的出现原因:

以前在框架中使用的模糊效果是使用预先计算的半径,而影响模糊效果的唯一方法是调整采样像素时的间距。当每个像素有限的采样次数时,将采样像素之间的间距的倍数改变超过1.5,就会引入严重的阻塞伪影。

解决方法:

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

新的GPUImageiOSBlurFilter将这种调整了任意半径的高斯模糊滤镜与调整了模糊后的颜色的颜色校正滤镜相结合,看起来能够复制苹果在模糊后对颜色进行的调整。下面的对比图显示了苹果控制中心视图左侧的内置模糊效果,右侧是我新的GPUImage模糊滤镜:

Apple's blur GPUImage's blur

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

正确地实现模糊只是其中一件事。苹果仍然没有提供一种快速获取视图后面图像内容的方法,所以这很可能成为快速更改内容的瓶颈。

所以我切换到了GPUImageiOSBlurFilter,这为我提供了更快的渲染。我不用它进行实时模糊处理,但我需要用它来对图像进行模糊处理,以在UITableViewCell中显示,速度很快。谢谢!

Brad,请你更新GPUImage的pod specs吗?旧的0.1.1 specs中没有GPUImageiOSBlurFilter。谢谢!

- 我猜你是指CocoaPods吗?我没有维护那里的任何内容,也没有使用CocoaPods,所以由负责的人指向存储库中的最新版本。我只维护GitHub存储库。如果你想要最新的代码,我建议直接从GitHub拉取。

嗨Brad。我想知道模糊始终具有浅色背景的原因是什么?即使在模糊黑色图像时,我最终也得到了灰色的颜色。

- 我试图模仿Apple在控制中心模糊中所做的事情(我上面提到的“颜色校正滤镜”)。他们不仅仅模糊,还似乎减少了亮度的动态范围,以防止背景洗出文本或放置在模糊视图上的控件。我不能保证在所有情况下都能与他们的颜色调整匹配,但它似乎与我尝试过的几个测试背景相符。

这似乎是有道理的,我注意到他们在使用他们在WWDC上提供的UIImage+Effects类时也会做同样的事情,只是想知道是否可以在不变亮图像的情况下实现这种效果。

- 嗯,你只需要去除最后的颜色校正步骤(将GPUImageLuminanceRangeFilter替换为GPUImageFilter中的透传GPUImageFilter),就能得到单独的模糊效果。GPUImageiOSBlurFilter并没有太多的内容,所以很容易克隆并以这种方式进行修改。我甚至可以将模糊的降/升采样移入主要的高斯模糊类中,使它更简单。

所以我考虑更新这个类,添加一个BOOL属性来控制是否有霜化效果(是否关闭),如果我提交一个拉取请求,你会有兴趣合并吗?

- 我可以考虑将这个作为一个选项,用透传来替换最后一步的颜色校正滤镜。如果在滤镜构建之后进行此切换,可能需要检查一两件事情,强制处理规模放大,但这并不难做到。

是的,移除GPUImageLuminanceRangeFilter确实降低了输出图像的质量,所以我不得不将降采样从4降低到2。我现在已经更新了我的本地副本 - 仍在决定使用哪种效果,但这个选项很好。但我会让你进一步研究并根据你的意愿更新这个类 🙂

关于pod spec的问题 - CocoaPods不需要更新任何内容。kyr-dunenkoff遇到的问题是在你的GitHub存储库中,最新的发布标签是v0.1.1,其中没有iOS 7模糊滤镜。你在存储库中的pod spec指向了那个版本。当你在GitHub上创建一个v0.1.2标签,并更新pod spec指向它时,一切都会好起来的。在此期间,kyr-dunenkoff可以更新pod文件,只需基于HEAD获取即可。

0