【发布时间】:2015-06-23 05:32:06
【问题描述】:
JavaFX 中有一个旧错误会阻止您正确使用保存图像
ImageIO.write(SwingFXUtils.fromFXImage( wi, null), "jpg", new File( fileName1));
当您从节点拍摄快照并尝试将其保存为 jpg 文件时,会出现此问题。当您将 jpg 加载到图像并保存该图像时,它不会发生。
现在已经有一段时间了,它仍然没有修复。是否有适当的解决方法而无需使用 awt?
我知道 SwingFXUtils 在内部使用 awt,但在你自己的项目中使用它感觉不对。
我检查了错误报告。他们被关闭了
但是,这是一个问题,并没有解决。
这是完整的示例代码,请更改 fileName1 和 fileName2 变量以匹配您的路径:
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
public class ImageSave extends Application {
String fileName1 = "c:/temp/1.jpg"; // TODO: change filepath
String fileName2 = "c:/temp/2.jpg"; // TODO: change filepath
ImageView imageView;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Image Crop");
BorderPane root = new BorderPane();
Button button = new Button( "Save");
button.setOnAction(e -> save());
root.setTop(button);
// container for image layers
ScrollPane scrollPane = new ScrollPane();
// image layer: a group of images
Group imageLayer = new Group();
// load the image
// Image image = new Image( getClass().getResource( "cat.jpg").toExternalForm());
Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Gatto_europeo4.jpg/1024px-Gatto_europeo4.jpg");
// the container for the image as a javafx node
imageView = new ImageView( image);
// add image to layer
imageLayer.getChildren().add( imageView);
// use scrollpane for image view in case the image is large
scrollPane.setContent(imageLayer);
// put scrollpane in scene
root.setCenter(scrollPane);
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.show();
}
private void save() {
SnapshotParameters parameters = new SnapshotParameters();
// parameters.setFill(Color.TRANSPARENT);
WritableImage wi = new WritableImage( (int) imageView.getBoundsInLocal().getWidth(), (int) imageView.getBoundsInLocal().getHeight());
imageView.snapshot(parameters, wi);
// save image
// !!! has bug because of transparency (use approach below) !!!
// --------------------------------
try {
ImageIO.write(SwingFXUtils.fromFXImage( wi, null), "jpg", new File( fileName1));
System.out.println( "Image saved to " + fileName1);
} catch (IOException e) {
e.printStackTrace();
}
// save image (without alpha)
// --------------------------------
BufferedImage bufImageARGB = SwingFXUtils.fromFXImage(wi, null);
BufferedImage bufImageRGB = new BufferedImage(bufImageARGB.getWidth(), bufImageARGB.getHeight(), BufferedImage.OPAQUE);
Graphics2D graphics = bufImageRGB.createGraphics();
graphics.drawImage(bufImageARGB, 0, 0, null);
try {
ImageIO.write(bufImageRGB, "jpg", new File( fileName2));
System.out.println( "Image saved to " + fileName2);
} catch (IOException e) {
e.printStackTrace();
}
graphics.dispose();
}
}
JavaFX 版本:
awt 版本:
【问题讨论】:
-
也许我遗漏了一些东西,但这在 Java 8u60 ea、OS X 10.9.5 上对我来说是正确的。 Java 8u20 中也为我解决了此类问题(请参阅:stackoverflow.com/questions/16721917/display-rtp-mjpeg)。请注意,在测试时,我注释掉了您的快照代码,使
image变量成为ImageSave类的成员,并使用fromFXImage( image, null)而不是fromFXImage( wi, null)。不确定这些修改是否会影响您的测试或您试图演示的内容。如果您仍然认为这是一个问题,那么总会有:bugreport.java.com -
快照方法是问题所在,因为它将 PixelWriter.Type 设置为 INT_ARGB_PRE,因此之后您的图像中(甚至在图像中)有一个 alpha。 SwingFXUtils.fromFXImage() 将完成剩下的工作,即使您尝试将 BufferedImage 添加到 RGB 类型的方法。该方法不应在 jpeg 文件上设置 alpha!他想为快照添加透明度。
-
@jewelsea:我刚试过,你是对的。 NwDx也是如此。快照方法是问题所在。当我加载图像然后保存它时,一切都很好。当我对图像进行快照并保存时,就会出现问题。
-
@NwDX:我不想增加透明度。我希望快照和保存到 jpg 的工作正常。
-
@Roland 感谢您解决问题。
标签: javafx