图片处理中,调节饱和度、明度、色相是非常常见的功能,这篇文章带你深入理解饱和度的调节,文末附录代码实现。
一、饱和度与明度的定义
一个彩色像素由RGB组成。
明度指RGB三通道的平均值,平局值越高明度越高。
饱和度指RGB三通道中最大值与最小值之差,差别越大,饱和度越大,颜色看起来越鲜艳。
饱和度调节 明度调节
饱和度与明度的关联性:
从饱和度、明度的定义来看,两个值的调节是相互影响的。参考下图,饱和度取最大值255时,就限制最大值、最小值分别为255和0,则明度值为127.5。明度值取最大值255或最小值0时,则最大值和最小值相同都是255或0,即饱和度为0。
二、调节饱和度的算法原理
上面介绍的是比较简单的理解,略去了细节,实际上HSV模型,是基于人的视觉感知来定义的,本没有公式计算
参考:孟塞尔颜色体系
饱和度的算法有很多种,这里介绍一种,设饱和度S的取值范围[-100, 100]。
当前饱和度为:
L为明度联系上面明度和饱和度的关系曲线,就能理解为什么以128为分界线,有两个算法
根据设置的饱和度s,反求出新的RGB值
实现效果
三、调节饱和度的代码实现
#include"f_Saturation.h"
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include"Commen.h"
int f_Saturation(unsigned char *srcData, int width, int height, int stride, int saturation)
{
int ret = 0;
if(saturation == 0)
return ret;
unsigned char* pSrc = srcData;
int r, g, b, rgbMin, rgbMax;
saturation = CLIP3(saturation,-100,100);
int k = saturation / 100.0f * 128;
int alpha = 0;
int offset = stride - width * 4;
for(int j = 0; j < height; j++)
{
for(int i = 0; i < width; i++)
{
r = pSrc[2];
g = pSrc[1];
b = pSrc[0];
rgbMin = MIN2(MIN2(r, g), b);
rgbMax = MAX2(MAX2(r, g), b);
int delta = (rgbMax - rgbMin);
int value = (rgbMax + rgbMin);
// 饱和度为0,不处理
if(delta ==0)
{
pSrc += 4;
continue;
}
int L = value >> 1;
int S = L < 128 ? (delta << 7) / value : (delta << 7) / (510 - value);
if(k >= 0)
{
alpha = k + S >= 128 ? S : 128 - k;
alpha = 128 * 128 / alpha - 128;
}
else
alpha = k;
r = r + ((r - L) * alpha >> 7);
g = g + ((g - L) * alpha >> 7);
b = b + ((b - L) * alpha >> 7);
pSrc[0] = CLIP3(b, 0, 255);
pSrc[1] = CLIP3(g, 0, 255);
pSrc[2] = CLIP3(r, 0, 255);
pSrc += 4;
}
pSrc += offset;
}
return ret;
};
网友评论