changeset 10646:a6a1352252be jdk-10+26

8129747: SwingFXUtils.fromFXImage seems to have a bug inside Reviewed-by: kcr
author psadhukhan
date Thu, 21 Sep 2017 10:38:05 -0700
parents c54912fb7e66
children 48181ab479ee 5000ccd0dedf
files modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java tests/system/src/test/java/test/javafx/embed/swing/FXImageConversionTest.java
diffstat 3 files changed, 137 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java	Thu Sep 21 13:36:38 2017 +0530
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/JFXPanel.java	Thu Sep 21 10:38:05 2017 -0700
@@ -682,7 +682,7 @@
             int newPixelH = (int) Math.ceil(pHeight * newScaleFactorY);
             pixelsIm = new BufferedImage(newPixelW, newPixelH,
                                          SwingFXUtils.getBestBufferedImageType(
-                                             scenePeer.getPixelFormat(), null));
+                                             scenePeer.getPixelFormat(), null, false));
             if (oldIm != null) {
                 double ratioX = newScaleFactorX / scaleFactorX;
                 double ratioY = newScaleFactorY / scaleFactorY;
--- a/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java	Thu Sep 21 13:36:38 2017 +0530
+++ b/modules/javafx.swing/src/main/java/javafx/embed/swing/SwingFXUtils.java	Thu Sep 21 10:38:05 2017 -0700
@@ -38,6 +38,7 @@
 import javafx.scene.image.PixelWriter;
 import javafx.scene.image.WritableImage;
 import javafx.scene.image.WritablePixelFormat;
+import javafx.scene.paint.Color;
 import com.sun.javafx.tk.Toolkit;
 import javax.swing.SwingUtilities;
 import sun.awt.image.IntegerComponentRaster;
@@ -132,12 +133,16 @@
      * @return
      */
     static int
-        getBestBufferedImageType(PixelFormat<?> fxFormat, BufferedImage bimg)
+            getBestBufferedImageType(PixelFormat<?> fxFormat, BufferedImage bimg,
+                                     boolean isOpaque)
     {
         if (bimg != null) {
             int bimgType = bimg.getType();
             if (bimgType == BufferedImage.TYPE_INT_ARGB ||
-                bimgType == BufferedImage.TYPE_INT_ARGB_PRE)
+                bimgType == BufferedImage.TYPE_INT_ARGB_PRE ||
+                (isOpaque &&
+                     (bimgType == BufferedImage.TYPE_INT_BGR ||
+                      bimgType == BufferedImage.TYPE_INT_RGB)))
             {
                 // We will allow the caller to give us a BufferedImage
                 // that has an alpha channel, but we might not otherwise
@@ -193,6 +198,18 @@
         }
     }
 
+    private static boolean checkFXImageOpaque(PixelReader pr, int iw, int ih) {
+        for (int x = 0; x < iw; x++) {
+            for (int y = 0; y < ih; y++) {
+                Color color = pr.getColor(x,y);
+                if (color.getOpacity() != 1.0) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     /**
      * Snapshots the specified JavaFX {@link Image} object and stores a
      * copy of its pixels into a {@link BufferedImage} object, creating
@@ -229,7 +246,26 @@
         }
         int iw = (int) img.getWidth();
         int ih = (int) img.getHeight();
-        int prefBimgType = getBestBufferedImageType(pr.getPixelFormat(), bimg);
+        PixelFormat<?> fxFormat = pr.getPixelFormat();
+        boolean srcPixelsAreOpaque = false;
+        switch (fxFormat.getType()) {
+            case INT_ARGB_PRE:
+            case INT_ARGB:
+            case BYTE_BGRA_PRE:
+            case BYTE_BGRA:
+                // Check fx image opacity only if
+                // supplied BufferedImage is without alpha channel
+                if (bimg != null &&
+                        (bimg.getType() == BufferedImage.TYPE_INT_BGR ||
+                         bimg.getType() == BufferedImage.TYPE_INT_RGB)) {
+                    srcPixelsAreOpaque = checkFXImageOpaque(pr, iw, ih);
+                }
+                break;
+            case BYTE_RGB:
+                srcPixelsAreOpaque = true;
+                break;
+        }
+        int prefBimgType = getBestBufferedImageType(pr.getPixelFormat(), bimg, srcPixelsAreOpaque);
         if (bimg != null) {
             int bw = bimg.getWidth();
             int bh = bimg.getHeight();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/system/src/test/java/test/javafx/embed/swing/FXImageConversionTest.java	Thu Sep 21 10:38:05 2017 -0700
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.javafx.embed.swing;
+
+import java.awt.image.BufferedImage;
+import javafx.embed.swing.SwingFXUtils;
+import javafx.scene.image.PixelWriter;
+import javafx.scene.image.WritableImage;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import junit.framework.Assert;
+
+public class FXImageConversionTest {
+
+    private static int width = 100;
+    private static int height = 100;
+
+    @Test public void testImageConversionRGBOpaque() {
+        WritableImage newimage = new WritableImage(width, height);
+        PixelWriter pw = newimage.getPixelWriter();
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                pw.setArgb(x, y, 0xff000000);
+            }
+        }
+        try {
+            BufferedImage b = new BufferedImage(width + 1, height + 1,
+                                                BufferedImage.TYPE_INT_RGB);
+            BufferedImage bf = SwingFXUtils.fromFXImage(newimage, b);
+
+            assertTrue(bf.getType() == BufferedImage.TYPE_INT_RGB);
+        } catch (ClassCastException cex) {
+            Assert.fail("FX image conversion wrong cast " + cex);
+        }
+    }
+
+    @Test public void testImageConversionRGBNotOpaque() {
+        WritableImage newimage = new WritableImage(width, height);
+        PixelWriter pw = newimage.getPixelWriter();
+        for (int x = 0; x < width/2; x++) {
+            for (int y = 0; y < height/2; y++) {
+                pw.setArgb(x, y, 0xff000000);
+            }
+        }
+        try {
+            BufferedImage b = new BufferedImage(width + 1, height + 1,
+                                                BufferedImage.TYPE_INT_RGB);
+            BufferedImage bf = SwingFXUtils.fromFXImage(newimage, b);
+
+            assertTrue(bf.getType() == BufferedImage.TYPE_INT_ARGB_PRE);
+        } catch (ClassCastException cex) {
+            Assert.fail("FX image conversion wrong cast " + cex);
+        }
+    }
+
+    @Test public void testImageConversionGray() {
+        WritableImage newimage = new WritableImage(width, height);
+        PixelWriter pw = newimage.getPixelWriter();
+        for (int x = 0; x < width; x++) {
+            for (int y = 0; y < height; y++) {
+                pw.setArgb(x, y, 0xff000000);
+            }
+        }
+        try {
+            BufferedImage b = new BufferedImage(width + 1, height + 1,
+                                                BufferedImage.TYPE_BYTE_GRAY);
+            BufferedImage bf = SwingFXUtils.fromFXImage(newimage, b);
+
+            assertTrue(bf.getType() == BufferedImage.TYPE_INT_ARGB_PRE);
+        } catch (ClassCastException cex) {
+            Assert.fail("FX image conversion wrong cast " + cex);
+        }
+    }
+}