簡體   English   中英

使用SwingX的ImageView進行CollorAdjust調整?

[英]CollorAdjust with SwingX's ImageView?

我有一個關於調整從swingx庫加載到jXImageView的圖像的對比度,飽和度和色相的問題。

我有ColorAdjust方法。

ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setContrast(0.3);
colorAdjust.setHue(-0.03);
colorAdjust.setBrightness(0.2);
colorAdjust.setSaturation(0.2);

當用戶單擊“增強”按鈕時,圖像應該有所變化,但是該怎么做? 記住:我正在使用jXImageView。

我已經通過使用以下代碼提高了對比度:

    float brightenFactor = 1.5f;
    BufferedImage imagem = (BufferedImage) jXImageView2.getImage();
    RescaleOp op = new RescaleOp(brightenFactor, 0, null);
    imagem = op.filter(imagem, imagem);
    jXImageView2.updateUI();

編輯

我試着:

BufferedImage imagem = (BufferedImage) jXImageView2.getImage();
Image image = SwingFXUtils.toFXImage(imagem, null);//<--ERROR on that line (incompatible types: writable image cannot be converted to Image)
ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setContrast(0.3);
colorAdjust.setHue(-0.03);
colorAdjust.setBrightness(0.2);
colorAdjust.setSaturation(0.2);
ImageView imageView = new ImageView(image);//<--ERROR on taht line no suitable constructor for ImageView(java.awt.Image)
imageView.setFitWidth(imagem.getWidth());
imageView.setPreserveRatio(true);
imagem = SwingFXUtils.fromFXImage(imageView.snapshot(null, null), null);
jXImageView2.setImage(imagem);

...但是沒有成功。

樣品溶液

  • 左側的圖像是原始圖像。
  • 右邊的圖像是調整后的圖像(其顏色已降低飽和度以使圖像變為單色)。

調整后的顏色

該解決方案的工作原理是:

  1. 將Swing / AWT BufferedImage轉換為JavaFX Image
  2. 使用JavaFX ColorAdjust效果修改圖像。
  3. 拍攝經過顏色調整的圖像的快照以創建新的JavaFX圖像。
  4. 新的JavaFX映像將轉換回新的Swing / AWT BufferedImage。

由於該解決方案混合了兩個不同的工具箱,因此在創建該解決方案時要考慮以下因素:

  1. 請注意用於確保給定工具箱調用使用正確類的導入操作; 例如,JavaFX和Swing / AWT都具有ColorImage類,因此必須確保在正確的上下文中使用給定工具箱的完全限定類-將Swing Image直接傳遞給JavaFX API將是錯誤的,反之亦然-反之亦然。

  2. 注意線程規則。 JavaFX場景的快照必須在JavaFX應用程序線程上進行。 必須在Swing事件分配線程上執行Swing API。 各個工具箱的各種實用程序(例如SwingUtilities和JavaFX Platform類)用於確保滿足給定工具箱的線程約束。

  3. 必須先初始化JavaFX工具箱,然后才能使用它。 通常,當您的應用程序擴展JavaFX Application類時,將隱式完成此操作。 但是,Swing應用程序不會擴展JavaFX應用程序類。 因此,也許有些違反直覺且文獻JFXPanel在使用該工具箱之前,必須實例化JFXPanel來初始化JavaFX工具箱。

筆記

  1. 該解決方案旨在滿足問題的特定要求(這是一個Swing應用程序,需要進行一些顏色調整)。 如果僅希望從JavaFX內調整圖像顏色而不使用Swing,則存在更簡單的解決方案 ,因此是首選。

  2. 調用System.exit通常足以關閉JavaFX工具包。 該示例應用程序調用Platform.exit來顯式關閉JavaFX工具包,但是在這種情況下,可能不需要顯式調用Platform.exit

這意味着可以從Swing程序使用解決方案中的ColorAdjuster,而無需Swing程序顯式導入任何JavaFX類(盡管在內部,ColorAdjuster會導入這些類,並且系統必須滿足正常的最低要求才能同時運行Swing和JavaFX工具包)。 在可能的情況下,最好將導入的混合減少到每個類的單個工具箱中,因為混合JavaFX / Swing應用程序在單個類中混合導入是乏味的錯誤的好來源,這是由於潛在的名稱沖突和與線程相關的麻煩。

ColorAdjuster.java

圖像色彩調整實用程序。

import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.SnapshotParameters;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;

import javax.swing.SwingUtilities;
import java.awt.image.BufferedImage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/** Uses JavaFX to adjust the color of an AWT/Swing BufferedImage */
public class ColorAdjuster {
    // Instantiation of a JFXPanel is necessary otherwise the JavaFX toolkit is not initialized.
    // The JFXPanel doesn't actually need to be used, instantiating it in the constructor is enough to trigger toolkit initialization.
    private final JFXPanel fxPanel;

    public ColorAdjuster() {
        // perhaps this check is not necessary, but I feel a bit more comfortable if it is there.
        if (!SwingUtilities.isEventDispatchThread()) {
            throw new IllegalArgumentException(
                    "A ColorAdjuster must be created on the Swing Event Dispatch thread.  " +
                            "Current thread is " + Thread.currentThread()
            );
        }

        fxPanel = new JFXPanel();
    }

    /** 
     * Color adjustments to the buffered image are performed with parameters in the range -1.0 to 1.0
     * 
     * @return a new BufferedImage which has colors adjusted from the original image.
     **/
    public BufferedImage adjustColor(
            BufferedImage originalImage,
            double hue,
            double saturation,
            double brightness,
            double contrast
    ) throws ExecutionException, InterruptedException {
        // This task will be executed on the JavaFX thread.
        FutureTask<BufferedImage> conversionTask = new FutureTask<>(() -> {
            // create a JavaFX color adjust effect.
            final ColorAdjust monochrome = new ColorAdjust(0, -1, 0, 0);

            // convert the input buffered image to a JavaFX image and load it into a JavaFX ImageView.
            final ImageView imageView = new ImageView(
                    SwingFXUtils.toFXImage(
                            originalImage, null
                    )
            );

            // apply the color adjustment.
            imageView.setEffect(monochrome);

            // snapshot the color adjusted JavaFX image, convert it back to a Swing buffered image and return it.
            SnapshotParameters snapshotParameters = new SnapshotParameters();
            snapshotParameters.setFill(Color.TRANSPARENT);

            return SwingFXUtils.fromFXImage(
                    imageView.snapshot(
                            snapshotParameters,
                            null
                    ),
                    null
            );
        });

        Platform.runLater(conversionTask);

        return conversionTask.get();
    }
}

ColorAdjustingSwingAppUsingJavaFX.java

測試線束:

import javafx.application.Platform;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.ExecutionException;

public class ColorAdjustingSwingAppUsingJavaFX {

    private static void initAndShowGUI() {
        try {
            // This method is invoked on Swing thread
            JFrame frame = new JFrame();

            // read the original image from a URL.
            URL url = new URL(
                    IMAGE_LOC
            );
            BufferedImage originalImage   = ImageIO.read(url);

            // use JavaFX to convert the original image to monochrome.
            ColorAdjuster colorAdjuster = new ColorAdjuster();
            BufferedImage monochromeImage = colorAdjuster.adjustColor(
                    originalImage,
                    0, -1, 0, 0
            );

            // add the original image and the converted image to the Swing frame.
            frame.getContentPane().setLayout(new FlowLayout());
            frame.getContentPane().add(
                    new JLabel(
                            new ImageIcon(originalImage)
                    )
            );
            frame.getContentPane().add(
                    new JLabel(
                            new ImageIcon(monochromeImage)
                    )
            );

            // set a handler to close the application on request.
            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    // shutdown the JavaFX runtime.
                    Platform.exit();

                    // exit the application.
                    System.exit(0);
                }
            });

            // display the Swing frame.
            frame.pack();
            frame.setLocation(400, 300);
            frame.setVisible(true);
        } catch (IOException | InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(
                ColorAdjustingSwingAppUsingJavaFX::initAndShowGUI
        );
    }


    // icon source: http://www.iconarchive.com/artist/aha-soft.html
    // icon license: Free for non-commercial use, commercial usage: Not allowed
    private static final String IMAGE_LOC =
            "http://icons.iconarchive.com/icons/aha-soft/desktop-buffet/128/Pizza-icon.png";
}

您需要將BufferedImage轉換為javafx.scene.image.Image ,可以使用類似...

Image image = SwingFXUtils.toFXImage(imagem, null);

然后您可以應用ColorAdjust ...

ColorAdjust colorAdjust = new ColorAdjust();
colorAdjust.setContrast(0.1);
colorAdjust.setHue(-0.05);
colorAdjust.setBrightness(0.1);
colorAdjust.setSaturation(0.2);

ImageView imageView = new ImageView(image);
imageView.setFitWidth(image.getWidth());
imageView.setPreserveRatio(true);
imageView.setEffect(colorAdjust);

然后再轉換回去...

imagem = SwingFXUtils.fromFXImage(imageView.snapshot(null, null), null);

這個想法是從jewelsea / SaveAdjustedImage.java中竊取的 我不知道的是,是否首先需要在屏幕上實現ImageView ……

更新

請注意,您正在跨兩個不同的UI框架,就像他們在電影中所說的那樣:“不要越過流!”

與Swing相比,JavaFX具有更為嚴格控制的一組需求,這既是件好事,也有不好的事。

您必須要做的就是讓JavaFX代碼在其事件線程中運行。 例如,這比聽起來(似乎需要)要棘手。

在此處輸入圖片說明

原創| 顏色調整(取自JavaDocs示例 單色...

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import javax.imageio.ImageIO;

public class Test extends Application {

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

    @Override
    public void start(Stage stage) throws Exception {

        try {
            System.out.println("Load image...");
            BufferedImage imagem = ImageIO.read(new File("..."));
            Image image = SwingFXUtils.toFXImage(imagem, null);

            ColorAdjust colorAdjust = new ColorAdjust();
            colorAdjust.setHue(0);
            colorAdjust.setSaturation(-1);
            colorAdjust.setBrightness(0);
            colorAdjust.setContrast(0);
//          colorAdjust.setHue(-0.05);
//          colorAdjust.setSaturation(0.2);
//          colorAdjust.setBrightness(0.1);
//          colorAdjust.setContrast(0.1);

            ImageView imageView = new ImageView(image);
            imageView.setFitWidth(image.getWidth());
            imageView.setPreserveRatio(true);
            imageView.setEffect(colorAdjust);

            System.out.println("Convert and save...");
            imagem = SwingFXUtils.fromFXImage(imageView.snapshot(null, null), null);
            ImageIO.write(imagem, "png", new File("ColorAdjusted.png"));
        } catch (IOException exp) {
            exp.printStackTrace();
        } finally {
            Platform.exit();
        }
    }

}

接下來的事情是嘗試弄清楚如何使它作為實用程序類工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM