Повышение производительности обработки JavaFX

#image-processing #javafx

#обработка изображений #javafx

Вопрос:

Я работаю над обработкой изображений с помощью JavaFX. Я думаю, что мой код недостаточно эффективен (с HD-изображениями обновление происходит очень медленно). Потому что я делаю a for для каждого пикселя моего изображения каждый раз, когда мне приходится его обновлять. Но я не знаю, как поступить по-другому.

Итак, мне нужна помощь, чтобы повысить производительность моей обработки.

Это мой код :

 import javafx.application.Application;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.Slider;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Example extends Application {

    private Image src;
    private WritableImage dest;
    private int width;
    private int height;
    int value = 0;

@Override
public void start(Stage stage) {
    AnchorPane root = new AnchorPane();
    initImage(root);
    Scene scene = new Scene(root);
    stage.setTitle("Demo processing");
    stage.setResizable(false);
    stage.setScene(scene);
    stage.show();
}

private void initImage(AnchorPane root) {
    src = new Image(
            "http://mikecann.co.uk/wp-content/uploads/2009/12/ScreenHunter_02-Dec.-10-19.41-1024x484.jpg");
    width = (int) src.getWidth();
    height = (int) src.getHeight();
    root.setPrefSize(800, 800   50);
    ScrollPane scrollPane = new ScrollPane();
    scrollPane.setPrefHeight(600);
    scrollPane.setPrefWidth(1000);
    dest = new WritableImage(width, height);
    ImageView destView = new ImageView(dest);

    scrollPane.setContent(destView);

    root.getChildren().add(scrollPane);
    AnchorPane.setTopAnchor(scrollPane, 0.0);

    Slider slider = new Slider(0, 255, 1);
    slider.setPrefSize(800, 50);
    slider.setShowTickLabels(true);
    slider.setShowTickMarks(true);
    slider.setSnapToTicks(true);
    slider.setMajorTickUnit(1.0);
    slider.setMinorTickCount(0);
    slider.setLayoutY(700);
    slider.valueProperty().addListener(new InvalidationListener() {
        @Override
        public void invalidated(Observable o) {
            value = (int) ((DoubleProperty) o).get();
            color();
        }
    });
    root.getChildren().add(slider);
    color();
}

private void color() {
    PixelReader reader = src.getPixelReader();
    PixelWriter writer = dest.getPixelWriter();
    for (int x = 0; x < width; x  ) {
        for (int y = 0; y < height; y  ) {
            Color color = reader.getColor(x, y);
            double red = (double) value * x * y / (width * height) / 255;
            double green = color.getGreen();
            double blue = (double) value * ((width * height) - x * y)
                    / (width * height) / 255;
                writer.setColor(x, y, Color.color(red, green, blue));
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
 

И это с изображением Full HD :

         src = new Image(
            "http://www.freedomwallpaper.com//nature-wallpaper-hd/hd_sunshine_hd.jpg");
 

Комментарии:

1. Перекрестная публикация с ответами на форуме Oracle JavaFX

Ответ №1:

Получение цвета каждого пикселя в цикле происходит слишком медленно. Итак, сначала получите целые пиксели и измените цвета, наконец, wirte изменил цвета с помощью PixelWriter. Вот так

 private void color() {
    PixelReader reader = src.getPixelReader();
    WritablePixelFormat<IntBuffer> format = WritablePixelFormat.getIntArgbInstance();
    int[] pixels = new int[width * height]; // Buffer for all pixels
    reader.getPixels(0, 0, width, height, format, pixels, 0, width); // get all pixels by argb format
    int alpha = 0xFF << 24;
    for (int x = 0; x < width; x  ) {
        for (int y = 0; y < height; y  ) {
            int index = x   y * width;
            int argb = pixels[index];
            int red = value * x * y / (width * height);
            int green = (argb >> 8) amp; 0xFF;
            int blue = value * ((width * height) - x * y)
                    / (width * height);
            int newArgb = alpha | (red << 16) | (green << 8) | blue;
            pixels[index] = newArgb;
        }
    }
    PixelWriter writer = dest.getPixelWriter();
    writer.setPixels(0, 0, width, height, format, pixels, 0, width); // write entire image
}