基于固定基图像的图像混合操作:
针对图像各像素与常量值之间的混合操作
图像的基本属性。首先是亮度,也称灰度,它是大 家常说的YUV格式的Y分量,如果使用RGB表示图像,那么可采用前面 章节中提到的公式转换出亮度信息;其次是对比度(contrast),即画面黑与白的比值,也就是从黑到白的渐变层次,比值越大,说明从黑到白的渐变层次越多,色彩表现越丰富;最后是饱和度(saturation),是指 色彩的鲜艳程度,也称为色彩的纯度。
亮度调节
亮度调节有两种一种是线性调节, 一种是非线性调节
亮度值可视为颜色值中“非黑色”的数量。对于RGB颜色值,“浅色” 意味着颜色值分量接近于1.0,而“深色”则意味着颜色值分量接近于0.0。
1.非线性调节
顶点着色器
attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;
void main()
{
varyTextCoord = textCoordinate;
gl_Position = position;
}
片元着色器让每一个RGB颜色分量都加上相同的增量
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
/*
以纹素的方式填充纹理, shader会自动的根据纹理坐标去提取纹素来填充
colorMap 纹理
varyTextCoord 纹理坐标
*/
lowp vec4 temp = texture2D(colorMap, varyTextCoord);
//取值范围0-1, glsl不允许不同的类进行计算
float brightness = 0.5;
gl_FragColor = vec4(temp.r+brightness, temp.g+brightness, temp.b+brightness, temp.a);
}
brightness 可以使用attribute的方式当做参数, 这样可以动态修改
非线性调节结果, 结果感觉像是从外面加了一层蒙版一样的感觉, 不太自然
2.线性调节
为什么说线性调节会比较自然呢, 因为人眼并不会去区分RGB颜色分量占多少比例, 而是对明暗比较明暗, HSL就是通过色相(Hue)、饱和度 (Saturation)、明度(Lightness)三个通道的颜色,每个通道都可使用 0~255的数值来表示。这种调节是通过对色相、饱和度、明度三个颜色 通道的变化及其相互之间的叠加来得到各种颜色。符合人眼的直观感觉.
- 线性调节的顶点着色器和非线性调节的顶点着色器是一样
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
lowp vec4 color = texture2D(colorMap, varyTextCoord);
//这里的HSL是以0-255来表示的, 所以需要先把0-1范围的RGB值转为0-255
float r = color.r * 255.0;
float g = color.g * 255.0;
float b = color.b * 255.0;
//RGB最大值减去RGB最小值,除以2即为L
float L = ((max(r, max(g, b)) + min(r, min(g, b))) / 2.0);
float rHS = 0.0;
float gHS = 0.0;
float bHS = 0.0;
//
if(L > 128.0) {
rHS = (r * 128.0 - (L - 128.0) * 256.0) / (256.0 - L);
gHS = (g * 128.0 - (L - 128.0) * 256.0) / (256.0 - L);
bHS = (b * 128.0 - (L - 128.0) * 256.0) / (256.0 - L);
} else {
rHS = r * 128.0 / L;
gHS = g * 128.0 / L;
bHS = b * 128.0 / L;
}
// [0-255]
float delta = 50.0;
float newL = L + delta - 128.0;
float newR = .0;
float newG = .0;
float newB = .0;
if(newL > 0.0) {
newR = rHS + (256.0 - rHS) * newL / 128.0;
newG = gHS + (256.0 - gHS) * newL / 128.0;
newB = bHS + (256.0 - bHS) * newL / 128.0;
} else {
newR = rHS + rHS * newL / 128.0;
newG = gHS + gHS * newL / 128.0;
newB = bHS + bHS * newL / 128.0;
}
//这里的值RGB值根据delta值不同, 可能会大于1, 不过在OpenGL ES 中大于1的值会被处理成1, 也就是全部是白色的了.
gl_FragColor = vec4(newR/255.0, newG/255.0, newB/255.0, color.a);
}
看起来好像是比较自然, 从内部向外部出来的颜色.
- 前面提到过, 亮度值可视为颜色中非黑色的数量, 所以提升亮度可以通过减少图片展黑色的数量来做.
使用mix
函数来差值减少黑色数量, 如果ratio是0.0,它会返回第一个输入;如果是1.0,会返回第二个输入值。输入0.2则会返回80%的第一个输入颜色和20%的第二个输入颜色,即返回两个纹理的混合色。输入大与1的数, 则会提升图片亮度.
mix(colorA, colorB, ratio)
片元着色器
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
lowp vec4 color = texture2D(colorMap, varyTextCoord);
lowp vec3 rgb = color.rgb;
vec3 black = vec3(0.0, 0.0, 0.0);
float ut = 3.0;
vec3 mixColor = mix(black, rgb, ut);
gl_FragColor = vec4(mixColor, color.a);
}
black
定义一个黑色, 使用mix来差值计算黑色所占的比例, 下面是当ut值为3时的渲染结果.
同样也可以把
black
改成其他的颜色值, 来混和成不同的结果.
- 还有一种更简单的方式直接对RGBA执行一个相同的倍数值
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
vec4 sample0 = texture2D(colorMap, varyTextCoord);
gl_FragColor = sample0 * 1.5;
}
对比度调节
图像对比度描述了颜色值相对于灰度值的突出程度。当计算图像中的对比度时,可将50%的灰度图作为基图像
vec3(0.5, 0.5, 0.5)
在进行插值计算值, 原图所占的分量越大, 则灰度越少, 对比度越明显, 即ut小于1, 将个颜色分量越接近0.5, 降低图像对比度; 大于1将颜色分量远离0.5, 增加对比度;
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
lowp vec4 color = texture2D(colorMap, varyTextCoord);
lowp vec3 rgb = color.rgb;
//亮度
// vec3 target = vec3(0.0, 0.0, 0.0);
//对比度
vec3 target = vec3(0.5, 0.5, 0.5);
float ut = 2.5;
vec3 mixColor = mix(target, rgb, ut);
gl_FragColor = vec4(mixColor, color.a);
}
反像
反像操作针对图像的“负”数据的工作方式进行建模,从白色中减去各像素的颜色值即可获得反像,如下所示:
vec3(1.0,1.0, 1.0) - color.rgb
基于负像的片元着色器代码,分别创建了某一颜色值及其负值。随后,可用变量uT对其进行混合。uT= 1处表示原始颜色值,uT= 0处则表示负值。
precision highp float;
varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;
void main()
{
lowp vec4 color = texture2D(colorMap, varyTextCoord);
lowp vec3 rgb = color.rgb;
//亮度
// vec3 target = vec3(0.0, 0.0, 0.0);
//对比度
// vec3 target = vec3(0.5, 0.5, 0.5);
//反像
vec3 neg = vec3(1.0, 1.0, 1.0) - rgb;
float ut = 0.0;
gl_FragColor = vec4(mix(neg, rgb, ut), color.a);
}