Reputation: 6476
Let's say I am given two colors.
public final static Color FAR = new Color(237, 237, 30);
public final static Color CLOSE = new Color(58, 237, 221);
How would I transition from one color to the next without dipping into dark colors?
I have come up with ideas such as
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()));
OR
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());
But unfortunately none of them smoothly transition from one color to the next. Would anyone know how to do so while keeping the color bright and not dipping into darker colors, or how to ensure that gradient transition is smooth rather than slow at first then fast and then slow again?
I really ca not come up with any formula.
Upvotes: 5
Views: 8932
Reputation: 65811
This works nicely for me:
// 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);
}
}
}
Not the neatest bit of code but it works.
Upvotes: 1
Reputation: 2356
You're using the wrong sign in the calcuations. Should be plus, not minus, to apply the ratio properly.
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()));
The reason you are getting dark colours with your existing implementation is that with (-), they would often fall close to zero (less than 50? or negative but greater than -50?) and in the negative case, well, you are taking the absolute value so it becomes a small positive number, i.e. a dark colour.
Upvotes: 7
Reputation: 12939
(ratio * FAR.getGreen()) + ((1 - ratio) * CLOSE.getGreen())
if ratio goest from 0 to 1, then this is weighted average, lets say ratio = 1/2, then it would be aritmetical average, if ratio = 1/3, then it is weighted average where FAR has weight 1 and CLOSE has weight 2
Upvotes: 1