【问题标题】:JavaFX PixelWriter low performanceJavaFX PixelWriter 性能低下
【发布时间】:2015-03-25 15:39:32
【问题描述】:

我创建了一个简单的 JavaFX 图像编辑器。 ImageView 有两个实例(打开用于原始图像,一个用于编辑后的图像)。 一种方法将 WritableImage 转换为灰度。 问题是,转换所花费的时间大约是 Swing 执行相同任务所需时间的两倍。知道为什么吗?

@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");
}

摇摆代码:

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");
}

【问题讨论】:

  • 作为替代实现,您可以应用ColorAdjust 效果来降低颜色的饱和度。

标签: java swing javafx imageview


【解决方案1】:

在快速测试中,如果您只执行 int 计算,而不是操作 Color 对象,它的运行速度会快 10 倍。 JavaFX Color 类是比 AWT Color 类更丰富的实现;我想这是以额外开销为代价的。

    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);

【讨论】:

  • 完美,Swing 有类似的吗?
  • 我认为 Swing around 图像的大多数低级原语都在 awt 类中。最接近 JavaFX 的 PixelWriter 似乎是 java.awt.image.MemoryImageSource。免责声明:我对 Swing 了解不多。
  • 我也忘记了我的大部分 Swing/AWT 技能,但您可以尝试修改现有代码以避免创建 Color 对象。有一个BufferedImage.getRGB(...) 用像素数据填充int[];你可以像在JavaFX代码中一样提取红绿蓝分量(没有alpha分量),然后映射成一个新数组并调用BufferedImage.setRGB(...)
【解决方案2】:

基于ColorAdjust 的示例,当您将鼠标悬停在图像上时,通过去饱和将彩色图像转换为单色。

给定适当的硬件(运行 JavaFX 的大多数系统都可以使用),JavaFX 运行时可能会在硬件中执行一些颜色调整的实现,这可能会导致比使用 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();
    }
}

【讨论】:

    猜你喜欢
    • 2011-06-15
    • 2011-11-03
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多