From d1b23cf186253964e1dd8a3ebf728c493aa9ee4d Mon Sep 17 00:00:00 2001 From: aaditagrawal <103925638+aaditagrawal@users.noreply.github.com> Date: Fri, 25 Oct 2024 15:07:09 +0530 Subject: [PATCH] Add files via upload --- src/GameOfLifeProcessor.java | 185 +++++++++++++++++ src/ImageProcessor.java | 113 +++++++++++ src/MusicPlayer.java | 82 ++++++++ src/TheImaniPulator.java | 374 +++++++++++++++++++++++++++++++++++ src/WelcomeScreen.java | 75 +++++++ 5 files changed, 829 insertions(+) create mode 100644 src/GameOfLifeProcessor.java create mode 100644 src/ImageProcessor.java create mode 100644 src/MusicPlayer.java create mode 100644 src/TheImaniPulator.java create mode 100644 src/WelcomeScreen.java diff --git a/src/GameOfLifeProcessor.java b/src/GameOfLifeProcessor.java new file mode 100644 index 0000000..ba42edd --- /dev/null +++ b/src/GameOfLifeProcessor.java @@ -0,0 +1,185 @@ +// GameOfLifeProcessor.java +package jfxlabproj.gameoflife; + +import java.util.concurrent.atomic.AtomicReference; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.image.PixelReader; +import javafx.scene.image.WritableImage; +import javafx.scene.paint.Color; +import javafx.util.Duration; + +public class GameOfLifeProcessor { + + private static Timeline timeline; + + public static void startGameOfLife(ImageView imageView) { + if (imageView.getImage() == null) return; + + // Convert to black and white with chunks + Image source = imageView.getImage(); + int width = 640; + int height = (int) (source.getHeight() * (640.0 / source.getWidth())); + int chunkSize = 8; // Reduced chunk size for better detail + WritableImage bwImage = new WritableImage(width, height); + PixelReader reader = source.getPixelReader(); + + // Calculate average brightness and variance of the entire image + double totalBrightness = 0; + double[] brightnesses = new double[width * height]; + int pixelCount = 0; + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + Color color = reader.getColor( + (int) ((x * source.getWidth()) / 640.0), + (int) ((y * source.getWidth()) / 640.0) + ); + double brightness = color.getBrightness(); + brightnesses[pixelCount] = brightness; + totalBrightness += brightness; + pixelCount++; + } + } + + double averageBrightness = totalBrightness / pixelCount; + + // Calculate variance + double variance = 0; + for (int i = 0; i < pixelCount; i++) { + variance += Math.pow(brightnesses[i] - averageBrightness, 2); + } + variance /= pixelCount; + + // Adjust threshold based on variance + double varianceWeight = Math.min(1.0, Math.max(0.1, variance * 10)); + double threshold = averageBrightness * varianceWeight; + + for (int y = 0; y < height; y += chunkSize) { + for (int x = 0; x < width; x += chunkSize) { + double chunkBrightness = 0; + int validPixels = 0; + + // Calculate average brightness for the chunk + for (int cy = 0; cy < chunkSize && (y + cy) < height; cy++) { + for (int cx = 0; cx < chunkSize && (x + cx) < width; cx++) { + Color color = reader.getColor( + (int) (((x + cx) * source.getWidth()) / 640.0), + (int) (((y + cy) * source.getWidth()) / 640.0) + ); + chunkBrightness += color.getBrightness(); + validPixels++; + } + } + + double avgChunkBrightness = chunkBrightness / validPixels; + Color chunkColor = (avgChunkBrightness < threshold) + ? Color.BLACK + : Color.WHITE; + + // Set the color for the entire chunk + for (int cy = 0; cy < chunkSize && (y + cy) < height; cy++) { + for (int cx = 0; cx < chunkSize && (x + cx) < width; cx++) { + bwImage + .getPixelWriter() + .setColor(x + cx, y + cy, chunkColor); + } + } + } + } + + AtomicReference bwImageRef = new AtomicReference<>( + bwImage + ); + imageView.setImage(bwImageRef.get()); + + // Start Game of Life + timeline = new Timeline( + new KeyFrame(Duration.millis(200), event -> { + WritableImage nextGeneration = new WritableImage(width, height); + PixelReader pixelReader = bwImageRef.get().getPixelReader(); + + for (int y = 0; y < height; y += chunkSize) { + for (int x = 0; x < width; x += chunkSize) { + int aliveNeighbors = countAliveNeighbors( + pixelReader, + x, + y, + width, + height, + chunkSize + ); + Color currentColor = pixelReader.getColor(x, y); + Color nextColor; + + if (currentColor.equals(Color.BLACK)) { + nextColor = (aliveNeighbors == 3 || + aliveNeighbors == 2) + ? Color.BLACK + : Color.WHITE; + } else { + nextColor = (aliveNeighbors == 3) + ? Color.BLACK + : Color.WHITE; + } + + // Set the color for the entire chunk in the next generation + for ( + int cy = 0; + cy < chunkSize && (y + cy) < height; + cy++ + ) { + for ( + int cx = 0; + cx < chunkSize && (x + cx) < width; + cx++ + ) { + nextGeneration + .getPixelWriter() + .setColor(x + cx, y + cy, nextColor); + } + } + } + } + + bwImageRef.set(nextGeneration); + imageView.setImage(bwImageRef.get()); + }) + ); + + timeline.setCycleCount(Timeline.INDEFINITE); + timeline.play(); + } + + public static void stopGameOfLife() { + if (timeline != null) { + timeline.stop(); + } + } + + private static int countAliveNeighbors( + PixelReader reader, + int x, + int y, + int width, + int height, + int chunkSize + ) { + int count = 0; + for (int dy = -chunkSize; dy <= chunkSize; dy += chunkSize) { + for (int dx = -chunkSize; dx <= chunkSize; dx += chunkSize) { + if (dx == 0 && dy == 0) continue; + int nx = x + dx; + int ny = y + dy; + if (nx >= 0 && nx < width && ny >= 0 && ny < height) { + if (reader.getColor(nx, ny).equals(Color.BLACK)) { + count++; + } + } + } + } + return count; + } +} diff --git a/src/ImageProcessor.java b/src/ImageProcessor.java new file mode 100644 index 0000000..57c6f4e --- /dev/null +++ b/src/ImageProcessor.java @@ -0,0 +1,113 @@ +// ImageProcessor.java +package jfxlabproj; + +import javafx.animation.FadeTransition; +import javafx.scene.effect.Bloom; +import javafx.scene.effect.ColorAdjust; +import javafx.scene.effect.DropShadow; +import javafx.scene.effect.GaussianBlur; +import javafx.scene.effect.InnerShadow; +import javafx.scene.effect.SepiaTone; +import javafx.scene.image.ImageView; +import javafx.scene.paint.Color; +import javafx.util.Duration; + +public class ImageProcessor { + + public static void applySepia(ImageView imageView) { + if (imageView.getImage() != null) { + SepiaTone sepia = new SepiaTone(0.7); + Bloom bloom = new Bloom(0.2); + bloom.setInput(sepia); + + DropShadow shadow = new DropShadow(); + shadow.setRadius(10.0); + shadow.setSpread(0.3); + shadow.setColor(Color.rgb(0, 0, 0, 0.4)); + shadow.setInput(bloom); + + FadeTransition ft = new FadeTransition( + Duration.millis(300), + imageView + ); + ft.setFromValue(0.7); + ft.setToValue(1.0); + + imageView.setEffect(shadow); + ft.play(); + } + } + + public static void applyInvert(ImageView imageView) { + if (imageView.getImage() != null) { + ColorAdjust colorAdjust = new ColorAdjust(); + colorAdjust.setBrightness(-1.0); + colorAdjust.setContrast(0); + colorAdjust.setHue(1.0); + colorAdjust.setSaturation(-1.0); + + InnerShadow innerShadow = new InnerShadow(); + innerShadow.setRadius(5.0); + innerShadow.setColor(Color.rgb(255, 255, 255, 0.3)); + innerShadow.setInput(colorAdjust); + + FadeTransition ft = new FadeTransition( + Duration.millis(300), + imageView + ); + ft.setFromValue(0.7); + ft.setToValue(1.0); + + imageView.setEffect(innerShadow); + ft.play(); + } + } + + public static void applyBlur(ImageView imageView) { + if (imageView.getImage() != null) { + GaussianBlur blur = new GaussianBlur(15); + Bloom bloom = new Bloom(0.3); + bloom.setInput(blur); + + DropShadow shadow = new DropShadow(); + shadow.setRadius(15.0); + shadow.setSpread(0.4); + shadow.setColor(Color.rgb(0, 0, 0, 0.3)); + shadow.setInput(bloom); + + FadeTransition ft = new FadeTransition( + Duration.millis(300), + imageView + ); + ft.setFromValue(0.7); + ft.setToValue(1.0); + + imageView.setEffect(shadow); + ft.play(); + } + } + + public static void applyGrayscale(ImageView imageView) { + if (imageView.getImage() != null) { + ColorAdjust grayscale = new ColorAdjust(); + grayscale.setSaturation(-1); + grayscale.setContrast(0.2); + grayscale.setBrightness(0.1); + + InnerShadow innerShadow = new InnerShadow(); + innerShadow.setRadius(5.0); + innerShadow.setColor(Color.rgb(0, 0, 0, 0.3)); + innerShadow.setInput(grayscale); + + FadeTransition ft = new FadeTransition( + Duration.millis(300), + imageView + ); + ft.setFromValue(0.7); + ft.setToValue(1.0); + + imageView.setEffect(innerShadow); + ft.play(); + } + } +} diff --git a/src/MusicPlayer.java b/src/MusicPlayer.java new file mode 100644 index 0000000..1e94fb6 --- /dev/null +++ b/src/MusicPlayer.java @@ -0,0 +1,82 @@ +package jfxlabproj.musicplayer; + +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javafx.scene.image.Image; +import javafx.scene.image.PixelReader; +import javafx.scene.paint.Color; +import javax.sound.sampled.*; + +public class MusicPlayer { + + private static final int BASE_NOTE = 262; // C4 note + private ScheduledExecutorService executor; + private volatile boolean isPlaying = false; + + public void playImageAsMusic(Image image) { + if (image == null) return; + if (isPlaying) return; // Prevent starting multiple playbacks simultaneously + + PixelReader reader = image.getPixelReader(); + int width = (int) image.getWidth(); + int height = (int) image.getHeight(); + + executor = Executors.newScheduledThreadPool(1); + isPlaying = true; + executor.scheduleAtFixedRate( + () -> { + Random random = new Random(); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (!isPlaying) return; // Stop processing if paused + + Color color = reader.getColor(x, y); + double brightness = color.getBrightness(); + int note = BASE_NOTE + (int) (brightness * 300); // Vary note based on brightness, reduced range for smoother sound + int duration = 150 + random.nextInt(150); // Randomize duration between 150ms and 300ms + playTone(note, duration, 0.2f); // Reduce volume + } + } + }, + 0, + 300, + TimeUnit.MILLISECONDS + ); + } + + public void pauseMusic() { + if (executor != null) { + isPlaying = false; + executor.shutdown(); + } + } + + private void playTone(int hz, int duration, float volume) { + try { + byte[] buf = new byte[1]; + AudioFormat audioFormat = new AudioFormat(44100, 8, 1, true, false); + SourceDataLine sdl = AudioSystem.getSourceDataLine(audioFormat); + sdl.open(audioFormat); + sdl.start(); + + FloatControl volumeControl = (FloatControl) sdl.getControl( + FloatControl.Type.MASTER_GAIN + ); + volumeControl.setValue(20f * (float) Math.log10(volume)); // Set volume level + + for (int i = 0; i < (duration * 44100) / 1000; i++) { + double angle = (i / (44100.0 / hz)) * 2.0 * Math.PI; + buf[0] = (byte) (Math.sin(angle) * 100.0); // Reduce amplitude for a softer sound + sdl.write(buf, 0, 1); + } + + sdl.drain(); + sdl.stop(); + sdl.close(); + } catch (LineUnavailableException e) { + e.printStackTrace(); + } + } +} diff --git a/src/TheImaniPulator.java b/src/TheImaniPulator.java new file mode 100644 index 0000000..26e0df4 --- /dev/null +++ b/src/TheImaniPulator.java @@ -0,0 +1,374 @@ +package jfxlabproj; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javafx.application.Application; +import javafx.embed.swing.SwingFXUtils; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; +import javafx.stage.FileChooser; +import javafx.stage.Stage; +import javax.imageio.ImageIO; +import jfxlabproj.gameoflife.GameOfLifeProcessor; +import jfxlabproj.musicplayer.MusicPlayer; + +public class TheImaniPulator extends Application { + + private ImageView imageView; + private Image originalImage; + private MusicPlayer musicPlayer; + private Button activeButton = null; + private Label statusLabel; + + @Override + public void start(Stage primaryStage) { + primaryStage.setTitle("Image Processor"); + + Scene welcomeScene = WelcomeScreen.createScene(primaryStage); + primaryStage.setScene(welcomeScene); + + primaryStage.show(); + } + + public Scene createMainScene(Stage primaryStage) { + HBox root = new HBox(30); + root.setAlignment(Pos.CENTER); + root.setStyle("-fx-background-color: #F5F5F7;"); + root.setPadding(new Insets(30)); + + VBox leftSide = new VBox(20); + leftSide.setAlignment(Pos.CENTER); + leftSide.setStyle( + "-fx-background-color: white; -fx-background-radius: 20; -fx-padding: 20;" + + "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 5);" + ); + + imageView = new ImageView(); + imageView.setFitWidth(400); + imageView.setFitHeight(500); + imageView.setPreserveRatio(true); + imageView.setStyle( + "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 5);" + ); + + statusLabel = new Label("Image Processor"); + statusLabel.setStyle( + "-fx-font-family: 'SF Pro Display'; -fx-font-size: 18px; " + + "-fx-font-weight: bold; -fx-text-fill: #1D1D1F;" + ); + + Button loadButton = new Button("Choose Image"); + styleButton(loadButton); + + leftSide.getChildren().addAll(imageView, loadButton, statusLabel); + + VBox rightSide = new VBox(15); + rightSide.setAlignment(Pos.TOP_CENTER); + rightSide.setPrefWidth(400); + rightSide.setStyle( + "-fx-background-color: white; -fx-background-radius: 20; -fx-padding: 30;" + + "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 10, 0, 0, 5);" + ); + + Label titleLabel = new Label("Image Processor"); + titleLabel.setStyle( + "-fx-font-family: 'SF Pro Display'; -fx-font-size: 32px; -fx-font-weight: bold;" + ); + titleLabel.setTextFill(Paint.valueOf("#1D1D1F")); + + Label filterLabel = new Label("Image Filters"); + Label saveLabel = new Label("Save Options"); + Label specialLabel = new Label("Special Effects"); + Label musicLabel = new Label("Music Controls"); + + filterLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16px;"); + saveLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16px;"); + specialLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16px;"); + musicLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16px;"); + + Button blurButton = new Button("Blur"); + Button grayscaleButton = new Button("Grayscale"); + Button sepiaButton = new Button("Sepia"); + Button resetButton = new Button("Reset"); + Button saveAsJpegButton = new Button("Save as JPEG"); + Button saveAsPngButton = new Button("Save as PNG"); + Button saveAsHeifButton = new Button("Save as HEIF"); + Button gameOfLifeButton = new Button("Game of Life"); + Button playMusicButton = new Button("Play as Music"); + Button pauseMusicButton = new Button("Pause Music"); + Button invertButton = new Button("Invert Colors"); + + int buttonWidth = 150; + for (Button btn : new Button[] { + blurButton, + grayscaleButton, + sepiaButton, + resetButton, + saveAsJpegButton, + saveAsPngButton, + saveAsHeifButton, + gameOfLifeButton, + playMusicButton, + pauseMusicButton, + invertButton, + }) { + styleButton(btn); + btn.setPrefWidth(buttonWidth); + btn.setWrapText(true); + } + + GridPane filterGrid = new GridPane(); + filterGrid.setHgap(10); + filterGrid.setVgap(10); + filterGrid.add(blurButton, 0, 0); + filterGrid.add(grayscaleButton, 1, 0); + filterGrid.add(sepiaButton, 0, 1); + filterGrid.add(resetButton, 1, 1); + filterGrid.add(invertButton, 0, 2); + + GridPane saveGrid = new GridPane(); + saveGrid.setHgap(10); + saveGrid.setVgap(10); + saveGrid.add(saveAsJpegButton, 0, 0); + saveGrid.add(saveAsPngButton, 1, 0); + saveGrid.add(saveAsHeifButton, 0, 1); + + GridPane specialGrid = new GridPane(); + specialGrid.setHgap(10); + specialGrid.add(gameOfLifeButton, 0, 0); + + GridPane musicGrid = new GridPane(); + musicGrid.setHgap(10); + musicGrid.add(playMusicButton, 0, 0); + musicGrid.add(pauseMusicButton, 1, 0); + + blurButton.setOnAction(e -> { + if (originalImage != null) { + setActiveButton(blurButton); + ImageProcessor.applyBlur(imageView); + updateStatus("Blur"); + } + }); + + grayscaleButton.setOnAction(e -> { + if (originalImage != null) { + setActiveButton(grayscaleButton); + ImageProcessor.applyGrayscale(imageView); + updateStatus("Grayscale"); + } + }); + + sepiaButton.setOnAction(e -> { + if (originalImage != null) { + setActiveButton(sepiaButton); + ImageProcessor.applySepia(imageView); + updateStatus("Sepia"); + } + }); + + invertButton.setOnAction(e -> { + if (originalImage != null) { + setActiveButton(invertButton); + ImageProcessor.applyInvert(imageView); + updateStatus("Invert Colors"); + } + }); + + resetButton.setOnAction(e -> { + if (originalImage != null) { + GameOfLifeProcessor.stopGameOfLife(); + setActiveButton(null); + imageView.setImage(originalImage); + imageView.setEffect(null); + updateStatus("Image Processor"); + } + }); + + saveAsJpegButton.setOnAction(e -> { + saveImage(primaryStage, "jpeg"); + updateStatus("Saving as JPEG"); + }); + + saveAsPngButton.setOnAction(e -> { + saveImage(primaryStage, "png"); + updateStatus("Saving as PNG"); + }); + + saveAsHeifButton.setOnAction(e -> { + saveImage(primaryStage, "heif"); + updateStatus("Saving as HEIF"); + }); + + gameOfLifeButton.setOnAction(e -> { + if (originalImage != null) { + setActiveButton(gameOfLifeButton); + GameOfLifeProcessor.startGameOfLife(imageView); + updateStatus("Game of Life"); + } + }); + + playMusicButton.setOnAction(e -> { + if (originalImage != null) { + setActiveButton(playMusicButton); + musicPlayer = new MusicPlayer(); + musicPlayer.playImageAsMusic(originalImage); + updateStatus("Playing Music"); + } + }); + + pauseMusicButton.setOnAction(e -> { + if (musicPlayer != null) { + setActiveButton(null); + musicPlayer.pauseMusic(); + updateStatus("Music Paused"); + } + }); + + loadButton.setOnAction(e -> { + FileChooser fileChooser = new FileChooser(); + fileChooser + .getExtensionFilters() + .add( + new FileChooser.ExtensionFilter( + "Image Files", + "*.png", + "*.jpg", + "*.jpeg", + "*.gif" + ) + ); + File file = fileChooser.showOpenDialog(primaryStage); + if (file != null) { + Image image = new Image(file.toURI().toString()); + imageView.setImage(image); + originalImage = image; + setActiveButton(null); + updateStatus("Image Processor"); + } + }); + + rightSide + .getChildren() + .addAll( + titleLabel, + filterLabel, + filterGrid, + saveLabel, + saveGrid, + specialLabel, + specialGrid, + musicLabel, + musicGrid + ); + + root.getChildren().addAll(leftSide, rightSide); + + Scene scene = new Scene(root, 1000, 700); + scene.setFill(Color.web("#F5F5F7")); + + return scene; + } + + private void updateStatus(String status) { + statusLabel.setText(status); + } + + private void setActiveButton(Button button) { + if (activeButton != null) { + styleButton(activeButton); + } + activeButton = button; + if (activeButton != null) { + activeButton.setStyle( + "-fx-background-color: #FFC799;" + + "-fx-text-fill: black;" + + "-fx-font-family: 'SF Pro Text';" + + "-fx-font-size: 16px;" + + "-fx-padding: 12px 20px;" + + "-fx-background-radius: 10px;" + + "-fx-cursor: hand;" + + "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.2), 10, 0, 0, 5);" + ); + } + } + + private void saveImage(Stage stage, String format) { + if (imageView.getImage() != null) { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save Image"); + fileChooser.setInitialFileName("processed_image." + format); + fileChooser + .getExtensionFilters() + .add( + new FileChooser.ExtensionFilter( + format.toUpperCase() + " files", + "*." + format + ) + ); + File file = fileChooser.showSaveDialog(stage); + if (file != null) { + try { + BufferedImage bufferedImage = SwingFXUtils.fromFXImage( + imageView.getImage(), + null + ); + ImageIO.write(bufferedImage, format, file); + } catch (IOException ex) { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("Error"); + alert.setHeaderText("Could not save image"); + alert.setContentText("Error: " + ex.getMessage()); + alert.showAndWait(); + } + } + } + } + + private void styleButton(Button button) { + String defaultStyle = + "-fx-background-color: #F5F5F7;" + + "-fx-text-fill: #1D1D1F;" + + "-fx-font-family: 'SF Pro Text';" + + "-fx-font-size: 16px;" + + "-fx-padding: 12px 20px;" + + "-fx-background-radius: 10px;" + + "-fx-cursor: hand;" + + "-fx-border-color: #D2D2D7;" + + "-fx-border-radius: 10px;" + + "-fx-border-width: 1px;"; + + String hoverStyle = + "-fx-background-color: #E8E8ED;" + + "-fx-text-fill: #1D1D1F;" + + "-fx-font-family: 'SF Pro Text';" + + "-fx-font-size: 16px;" + + "-fx-padding: 12px 20px;" + + "-fx-background-radius: 10px;" + + "-fx-cursor: hand;" + + "-fx-border-color: #007AFF;" + + "-fx-border-radius: 10px;" + + "-fx-border-width: 2px;" + + "-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.1), 5, 0, 0, 2);"; + + button.setStyle(defaultStyle); + button.setOnMouseEntered(e -> button.setStyle(hoverStyle)); + button.setOnMouseExited(e -> button.setStyle(defaultStyle)); + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/src/WelcomeScreen.java b/src/WelcomeScreen.java new file mode 100644 index 0000000..a2711e3 --- /dev/null +++ b/src/WelcomeScreen.java @@ -0,0 +1,75 @@ +package jfxlabproj; + +import javafx.animation.FadeTransition; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; +import javafx.stage.Stage; +import javafx.util.Duration; + +public class WelcomeScreen { + + public static Scene createScene(Stage primaryStage) { + VBox root = new VBox(30); + root.setAlignment(Pos.CENTER); + root.setStyle("-fx-background-color: #1E1E1E;" + "-fx-padding: 40px;"); + + Label welcomeLabel = new Label("Image Processor"); + welcomeLabel.setStyle( + "-fx-font-family: 'SF Pro Display';" + + "-fx-font-size: 48px;" + + "-fx-font-weight: bold;" + + "-fx-text-fill: #FFFFFF;" + ); + + Label subtitleLabel = new Label("Made by Aadit, Akhil and Saurabh."); + subtitleLabel.setStyle( + "-fx-font-family: 'SF Pro Text';" + + "-fx-font-size: 18px;" + + "-fx-text-fill: #BBBBBB;" + ); + + Button nextButton = new Button("Get Started"); + nextButton.setStyle( + "-fx-background-color: #0F0F0F;" + + "-fx-text-fill: white;" + + "-fx-font-family: 'SF Pro Text';" + + "-fx-font-size: 16px;" + + "-fx-padding: 12px 24px;" + + "-fx-background-radius: 8px;" + + "-fx-cursor: hand;" + ); + + nextButton.setOnMouseEntered(e -> + nextButton.setStyle( + nextButton.getStyle() + "-fx-background-color: #0071E3;" + ) + ); + nextButton.setOnMouseExited(e -> + nextButton.setStyle( + nextButton.getStyle() + "-fx-background-color: #0F0F0F;" + ) + ); + + nextButton.setOnAction(e -> { + FadeTransition ft = new FadeTransition(Duration.millis(300), root); + ft.setFromValue(1.0); + ft.setToValue(0.0); + ft.setOnFinished(event -> { + TheImaniPulator mainApp = new TheImaniPulator(); + primaryStage.setScene(mainApp.createMainScene(primaryStage)); + }); + ft.play(); + }); + + root.getChildren().addAll(welcomeLabel, subtitleLabel, nextButton); + + Scene scene = new Scene(root, 800, 600); + scene.setFill(Color.web("#1E1E1E")); + + return scene; + } +}