From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: epserv Date: Sun, 6 Dec 2020 16:57:19 +0500 Subject: [PATCH] Optimise Bukkit's MapPalette diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java index 95fe3f4d081053a6cf484e4ef07b474f2dc2ab02..beef3860f9f3bdd8c1924663fe5042501bcc6898 100644 --- a/src/main/java/org/bukkit/map/MapPalette.java +++ b/src/main/java/org/bukkit/map/MapPalette.java @@ -22,7 +22,9 @@ public final class MapPalette { return new Color(r, g, b); } - private static double getDistance(@NotNull Color c1, @NotNull Color c2) { + // Yatopia start - faster method + private static int getDistanceSquared(@NotNull Color c1, @NotNull Color c2) { + /* double rmean = (c1.getRed() + c2.getRed()) / 2.0; double r = c1.getRed() - c2.getRed(); double g = c1.getGreen() - c2.getGreen(); @@ -31,7 +33,21 @@ public final class MapPalette { double weightG = 4.0; double weightB = 2 + (255 - rmean) / 256.0; return weightR * r * r + weightG * g * g + weightB * b * b; + */ + if (c1.getRGB() == c2.getRGB()) { + return 0; + } + int r = c1.getRed() - c2.getRed(), + g = c1.getGreen() - c2.getGreen(), + b = c1.getBlue() - c2.getBlue(); + // because of performed tests, this accuracy is enough + return r * r + g * g + b * b; + } + // getDistance method itself + private static double getDistance(@NotNull Color c1, @NotNull Color c2) { + return Math.sqrt(getDistanceSquared(c1, c2)); } + // Yatopia end @NotNull static final Color[] colors = { @@ -95,6 +111,24 @@ public final class MapPalette { c(60, 31, 43), c(74, 37, 53), c(86, 44, 62), c(45, 23, 32), c(14, 127, 93), c(17, 155, 114), c(20, 180, 133), c(10, 95, 70) }; + // Yatopia start + @NotNull + static Color[] sortedColors = new Color[colors.length]; + @NotNull + static int[] sortedRgbColors = new int[colors.length]; + @NotNull + static int[] rgbColors = new int[colors.length]; + static { + for (short i = 0; i < rgbColors.length; i++) { + rgbColors[i] = colors[i].getRGB(); + } + sortedRgbColors = rgbColors.clone(); + java.util.Arrays.sort(sortedRgbColors); + for (short i = 0; i < sortedColors.length; i++) { + sortedColors[i] = new Color(sortedRgbColors[i]); + } + } + // Yatopia end // Interface /** @@ -235,6 +269,8 @@ public final class MapPalette { public static byte matchColor(@NotNull Color color) { if (color.getAlpha() < 128) return 0; + // Yatopia start - use binary search + /* int index = 0; double best = -1; @@ -245,9 +281,30 @@ public final class MapPalette { index = i; } } + */ + int index = 0; + int binaryIndex = java.util.Arrays.binarySearch(sortedRgbColors, color.getRGB()); + if (binaryIndex >= 0) { + return (byte) (binaryIndex < 128 ? binaryIndex : binaryIndex - 256); + } + int insertionPoint = (-binaryIndex) - 1; + if (insertionPoint == sortedColors.length - 1) { + index = sortedColors.length - 1; + } else { + // now don't loop over all the colors, just select one of neighbor colors + // we don't need a distance itself, so we can use distance squared + int d1 = getDistanceSquared(color, sortedColors[insertionPoint - 1]), d2 = getDistanceSquared(color, sortedColors[insertionPoint]); + if (d1 > d2) { + index = insertionPoint; + } else { + index = insertionPoint - 1; + } + } + index = com.google.common.primitives.Ints.indexOf(rgbColors, sortedRgbColors[index]); + // Yatopia end // Minecraft has 143 colors, some of which have negative byte representations - return (byte) (index < 128 ? index : -129 + (index - 127)); + return (byte) (index < 128 ? index : index - 256); // Yatopia } /**