Image processing Javafx对图像像素应用过滤器

Image processing Javafx对图像像素应用过滤器,image-processing,javafx,Image Processing,Javafx,我正在编写一个照片管理应用程序github.com/lanthale/photoslide,因此我想实现basich图像增强效果。我的基本过滤器(转换为灰度)正在工作,但如果我移动滑块,在进行更新之前总是需要1秒或2秒。 如何实现即时更新图像的版本 以下是过滤器的代码: public class SampleFilter { private final Image image; public SampleFilter(Image img) { this.image = img; }

我正在编写一个照片管理应用程序github.com/lanthale/photoslide,因此我想实现basich图像增强效果。我的基本过滤器(转换为灰度)正在工作,但如果我移动滑块,在进行更新之前总是需要1秒或2秒。 如何实现即时更新图像的版本

以下是过滤器的代码:

public class SampleFilter {

private final Image image;

public SampleFilter(Image img) {
    this.image = img;
}

public Image filter(double redLimit, double greenLimit, double blueLimit) {
    if (redLimit == 0) {
        redLimit = 0.2162;
        greenLimit = 0.7152;
        blueLimit = 0.0722;
    }
    PixelReader pixelReader = image.getPixelReader();
    int height = (int) image.getHeight();
    int width = (int) image.getWidth();
    WritableImage filteredImage = new WritableImage(pixelReader, width, height);
    PixelWriter pixelWriter = filteredImage.getPixelWriter();
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int pixel = pixelReader.getArgb(x, y);

            int alpha = ((pixel >> 24) & 0xff);
            int red = ((pixel >> 16) & 0xff);
            int green = ((pixel >> 8) & 0xff);
            int blue = (pixel & 0xff);

            int grayLevel = (int) (redLimit * red + greenLimit * green + blueLimit * blue);
            int gray = (alpha << 24) + (grayLevel << 16) + (grayLevel << 8) + grayLevel;

            pixelWriter.setArgb(x, y, gray);
        }
    }
    return filteredImage;
}
apertureSlider.valueProperty().addListener((o) -> {
        executorParallel.submit(() -> {    
            if (shownImage==null){
                lightController.getImageView().setCache(true);
                shownImage=lightController.getImageView().getImage();
            }
            SampleFilter sf=new SampleFilter(shownImage);
            double val=apertureSlider.getValue();
            Image filteredImage = sf.filter(val, val+0.5, val-0.20);
            Platform.runLater(() -> {
                lightController.getImageView().setImage(filteredImage);
            });                
        });
    });

感谢您提供有关操作像素阵列而不是argb值的提示。我现在有一个版本,几乎可以正常工作。几乎我的意思是,现在可以移动滑块,并且在移动滑块的过程中图像会发生变化。左边有点滞后,但我认为也可以通过一些后台任务或其他优化来消除这一点

以下是更快的版本:

public class SampleFilter {

private final Image image;
private WritableImage filteredImage;
private int[] buffer;

public SampleFilter(Image img) {
    this.image = img;
}

public Image filter(double redLimit, double greenLimit, double blueLimit) {
    if (redLimit == 0) {
        redLimit = 0.2162;
        greenLimit = 0.7152;
        blueLimit = 0.0722;
    }
    PixelReader pixelReader = image.getPixelReader();
    int height = (int) image.getHeight();
    int width = (int) image.getWidth();
    if (buffer == null) {
        buffer = new int[width * height * 4];
        pixelReader.getPixels(0, 0, width, height, PixelFormat.getIntArgbInstance(), buffer, 0, width * 4);
    }
    filteredImage = new WritableImage(pixelReader, width, height);
    PixelWriter pixelWriter = filteredImage.getPixelWriter();
    int[] targetBuffer = new int[width * height * 4];
    for (int i = 0; i < buffer.length; i++) {
        int pixel = buffer[i];
        int alpha = ((pixel >> 24) & 0xff);
        int red = ((pixel >> 16) & 0xff);
        int green = ((pixel >> 8) & 0xff);
        int blue = (pixel & 0xff);

        int grayLevel = (int) (redLimit * red + greenLimit * green + blueLimit * blue);
        int gray = (alpha << 24) + (grayLevel << 16) + (grayLevel << 8) + grayLevel;
        targetBuffer[i]=gray;
    }
    pixelWriter.setPixels(0, 0, width, height, PixelFormat.getIntArgbInstance(), targetBuffer, 0, width*4);
    return filteredImage;
}    
公共类采样过滤器{
私有最终图像;
私有可写映像筛选器图像;
私有int[]缓冲区;
公共样本过滤器(图像img){
this.image=img;
}
公共图像过滤器(双红限、双绿限、双蓝限){
如果(redLimit==0){
红限=0.2162;
绿限=0.7152;
蓝限=0.0722;
}
PixelReader PixelReader=image.getPixelReader();
int height=(int)image.getHeight();
int width=(int)image.getWidth();
if(buffer==null){
缓冲区=新整数[宽度*高度*4];
pixelReader.getPixels(0,0,宽度,高度,PixelFormat.getIntargBinInstance(),缓冲区,0,宽度*4);
}
filteredImage=新的可写图像(像素阅读器、宽度、高度);
PixelWriter PixelWriter=filteredImage.getPixelWriter();
int[]targetBuffer=新int[宽度*高度*4];
for(int i=0;i>24)和0xff);
int红色=((像素>>16)和0xff);
int绿色=((像素>>8)和0xff);
蓝色整数=(像素和0xff);
int灰度=(int)(红色极限*红色+绿色极限*绿色+蓝色极限*蓝色);

int gray=(alpha a)配置文件以查找瓶颈b)尽一切努力修复瓶颈c)如果瓶颈不可修复,则使其看起来更快(我怀疑-但这是一个没有配置文件的胡乱猜测!-部分问题可能是您太频繁地触发新的筛选过程,请检查是否存在更改)另请注意:您不得从fx应用程序线程访问活动场景图(或其任何属性)中的节点(情况可能是这样,取决于lightController的imageView是否处于活动状态)我怀疑是pixelReader.getArb和pixelWriter.setArgb调用减慢了速度。最好将所有内容读入数组,处理数组(可能在适当的位置,可能制作新副本,取决于算法的需要)然后通过将整个目标阵列传递给pixelWriter,一次设置所有像素。谢谢。我现在设法使用阵列的,这是加速的方法。