C# 调整饱和度

545 阅读2分钟

主要思想: 也是将RGB转换为HSL色彩空间然后再调节其S,但是加了补偿。 之前直接将RGB转换HSl再调整S之后再换回RGB,发现不仅效果不明显,反而一下子就出现色斑了。 当然可以直接用DLL,比如ImageProcessor,可以直接用image类型来调整。

public  void AdjustSaturationByIF(Image MImage,int degree)
{
    // 只调整图像的饱和度值
    ImageFactory imageF = new ImageFactory();
    imageF.Load(MImage);
    imageF.Saturation(degree);
    ...
}

图像的饱和度调整有很多方法,最简单的就是判断每个象素的R、G、B值是否大于或小于128,大于加上调整值,小于则减去调整值;也可将象素RGB转换为HSV或者HSL,然后调整其S部分,从而达到线性调整图象饱和度的目的。这几种方法我都测试过,效果均不太好,简单的就不说了,利用HSV和HSL调整饱和度,其调节范围很窄,饱和度没达到,难看的色斑却出现了。而Photoshop的饱和度调整调节范围大多了,效果也好多了。 算法参考:CSDN博主「阿发伯」的Photoshop饱和度调整

public static void Swap(ref int a,ref int b) 
{
    a += b;
    b = a - b;
    a -= b;
}
public static void Check(ref int Value) 
{
    if (Value < 0) Value = 0;
    else if (Value > 255) Value = 255;
}
public static void AssignRGB(out int R, out int G, out int B ,int  r,int g,int b) 
{
    R = r;
    G = g;
    B = b;
 }
 public static void SetRGB2HSB(ref int R, ref int G, ref int B, int degree)
 {
     degree = degree * 255 / 100;
     int rgbMax = R;
     int rgbMin = G;
     int rgbC = B;
     if (rgbMax < rgbC) Swap(ref rgbMax, ref rgbC);
     if (rgbMax < rgbMin) Swap(ref rgbMax, ref rgbMin);
     if (rgbMin > rgbC) Swap(ref rgbMin, ref rgbC);
     int delta = rgbMax - rgbMin;
     int H, S;

     int value = rgbMax + rgbMin;
     int L = (value + 1) >> 1;
     if (delta == 0) H = S = 0;
     else
     {
         if (L < 128) S = delta * 255 / value;
         else S = delta * 255 / (510 - value);
         if (rgbMax == R) H = (G - B) * 60 / delta;
         else if (rgbMax == G) H = (B - R) * 60 / delta + 120;
         else H = (R - G) * 60 / delta + 240;
         if (H < 0) H += 360;
         H /= 60;
         if (degree != 0)
         {
             if (degree > 0)
             {
                 degree = degree + S >= 255 ? S : 255 - degree;
                 degree = 65025 / degree - 255;
             }
                 rgbMax = rgbMax + (rgbMax - L) * degree / 255;
                 rgbMin = rgbMin + (rgbMin - L) * degree / 255;
                 rgbC = rgbC + (rgbC - L) * degree / 255;
         }
      }
      Check(ref rgbMax);
      Check(ref rgbMin);
      Check(ref rgbC);
      if (S != 0) AssignRGB(out R, out G, out B, rgbMax, rgbC, rgbMin);
        
 }
 public void AdjustSaturationPS(System.Drawing.Image image, int degree)
 {
     int[] RGB = new int[3];
     Bitmap bitmap = new Bitmap(image);
     BitmapData data = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height),
     ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
     if (degree < 0) degree = 0;
     unsafe
     {
         byte* ptr = (byte*)(data.Scan0);
         for (int i = 0; i < data.Height; i++)
         {
             for (int j = 0; j < data.Width; j++)
             {
                 for (int k = 0; k < 3; k++)
                 {
                     RGB[k] = ptr[k];
                 }
                 SetRGB2HSB(ref RGB[0],ref RGB[1],ref RGB[2],degree);
                 for (int k = 0; k < 3; k++)
                 {
                     ptr[k] = (byte)RGB[k];
                 }
                 ptr += 3;
             }
             ptr += data.Stride - data.Width * 3;
         }
     }
  bitmap.UnlockBits(data);
  ...
}