按一定百分比向或远离某个色调着色

发布于 2024-09-06 19:27:18 字数 3674 浏览 10 评论 0 原文

我正在尝试模拟 色调效果开放 XML。它的作用是通过改变色调来改变图像中像素的色调。它需要 2 个参数:1)hue(以度为单位)和 2)amt(数量,百分比)。我遇到的问题是#2。规范规定:

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

  • amt(数量)- 指定颜色值移动的量。
  • 色调(色调)- 指定要着色的色调。

不管 XML 构造如何,我都可以模拟 amt 为 100% 的值。例如,如果我想要蓝色(色调:240°),我可以创建这个(有色)。下面是一个示例:

原始有色(色调 = 240,数量 = 100%)。
原始 Modified

这只需将色调设置为 240,保持饱和度和亮度相同并转换为 RGB 和写入每个像素。

但这是我无法实现的:

Hue=240 (蓝色),Amount = 30%,<分别为强>50%和80%
30% 50% 80%

同样,Amount 的规范表示指定颜色值移动的程度 。我在这里尝试了各种方法来使其正常工作,但似乎无法(hue=hue*amountoriginalhue * amount + Hue 等。 )

更多示例:色调=120绿色),金额 = 30%50%<分别为 /strong>、80%100%。我能得到的100%
30% 50% 80% 100%

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

像素 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

像素 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


所以,问题是:有人知道这应该如何工作吗?

注意:这重复:

I'm trying emulate the Tint Effect of Open XML. What it does is change the hue of pixels in an image by shifting the hue. It takes 2 parameters: 1) the hue (in degrees) and 2) the amt (the amount, a percentage). It is #2 that I'm having issues with. The spec states:

Tint: Shifts effect color values either towards or away from hue by the
specified amount.

  • amt (Amount) - Specifies by how much the color value is shifted.
  • hue (Hue) - Specifies the hue towards which to tint.

Never minding the XML construction, I can emulate values that have an amt of 100%. So for example, if I want Blue (hue: 240°), I can create this (the Tinted one). Here's an example:

Original and Tinted (hue = 240, Amount = 100%).
Original Modified

This is achieved simply by setting the hue to 240, keeping saturation and luminance the same and converting to RGB and writing each pixel.

Here's what I can't achieve though:

Hue=240 (blue), Amount = 30%, 50% and 80%, respectively
30% 50% 80%

Again, the spec for Amount says Specifies by how much the color value is shifted. I've tried all sorts of ways here to get this to work, but can't seem to (hue=hue*amount, originalhue * amount + hue, etc.)

More examples: Hue=120 (green), Amount = 30%, 50%, 80% and 100%, respectively. The 100% one I can get.
30% 50% 80% 100%

Here are some value lists of a single pixel in the pictures above:

Pixel 159, 116 - Blue Pictures

        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 - Green Pictures

        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

So, the question is: Does anyone know how this should work?

Note: This is not a duplicate of:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你没皮卡萌 2024-09-13 19:27:19

我非常确定您的问题是由您插值角度的方式引起的。这是一个插值函数(用 python 编写),应该可以解决这个问题。它基于 xna 论坛主题最短 2D 角度插值

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) 应该会产生所需的结果。

编辑:据我了解,您的目标是将原始色调向特定目标色调旋转一定的给定量。我相信您已经熟悉这一点,但为了便于说明,这里有一个色轮。

色轮
(来源:sapdesignguild.org

问题是混合(或插值)两个角度并不简单,因此像 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)

我的猜测是第二个结果是您正在寻找的那个,但我可能是错的,并且错误可能完全在其他地方......

I am quite certain that your problem results from the way you are interpolating angles. Here's an interpolation function (written in python) that should do the trick. It is based on a suggestion from the xna forums thread 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

Now, interpolate(originalHue,hue,amount) should produce the desired result.

Edit: It is my understanding that your goal is to rotate the original hue towards a certain target hue by some given amount. I'm sure you're already familiar with this, but for the sake of illustration, here's a color wheel.

Color Wheel
(source: sapdesignguild.org)

The problem is that mixing (or interpolating) two angles is not trivial, so code like hue = ((hue - originalHue) * amount) + originalHue will not work. There is an infinite number of ways you can go from one angle to another because of the wraparound at 360°. To get from 0° to 60° you could rotate 60° counter-clockwise, 420° counter-clockwise, 300° clockwise etc. Usually the shortest angle is the desired one.

For example, lets consider the penguin necks: if your original hue is 30° (orange), your target is 240° (blue) and the amount is 50%, you would get the following results:

//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)

My guess is that the second result is the one you are looking for, but I may be wrong and the error could be somewhere else entirely...

千と千尋 2024-09-13 19:27:19

您应该查看 TintParams在 GDI+ 中(尽管不是 .NET 的一部分)——这可能正是您正在寻找的。

You should take a look at TintParams in GDI+ (not part of .NET though) - this may be just what you're looking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文