Untitled

 avatar
unknown
plain_text
5 months ago
31 kB
3
Indexable
package com.example.multimediadata;

import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.image.*;
import javafx.stage.FileChooser;
import javafx.scene.paint.Color;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.*;

public class HelloController implements Initializable {
    @FXML
    private ComboBox<String> categoryComboBox;
    @FXML
    private ComboBox<String> subMethodComboBox;
    @FXML
    private ImageView beforeImageView;
    @FXML
    private ImageView afterImageView;
    @FXML
    private Slider powerSlider;
    @FXML
    private Label laplacianLabel;
    @FXML
    private CheckBox laplacianCheckBox;
    @FXML
    private Label histogramLabel;
    @FXML
    private CheckBox histogramCheckBox;
    @FXML
    private ImageView originalHistogramView;
    @FXML
    private ImageView modifiedHistogramView;
    @FXML
    private Slider thresholdSlider;
    @FXML
    private Label thresholdLabel;
    @FXML
    private Label otsuThresholdLabel;

    private WritableImage laplacianImage;
    private File selectedFile;
    private String selectedCategory = "Ничего";
    private String selectedSubMethod = "";

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        categoryComboBox.setValue("Ничего");
        subMethodComboBox.setVisible(false);
        subMethodComboBox.setItems(FXCollections.observableArrayList());
        subMethodComboBox.setValue(null);

        powerSlider.setVisible(false);
        laplacianLabel.setVisible(false);
        laplacianCheckBox.setVisible(false);
        thresholdSlider.setVisible(false);
        thresholdLabel.setVisible(false);
        otsuThresholdLabel.setVisible(false);
    }

    @FXML
    public void onSelectPhoto() {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Выберите изображение");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg", "*.jpeg")
        );
        selectedFile = fileChooser.showOpenDialog(null);
        if (selectedFile != null) {
            try {
                Image image = new Image(new FileInputStream(selectedFile));
                beforeImageView.setImage(image);
                beforeImageView.setPreserveRatio(true);
                applyChanges();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
    }

    @FXML
    public void onCategoryChange() {
        selectedCategory = categoryComboBox.getValue();
        selectedSubMethod = "";
        subMethodComboBox.getItems().clear();
        subMethodComboBox.setValue(null);
        powerSlider.setVisible(false);
        laplacianLabel.setVisible(false);
        laplacianCheckBox.setVisible(false);
        thresholdSlider.setVisible(false);
        thresholdLabel.setVisible(false);
        otsuThresholdLabel.setVisible(false);

        subMethodComboBox.setVisible(false);

        if (selectedCategory.equals("Градиент")) {
            subMethodComboBox.setItems(FXCollections.observableArrayList("Робертса", "Собеля"));
            subMethodComboBox.setVisible(true);
        } else if (selectedCategory.equals("Пороговый фильтр")) {
            subMethodComboBox.setItems(FXCollections.observableArrayList("Глобальный порог", "Метод Оцу"));
            subMethodComboBox.setVisible(true);
        }

        applyChanges();
    }

    @FXML
    public void onSubMethodChange() {
        selectedSubMethod = subMethodComboBox.getValue();
        applyChanges();
    }

    @FXML
    public void onSliderChange() {
        applyChanges();
    }

    @FXML
    public void onThresholdSliderChange() {
        applyChanges();
    }

    @FXML
    public void onLaplacianCheckBoxChange() {
        applyChanges();
    }

    @FXML
    public void onHistogramCheckBoxChange() {
        if (histogramCheckBox.isSelected()) {
            generateAndDisplayHistograms();
        } else {
            originalHistogramView.setVisible(false);
            modifiedHistogramView.setVisible(false);
        }
    }

    private void applyChanges() {
        if (selectedFile != null) {
            powerSlider.setVisible(false);
            laplacianLabel.setVisible(false);
            laplacianCheckBox.setVisible(false);
            thresholdSlider.setVisible(false);
            thresholdLabel.setVisible(false);
            otsuThresholdLabel.setVisible(false);

            switch (selectedCategory) {
                case "Ничего":
                    applyNoEffect();
                    break;
                case "Негатив":
                    applyNegativeEffect();
                    break;
                case "Степенное преобразование":
                    powerSlider.setVisible(true);
                    applyPowerTransformation();
                    break;
                case "Лапласиан":
                    laplacianLabel.setVisible(true);
                    laplacianCheckBox.setVisible(true);
                    applyLaplacian();
                    break;
                case "Градиент":
                    if (selectedSubMethod != null) {
                        switch (selectedSubMethod) {
                            case "Робертса":
                                applyRobertsGradient();
                                break;
                            case "Собеля":
                                applySobelGradient();
                                break;
                        }
                    }
                    break;
                case "Пороговый фильтр":
                    if (selectedSubMethod != null) {
                        switch (selectedSubMethod) {
                            case "Глобальный порог":
                                thresholdSlider.setVisible(true);
                                thresholdLabel.setVisible(true);
                                applyGlobalThreshold();
                                break;
                            case "Метод Оцу":
                                otsuThresholdLabel.setVisible(true);
                                applyOtsuThreshold();
                                break;
                        }
                    }
                    break;
                case "Линейный сглаживающий (усредняющий) фильтр":
                    applyAverageFilter();
                    break;
                case "Медианный фильтр":
                    applyMedianFilter();
                    break;
                case "Эквализация гистограммы":
                    applyHistogramEqualization();
                    break;
                default:
                    applyNoEffect();
                    break;
            }

            if (histogramCheckBox.isSelected()) {
                generateAndDisplayHistograms();
            }
        }
    }

    private void applyNoEffect() {
        Image originalImage = beforeImageView.getImage();
        afterImageView.setImage(originalImage);
    }

    private void applyNegativeEffect() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();

            WritableImage afterImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = afterImage.getPixelWriter();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int alpha = (argb >> 24) & 0xff;
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;

                    int negRed = 255 - red;
                    int negGreen = 255 - green;
                    int negBlue = 255 - blue;

                    int negativeArgb = (alpha << 24) | (negRed << 16) | (negGreen << 8) | negBlue;
                    writer.setArgb(x, y, negativeArgb);
                }
            }
            afterImageView.setImage(afterImage);
        }
    }

    private void applyPowerTransformation() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();
            double gamma = powerSlider.getValue();

            WritableImage afterImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = afterImage.getPixelWriter();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int alpha = (argb >> 24) & 0xff;
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;

                    int newRed = clamp((int) (255 * Math.pow((red / 255.0), gamma)));
                    int newGreen = clamp((int) (255 * Math.pow((green / 255.0), gamma)));
                    int newBlue = clamp((int) (255 * Math.pow((blue / 255.0), gamma)));

                    int powerArgb = (alpha << 24) | (newRed << 16) | (newGreen << 8) | newBlue;
                    writer.setArgb(x, y, powerArgb);
                }
            }
            afterImageView.setImage(afterImage);
        }
    }

    private void applyRobertsGradient() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();

            WritableImage afterImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = afterImage.getPixelWriter();

            for (int y = 0; y < height - 1; y++) {
                for (int x = 0; x < width - 1; x++) {
                    int argb1 = reader.getArgb(x, y);
                    int argb2 = reader.getArgb(x + 1, y + 1);
                    int argb3 = reader.getArgb(x + 1, y);
                    int argb4 = reader.getArgb(x, y + 1);

                    int redX = ((argb1 >> 16) & 0xff) - ((argb2 >> 16) & 0xff);
                    int redY = ((argb3 >> 16) & 0xff) - ((argb4 >> 16) & 0xff);
                    int gradientRed = clamp((int) Math.sqrt(redX * redX + redY * redY));

                    int greenX = ((argb1 >> 8) & 0xff) - ((argb2 >> 8) & 0xff);
                    int greenY = ((argb3 >> 8) & 0xff) - ((argb4 >> 8) & 0xff);
                    int gradientGreen = clamp((int) Math.sqrt(greenX * greenX + greenY * greenY));

                    int blueX = (argb1 & 0xff) - (argb2 & 0xff);
                    int blueY = (argb3 & 0xff) - (argb4 & 0xff);
                    int gradientBlue = clamp((int) Math.sqrt(blueX * blueX + blueY * blueY));

                    int alpha = (argb1 >> 24) & 0xff;
                    int gradientArgb = (alpha << 24) | (gradientRed << 16) | (gradientGreen << 8) | gradientBlue;
                    writer.setArgb(x, y, gradientArgb);
                }
            }
            afterImageView.setImage(afterImage);
        }
    }

    private void applySobelGradient() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();

            int[][] sobelX = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
            int[][] sobelY = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};

            WritableImage afterImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = afterImage.getPixelWriter();

            for (int y = 1; y < height - 1; y++) {
                for (int x = 1; x < width - 1; x++) {
                    int gradientRedX = 0, gradientGreenX = 0, gradientBlueX = 0;
                    int gradientRedY = 0, gradientGreenY = 0, gradientBlueY = 0;

                    for (int i = -1; i <= 1; i++) {
                        for (int j = -1; j <= 1; j++) {
                            int argb = reader.getArgb(x + j, y + i);

                            gradientRedX += ((argb >> 16) & 0xff) * sobelX[i + 1][j + 1];
                            gradientGreenX += ((argb >> 8) & 0xff) * sobelX[i + 1][j + 1];
                            gradientBlueX += (argb & 0xff) * sobelX[i + 1][j + 1];

                            gradientRedY += ((argb >> 16) & 0xff) * sobelY[i + 1][j + 1];
                            gradientGreenY += ((argb >> 8) & 0xff) * sobelY[i + 1][j + 1];
                            gradientBlueY += (argb & 0xff) * sobelY[i + 1][j + 1];
                        }
                    }

                    int gradientRed = clamp((int) Math.sqrt(gradientRedX * gradientRedX + gradientRedY * gradientRedY));
                    int gradientGreen = clamp((int) Math.sqrt(gradientGreenX * gradientGreenX + gradientGreenY * gradientGreenY));
                    int gradientBlue = clamp((int) Math.sqrt(gradientBlueX * gradientBlueX + gradientBlueY * gradientBlueY));

                    int alpha = (reader.getArgb(x, y) >> 24) & 0xff;
                    int sobelArgb = (alpha << 24) | (gradientRed << 16) | (gradientGreen << 8) | gradientBlue;
                    writer.setArgb(x, y, sobelArgb);
                }
            }
            afterImageView.setImage(afterImage);
        }
    }

    private void applyLaplacian() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();

            int[][] laplacianMask = {
                    {0, 1, 0},
                    {1, -4, 1},
                    {0, 1, 0}
            };

            WritableImage laplacianResult = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = laplacianResult.getPixelWriter();

            for (int y = 1; y < height - 1; y++) {
                for (int x = 1; x < width - 1; x++) {
                    int sumRed = 0, sumGreen = 0, sumBlue = 0;

                    for (int i = -1; i <= 1; i++) {
                        for (int j = -1; j <= 1; j++) {
                            int argb = reader.getArgb(x + j, y + i);
                            int red = (argb >> 16) & 0xff;
                            int green = (argb >> 8) & 0xff;
                            int blue = argb & 0xff;

                            sumRed += red * laplacianMask[i + 1][j + 1];
                            sumGreen += green * laplacianMask[i + 1][j + 1];
                            sumBlue += blue * laplacianMask[i + 1][j + 1];
                        }
                    }

                    sumRed = clamp(Math.abs(sumRed));
                    sumGreen = clamp(Math.abs(sumGreen));
                    sumBlue = clamp(Math.abs(sumBlue));

                    int argbCenter = reader.getArgb(x, y);
                    int alpha = (argbCenter >> 24) & 0xff;

                    int laplacianArgb = (alpha << 24) | (sumRed << 16) | (sumGreen << 8) | sumBlue;
                    writer.setArgb(x, y, laplacianArgb);
                }
            }

            if (laplacianCheckBox.isSelected()) {
                laplacianImage = laplacianResult;
                combineImagesWithLaplacian();
            } else {
                afterImageView.setImage(laplacianResult);
            }
        }
    }

    private void combineImagesWithLaplacian() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null && laplacianImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();

            WritableImage combinedImage = new WritableImage(width, height);
            PixelReader originalReader = beforeImage.getPixelReader();
            PixelReader laplacianReader = laplacianImage.getPixelReader();
            PixelWriter writer = combinedImage.getPixelWriter();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int originalArgb = originalReader.getArgb(x, y);
                    int laplacianArgb = laplacianReader.getArgb(x, y);

                    int alpha = (originalArgb >> 24) & 0xff;

                    int originalRed = (originalArgb >> 16) & 0xff;
                    int originalGreen = (originalArgb >> 8) & 0xff;
                    int originalBlue = originalArgb & 0xff;

                    int laplacianRed = (laplacianArgb >> 16) & 0xff;
                    int laplacianGreen = (laplacianArgb >> 8) & 0xff;
                    int laplacianBlue = laplacianArgb & 0xff;

                    int combinedRed = clamp(originalRed + laplacianRed);
                    int combinedGreen = clamp(originalGreen + laplacianGreen);
                    int combinedBlue = clamp(originalBlue + laplacianBlue);

                    int combinedArgb = (alpha << 24) | (combinedRed << 16) | (combinedGreen << 8) | combinedBlue;
                    writer.setArgb(x, y, combinedArgb);
                }
            }
            afterImageView.setImage(combinedImage);
        }
    }

    private void applyGlobalThreshold() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();
            int threshold = (int) thresholdSlider.getValue();

            WritableImage thresholdImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = thresholdImage.getPixelWriter();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int alpha = (argb >> 24) & 0xff;
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;
                    int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
                    int binary = (luminance >= threshold) ? 255 : 0;
                    int binaryArgb = (alpha << 24) | (binary << 16) | (binary << 8) | binary;
                    writer.setArgb(x, y, binaryArgb);
                }
            }
            afterImageView.setImage(thresholdImage);
        }
    }

    private void applyOtsuThreshold() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();
            int totalPixels = width * height;

            int[] histogram = new int[256];
            PixelReader reader = beforeImage.getPixelReader();
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;
                    int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
                    histogram[luminance]++;
                }
            }
            double sum = 0;
            for (int t = 0; t < 256; t++) {
                sum += t * histogram[t];
            }

            double sumB = 0;
            int wB = 0;
            int wF = 0;

            double maxVariance = 0;
            int threshold = 0;

            for (int t = 0; t < 256; t++) {
                wB += histogram[t];
                if (wB == 0) continue;

                wF = totalPixels - wB;
                if (wF == 0) break;

                sumB += t * histogram[t];

                double mB = sumB / wB;
                double mF = (sum - sumB) / wF;

                double varianceBetween = (double) wB * (double) wF * (mB - mF) * (mB - mF);

                if (varianceBetween > maxVariance) {
                    maxVariance = varianceBetween;
                    threshold = t;
                }
            }

            otsuThresholdLabel.setText("Порог Оцу: " + threshold);
            otsuThresholdLabel.setVisible(true);

            WritableImage thresholdImage = new WritableImage(width, height);
            PixelWriter writer = thresholdImage.getPixelWriter();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int alpha = (argb >> 24) & 0xff;
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;
                    int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
                    int binary = (luminance >= threshold) ? 255 : 0;
                    int binaryArgb = (alpha << 24) | (binary << 16) | (binary << 8) | binary;
                    writer.setArgb(x, y, binaryArgb);
                }
            }

            afterImageView.setImage(thresholdImage);
        }
    }

    private void generateAndDisplayHistograms() {
        Image originalImage = beforeImageView.getImage();
        Image modifiedImage = afterImageView.getImage();

        if (originalImage != null && modifiedImage != null) {
            Image originalHistogram = generateHistogram(originalImage);
            Image modifiedHistogram = generateHistogram(modifiedImage);

            originalHistogramView.setImage(originalHistogram);
            modifiedHistogramView.setImage(modifiedHistogram);

            originalHistogramView.setVisible(true);
            modifiedHistogramView.setVisible(true);
        }
    }

    private Image generateHistogram(Image image) {
        int width = 256;
        int height = 100;
        int[] histogram = new int[256];

        PixelReader reader = image.getPixelReader();
        int imgWidth = (int) image.getWidth();
        int imgHeight = (int) image.getHeight();

        for (int y = 0; y < imgHeight; y++) {
            for (int x = 0; x < imgWidth; x++) {
                int argb = reader.getArgb(x, y);
                int red = (argb >> 16) & 0xff;
                int green = (argb >> 8) & 0xff;
                int blue = argb & 0xff;
                int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
                histogram[luminance]++;
            }
        }

        int max = 0;
        for (int value : histogram) {
            if (value > max) {
                max = value;
            }
        }

        WritableImage histogramImage = new WritableImage(width, height);
        PixelWriter writer = histogramImage.getPixelWriter();


        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                writer.setColor(x, y, Color.WHITE);
            }
        }

        for (int i = 0; i < width; i++) {
            double ratio = (double) histogram[i] / max;
            int barHeight = (int) Math.round(ratio * height);

            for (int y = height - barHeight; y < height; y++) {
                writer.setColor(i, y, Color.BLACK);
            }
        }

        return histogramImage;
    }


    private void applyMedianFilter() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();

            WritableImage medianImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = medianImage.getPixelWriter();

            for (int y = 1; y < height - 1; y++) {
                for (int x = 1; x < width - 1; x++) {
                    List<Integer> reds = new ArrayList<>();
                    List<Integer> greens = new ArrayList<>();
                    List<Integer> blues = new ArrayList<>();

                    for (int i = -1; i <= 1; i++) {
                        for (int j = -1; j <= 1; j++) {
                            int argb = reader.getArgb(x + j, y + i);
                            reds.add((argb >> 16) & 0xff);
                            greens.add((argb >> 8) & 0xff);
                            blues.add(argb & 0xff);
                        }
                    }

                    Collections.sort(reds);
                    Collections.sort(greens);
                    Collections.sort(blues);

                    int medianRed = reds.get(4);
                    int medianGreen = greens.get(4);
                    int medianBlue = blues.get(4);

                    int alpha = (reader.getArgb(x, y) >> 24) & 0xff;
                    int medianArgb = (alpha << 24) | (medianRed << 16) | (medianGreen << 8) | medianBlue;
                    writer.setArgb(x, y, medianArgb);
                }
            }

            afterImageView.setImage(medianImage);
        }
    }

    private void applyHistogramEqualization() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();
            int totalPixels = width * height;
            int L = 256;
            int[] histogram = new int[L];

            PixelReader reader = beforeImage.getPixelReader();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;
                    int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
                    histogram[luminance]++;
                }
            }

            double[] cdf = new double[L];
            cdf[0] = (double) histogram[0] / totalPixels;
            for (int k = 1; k < L; k++) {
                cdf[k] = cdf[k - 1] + ((double) histogram[k] / totalPixels);
            }

            int[] s = new int[L];
            for (int k = 0; k < L; k++) {
                s[k] = clamp((int) Math.round((L - 1) * cdf[k]));
            }

            WritableImage equalizedImage = new WritableImage(width, height);
            PixelWriter writer = equalizedImage.getPixelWriter();

            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    int argb = reader.getArgb(x, y);
                    int alpha = (argb >> 24) & 0xff;
                    int red = (argb >> 16) & 0xff;
                    int green = (argb >> 8) & 0xff;
                    int blue = argb & 0xff;
                    int luminance = (int) (0.299 * red + 0.587 * green + 0.114 * blue);
                    int equalizedLuminance = s[luminance];
                    int equalizedArgb = (alpha << 24) | (equalizedLuminance << 16) | (equalizedLuminance << 8) | equalizedLuminance;
                    writer.setArgb(x, y, equalizedArgb);
                }
            }
            afterImageView.setImage(equalizedImage);
        }
    }

    private void applyAverageFilter() {
        Image beforeImage = beforeImageView.getImage();
        if (beforeImage != null) {
            int width = (int) beforeImage.getWidth();
            int height = (int) beforeImage.getHeight();
            int[][] averageMask = {
                    {1, 1, 1},
                    {1, 1, 1},
                    {1, 1, 1}
            };

            WritableImage afterImage = new WritableImage(width, height);
            PixelReader reader = beforeImage.getPixelReader();
            PixelWriter writer = afterImage.getPixelWriter();
            
            for (int y = 1; y < height - 1; y++) {
                for (int x = 1; x < width - 1; x++) {
                    int sumRed = 0, sumGreen = 0, sumBlue = 0;
                    
                    for (int i = -1; i <= 1; i++) {
                        for (int j = -1; j <= 1; j++) {
                            int argb = reader.getArgb(x + j, y + i);
                            sumRed += (argb >> 16) & 0xff;
                            sumGreen += (argb >> 8) & 0xff;
                            sumBlue += argb & 0xff;
                        }
                    }
                    
                    int averageRed = clamp(sumRed / 9);
                    int averageGreen = clamp(sumGreen / 9);
                    int averageBlue = clamp(sumBlue / 9);
                    int alpha = (reader.getArgb(x, y) >> 24) & 0xff;
                    int averageArgb = (alpha << 24) | (averageRed << 16) | (averageGreen << 8) | averageBlue;
                    writer.setArgb(x, y, averageArgb);
                }
            }
            afterImageView.setImage(afterImage);
        }
    }

    private int clamp(int value) {
        return Math.max(0, Math.min(255, value));
    }
}
Editor is loading...
Leave a Comment