PS里的亮度/对比度/饱和度/色阶算法-OpenGL实现

1.亮度

  • PS里的亮度调整,主要是控制图片整体的亮度,可以弥补曝光过度和曝光补足需要补光的问题。
    在这里插入图片描述
  • 对RGB图像来说,亮度算法有很多种,最简单的一种就是直接整体提升或降低像素的RGB值。(RGB值为0到1,0纯黑,1纯白)
  • 公式如下:
    • 新RGB值 = 旧RGB值 + 亮度值
    • 亮度值在-1到1之间
    • 新RGB值需要控制范围0到1
使用OpenGL实现:

顶点着色器:

attribute vec2 a_position;
attribute vec2 a_texCoord;
varying vec2 texcoordOut;

void main()
{
    
    
    texcoordOut = a_texCoord;
    gl_Position = vec4(a_position, 0.0, 1.0);
}

片段着色器:
u_texture为原图,brightness为调整亮度值,变化范围-1到1

precision highp float;

uniform sampler2D u_texture;
varying vec2 texcoordOut;

uniform float brightness;

void main()
{
    
    
    vec4 srcColor = texture2D(u_texture, texcoordOut);
    gl_FragColor = vec4(clamp(srcColor.rgb + brightness, 0.0, 1.0), srcColor.a);
}
效果:

请添加图片描述

2.对比度

  • PS里的对比度调整,可以增大图片明暗区别,两处更亮,暗处更暗,使得明暗更分明在这里插入图片描述

  • 对RGB图像来说,对比度算法依然有很多种,在不知道图像平均亮度的情况下,可以取0.5作为图像的平均亮度。超出0.5的像素做类似提亮的操作,低于0.5的像素做类似压暗的操作。(RGB值为0到1,0纯黑,1纯白)

  • 公式如下:

    • 新RGB值 = 旧RGB值 + (旧RGB值 - 0.5)× 对比度值
    • 对比度值在0到1之间
    • 新RGB值需要控制范围0到1
使用OpenGL实现:

顶点着色器:

attribute vec2 a_position;
attribute vec2 a_texCoord;
varying vec2 texcoordOut;

void main()
{
    
    
    texcoordOut = a_texCoord;
    gl_Position = vec4(a_position, 0.0, 1.0);
}

片段着色器:
u_texture为原图,contrast为调整对比度值,变化范围0到1

precision highp float;

uniform sampler2D u_texture;
varying vec2 texcoordOut;

uniform float contrast;

void main()
{
    
    
    vec4 srcColor = texture2D(u_texture, texcoordOut);
    vec3 contrastColor = srcColor.rgb + (srcColor.rgb - vec3(0.5)) * contrast;
    gl_FragColor = vec4(clamp(contrastColor, 0.0, 1.0), srcColor.a);
}
效果:

请添加图片描述

3.饱和度

  • PS里的饱和度调整,可以使得颜色更饱满,更鲜艳。降低饱和度时,图片会越接近灰色(相当于失去了所有的色彩)
    在这里插入图片描述

  • 饱和度调整算法,需要先将RGB颜色转为HSV颜色,然后调整其S部分,最后再传唤回RGB颜色。从而达到线性调整饱和度的目的。(RGB值为0到1,0纯黑,1纯白)

    扫描二维码关注公众号,回复: 14733254 查看本文章
  • PS饱和度调整算法主要是利用HSL颜色空间进行饱和度S的上下限控制,对RGB空间进行补丁式调整。调整过程是在RGB空间进行,其原理简单的说就是判断每个像素点R/G/B值是否大于或小于平均值,大于加上调整值,小于则减去调整值,如何计算各个像素点的调整系数是关键。本算法主体思想就是利用HSL来计算各点的调整系数。

  • 公式如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

使用OpenGL实现:

顶点着色器:

attribute vec2 a_position;
attribute vec2 a_texCoord;
varying vec2 texcoordOut;

void main()
{
    
    
    texcoordOut = a_texCoord;
    gl_Position = vec4(a_position, 0.0, 1.0);
}

片段着色器:
u_texture为原图,saturation为调整饱和度值,变化范围-1到1

precision highp float;

uniform sampler2D u_texture;
varying vec2 texcoordOut;

uniform float saturation;

void main()
{
    
    
    vec4 srcColor = texture2D(u_texture, texcoordOut);
    
    float rgbMax = max(max(srcColor.r, srcColor.g), srcColor.g);
    float rgbMin = min(min(srcColor.r, srcColor.g), srcColor.g);
    
    float delta = rgbMax - rgbMin;
    
    float value = rgbMax + rgbMin;
    
    // HSL
    float L = value / 2.0;
    float S;
    if (L < 0.5) {
    
    
        S = delta / value;
    } else {
    
    
        S = delta / (2.0 - value);
    }
    
    float alpha;
    vec3 resultColor;
    if (saturation < 0.0) {
    
    
        alpha = saturation;
        resultColor = vec3(L) + (srcColor.rgb - vec3(L)) * (1.0 + alpha);
    } else {
    
    
        if (saturation + S >= 1.0) {
    
    
            alpha = S;
        } else {
    
    
            alpha = 1.0 - saturation;
        }
        alpha = 1.0 / alpha - 1.0;
        resultColor = srcColor.rgb + (srcColor.rgb - vec3(L)) * alpha;
    }
    
    gl_FragColor = vec4(clamp(resultColor, 0.0, 1.0), srcColor.a);
}
效果:

请添加图片描述

4.色阶

  • 色阶是什么:色阶就是用直方图描述出的整张图片的明暗信息。
  • 从左至右是从暗到亮的像素分布,黑色三角代表最暗地方(纯黑),白色三角代表最亮地方(纯白)。灰色三角代表中间调。

在这里插入图片描述

  • 每一个色阶定义有两组值:

    • 一组是输入色阶值,包含黑灰白三个值, 上图中:黑点值为0,灰点为1.0,白点为255
    • 另一组是输入色阶值,包含黑白两个值,上图中:输出色阶黑为0,白为255
  • 色阶调整的实现是:

    • 当输入值<黑点值时,全部变为输出色阶的黑值。
    • 当输入值>白点时,全部变为输出色阶的白值。
    • 当输入值介于黑值与白值之间时,则结合灰度系数,按比例重新计算,变为一个新的值。
使用OpenGL实现:

顶点着色器:

attribute vec2 a_position;
attribute vec2 a_texCoord;
varying vec2 texcoordOut;

void main()
{
    
    
    texcoordOut = a_texCoord;
    gl_Position = vec4(a_position, 0.0, 1.0);
}

片段着色器:
u_texture为原图,highLight为白点值,变化范围0到1,shadow为黑点值,变化范围0到1,midtone为灰点值,变化范围0到1。 需要注意必须满足:shadow < midtone< highLight

precision highp float;

uniform sampler2D u_texture;
varying vec2 texcoordOut;

uniform float highLight;
uniform float shadow;
uniform float midtone;

void main()
{
    
    
    vec4 srcColor = texture2D(u_texture, texcoordOut);
    
    float diff = highLight - shadow;
    vec3 rgbDiff = max(srcColor.rgb - shadow, 0.0);
    
    gl_FragColor = vec4(clamp(pow(rgbDiff / diff, vec3(1.0 / midtone)), 0.0, 1.0), srcColor.a);
}
效果:

效果为黑点值0.1,白点值0.9,只移动灰点值的效果:
请添加图片描述

猜你喜欢

转载自blog.csdn.net/q345911572/article/details/127462885