iOS应用中实现图片滤镜的一个简单方法
23 Jan 2015iOS应用中实现图片滤镜的一个简单方法
最近做的一个项目要用到图片滤镜,我对于OpenGL
和图形图片处理完全是外行。当然,在iOS上做图片处理绕不开的两个框架GPUImage
和苹果自家的Core Image
。根据以前的项目经验 GPUImage
因为内存还有其他一些问题,一直高居崩溃排行榜的榜首。但是Core Image
在没有技术积累的情况下我又没有把握在一周之内写出一个框架可以叫产品和UI同学自由调整滤镜效果。偶然中发现了 GPUImage
中的一个滤镜 GPUImageLookupFilter
。简直是神器,对于码农的工作量来说 瞬间降到0,分分钟搞定,然后将效果调试的任务丢给产品和UI就可以了。
滤镜的原理
首先我们了解一下关于图片滤镜的基本知识,也就是应该怎么实现一个图片滤镜。
整个滤镜的计算过程一般可以拆解成几个步骤。
1. 在原图上做一对一的像素彩色转换。
对于RGB
的颜色通道调整都是独立的,不会相互影响。
由于这个方法可以表述成
[0, 255] -> [0, 255]
的映射数组, 那么使用255个不同灰度的全灰图片很简单的就把instagram的图片滤镜功能了解清楚了.记下所有计算结果.
如果你只是想看到一个大概的结果, 这个解码过程可以这样用一张图简化
2. 暗脚风格的Mask。通常只需要设计师生成一张带暗角的透明PNG 然后和图片合成在一起。
合成的方式有很多种 [ Insight into Photoshop 7.0 Blending Modes ] 这片文章中有详细的介绍。所有的合成方式
GPUImage
基本上都实现了。
3. 还有就是材质和相框,使用方法和给图片添加暗脚是一样的。
GPUImageLookupFilter
的使用
GPUImageLookupFilter
通过一个颜色映射表来实现颜色转换。这种查表法的原理就是在一张表中为每种颜色纪录一个对应的映射目标的颜色。当用查表法对一张照片做颜色映射时,只需要遍历照片的每个像素点,然后在表中找到该像素颜色对应的目标颜色,最后将该像素设置为目标颜色即可。查表法实现的前提是颜色的映射与周围的颜色无关,即一种颜色无论周围的颜色为何、无论其位于照片的哪个位置,其目标颜色都应该是相同的。
RGB
的颜色数量表示为255*255*2555 = 16777216
如果要记录每种颜色的映射结果,那么需要一千六百多万条记录,这显然无法应用到实际的工程中。为了简化起见,一般每相近的 4 种颜色采用一条记录存储,这样颜色表只需要 64*64*64 = 262144
条记录。
这是一张基准颜色表。设计师或产品经理在
PS
中调整好的效果可能是这样的一组Action
将这些调整应用到基准颜色表上就得到了一张映射表。
上表将 262144 种颜色分为 8 个块,每块
64*64
格,每一格的颜色都不同。进行颜色映射时,首先使用数字图像处理软件对该基准颜色表应用要模拟的滤镜来生成映射表(如下图),然后对要处理的照片的每个像素,从基准颜色表中找到该像素颜色的位置,然后在映射表的相应位置就可以得到目的颜色。
暗角的添加
暗角我没有使用PNG素材而是使用了GPUImage
中的另外一个滤镜 GPUImageVignetteFilter
Demo Code
1 -(UIImage *)lookkupImageFilterWithFilterName:(NSString *)filterName originImage:(UIImage *)originImage{
2
3 GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithImage:originImage];
4 GPUImagePicture *lookupImageSource = [[GPUImagePicture alloc] initWithImage:[UIImage imageNamed:filterName]];
5 GPUImageLookupFilter *lookupFilter = [[GPUImageLookupFilter alloc] init];
6
7 [stillImageSource addTarget:lookupFilter];
8 [lookupImageSource addTarget:lookupFilter];
9 if (self.hasVignetteEffect) {
10 [lookupFilter useNextFrameForImageCapture];
11 GPUImageVignetteFilter *vignettefilter = [[GPUImageVignetteFilter alloc] init];
12 vignettefilter.vignetteEnd = kAlohaImageVignetteEnd;
13 vignettefilter.vignetteStart = kAlohaImageVignetteStart;
14
15 [lookupFilter addTarget:vignettefilter];
16 [stillImageSource processImage];
17 [lookupImageSource processImage];
18 [vignettefilter useNextFrameForImageCapture];
19 UIImage *filteredimage = [vignettefilter imageFromCurrentFramebuffer];
20 return filteredimage;
21 } else {
22 [stillImageSource processImage];
23 [lookupImageSource processImage];
24 [lookupFilter useNextFrameForImageCapture];
25 UIImage *filteredimage = [lookupFilter imageFromCurrentFramebuffer];
26 return filteredimage;
27 }
28 }
参考
Add Instagram-like effects to your iOS app. Insight into Photoshop 7.0 Blending Modes Instagram 是用什么语言编写的?为什么它的图片滤镜效果那么出众? GPUImage