Commit 60500aef authored by Ruben Dijkstra's avatar Ruben Dijkstra Committed by Phillip Webb

Add ImageBanner color distance calculation

Support CIE94 color distance calculations for improved ImageBanner
rendering. Based on code originally developed by Michael Simons and
added with his permission.

See gh-4647
parent 58d77ec9
......@@ -18,6 +18,7 @@ package org.springframework.boot;
import java.awt.Color;
import java.awt.Image;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
......@@ -214,15 +215,6 @@ public class ImageBanner implements Banner {
}
}
private static double getColorDistance(Color color1, Color color2) {
double redDelta = (color1.getRed() - color2.getRed()) * RED_WEIGHT;
double greenDelta = (color1.getGreen() - color2.getGreen()) * GREEN_WEIGHT;
double blueDelta = (color1.getBlue() - color2.getBlue()) * BLUE_WEIGHT;
return Math.pow(redDelta, 2.0d) + Math.pow(greenDelta, 2.0d)
+ Math.pow(blueDelta, 2.0d);
}
private static BufferedImage resizeImage(BufferedImage sourceImage, int maxWidth,
double aspectRatio) {
int width;
......@@ -246,4 +238,79 @@ public class ImageBanner implements Banner {
resizedImage.getGraphics().drawImage(image, 0, 0, null);
return resizedImage;
}
/**
* Computes the CIE94 distance between two colors.
*
* Contributed by michael-simons
* (original implementation https://github.com/michael-simons/dfx-mosaic/blob/public/src/main/java/de/dailyfratze/mosaic/images/CIE94ColorDistance.java)
*
* @param color1 the first color
* @param color2 the second color
* @return the distance between the colors
*/
private static double getColorDistance(final Color color1, final Color color2) {
// Convert to L*a*b* color space
float[] lab1 = toLab(color1);
float[] lab2 = toLab(color2);
// Make it more readable
double L1 = lab1[0];
double a1 = lab1[1];
double b1 = lab1[2];
double L2 = lab2[0];
double a2 = lab2[1];
double b2 = lab2[2];
// CIE94 coefficients for graphic arts
double kL = 1;
double K1 = 0.045;
double K2 = 0.015;
// Weighting factors
double sl = 1.0;
double kc = 1.0;
double kh = 1.0;
// See http://en.wikipedia.org/wiki/Color_difference#CIE94
double c1 = Math.sqrt(a1 * a1 + b1 * b1);
double deltaC = c1 - Math.sqrt(a2 * a2 + b2 * b2);
double deltaA = a1 - a2;
double deltaB = b1 - b2;
double deltaH = Math.sqrt(Math.max(0.0, deltaA * deltaA + deltaB * deltaB - deltaC * deltaC));
return Math.sqrt(Math.max(0.0, Math.pow((L1 - L2) / (kL * sl), 2) + Math.pow(deltaC / (kc * (1 + K1 * c1)), 2) + Math.pow(deltaH / (kh * (1 + K2 * c1)), 2.0)));
}
/**
* Returns the CIE L*a*b* values of this color.
*
* Implements the forward transformation described in
* https://en.wikipedia.org/wiki/Lab_color_space
*
* @param color the color to convert
* @return the xyz color components
*/
static float[] toLab(Color color) {
float[] xyz = color.getColorComponents(
ColorSpace.getInstance(ColorSpace.CS_CIEXYZ), null);
return xyzToLab(xyz);
}
static float[] xyzToLab(float[] colorvalue) {
double l = f(colorvalue[1]);
double L = 116.0 * l - 16.0;
double a = 500.0 * (f(colorvalue[0]) - l);
double b = 200.0 * (l - f(colorvalue[2]));
return new float[]{(float) L, (float) a, (float) b};
}
private static double f(double t) {
if (t > 216.0 / 24389.0) {
return Math.cbrt(t);
}
else {
return (1.0 / 3.0) * Math.pow(29.0 / 6.0, 2) * t + (4.0 / 29.0);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment