9
0
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:
OmeWillem
2024-07-06 02:41:10 +02:00
parent 1d16abdacf
commit 1d1093ba1f
2 changed files with 128 additions and 19 deletions

View File

@@ -22,6 +22,7 @@ import me.zimzaza4.geyserutils.geyser.replace.JavaAddEntityTranslatorReplace;
import me.zimzaza4.geyserutils.geyser.scoreboard.EntityScoreboard; import me.zimzaza4.geyserutils.geyser.scoreboard.EntityScoreboard;
import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator; import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator;
import me.zimzaza4.geyserutils.geyser.util.Converter; import me.zimzaza4.geyserutils.geyser.util.Converter;
import me.zimzaza4.geyserutils.geyser.util.DeltaUtils;
import me.zimzaza4.geyserutils.geyser.util.ReflectionUtils; import me.zimzaza4.geyserutils.geyser.util.ReflectionUtils;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
@@ -609,28 +610,45 @@ public class GeyserUtils implements Extension {
} }
private static int getColor(int argb) { private static int getColor(int argb) {
TextColor color = TextColor.color(argb); int r = (argb >> 16) & 0xFF;
List<TextColor> colors = Arrays.asList( int g = (argb >> 8) & 0xFF;
TextColor.color(255, 255, 255), // 0: White int b = argb & 0xFF;
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
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;
} }
} }

View File

@@ -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};
}
}