Там старая ошибка в JavaFX, который позволяет сохранять изображения надлежащим образом с помощьюСохранить изображение без использования AWT
ImageIO.write(SwingFXUtils.fromFXImage(wi, null), "jpg", new File(fileName1));
Проблема возникает, когда вы берете снимок с узла и попытаться сохранить его как JPG файл , Это не происходит, когда вы загружаете jpg и изображение и сохраняете это изображение.
Прошло некоторое время, и оно все еще не исправлено. Есть ли подходящее решение для этого без использования awt?
Я знаю, что SwingFXUtils использует awt внутренне, но наличие его в вашем собственном проекте кажется неправильным.
Я проверил отчеты об ошибках. Они были закрыты с
Однако, это проблема, и она не является фиксированной.
Вот полный пример кода, пожалуйста, измените переменные имя_файла1 и 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 еа, OS X 10.9.5. Подобные проблемы также были исправлены для меня в Java 8u20 (см. Http://stackoverflow.com/questions/16721917/display-rtp-mjpeg).Обратите внимание, что при тестировании я прокомментировал ваш код моментального снимка, превратил переменную 'image' в член класса' ImageSave' и использовал 'fromFXImage (изображение, null)' вместо 'fromFXImage (wi, null)'. Не уверен, что эти изменения скомпрометировали ваш тест или то, что вы пытались продемонстрировать. Если вы все еще считаете, что это проблема, всегда есть: http://bugreport.java.com – jewelsea
Метод моментального снимка является проблемой, поскольку он устанавливает PixelWriter.Type в INT_ARGB_PRE, поэтому после этого у вас есть альфа в вашем изображении (даже в изображении). И SwingFXUtils.fromFXImage() сделает все остальное, даже если вы попытаетесь добавить BufferedImage к методу с типом RGB. Метод не должен устанавливать альфа-файлы в jpeg-файлах! Он хочет добавить прозрачность к снимку. – NwDev
@jewelsea: Я просто попробовал, ты прав. Так же NwDx. Метод моментальных снимков - проблема. Когда я загружаю изображение, а затем сохраняю его, все в порядке. Когда я делаю снимок изображения и сохраняю его, возникает проблема. – Roland