以一定的百分比着色或远离色调

时间:2010-06-22 22:59:35

标签: c# image gdi+ hsl

我正在尝试模拟Open XML的Tint Effect。它的作用是通过移动色调来改变图像中像素的色调。它需要2个参数:1)hue(以度为单位)和2)amt(金额,百分比)。我遇到问题是#2。规范说明:

  

色调:将效果颜色值移向或远离色调   指定金额。

     
      
  • amt (金额) - 指定颜色值的移位量。
  •   
  • 色调(色调) - 指定要着色的色调。
  •   

从不关注XML构造,我可以模拟amt为100%的值。例如,如果我想要蓝色(色调:240°),我可以创建它( Tinted 一个)。这是一个例子:

原始着色(色调= 240,金额= 100%)。
Original Modified

这可以通过将色调设置为240,保持饱和度和亮度相同并转换为RGB并写入每个像素来实现。

这是我无法实现的目标:

Hue = 240 蓝色 ),金额= 30% 50% 80%,分别为 30% 50% 80%

同样,Amount的规范说明指定颜色值移位的数量。我已经尝试了各种各样的方法来实现这一点,但似乎不能(hue=hue*amountoriginalhue * amount + hue等。)

更多示例:Hue = 120 绿色 ),金额= 30% 50 % 80% 100% 100%我能得到的 30% 50% 80% 100%

以下是上图中单个像素的一些值列表:

Pixel 159,116 - 蓝色图片

        Hue    Amount    R    G    B    | H    S     L
Original                 244  196   10  |  48  0.92  0.5
Blue    240     30%      237   30   45  | 356  0.85  0.52
Blue    240     50%      245    9  156  | 323  0.93  0.5
Blue    240     80%      140   12  244  | 273  0.91  0.5
Blue    240    100%       12   12  244  | 240  0.91  0.5

Pixel 159,116 - 绿色图片

        Hue    Amount    R    G    B    | H    S     L
Original                 244  196   10  |  48  0.92  0.5
Green    120     30%     211  237   30  |  68  0.85  0.52
Green    120     50%     159  237   30  |  83  0.85  0.52
Green    120     80%      81  237   29  | 105  0.85  0.52
Green    120    100%      29  237   29  | 120  0.85  0.52


所以,问题是:有谁知道这应该如何运作?

  

注意:这是的重复:

     

2 个答案:

答案 0 :(得分:6)

我很确定你的问题是由你插入角度的方式产生的。这是一个插值函数(用python编写),应该可以解决这个问题。它基于xna论坛帖子Shortest 2D Angle Interpolation的建议。

def wrap(value, lower, upper):
    distance = upper - lower
    return value - ((value-lower)//distance)*distance

def shortestangle(a,b):
    angle = wrap(b-a, 0, 360)
    if angle>=180: angle -= 360
    return angle

def interpolate(a,b,amount):
    return (a+shortestangle(a,b)*amount)%360

现在,interpolate(originalHue,hue,amount)应该产生所需的结果。

编辑:据我所知,您的目标是将原始色调按某个给定量旋转到某个目标色调。我相信你已经熟悉了这个,但为了说明,这里有一个色轮。

Color Wheel http://www.sapdesignguild.org/resources/glossary_color/images/color_wheel2.jpg

问题在于混合(或插值)两个角度并不简单,因此像hue = ((hue - originalHue) * amount) + originalHue这样的代码将无效。由于360°环绕,您可以通过无数种方式从一个角度到另一个角度。要从0°到60°,您可以逆时针旋转60°,逆时针旋转420°,顺时针旋转300°等。通常最短的角度是所需的角度。

例如,让我们考虑一下企鹅脖子:如果你的原始色调是30°(橙色),你的目标是240°(蓝色),数量是50%,你会得到以下结果:

//Linear Interpolation
(30° + (240° - 30°)*0.5) = 135° (green)

//"Shortest 2D Angle Interpolation"
(30° + shortestangle(30°,240°)*0.5) % 360 = (30° + (-150°)*0.5) % 360 = 315° (magenta)

我的猜测是第二个结果是你要找的那个,但我可能错了,错误可能完全在其他地方......

答案 1 :(得分:1)

你应该看看GDI +中的TintParams(不是.NET的一部分) - 这可能正是你所寻找的。