着色器图像处理(亮度/对比度/反像)

基于固定基图像的图像混合操作:针对图像各像素与常量值之间的混合操作

图像的基本属性。首先是亮度,也称灰度,它是大 家常说的YUV格式的Y分量,如果使用RGB表示图像,那么可采用前面 章节中提到的公式转换出亮度信息;其次是对比度(contrast),即画面黑与白的比值,也就是从黑到白的渐变层次,比值越大,说明从黑到白的渐变层次越多,色彩表现越丰富;最后是饱和度(saturation),是指 色彩的鲜艳程度,也称为色彩的纯度。

着色器图像处理(亮度/对比度/反像)_第1张图片
原图

亮度调节

亮度调节有两种一种是线性调节, 一种是非线性调节

亮度值可视为颜色值中“非黑色”的数量。对于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张图片
Simulator Screen Shot - iPhone X - 2019-11-30 at 18.46.14.png
2.线性调节

为什么说线性调节会比较自然呢, 因为人眼并不会去区分RGB颜色分量占多少比例, 而是对明暗比较明暗, HSL就是通过色相(Hue)、饱和度 (Saturation)、明度(Lightness)三个通道的颜色,每个通道都可使用 0~255的数值来表示。这种调节是通过对色相、饱和度、明度三个颜色 通道的变化及其相互之间的叠加来得到各种颜色。符合人眼的直观感觉.

  1. 线性调节的顶点着色器和非线性调节的顶点着色器是一样
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);

}
着色器图像处理(亮度/对比度/反像)_第3张图片
Simulator Screen Shot - iPhone X - 2019-11-30 at 18.46.44.png

看起来好像是比较自然, 从内部向外部出来的颜色.

  1. 前面提到过, 亮度值可视为颜色中非黑色的数量, 所以提升亮度可以通过减少图片展黑色的数量来做.
    使用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时的渲染结果.

着色器图像处理(亮度/对比度/反像)_第4张图片
Simulator Screen Shot - iPhone X - 2019-12-01 at 13.22.24.png

同样也可以把 black改成其他的颜色值, 来混和成不同的结果.

  1. 还有一种更简单的方式直接对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);

}
着色器图像处理(亮度/对比度/反像)_第5张图片
Simulator Screen Shot - iPhone X - 2019-12-01 at 14.22.08.png

反像

反像操作针对图像的“负”数据的工作方式进行建模,从白色中减去各像素的颜色值即可获得反像,如下所示:

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);

}
着色器图像处理(亮度/对比度/反像)_第6张图片
Simulator Screen Shot - iPhone X - 2019-12-01 at 14.39.11.png

你可能感兴趣的:(着色器图像处理(亮度/对比度/反像))