GPUImage 自定義濾鏡
(轉載地址)http://www.itiger.me/?p=143
GPUImage 是一個基于 GPU 圖像和視頻處理的開源 iOS 框架。由于使用 GPU 來處理圖像和視頻,所以速度非臣舴担快,它的作者 BradLarson 稱在 iPhone4 上其處理速度是使用 CPU 來處理的 100 倍 (CoreImage 也能使用 GPU 來處理圖像,但我覺得 CoreImage 還是慢)妥粟。除了速度上的優(yōu)勢,GPUImage 還提供了很多很棒的圖像處理濾鏡赋访,但有時候這些基本功能仍然無法滿足實際開發(fā)中的需求碟狞,不用擔心 GPUImage 支持自定義濾鏡啄枕。
GPUImage 自定義濾鏡需要使用 OpenGL 著色語言( GLSL )編寫 Fragment Shader(片段著色器),除此之外你可能還需要一點點圖像處理相關的知識族沃。下面我將嘗試通過 GPUImage 中的 GPUImageColorInvertFilter(反色濾鏡)來講解一下它的運作過程频祝。
先看.h 文件:
#import "GPUImageFilter.h"
@interface GPUImageColorInvertFilter : GPUImageFilter
{
}
@end
很簡單泌参,可以看出 GPUImageColorInvertFilter 是繼承了 GPUImageFilter
然后看 .m 文件 中 @implementation 之前的一段代碼
NSString *const kGPUImageInvertFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4((1.0 - textureColor.rgb), textureColor.a);
}
);
第 1 行,可以看到 SHADER_STRING
宏中包含著我們的 Shader (著色器)代碼常空,我們的著色器字符串賦給一個 const NSString 對象(這個常量將在 GPUImageFilter 及其子類的初始化過程中用來設置 filter)沽一。
第 2、3 行聲明了兩個變量漓糙。
varying
變量是Vertex 和 Fragment Shader(頂點著色器和片段著色器)之間做數(shù)據(jù)傳遞用的铣缠,一般 Vertex Shader(頂點著色器) 修改 varying 變量的值,然后 Fragment Shader(片段著色器)使用該varying變量的值昆禽。因此varying 變量在 Vertex 和 Fragment Shader 中聲明必須一致蝗蛙。放到這里,也就是說 textureCoordinate
必須叫這個名字不能改醉鳖。
highp
聲明 textureCoordinate
精度(相應的還有mediump
和lowp
)捡硅。
vec2
聲明textureCoordinate
是一個二維向量。
uniform
聲明 inputImageTexture
是外部程序傳遞給 Shader 的變量盗棵, Shader 程序內部只能用壮韭,不能改。 sampler2D
聲明變量是一個2D紋理纹因。
第 4 行喷屋,相信你并不陌生,沒錯兒 Shader 也是從 main() 函數(shù)開始執(zhí)行的瞭恰。
第 5 行屯曹,texture2D
紋理取樣器,根據(jù)紋理坐標返回紋理單元的值寄疏。
第 6 行是牢,(1.0 - textureColor.rgb)
去 textureColor
也就是原圖的 RGB 值僵井,做了一個向量的減法陕截,這是圖像的反色算法,然后把經(jīng)過反色的 RGB 值和原圖的 Alpha 值組成一個新的 vec4(四維向量)值賦給 gl_FragColor
批什。 gl_FragColor
是 Fragment Shader 預先定義的變量农曲,賦給它的值就是該片段最終的顏色值。
Shader 到這里已經(jīng)解釋完了驻债,可能你依然云里霧里乳规,我來說一下我對這部分功能的理解,可能不對合呐,但目前是管用的暮的,方便你理解:GPUImage 中應該有一個 Vertex Shader(頂點著色器),它對圖像逐個像素掃描淌实,通過 textureCoordinate
變量將當前的掃描頂點坐標傳遞給我們的 Fragment Shader冻辩,inputImageTexture
包含我們要處理的圖像的全部信息猖腕,在 Shader 程序內部通過 texture2D
得到 inputImageTexture
在當前位置 textureCoordinate
的 RGBA 值,運用圖像處理知識恨闪,算出想要的新的 RGBA 值倘感,把結果值賦給 gl_FragColor
就算完成了。
現(xiàn)在我們繼續(xù)看代碼咙咽,在 Shader 之后是 GPUImageColorInvertFilter 的實現(xiàn):
@implementation GPUImageColorInvertFilter
- (id)init;
{
if (!(self = [super initWithFragmentShaderFromString:kGPUImageInvertFragmentShaderString]))
{
return nil;
}
return self;
}
@end
很簡單老玛,就是使用剛才的著色器代碼來設置 filter。這樣一個新的濾鏡就誕生了~
網(wǎng)絡上關于 GPUImage 自定義濾鏡 和 GLSL 的資料不是特別多钧敞,我斗膽把自己摸索到的理解在這里和你分享蜡豹,希望對你有所幫助,如有錯誤指出歡迎指出溉苛,另外余素,可以去這里查閱 OpenGL GLSL 文檔,玩的愉快炊昆!
對于textureCoordinate桨吊,我的理解是在默認的頂點著色器中已經(jīng)命名過了,所以在片段著色器中才使用這個凤巨。它表示紋理尺寸视乐,用來計算頂點坐標的,并傳遞給片段著色器使用敢茁。不知對不對佑淀。
GPUImageColorInvertFilter(反色濾鏡), 顏色取反,拿1減下彰檬;如黑色變白伸刃,白變黑......