mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-01-24 14:34:15 +08:00
parent
fb573d8205
commit
d4398764a1
@ -141,9 +141,9 @@ public class OfflineAccountSkinPane extends StackPane {
|
||||
return;
|
||||
}
|
||||
canvas.updateSkin(
|
||||
result.getSkin() != null ? new Image(result.getSkin().getInputStream()) : getDefaultTexture(),
|
||||
result.getSkin() != null ? result.getSkin().getImage() : getDefaultTexture(),
|
||||
result.getModel() == TextureModel.ALEX,
|
||||
result.getCape() != null ? new Image(result.getCape().getInputStream()) : null);
|
||||
result.getCape() != null ? result.getCape().getImage() : null);
|
||||
}
|
||||
}).start();
|
||||
}, skinItem.selectedDataProperty(), cslApiField.textProperty(), skinSelector.valueProperty(), capeSelector.valueProperty());
|
||||
|
@ -3,6 +3,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("org.glavo:simple-png-javafx:0.3.0")
|
||||
api("com.google.code.gson:gson:2.8.1")
|
||||
api("com.moandjiezana.toml:toml4j:0.7.2")
|
||||
api("org.tukaani:xz:1.8")
|
||||
|
@ -17,15 +17,12 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.auth.offline;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.PixelReader;
|
||||
import org.jackhuang.hmcl.util.Hex;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
@ -33,29 +30,21 @@ import java.util.Map;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class Texture {
|
||||
public final class Texture {
|
||||
private final String hash;
|
||||
private final byte[] data;
|
||||
private final Image image;
|
||||
|
||||
public Texture(String hash, byte[] data) {
|
||||
public Texture(String hash, Image image) {
|
||||
this.hash = requireNonNull(hash);
|
||||
this.data = requireNonNull(data);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
this.image = requireNonNull(image);
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return new ByteArrayInputStream(data);
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return data.length;
|
||||
public Image getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
private static final Map<String, Texture> textures = new HashMap<>();
|
||||
@ -68,15 +57,17 @@ public class Texture {
|
||||
return textures.get(hash);
|
||||
}
|
||||
|
||||
private static String computeTextureHash(BufferedImage img) {
|
||||
private static String computeTextureHash(Image img) {
|
||||
MessageDigest digest;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("SHA-256");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
int width = img.getWidth();
|
||||
int height = img.getHeight();
|
||||
|
||||
PixelReader reader = img.getPixelReader();
|
||||
int width = (int) img.getWidth();
|
||||
int height = (int) img.getHeight();
|
||||
byte[] buf = new byte[4096];
|
||||
|
||||
putInt(buf, 0, width);
|
||||
@ -84,7 +75,7 @@ public class Texture {
|
||||
int pos = 8;
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
putInt(buf, pos, img.getRGB(x, y));
|
||||
putInt(buf, pos, reader.getArgb(x, y));
|
||||
if (buf[pos + 0] == 0) {
|
||||
buf[pos + 1] = buf[pos + 2] = buf[pos + 3] = 0;
|
||||
}
|
||||
@ -99,8 +90,7 @@ public class Texture {
|
||||
digest.update(buf, 0, pos);
|
||||
}
|
||||
|
||||
byte[] sha256 = digest.digest();
|
||||
return String.format("%0" + (sha256.length << 1) + "x", new BigInteger(1, sha256));
|
||||
return Hex.encodeHex(digest.digest());
|
||||
}
|
||||
|
||||
private static void putInt(byte[] array, int offset, int x) {
|
||||
@ -112,25 +102,28 @@ public class Texture {
|
||||
|
||||
public static Texture loadTexture(InputStream in) throws IOException {
|
||||
if (in == null) return null;
|
||||
BufferedImage img;
|
||||
Image img;
|
||||
try (InputStream is = in) {
|
||||
img = ImageIO.read(is);
|
||||
}
|
||||
if (img == null) {
|
||||
throw new IIOException("No image found");
|
||||
img = new Image(is);
|
||||
}
|
||||
|
||||
String hash = computeTextureHash(img);
|
||||
if (img.isError()) {
|
||||
throw new IOException("No image found", img.getException());
|
||||
}
|
||||
return loadTexture(img);
|
||||
}
|
||||
|
||||
public static Texture loadTexture(Image image) {
|
||||
if (image == null) return null;
|
||||
|
||||
String hash = computeTextureHash(image);
|
||||
|
||||
Texture existent = textures.get(hash);
|
||||
if (existent != null) {
|
||||
return existent;
|
||||
}
|
||||
|
||||
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||
ImageIO.write(img, "png", buf);
|
||||
Texture texture = new Texture(hash, buf.toByteArray());
|
||||
|
||||
Texture texture = new Texture(hash, image);
|
||||
existent = textures.putIfAbsent(hash, texture);
|
||||
|
||||
if (existent != null) {
|
||||
@ -139,9 +132,4 @@ public class Texture {
|
||||
return texture;
|
||||
}
|
||||
|
||||
public static Texture loadTexture(String url) throws IOException {
|
||||
if (url == null) return null;
|
||||
return loadTexture(new URL(url).openStream());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
package org.jackhuang.hmcl.auth.offline;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.glavo.png.javafx.PNGJavaFXUtils;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.GameProfile;
|
||||
import org.jackhuang.hmcl.auth.yggdrasil.TextureModel;
|
||||
import org.jackhuang.hmcl.util.KeyUtils;
|
||||
@ -26,6 +27,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils;
|
||||
import org.jackhuang.hmcl.util.gson.UUIDTypeAdapter;
|
||||
import org.jackhuang.hmcl.util.io.HttpServer;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
@ -127,7 +129,8 @@ public class YggdrasilServer extends HttpServer {
|
||||
|
||||
if (Texture.hasTexture(hash)) {
|
||||
Texture texture = Texture.getTexture(hash);
|
||||
Response response = newFixedLengthResponse(Response.Status.OK, "image/png", texture.getInputStream(), texture.getLength());
|
||||
byte[] data = PNGJavaFXUtils.writeImageToArray(texture.getImage());
|
||||
Response response = newFixedLengthResponse(Response.Status.OK, "image/png", new ByteArrayInputStream(data), data.length);
|
||||
response.addHeader("Etag", String.format("\"%s\"", hash));
|
||||
response.addHeader("Cache-Control", "max-age=2592000, public");
|
||||
return response;
|
||||
|
Loading…
Reference in New Issue
Block a user