JavaFX PixelWriter low performance

一个人想着一个人 提交于 2019-12-08 07:26:24

问题


I created a simple JavaFX image editor. There are two instances of ImageView (on for the original image and one for the edited one). A method converts the WritableImage to grayscale. The problem is, the conversion takes approximately twice the time Swing needs to do the same task. Any idea why?

@FXML
void loadImage(ActionEvent event) {
    FileChooser fileChooser = new FileChooser();
    File file = fileChooser.showOpenDialog(Main.primaryStage);
    if (file != null) {
        Image image = new Image("file:" + file.getAbsolutePath());
        imViewOrig.setImage(image);
        PixelReader pr = imViewOrig.getImage().getPixelReader();
        WritableImage wi = new WritableImage(
            pr, 
            (int)imViewOrig.getImage().getWidth(), 
            (int)imViewOrig.getImage().getHeight());
        imViewEdit.setImage(wi);
    }
}

@FXML
void greyscale(ActionEvent event) {
    PixelReader pr = imViewOrig.getImage().getPixelReader();
    PixelWriter pw = ((WritableImage)imViewEdit.getImage()).getPixelWriter();
    long beginTime = System.currentTimeMillis();
    for (int x = 0; x < imViewEdit.getImage().getWidth(); x++) {
        for (int y = 0; y < imViewEdit.getImage().getHeight(); y++) {
            Color c = pr.getColor(x, y);
            double avg = (c.getRed() + c.getGreen() + c.getBlue()) / 3.;
            Color grey = new Color(avg, avg, avg, c.getOpacity());
            pw.setColor(x, y, grey);                
        }
    }
    System.out.println(System.currentTimeMillis() - beginTime + "ms");
}

Swing code:

public void greyscale() {
    long beginTime = System.currentTimeMillis();
    for (int x = 0; x < image.getWidth(); x++) {
        for (int y = 0; y < image.getHeight(); y++) {
            Color c = new Color(image.getRGB(x, y));
            int avg = (c.getRed() + c.getGreen() + c.getBlue()) / 3;
            Color grey = new Color(avg, avg, avg);
            image.setRGB(x, y, grey.getRGB());                
        }
    }
    repaint();
    System.out.println(System.currentTimeMillis() - beginTime + "ms");
}

回答1:


In a quick test, it works of the order of 10 times faster if you just do the int computations, instead of manipulating Color objects. The JavaFX Color class is a substantially richer implementation than the AWT Color class; I guess this comes at a cost of additional overhead.

    int width = (int)image.getWidth();
    int height = (int)image.getHeight();

    int[] pixels = new int[width * height];
    WritablePixelFormat<IntBuffer> pixelFormat = PixelFormat.getIntArgbPreInstance();
    pr.getPixels(0, 0, width, height, pixelFormat, pixels, 0, width);

    int[] newPixels = new int[pixels.length];
    for (int i = 0 ; i < pixels.length; i++) {
        int c = pixels[i];
        int a = c & 0xFF000000 ;
        int r = (c >> 16) & 0xFF ;
        int g = (c >> 8) & 0xFF ;
        int b = c & 0xFF ;
        int gray = (r+g+b) / 3 ;
        newPixels[i] = a | (gray << 16) | (gray << 8) | gray ;
    }

    pw.setPixels(0, 0, width, height, pixelFormat, newPixels, 0, width);



回答2:


ColorAdjust based sample which converts a color image to monochrome by desaturating it when you mouse-over the image.

Given appropriate hardware (which is available to most systems JavaFX runs on), the JavaFX runtime may perform some of the implementation of the color adjustment in hardware, which might lead to a more efficient implementation than manipulating pixels using a PixelWriter.

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.scene.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class Shadow extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Image image = new Image(
                "http://icons.iconarchive.com/icons/designbolts/smurfs-movie/512/smurfette-icon.png"
        );

        ImageView imageView = new ImageView(image);

        ColorAdjust monochrome = new ColorAdjust();
        monochrome.setSaturation(-1.0);

        imageView.effectProperty().bind(
                Bindings
                    .when(imageView.hoverProperty())
                        .then(monochrome)
                        .otherwise((ColorAdjust) null)
        );

        stage.setScene(new Scene(new Group(imageView), Color.AQUA));
        stage.show();
    }

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


来源:https://stackoverflow.com/questions/29260147/javafx-pixelwriter-low-performance

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!