Java平滑颜色过渡

5

假设我有两种颜色。

public final static Color FAR = new Color(237, 237, 30);
public final static Color CLOSE = new Color(58, 237, 221);

如何在不使用深色的情况下过渡从一种颜色到另一种颜色?

我想出了一些思路,比如:

    double ratio = diff / range; // goes from 1 to 0
    int red = (int)Math.abs((ratio * FAR.getRed()) - ((1 - ratio) * CLOSE.getRed()));
    int green = (int)Math.abs((ratio * FAR.getGreen()) - ((1 - ratio) * CLOSE.getGreen()));
    int blue = (int)Math.abs((ratio * FAR.getBlue()) - ((1 - ratio) * CLOSE.getBlue()));

或者

    double ratio = diff / range; // goes from 1 to 0
    int red = (int) ((1 - (diff / range)) * FAR.getRed() + CLOSE.getRed() - FAR.getRed());
    int green = (int) ((1 - (diff / range)) * FAR.getGreen() + CLOSE.getGreen() - FAR.getGreen());
    int blue = (int) ((1 - (diff / range)) * FAR.getBlue() + CLOSE.getBlue() - FAR.getBlue());

然而,不幸的是,它们中没有一种可以平滑地从一种颜色过渡到另一种颜色。

有人知道如何做到在保持颜色鲜艳的同时不使其变暗,或者如何确保渐变过渡平滑而不是起初缓慢,然后变快,再变慢吗?

我真的想不出任何公式。


2
diffrange都是整数吗?如果是,要注意整数除法。 - Alexis C.
我正在循环中使用它们,其中我从30开始并向下到0。我的范围是30双倍。因此,我将其用作平稳地在30个步骤中从1到0的手段。但是我认为步数不应该那么重要。 - Quillion
可能是在PHP中生成RGB渐变颜色的算法的重复问题。 - mbeckish
2
将RGB颜色空间视为立方体。在立方体上找到您的两种颜色,然后决定如何从一个点到另一个点以获得所需的过渡颜色。例如,您可以通过立方体挖掘隧道直接从一种颜色到另一种颜色。或者,您可以限制旅行沿着立方体表面进行,以避免不饱和的灰色颜色。 - mbeckish
3个回答

7

您在计算中使用了错误的符号。应该使用加号而不是减号来正确应用比例。

int red = (int)Math.abs((ratio * FAR.getRed()) + ((1 - ratio) * CLOSE.getRed()));
int green = (int)Math.abs((ratio * FAR.getGreen()) + ((1 - ratio) * CLOSE.getGreen()));
int blue = (int)Math.abs((ratio * FAR.getBlue()) + ((1 - ratio) * CLOSE.getBlue()));

你现有的实现出现深色的原因是,使用减号(-)时,它们通常会接近于零(小于50或者是负数但大于-50?)。如果是负数,你又取了绝对值,所以会变成一个小的正数,也就是一个深色。

谢谢,这个方法非常有效 :) 这是一个很难解决的问题,你帮我省了很多时间去研究颜色。 - Quillion
1
很高兴能够帮助。如果您需要多次执行此任务,编写一个辅助函数是很值得的。例如,编写一个 int interpolate(double ratio, int value1, int value2) 函数,它返回 (int)Math.abs((ratio * value1) + ((1 - ratio) * value2))。这样,在过渡颜色时,您总是清楚地知道自己要做什么。 - Alex Walker
这只是我为了好玩而闲逛的东西,所以我不想费心编写辅助函数。但是我正在做更多我想学习的颜色技巧,所以我想以后会发布更多问题。 - Quillion

1
(ratio * FAR.getGreen()) + ((1 - ratio) * CLOSE.getGreen())

如果比例从0变为1,那么这就是加权平均值。假设比例为1/2,则为算术平均值;如果比例为1/3,则FAR的权重为1,CLOSE的权重为2。


是的,我确实使用加权平均值,因为如果比率为0,我希望颜色接近;如果比率为1,则希望颜色远离。但是,我希望中间的颜色过渡平滑且明亮。 - Quillion

1
这对我非常有效:
// Steps between fading from one colour to another.
private static final int FadeSteps = 25;

private void fade(Label panel, Color colour) throws InterruptedException {
  final Color oldColour = panel.getBackground();
  final int dRed = colour.getRed() - oldColour.getRed();
  final int dGreen = colour.getGreen() - oldColour.getGreen();
  final int dBlue = colour.getBlue() - oldColour.getBlue();
  // No point if no difference.
  if (dRed != 0 || dGreen != 0 || dBlue != 0) {
    // Do it in n steps.
    for (int i = 0; i <= FadeSteps; i++) {
      final Color c = new Color(
              oldColour.getRed() + ((dRed * i) / FadeSteps),
              oldColour.getGreen() + ((dGreen * i) / FadeSteps),
              oldColour.getBlue() + ((dBlue * i) / FadeSteps));
      panel.setBackground(c);
      Thread.sleep(10);
    }
  }
}

不是最整洁的代码,但它可以工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接