title: Save image without having to use awt
body: <p>There's an old bug in JavaFX which prevents you to save images properly using </p>
  
  <pre><code>ImageIO.write(SwingFXUtils.fromFXImage( wi, null), "jpg", new File( fileName1));
  </code></pre>
  
  <p>The problem occurs when you take a snapshot from a node and try to save it as jpg file. It doesn't occur when you load a jpg into and image and save that image.</p>
  
  <p>It's been a while now and it still isn't fixed. Is there a proper workaround for this without having to use awt?</p>
  
  <p>I know that SwingFXUtils uses awt internally, but having it in your own project feels just wrong.</p>
  
  <p>I checked the bug reports. They were closed with</p>
  
  <p><a href="https://bugs.openjdk.java.net/browse/JDK-8119048" rel="nofollow noreferrer">Not an Issue</a>
  and
  <a href="https://bugs.openjdk.java.net/browse/JDK-8114609" rel="nofollow noreferrer">Fixed</a></p>
  
  <p>However, it is an issue and it isn't fixed.</p>
  
  <p>Here's full example code, please change the fileName1 and fileName2 variables to match your path:</p>
  
  <pre><code>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 -&gt; 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();
  
      }
  
  }
  </code></pre>
  
  <p>The JavaFX version:</p>
  
  <p><img src="https://i.stack.imgur.com/ipC6N.jpg" alt="enter image description here"></p>
  
  <p>The awt version:</p>
  
  <p><img src="https://i.stack.imgur.com/eAXzg.jpg" alt="enter image description here"></p>