Remove drawAvatarJ2D (#2027)

This commit is contained in:
Glavo
2023-02-02 21:26:58 +08:00
committed by GitHub
parent c86302df58
commit 259ed570ab

View File

@@ -23,6 +23,7 @@ import javafx.beans.value.ObservableValue;
import javafx.scene.canvas.Canvas; import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext; import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image; import javafx.scene.image.Image;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter; import javafx.scene.image.PixelWriter;
import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.auth.Account; import org.jackhuang.hmcl.auth.Account;
@@ -30,13 +31,10 @@ import org.jackhuang.hmcl.auth.ServerResponseMalformedException;
import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount; import org.jackhuang.hmcl.auth.microsoft.MicrosoftAccount;
import org.jackhuang.hmcl.auth.yggdrasil.*; import org.jackhuang.hmcl.auth.yggdrasil.*;
import org.jackhuang.hmcl.task.FileDownloadTask; import org.jackhuang.hmcl.task.FileDownloadTask;
import org.jackhuang.hmcl.ui.FXUtils;
import org.jackhuang.hmcl.util.ResourceNotFoundError; import org.jackhuang.hmcl.util.ResourceNotFoundError;
import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.javafx.BindingMapping; import org.jackhuang.hmcl.util.javafx.BindingMapping;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -217,23 +215,25 @@ public final class TexturesLoader {
// ==== Avatar ==== // ==== Avatar ====
public static void drawAvatar(Canvas canvas, Image skin) { public static void drawAvatar(Canvas canvas, Image skin) {
canvas.getGraphicsContext2D().clearRect(0, 0, canvas.getWidth(), canvas.getHeight()); GraphicsContext g = canvas.getGraphicsContext2D();
g.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
int size = (int) canvas.getWidth(); int size = (int) canvas.getWidth();
int scale = (int) skin.getWidth() / 64; int scale = (int) skin.getWidth() / 64;
int faceOffset = (int) Math.round(size / 18.0); int faceOffset = (int) Math.round(size / 18.0);
GraphicsContext g = canvas.getGraphicsContext2D();
try { try {
g.setImageSmoothing(false); g.setImageSmoothing(false);
drawAvatarFX(g, skin, size, scale, faceOffset); drawAvatar(g, skin, size, scale, faceOffset);
} catch (NoSuchMethodError ignored) { } catch (NoSuchMethodError ignored) {
// Earlier JavaFX did not support GraphicsContext::setImageSmoothing, fallback to Java 2D // Earlier JavaFX did not support GraphicsContext::setImageSmoothing
drawAvatarJ2D(g, skin, size, scale, faceOffset); // In order to prevent the blurring caused by bilinear interpolation,
// we use the self-implemented nearest neighbor interpolation to scale
drawAvatarSlow(g, skin, size, scale, faceOffset);
} }
} }
private static void drawAvatarFX(GraphicsContext g, Image skin, int size, int scale, int faceOffset) { private static void drawAvatar(GraphicsContext g, Image skin, int size, int scale, int faceOffset) {
g.drawImage(skin, g.drawImage(skin,
8 * scale, 8 * scale, 8 * scale, 8 * scale, 8 * scale, 8 * scale, 8 * scale, 8 * scale,
faceOffset, faceOffset, size - 2 * faceOffset, size - 2 * faceOffset); faceOffset, faceOffset, size - 2 * faceOffset, size - 2 * faceOffset);
@@ -242,27 +242,33 @@ public final class TexturesLoader {
0, 0, size, size); 0, 0, size, size);
} }
private static void drawAvatarJ2D(GraphicsContext g, Image skin, int size, int scale, int faceOffset) { private static void drawAvatarSlow(GraphicsContext g, Image skin, int size, int scale, int faceOffset) {
BufferedImage bi = FXUtils.fromFXImage(skin); PixelReader reader = skin.getPixelReader();
PixelWriter writer = g.getPixelWriter();
drawImage(writer, reader,
8 * scale, 8 * scale, 8 * scale, 8 * scale,
faceOffset, faceOffset, size - 2 * faceOffset, size - 2 * faceOffset);
drawImage(writer, reader,
40 * scale, 8 * scale, 8 * scale, 8 * scale,
0, 0, size, size);
}
BufferedImage avatar = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); /*
Graphics2D g2d = avatar.createGraphics(); * Scale and draw image using nearest-neighbor interpolation
*/
private static void drawImage(PixelWriter writer, PixelReader reader,
int sx, int sy, int sw, int sh,
int dx, int dy, int dw, int dh) {
double xScale = ((double) sw) / dw;
double yScale = ((double) sh) / dh;
g2d.drawImage(bi, for (int xOffset = 0; xOffset < dw; xOffset++) {
faceOffset, faceOffset, size - faceOffset, size - faceOffset, for (int yOffset = 0; yOffset < dh; yOffset++) {
8 * scale, 8 * scale, 16 * scale, 16 * scale, int color = reader.getArgb(sx + (int) (xOffset * xScale), sy + (int) (yOffset * yScale));
null);
g2d.drawImage(bi,
0, 0, size, size,
40 * scale, 8 * scale, 48 * scale, 16 * scale, null);
g2d.dispose(); // Draw only non-transparent pixels
if ((color >>> 24) != 0)
PixelWriter pw = g.getPixelWriter(); writer.setArgb(dx + xOffset, dy + yOffset, color);
for (int x = 0; x < size; x++) {
for (int y = 0; y < size; y++) {
pw.setArgb(x, y, avatar.getRGB(x, y));
} }
} }
} }