【问题标题】:Image hue modification in C#C#中的图像色调修改
【发布时间】:2010-10-01 08:09:01
【问题描述】:

我有一张图像,我想将该特定图像的色调修改为特定值。 我知道 rgb 到 hsl 和 hsl 到 rgb 转换数学公式,但我无法在 c# 中实现这个东西。

以下是伪:

for(x=0;x<image_width;x++)
{
  for(y=0;y<image_height;y++)
  {
    Color oldColor=GetColorFromPixel(x,y);
    Color newColor=ModifyHue(oldColor);
    SetColorPixel(x,y,newColor);    
  }
}

谢谢

【问题讨论】:

  • 如果您想要 C# 中的算法,请查看 this。检查这是否与 wiki says...

标签: c# image-processing


【解决方案1】:

由于Color 结构已经具有GetHue()GetSaturation()GetBrightness() 的事实,因此也可以从这些值构造颜色。所以我前段时间在网上某处找到了以下代码(目前无法再次找到它,但它来自微软的一个家伙博客,他也有一个测试,可以遍历所有KnownColor)。

/// <summary>
/// Creates a Color from alpha, hue, saturation and brightness.
/// </summary>
/// <param name="alpha">The alpha channel value.</param>
/// <param name="hue">The hue value.</param>
/// <param name="saturation">The saturation value.</param>
/// <param name="brightness">The brightness value.</param>
/// <returns>A Color with the given values.</returns>
public static Color FromAhsb(int alpha, float hue, float saturation, float brightness)
{

    if (0 > alpha || 255 < alpha)
    {
        throw new ArgumentOutOfRangeException("alpha", alpha,
          "Value must be within a range of 0 - 255.");
    }
    if (0f > hue || 360f < hue)
    {
        throw new ArgumentOutOfRangeException("hue", hue,
          "Value must be within a range of 0 - 360.");
    }
    if (0f > saturation || 1f < saturation)
    {
        throw new ArgumentOutOfRangeException("saturation", saturation,
          "Value must be within a range of 0 - 1.");
    }
    if (0f > brightness || 1f < brightness)
    {
        throw new ArgumentOutOfRangeException("brightness", brightness,
          "Value must be within a range of 0 - 1.");
    }

    if (0 == saturation)
    {
        return Color.FromArgb(alpha, Convert.ToInt32(brightness * 255),
          Convert.ToInt32(brightness * 255), Convert.ToInt32(brightness * 255));
    }

    float fMax, fMid, fMin;
    int iSextant, iMax, iMid, iMin;

    if (0.5 < brightness)
    {
        fMax = brightness - (brightness * saturation) + saturation;
        fMin = brightness + (brightness * saturation) - saturation;
    }
    else
    {
        fMax = brightness + (brightness * saturation);
        fMin = brightness - (brightness * saturation);
    }

    iSextant = (int)Math.Floor(hue / 60f);
    if (300f <= hue)
    {
        hue -= 360f;
    }
    hue /= 60f;
    hue -= 2f * (float)Math.Floor(((iSextant + 1f) % 6f) / 2f);
    if (0 == iSextant % 2)
    {
        fMid = hue * (fMax - fMin) + fMin;
    }
    else
    {
        fMid = fMin - hue * (fMax - fMin);
    }

    iMax = Convert.ToInt32(fMax * 255);
    iMid = Convert.ToInt32(fMid * 255);
    iMin = Convert.ToInt32(fMin * 255);

    switch (iSextant)
    {
        case 1:
            return Color.FromArgb(alpha, iMid, iMax, iMin);
        case 2:
            return Color.FromArgb(alpha, iMin, iMax, iMid);
        case 3:
            return Color.FromArgb(alpha, iMin, iMid, iMax);
        case 4:
            return Color.FromArgb(alpha, iMid, iMin, iMax);
        case 5:
            return Color.FromArgb(alpha, iMax, iMin, iMid);
        default:
            return Color.FromArgb(alpha, iMax, iMid, iMin);
    }
}

使用此功能,您可以在 HSB(或 HSV)颜色演示中而不是在 HSL 演示中工作。有关它们之间差异的更多信息,请查看this wikipedia article

【讨论】:

    【解决方案2】:

    如果你只是想试试或者性能不重要,最简单的方法是使用Bitmap.GetPixelBitmap.SetPixel方法:

    var bm = new Bitmap(filename);
    for(int x=0;x<bm.Width;x++)
    {
      for(y=0;y<bm.Height;y++)
      {
        Color oldColor=bm.GetPixel(x,y);
        Color newColor=ModifyHue(oldColor);
        bm.SetPixel(x,y,newColor);    
      }
    }
    

    如果您想要更高性能的操作,您应该查看Bitmap.LockBits 方法,该方法将整个位图固定在一个内存位置并允许您直接修改此内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多