亮度調(diào)節(jié)有兩種實現(xiàn)方式:一種方式是非線性亮度調(diào)節(jié),一種是線性亮度調(diào)節(jié).
1,非線性亮度調(diào)節(jié)(GPUImageBrightnessFilter)
它的實現(xiàn)非常簡單,即對圖像的RGB通道,每個通道增加相同的增量.
GPUImageBrightnessFilter就是使用這種方法.
這種方法的優(yōu)點:代碼簡單,亮度調(diào)整速度快.
缺點是:圖片信息損失比較大,調(diào)整過的圖像平淡,無層次感.
NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp float brightness;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
//通過調(diào)節(jié)uniform類型的brightness[-1.0,1.0]參數(shù)對rgb非線性調(diào)節(jié)亮度
gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);
}
);
2,線性亮度調(diào)節(jié)(GPUImageHSBFilter)
采用的HSL工業(yè)顏色標準,代表色相(Hue),飽和度(Saturation),明度(Lightness)三個通道的顏色,每個通道用0~255的數(shù)值表示.這種調(diào)節(jié)是通過對色相/飽和度/明度三個顏色通道的變化以及相互之間的疊加來得到各種顏色.
GPUImageHSBFilter使用的就是這種方法.
線性亮度調(diào)節(jié)就是先將RGB表示的圖像轉(zhuǎn)換為HSL的顏色空間,然后對L通道進行調(diào)節(jié),得到新的L值,再與HS通道合并為新的HSL,最終轉(zhuǎn)換為RGB得到新的圖像.
這種方法的優(yōu)點是:調(diào)節(jié)過的圖像層次感很強;
缺點是:代碼復(fù)雜,調(diào)節(jié)速度慢,而且當亮度增減量較大時圖像有較大失真.
GPUImageHSBFilter 繼承自GPUImageColorMatrixFilter, GPUImageHSBFilter中并沒有專有的fragmentShader,根據(jù)用戶對HSB的調(diào)整,計算出對應(yīng)的colorMatrix,有興趣的可以去研究GPUImageHSBFilter中的轉(zhuǎn)換算法
NSString *const kGPUImageColorMatrixFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp mat4 colorMatrix;
uniform lowp float intensity;
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
lowp vec4 outputColor = textureColor * colorMatrix;
//intensity代表了原始與修改后的顏色強度,其實就是一個合成用的系數(shù)
gl_FragColor = (intensity * outputColor) + ((1.0 - intensity) * textureColor);
}
);
3,飽和度調(diào)節(jié)
飽和度是用來表示顏色的鮮艷程度.
圖像飽和度調(diào)節(jié)有很多總方法,最簡單的方法就是判斷每個像素的R.G.B值是否大于128,若大于,則加上調(diào)節(jié)值,小于則減去調(diào)節(jié)值;
也可將像素RGB轉(zhuǎn)換為HSV,然后調(diào)整其S部分,從而達到線性調(diào)節(jié)圖像飽和度的目的,這種方法就是使用GPUImageHSBFilter濾鏡來調(diào)節(jié).
GPUImageSaturationFilter使用的是第一種方法.通過RGB計算出本像素點的亮度值,計算公式如下:
luminance = 0.2125 * R + 0.7154 * G + 0.0721 * B(人的眼球?qū)G色最敏感,所以對綠色取的百分比最大,紅色次之)
然后設(shè)計一個可以調(diào)節(jié)飽和度大小的參數(shù)saturation,取值范圍[0.0,2.0],默認為1.0,代表輸出圖像就是輸入圖像,像素不做任何變化.如果取值為0.0,則代表灰度圖;若值為2.0,則代表飽和度最大.
output = (1.0 - saturation) * vec3(luminance) + saturation * vec3(R,G,B)
因為飽和度代表了色彩的純度,所以增加飽和度時,首先要對RGB都乘以大于1.0的系數(shù),然后減去一個亮度值,防止其亮度不一致.反之,降低飽和度原理一樣.
NSString *const kGPUImageSaturationFragmentShaderString = SHADER_STRING
(
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp float saturation;
// Values from "Graphics Shaders: Theory and Practice" by Bailey and Cunningham
const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
// dot() 向量點乘函數(shù)
lowp float luminance = dot(textureColor.rgb, luminanceWeighting);
lowp vec3 greyScaleColor = vec3(luminance);
//mix()線性混合函數(shù)
gl_FragColor = vec4(mix(greyScaleColor, textureColor.rgb, saturation), textureColor.w);
}
);