diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/theme/Themes.java b/HMCL/src/main/java/org/jackhuang/hmcl/theme/Themes.java index ced817d7c0..36ff2f2594 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/theme/Themes.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/theme/Themes.java @@ -29,11 +29,11 @@ import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.SetChangeListener; +import javafx.embed.swing.SwingFXUtils; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.image.Image; -import javafx.scene.image.PixelReader; -import javafx.scene.image.PixelWriter; +import javafx.scene.image.PixelFormat; import javafx.scene.image.WritableImage; import javafx.scene.layout.Background; import javafx.scene.layout.BackgroundFill; @@ -78,6 +78,9 @@ import org.jetbrains.annotations.NotNullByDefault; import org.jetbrains.annotations.Nullable; +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -941,10 +944,11 @@ private static Background createThemeColorBackground(double opacity) { /// Creates a JavaFX image background with the requested opacity. private static Background createBackgroundWithOpacity(Image image, double opacity) { - PixelReader pixelReader = image.getPixelReader(); + if (image == null) return null; + if (opacity <= 0) { return new Background(new BackgroundFill(new Color(1, 1, 1, 0), CornerRadii.EMPTY, Insets.EMPTY)); - } else if (opacity >= 1. || pixelReader == null) { + } else if (opacity >= 1.0 || image.getPixelReader() == null) { return new Background(new BackgroundImage( image, BackgroundRepeat.NO_REPEAT, @@ -953,22 +957,43 @@ private static Background createBackgroundWithOpacity(Image image, double opacit new BackgroundSize(800, 480, false, false, true, true) )); } else { - WritableImage tempImage = new WritableImage((int) image.getWidth(), (int) image.getHeight()); - PixelWriter pixelWriter = tempImage.getPixelWriter(); - for (int y = 0; y < image.getHeight(); y++) { - for (int x = 0; x < image.getWidth(); x++) { - Color color = pixelReader.getColor(x, y); - Color newColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getOpacity() * opacity); - pixelWriter.setColor(x, y, newColor); - } + int targetWidth = 800; + int targetHeight = 480; + + double imageWidth = image.getWidth(); + double imageHeight = image.getHeight(); + + double scale = Math.max(targetWidth / imageWidth, targetHeight / imageHeight); + + BufferedImage srcBuffered = SwingFXUtils.fromFXImage(image, null); + + BufferedImage destBuffered = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = destBuffered.createGraphics(); + + AffineTransform at = new AffineTransform(); + at.scale(scale, scale); + g2d.drawImage(srcBuffered, at, null); + g2d.dispose(); + + WritableImage tempImage = SwingFXUtils.toFXImage(destBuffered, null); + + int[] buffer = new int[targetWidth * targetHeight]; + tempImage.getPixelReader().getPixels(0, 0, targetWidth, targetHeight, PixelFormat.getIntArgbInstance(), buffer, 0, targetWidth); + + int alphaMultiplier = (int) (opacity * 255); + for (int i = 0; i < buffer.length; i++) { + int argb = buffer[i]; + int a = ((argb >>> 24) * alphaMultiplier) / 255; + buffer[i] = (a << 24) | (argb & 0x00FFFFFF); } + tempImage.getPixelWriter().setPixels(0, 0, targetWidth, targetHeight, PixelFormat.getIntArgbInstance(), buffer, 0, targetWidth); + return new Background(new BackgroundImage( tempImage, - BackgroundRepeat.NO_REPEAT, - BackgroundRepeat.NO_REPEAT, + BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT, - new BackgroundSize(800, 480, false, false, true, true) + new BackgroundSize(targetWidth, targetHeight, false, false, true, true) )); } }