/
MapImage.java
150 lines (135 loc) · 5.03 KB
/
MapImage.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package net.aufdemrand.denizen.utilities.maps;
import net.aufdemrand.denizen.objects.dPlayer;
import net.aufdemrand.denizen.utilities.debugging.dB;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapPalette;
import org.bukkit.map.MapView;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MapImage extends MapObject {
protected boolean useCache;
protected byte[] cachedImage;
protected Image image;
protected ImageIcon imageIcon;
protected int width = 0;
protected int height = 0;
protected String fileTag;
protected String actualFile = null;
public MapImage(String xTag, String yTag, String visibilityTag, boolean debug, String fileTag,
int width, int height) {
this(xTag, yTag, visibilityTag, debug, fileTag, width, height, true);
}
public MapImage(String xTag, String yTag, String visibilityTag, boolean debug, String fileTag,
int width, int height, boolean useCache) {
super(xTag, yTag, visibilityTag, debug);
this.useCache = useCache;
if (useCache) {
this.cachedImage = null;
}
this.fileTag = fileTag;
if (width > 0 || height > 0) {
this.width = width > 0 ? width : 0;
this.height = height > 0 ? height : 0;
}
}
protected void setImage(Image image) {
this.image = image;
}
@Override
public Map<String, Object> getSaveData() {
Map<String, Object> data = super.getSaveData();
data.put("type", "IMAGE");
data.put("width", width);
data.put("height", height);
data.put("image", fileTag);
return data;
}
@Override
public void render(MapView mapView, MapCanvas mapCanvas, dPlayer player, UUID uuid) {
if (actualFile == null) {
String file = fileTag;
actualFile = DenizenMapManager.getActualFile(file);
imageIcon = new ImageIcon(actualFile);
image = imageIcon.getImage();
if (width == 0) {
width = image.getWidth(null);
}
if (height == 0) {
height = image.getHeight(null);
}
}
// Use custom functions to draw image to allow transparency and reduce lag intensely
byte[] bytes;
if (!useCache || cachedImage == null) {
bytes = imageToBytes(image, width, height);
if (useCache) {
cachedImage = bytes;
}
}
else {
bytes = cachedImage;
}
int x = getX(player, uuid);
int y = getY(player, uuid);
for (int x2 = 0; x2 < width; ++x2) {
for (int y2 = 0; y2 < height; ++y2) {
byte p = bytes[y2 * width + x2];
if (p != MapPalette.TRANSPARENT)
mapCanvas.setPixel(x + x2, y + y2, p);
}
}
}
private static final Color[] bukkitColors;
static {
Color[] colors = null;
try {
Field field = MapPalette.class.getDeclaredField("colors");
field.setAccessible(true);
colors = (Color[]) field.get(null);
} catch (Exception e) {
dB.echoError(e);
}
bukkitColors = colors;
}
private static byte[] imageToBytes(Image image, int width, int height) {
BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = temp.createGraphics();
graphics.drawImage(image, 0, 0, width, height, null);
graphics.dispose();
int[] pixels = new int[width * height];
temp.getRGB(0, 0, width, height, pixels, 0, width);
byte[] result = new byte[width * height];
for (int i = 0; i < pixels.length; i++) {
result[i] = matchColor(new Color(pixels[i]));
}
return result;
}
private static byte matchColor(Color color) {
if (color.getAlpha() < 128) return 0;
int index = 0;
double best = -1;
for (int i = 4; i < bukkitColors.length; i++) {
double distance = getDistance(color, bukkitColors[i]);
if (distance < best || best == -1) {
best = distance;
index = i;
}
}
return (byte) (index < 128 ? index : -129 + (index - 127));
}
private static double getDistance(Color c1, Color c2) {
double rmean = (c1.getRed() + c2.getRed()) / 2.0;
double r = c1.getRed() - c2.getRed();
double g = c1.getGreen() - c2.getGreen();
int b = c1.getBlue() - c2.getBlue();
double weightR = 2 + rmean / 256.0;
double weightG = 4.0;
double weightB = 2 + (255 - rmean) / 256.0;
return weightR * r * r + weightG * g * g + weightB * b * b;
}
}