【问题标题】:Rotate Hue in C#在 C# 中旋转色调
【发布时间】:2014-09-15 20:48:50
【问题描述】:

我希望复制 here 发现的 CSS3 色调旋转行为

原图

色调旋转 180 度的图像

我已经可以准确地将 RGB 值转换为 HSL 值并再次转换回来,但我不确定应用于色调组件以复制输出的数学函数是什么。

【问题讨论】:

  • This web page 显示您要在位图上使用的 ColorMatrix。
  • 我觉得我应该指出 HSL 实际上是一个非常糟糕的色彩空间来转换图像。组件不是孤立的——例如,改变其中的色调也会混淆实际的亮度和饱和度当通过更准确的色彩空间测量时。 LSHuv 或 LCHab 颜色空间会给您带来更好的感知效果。
  • 安息吧特里·普拉切特。

标签: c# gdi+


【解决方案1】:

加法。

就这么简单,只需将色调值加 180,然后确保它在 360 处环绕:

hue = (hue + 180) % 360;

【讨论】:

  • 我不熟悉 HSV/HSL,但不需要任何映射吗?我的意思是,颜色通常在 0-255 范围内表示。
  • @Mephy:色调以度数表示。如果您有不同的数值范围,您将使用从度数转换而来的值。对于 0-255 范围,180 度将转换为 128,360 度将转换为 256。
  • 我知道如何翻译一个值,只是好奇它是否通常存储在 0-360 或 0-255 范围内。
  • @Mephy:通常以度数表示。
  • @Mephy 可以在MSDN: Color.GetHue Method 看到“正常”的一个示例“..获取色调-饱和度-亮度 (HSB) 色调值,以度为单位.. ",源代码在referencesource.microsoft.com/#System.Drawing/commonui/System/… 另一个“正常”的例子在stackoverflow.com/questions/3018313/…
【解决方案2】:

我想指出如何实际上做到这一点。这是确切的问题,但没有好的答案。

给定一个 GDI+ Image,我想应用一个色相偏移并返回一个新图像。实际上,它将返回一个新的Bitmap。我将使用 C# 风格的伪代码。

首先是克隆 GDI+ 图像的基本方法(但还没有色相偏移):

Bitmap CloneImage(Image sourceImage, Single hueShiftAngleDegrees)
{
   Int32 width  = sourceImage.GetWidth();
   Int32 height = sourceImage.Getheight();

   //Create destination bitmap
   Bitmap bmpDest = new Bitmap(width, height, PixelFormat32bppARGB);
   
   //Create a Graphics that will draw onto our destination bitmap
   Graphics g = new Graphics(destinationBitmap);

   //Draw the source image into the destination
   g.DrawImage(sourceImage, MakeRect(0, 0, width, height), 
         0, 0, width, height, UnitPixel);

   return bmpDest;
}

接下来的想法是,当我们使用Graphics.DrawImage 方法时,我们可以提供一个ImageAttributes 类。

ImageAttributes attributes = new ImageAttributes();
g.DrawImage(sourceImage, MakeRect(0, 0, width, height), 
      0, 0, width, height, UnitPixel, attributes);

这些属性之一可以是 5x5 ColorMatrix

ColorMatrix cm = (
   ( rr, gr, br, ar, 0 ),
   ( rg, gg, bg, ag, 0 ),
   ( rb, gb, bb, ab, 0 ),
   ( ra, ga, ba, aa, 0 ),
   ( r1, g1, b1, a1, 1 )
);

ImageAttributes attributes = new ImageAttributes();
attributes.SetColorMatrix(cm);
g.DrawImage(sourceImage, MakeRect(0, 0, width, height), 
      0, 0, width, height, UnitPixel, attributes);

魔法来自可以执行色相转换的颜色矩阵。我创建了一个函数,它可以返回执行所需色调偏移的 ColorMatrix

ColorMatrix GetHueShiftColorMax(Single hueShiftDegrees)
{
    /* Return the matrix
    
        A00  A01  A02  0  0
        A10  A11  A12  0  0
        A20  A21  A22  0  0
          0    0    0  1  0
          0    0    0  0  1
    */
    Single theta = hueShiftDegrees/360 * 2*pi; //Degrees --> Radians
    Single c = cos(theta);
    Single s = sin(theta);

    Single A00 = 0.213 + 0.787*c - 0.213*s;
    Single A01 = 0.213 - 0.213*c + 0.413*s;
    Single A02 = 0.213 - 0.213*c - 0.787*s;

    Single A10 = 0.715 - 0.715*c - 0.715*s;
    Single A11 = 0.715 + 0.285*c + 0.140*s;
    Single A12 = 0.715 - 0.715*c + 0.715*s;

    Single A20 = 0.072 - 0.072*c + 0.928*s;
    Single A21 = 0.072 - 0.072*c - 0.283*s;
    Single A22 = 0.072 + 0.928*c + 0.072*s;

    ColorMatrix cm = new ColorMatrix(
          ( A00, A01, A02,  0,  0 ),
          ( A10, A11, A12,  0,  0 ),
          ( A20, A21, A22,  0,  0 ),
          (   0,   0,   0,  0,  0 ),
          (   0,   0,   0,  0,  1 )
    )

    return cm;
}

所以我将创建一种新的函数,它会复制图像并对其应用ColorMatrix

Bitmap Multiply(Image sourceImage, ColorMatrix cm)
{
   Int32 width  = sourceImage.GetWidth();
   Int32 height = sourceImage.Getheight();

   //Create destination bitmap
   Bitmap bmpDest = new Bitmap(width, height, PixelFormat32bppARGB);
   
   //Create a Graphics that will draw onto our destination bitmap
   Graphics g = new Graphics(destinationBitmap);

   //Draw the source image into the destination
   ImageAttributes attributes = new ImageAttributes();
   attributes.SetColorMatrix(cm);
   g.DrawImage(sourceImage, MakeRect(0, 0, width, height), 
         0, 0, width, height, UnitPixel, attributes);

   return bmpDest;
}

而我们的色相偏移算法变为:

Bitmap ApplyHueShift(Image sourceImage, Single hueShiftAngleDegrees)
{
   ColorMatrix cm = GetHueShiftColorMatrix(hueShiftAngleDegrees);

   return Multiply(sourceImage, cm);
}

我不知道色相偏移颜色矩阵的来源。它只存在于 MSDN 页面 Hue rotation effect archive:

【讨论】:

    猜你喜欢
    • 2010-11-07
    • 1970-01-01
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2011-01-17
    相关资源
    最近更新 更多