[英]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);
...但是沒有成功。
樣品溶液
該解決方案的工作原理是:
由於該解決方案混合了兩個不同的工具箱,因此在創建該解決方案時要考慮以下因素:
請注意用於確保給定工具箱調用使用正確類的導入操作; 例如,JavaFX和Swing / AWT都具有Color
和Image
類,因此必須確保在正確的上下文中使用給定工具箱的完全限定類-將Swing Image直接傳遞給JavaFX API將是錯誤的,反之亦然-反之亦然。
注意線程規則。 JavaFX場景的快照必須在JavaFX應用程序線程上進行。 必須在Swing事件分配線程上執行Swing API。 各個工具箱的各種實用程序(例如SwingUtilities
和JavaFX Platform
類)用於確保滿足給定工具箱的線程約束。
Application
類時,將隱式完成此操作。 但是,Swing應用程序不會擴展JavaFX應用程序類。 因此,也許有些違反直覺且文獻JFXPanel
在使用該工具箱之前,必須實例化JFXPanel
來初始化JavaFX工具箱。 筆記
該解決方案旨在滿足問題的特定要求(這是一個Swing應用程序,需要進行一些顏色調整)。 如果僅希望從JavaFX內調整圖像顏色而不使用Swing,則存在更簡單的解決方案 ,因此是首選。
調用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.