mirror of
https://github.com/GeyserExtensionists/GeyserUtils.git
synced 2025-12-19 15:09:24 +00:00
Fixed that colors actually match for the most part
This commit is contained in:
@@ -22,6 +22,7 @@ import me.zimzaza4.geyserutils.geyser.replace.JavaAddEntityTranslatorReplace;
|
||||
import me.zimzaza4.geyserutils.geyser.scoreboard.EntityScoreboard;
|
||||
import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator;
|
||||
import me.zimzaza4.geyserutils.geyser.util.Converter;
|
||||
import me.zimzaza4.geyserutils.geyser.util.DeltaUtils;
|
||||
import me.zimzaza4.geyserutils.geyser.util.ReflectionUtils;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
@@ -609,28 +610,45 @@ public class GeyserUtils implements Extension {
|
||||
}
|
||||
|
||||
private static int getColor(int argb) {
|
||||
TextColor color = TextColor.color(argb);
|
||||
List<TextColor> colors = Arrays.asList(
|
||||
TextColor.color(255, 255, 255), // 0: White
|
||||
TextColor.color(255, 170, 0), // 1: Orange -> Gold
|
||||
TextColor.color(255, 85, 255), // 2: Magenta -> Light Purple
|
||||
TextColor.color(85, 85, 255), // 3: Light Blue -> Blue
|
||||
TextColor.color(255, 255, 85), // 4: Yellow
|
||||
TextColor.color(85, 255, 85), // 5: Lime -> Green
|
||||
TextColor.color(255, 85, 85), // 6: Pink -> Red
|
||||
TextColor.color(170, 170, 170), // 7: Gray
|
||||
TextColor.color(85, 85, 85), // 8: Light Gray -> Dark Gray
|
||||
TextColor.color(85, 255, 255), // 9: Cyan -> Aqua
|
||||
TextColor.color(0, 170, 0), // 10: Green > Dark Green
|
||||
TextColor.color(0, 0, 170), // 11: Blue -> Dark Blue
|
||||
TextColor.color(170, 0, 170), // 12: Purple -> Dark Purple
|
||||
TextColor.color(0, 170, 0), // 13: Green -> Dark Green
|
||||
TextColor.color(170, 0, 0), // 14: Red -> Dark Red
|
||||
TextColor.color(0, 0, 0) // 15: Black
|
||||
int r = (argb >> 16) & 0xFF;
|
||||
int g = (argb >> 8) & 0xFF;
|
||||
int b = argb & 0xFF;
|
||||
|
||||
double[] colorLab = DeltaUtils.rgbToLab(r, g, b);
|
||||
|
||||
List<int[]> colors = Arrays.asList(
|
||||
new int[]{249, 255, 254}, // 0: White
|
||||
new int[]{249, 128, 29}, // 1: Orange
|
||||
new int[]{199, 78, 189}, // 2: Magenta
|
||||
new int[]{58, 179, 218}, // 3: Light Blue
|
||||
new int[]{254, 216, 61}, // 4: Yellow
|
||||
new int[]{128, 199, 31}, // 5: Lime
|
||||
new int[]{243, 139, 170}, // 6: Pink
|
||||
new int[]{71, 79, 82}, // 7: Gray
|
||||
new int[]{159, 157, 151}, // 8: Light Gray
|
||||
new int[]{22, 156, 156}, // 9: Cyan
|
||||
new int[]{137, 50, 184}, // 10: Purple
|
||||
new int[]{60, 68, 170}, // 11: Blue
|
||||
new int[]{131, 84, 50}, // 12: Brown
|
||||
new int[]{94, 124, 22}, // 13: Green
|
||||
new int[]{176, 46, 38}, // 14: Red
|
||||
new int[]{29, 29, 33} // 15: Black
|
||||
);
|
||||
|
||||
return colors.indexOf(TextColor.nearestColorTo(colors, color));
|
||||
int closestColorIndex = -1;
|
||||
double minDeltaE = Double.MAX_VALUE;
|
||||
|
||||
for (int i = 0; i < colors.size(); i++) {
|
||||
int[] rgb = colors.get(i);
|
||||
double[] lab = DeltaUtils.rgbToLab(rgb[0], rgb[1], rgb[2]);
|
||||
double deltaE = DeltaUtils.calculateDeltaE(colorLab, lab);
|
||||
if (deltaE < minDeltaE) {
|
||||
minDeltaE = deltaE;
|
||||
closestColorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return closestColorIndex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
package me.zimzaza4.geyserutils.geyser.util;
|
||||
|
||||
public class DeltaUtils {
|
||||
public static double calculateDeltaE(double[] lab1, double[] lab2) {
|
||||
// CIEDE2000 algorithm implementation
|
||||
double deltaL = lab2[0] - lab1[0];
|
||||
double lBar = (lab1[0] + lab2[0]) / 2.0;
|
||||
double c1 = Math.sqrt(lab1[1] * lab1[1] + lab1[2] * lab1[2]);
|
||||
double c2 = Math.sqrt(lab2[1] * lab2[1] + lab2[2] * lab2[2]);
|
||||
double cBar = (c1 + c2) / 2.0;
|
||||
double a1Prime = lab1[1] + lab1[1] / 2.0 * (1 - Math.sqrt(Math.pow(cBar, 7) / (Math.pow(cBar, 7) + Math.pow(25, 7))));
|
||||
double a2Prime = lab2[1] + lab2[1] / 2.0 * (1 - Math.sqrt(Math.pow(cBar, 7) / (Math.pow(cBar, 7) + Math.pow(25, 7))));
|
||||
double c1Prime = Math.sqrt(a1Prime * a1Prime + lab1[2] * lab1[2]);
|
||||
double c2Prime = Math.sqrt(a2Prime * a2Prime + lab2[2] * lab2[2]);
|
||||
double cBarPrime = (c1Prime + c2Prime) / 2.0;
|
||||
double deltaCPrime = c2Prime - c1Prime;
|
||||
double h1Prime = Math.atan2(lab1[2], a1Prime);
|
||||
if (h1Prime < 0) h1Prime += 2 * Math.PI;
|
||||
double h2Prime = Math.atan2(lab2[2], a2Prime);
|
||||
if (h2Prime < 0) h2Prime += 2 * Math.PI;
|
||||
double deltahPrime = h2Prime - h1Prime;
|
||||
if (Math.abs(deltahPrime) > Math.PI) deltahPrime -= 2 * Math.PI * Math.signum(deltahPrime);
|
||||
double deltaHPrime = 2 * Math.sqrt(c1Prime * c2Prime) * Math.sin(deltahPrime / 2.0);
|
||||
double lBarPrime = (lab1[0] + lab2[0]) / 2.0;
|
||||
double cBarPrimeDelta = (c1Prime + c2Prime) / 2.0;
|
||||
double hBarPrime = (h1Prime + h2Prime) / 2.0;
|
||||
if (Math.abs(h1Prime - h2Prime) > Math.PI) hBarPrime -= Math.PI;
|
||||
double t = 1 - 0.17 * Math.cos(hBarPrime - Math.PI / 6) + 0.24 * Math.cos(2 * hBarPrime) + 0.32 * Math.cos(3 * hBarPrime + Math.PI / 30) - 0.20 * Math.cos(4 * hBarPrime - 63 * Math.PI / 180);
|
||||
double deltaTheta = 30 * Math.exp(-((hBarPrime - 275 * Math.PI / 180) / 25 * Math.PI / 180) * ((hBarPrime - 275 * Math.PI / 180) / 25 * Math.PI / 180));
|
||||
double rC = 2 * Math.sqrt(Math.pow(cBarPrimeDelta, 7) / (Math.pow(cBarPrimeDelta, 7) + Math.pow(25, 7)));
|
||||
double sL = 1 + (0.015 * (lBarPrime - 50) * (lBarPrime - 50)) / Math.sqrt(20 + (lBarPrime - 50) * (lBarPrime - 50));
|
||||
double sC = 1 + 0.045 * cBarPrimeDelta;
|
||||
double sH = 1 + 0.015 * cBarPrimeDelta * t;
|
||||
double rT = -Math.sin(2 * deltaTheta) * rC;
|
||||
return Math.sqrt((deltaL / sL) * (deltaL / sL) + (deltaCPrime / sC) * (deltaCPrime / sC) + (deltaHPrime / sH) * (deltaHPrime / sH) + rT * (deltaCPrime / sC) * (deltaHPrime / sH));
|
||||
}
|
||||
|
||||
public static double[] rgbToLab(int r, int g, int b) {
|
||||
// Convert RGB to XYZ
|
||||
double[] xyz = rgbToXyz(r, g, b);
|
||||
// Convert XYZ to Lab
|
||||
return xyzToLab(xyz[0], xyz[1], xyz[2]);
|
||||
}
|
||||
|
||||
private static double[] rgbToXyz(int r, int g, int b) {
|
||||
double var_R = (r / 255.0);
|
||||
double var_G = (g / 255.0);
|
||||
double var_B = (b / 255.0);
|
||||
|
||||
if (var_R > 0.04045) var_R = Math.pow((var_R + 0.055) / 1.055, 2.4);
|
||||
else var_R = var_R / 12.92;
|
||||
if (var_G > 0.04045) var_G = Math.pow((var_G + 0.055) / 1.055, 2.4);
|
||||
else var_G = var_G / 12.92;
|
||||
if (var_B > 0.04045) var_B = Math.pow((var_B + 0.055) / 1.055, 2.4);
|
||||
else var_B = var_B / 12.92;
|
||||
|
||||
var_R = var_R * 100.0;
|
||||
var_G = var_G * 100.0;
|
||||
var_B = var_B * 100.0;
|
||||
|
||||
// Observer. = 2°, Illuminant = D65
|
||||
double x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
|
||||
double y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
|
||||
double z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
|
||||
|
||||
return new double[]{x, y, z};
|
||||
}
|
||||
|
||||
private static double[] xyzToLab(double x, double y, double z) {
|
||||
double ref_X = 95.047;
|
||||
double ref_Y = 100.000;
|
||||
double ref_Z = 108.883;
|
||||
|
||||
double var_X = x / ref_X;
|
||||
double var_Y = y / ref_Y;
|
||||
double var_Z = z / ref_Z;
|
||||
|
||||
if (var_X > 0.008856) var_X = Math.pow(var_X, 1.0/3.0);
|
||||
else var_X = (7.787 * var_X) + (16.0 / 116.0);
|
||||
if (var_Y > 0.008856) var_Y = Math.pow(var_Y, 1.0/3.0);
|
||||
else var_Y = (7.787 * var_Y) + (16.0 / 116.0);
|
||||
if (var_Z > 0.008856) var_Z = Math.pow(var_Z, 1.0/3.0);
|
||||
else var_Z = (7.787 * var_Z) + (16.0 / 116.0);
|
||||
|
||||
double l = (116.0 * var_Y) - 16.0;
|
||||
double a = 500.0 * (var_X - var_Y);
|
||||
double b = 200.0 * (var_Y - var_Z);
|
||||
|
||||
return new double[]{l, a, b};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user