Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8223425

JavaFX clipboard causes image to display incorrectly on non-black backgrounds

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: P4 P4
    • tbd
    • jfx13, 8u212
    • javafx
    • x86_64
    • windows_7

      A DESCRIPTION OF THE PROBLEM :
      **The Problem**

      JavaFX's default way of getting an image from the Windows clipboard, `Clipboard.getSystemClipboard().getImage();`, appears to be broken.

      Something seems to go wrong with the transparency of the image. Set on a black background, the image appears fine, but set on a white background, nothing shows at all.

      Here's an animation demonstrating that: https://i.stack.imgur.com/TgszF.gif

      The provided source code allows easy comparison between the JavaFX and AWT clipboards.

      **What I Know**

      This problem with images doesn't occur on the AWT clipboard, just the JavaFX clipboard.

      *Problem Applications*

      JavaFX seems to have this same transparency problem with various applications that copy an image to the clipboard:

          Adobe Reader (from a PDF with images)
          Foxit Reader (from a PDF with images)
              Here's a pdf with an image, for your convenience: https://drive.google.com/file/d/1waZRrQM6VTN1YzaVSHkxDIzV456Jqi0y/view?usp=sharing
          Microsoft Word 365 (from a .docx file with images)
              Here's a .docx file with an image, for your convenience: https://drive.google.com/file/d/1s3anuuIXZ4NcJGAbpYakwgqH_YAGPo9x/view?usp=sharing
          Windows 7's Paint (.png, .jpg, .gif, .bmp)
          Greenshot (which is an enhanced screenshot utility)
          Firefox 65.0.2 (copying the Google.com logo)

      *Applications Without The Issue*

      I've also found a few applications that copy an image to the clipboard and JavaFX can pull it out using the default method no problem:

          Paint.net
          The PrtScn button
          The Windows Snipping Tool
          Google Chrome 72.0.3626.121 (copying the Google.com logo)


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Copy an image from practically any application
      [I've been able to replicate this problem with the following applications:
          Adobe Reader (from a PDF with images)
          Foxit Reader (from a PDF with images)
          Microsoft Word 365 (from a .docx file with images)
          Windows 7's Paint (.png, .jpg, .gif, .bmp)
          Greenshot (which is an enhanced screenshot utility)
          Firefox 65.0.2 (copying the Google.com logo)
      ]
      2. Try to create and display an Image from the image copied to the JavaFX Clipboard.




      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      An image that maintains the same properties as the image that was copied
      ACTUAL -
      When displayed over something black, the image appears fine, when displayed over something white, no color shows. When displayed on a color in between, various colors do not display correctly, if at all.

      Here's an animation of the actual result on numerous backgrounds, using a TV color testing graphic: https://i.stack.imgur.com/TgszF.gif

      ---------- BEGIN SOURCE ----------
      // Instructions: This program allows you to easily compare the JavaFX and the Swing/AWT clipboard.
      // First copy an image from some application.
      // JavaFX button -> paste the image from the JavaFX clipboard.
      // AWT button -> paste the image from the AWT clipboard.
      // Use the color changer at the top to see how the image changes based on background that
      // the image is displayed on.

      package sample;

      import com.sun.glass.ui.ClipboardAssistance;
      import javafx.application.Application;
      import javafx.embed.swing.SwingFXUtils;
      import javafx.geometry.Insets;
      import javafx.geometry.Pos;
      import javafx.scene.Scene;
      import javafx.scene.control.Alert;
      import javafx.scene.control.Button;
      import javafx.scene.control.ColorPicker;
      import javafx.scene.control.Label;
      import javafx.scene.image.Image;
      import javafx.scene.image.ImageView;
      import javafx.scene.input.Clipboard;
      import javafx.scene.layout.Background;
      import javafx.scene.layout.BackgroundFill;
      import javafx.scene.layout.BorderPane;
      import javafx.scene.layout.CornerRadii;
      import javafx.stage.Stage;

      import java.awt.*;
      import java.awt.datatransfer.DataFlavor;
      import java.awt.datatransfer.Transferable;
      import java.awt.datatransfer.UnsupportedFlavorException;
      import java.io.IOException;

      /**
       * A program to test out the differences between the AWT Java Clipboard and the JavaFX Clipboard.
       * <p>
       * Based on the code by crusam: https://stackoverflow.com/q/48932575/5432315
       */
      public class ClipBoardFxAwtComparison extends Application {

          @Override
          public void start(final Stage primaryStage) {
              final BorderPane root = new BorderPane();
              final ImageView view = new ImageView();

              final Button awtButton = new Button("AWT");
              awtButton.setOnAction(event -> loadImageFromAwtClipboard(view));

              final Button javaFXButton = new Button("JavaFX");
              javaFXButton.setOnAction(event -> loadImageFromJavaFXClipboard(view));

              root.setCenter(view);

              final BorderPane buttonPane = new BorderPane();
              buttonPane.setLeft(awtButton);
              buttonPane.setCenter(new Label("Copy and image then click a button to paste it."));
              buttonPane.setRight(javaFXButton);
              root.setBottom(buttonPane);

              final ColorPicker colorPicker = new ColorPicker();
              colorPicker.setOnAction(event -> {
                  root.setBackground(
                          new Background(
                                  new BackgroundFill(
                                          colorPicker.getValue(),
                                          CornerRadii.EMPTY,
                                          Insets.EMPTY)
                          )
                  );
              });

              BorderPane.setAlignment(colorPicker, Pos.CENTER);
              root.setTop(colorPicker);

              final Scene scene = new Scene(root, 400, 400);
              primaryStage.setScene(scene);
              primaryStage.show();

              listenToClipboard();
          }

          /**
           * This little bit of magic comes courtesy of Александр Савостьянов: https://stackoverflow.com/a/47550034/5432315
           */
          private void listenToClipboard() {
              Clipboard clipboard = Clipboard.getSystemClipboard();
              new ClipboardAssistance(com.sun.glass.ui.Clipboard.SYSTEM) {
                  @Override
                  public void contentChanged() {
                      System.out.println("System clipboard content changed.");
                      System.out.println("Clipboard content types: ");
                      clipboard.getContentTypes().forEach(System.out::println);
                      System.out.println();
                  }
              };
          }

          private void loadImageFromJavaFXClipboard(final ImageView view) {
              System.out.println("Adding an image from the JavaFX Clipboard...");
              final Clipboard clipboard = Clipboard.getSystemClipboard();

              if (clipboard.hasImage()) {
                  final Image image = clipboard.getImage();
                  view.setImage(image);
              } else {
                  new Alert(Alert.AlertType.INFORMATION, "No image detected on the Clipboard!").show();
              }
          }

          private void loadImageFromAwtClipboard(final ImageView view) {
              System.out.println("Adding an image from the AWT Clipboard...");

              try {
                  final Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);

                  if (t != null && t.isDataFlavorSupported(DataFlavor.imageFlavor)) {
                      final java.awt.image.BufferedImage img = (java.awt.image.BufferedImage) t.getTransferData(DataFlavor.imageFlavor);

                      final Image image = SwingFXUtils.toFXImage(img, null);

                      view.setImage(image);
                  } else {
                      new Alert(Alert.AlertType.INFORMATION, "No image detected on the Clipboard!").show();
                  }
              } catch (final UnsupportedFlavorException | IOException e) {
                  e.printStackTrace();
              }
          }

          public static void main(final String[] args) {
              launch(args);
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


            arapte Ambarish Rapte
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: