--- old/modules/swing/src/main/java/javafx/embed/swing/SwingFXUtils.java 2014-09-23 19:50:06.000000000 -0700 +++ new/modules/swing/src/main/java/javafx/embed/swing/SwingFXUtils.java 2014-09-23 19:50:06.000000000 -0700 @@ -30,8 +30,6 @@ import java.awt.Graphics2D; import java.awt.SecondaryLoop; import java.awt.image.BufferedImage; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.IntBuffer; import java.security.AccessController; import java.security.PrivilegedAction; @@ -108,7 +106,7 @@ } else if (bw < iw || bh < ih) { int empty[] = new int[iw]; PixelWriter pw = wimg.getPixelWriter(); - PixelFormat pf = PixelFormat.getIntArgbPreInstance(); + PixelFormat pf = PixelFormat.getIntArgbPreInstance(); if (bw < iw) { pw.setPixels(bw, 0, iw-bw, bh, pf, empty, 0, 0); } @@ -133,6 +131,78 @@ } /** + * Determine the optimal BufferedImage type to use for the specified + * {@code fxFormat} allowing for the specified {@code bimg} to be used + * as a potential default storage space if it is not null and is compatible. + * + * @param fxFormat the PixelFormat of the source FX Image + * @param bimg an optional existing {@code BufferedImage} to be used + * for storage if it is compatible, or null + * @return + */ + private static int + getBestBufferedImageType(PixelFormat fxFormat, BufferedImage bimg) + { + if (bimg != null) { + int bimgType = bimg.getType(); + if (bimgType == BufferedImage.TYPE_INT_ARGB || + bimgType == BufferedImage.TYPE_INT_ARGB_PRE) + { + // We will allow the caller to give us a BufferedImage + // that has an alpha channel, but we might not otherwise + // construct one ourselves. + // We will also allow them to choose their own premultiply + // type which may not match the image. + // If left to our own devices we might choose a more specific + // format as indicated by the choices below. + return bimgType; + } + } + switch (fxFormat.getType()) { + default: + case BYTE_BGRA_PRE: + case INT_ARGB_PRE: + return BufferedImage.TYPE_INT_ARGB_PRE; + case BYTE_BGRA: + case INT_ARGB: + return BufferedImage.TYPE_INT_ARGB; + case BYTE_RGB: + return BufferedImage.TYPE_INT_RGB; + case BYTE_INDEXED: + return (fxFormat.isPremultiplied() + ? BufferedImage.TYPE_INT_ARGB_PRE + : BufferedImage.TYPE_INT_ARGB); + } + } + + /** + * Determine the appropriate {@link WritablePixelFormat} type that can + * be used to transfer data into the indicated BufferedImage. + * + * @param bimg the BufferedImage that will be used as a destination for + * a {@code PixelReader#getPixels()} operation. + * @return + */ + private static WritablePixelFormat + getAssociatedPixelFormat(BufferedImage bimg) + { + switch (bimg.getType()) { + // We lie here for xRGB, but we vetted that the src data was opaque + // so we can ignore the alpha. We use ArgbPre instead of Argb + // just to get a loop that does not have divides in it if the + // PixelReader happens to not know the data is opaque. + case BufferedImage.TYPE_INT_RGB: + case BufferedImage.TYPE_INT_ARGB_PRE: + return PixelFormat.getIntArgbPreInstance(); + case BufferedImage.TYPE_INT_ARGB: + return PixelFormat.getIntArgbInstance(); + default: + // Should not happen... + throw new InternalError("Failed to validate BufferedImage type"); + } + } + + /** * Snapshots the specified JavaFX {@link Image} object and stores a * copy of its pixels into a {@link BufferedImage} object, creating * a new object if needed. @@ -168,14 +238,11 @@ } int iw = (int) img.getWidth(); int ih = (int) img.getHeight(); + int prefBimgType = getBestBufferedImageType(pr.getPixelFormat(), bimg); if (bimg != null) { - int type = bimg.getType(); int bw = bimg.getWidth(); int bh = bimg.getHeight(); - if (bw < iw || bh < ih || - (type != BufferedImage.TYPE_INT_ARGB && - type != BufferedImage.TYPE_INT_ARGB_PRE)) - { + if (bw < iw || bh < ih || bimg.getType() != prefBimgType) { bimg = null; } else if (iw < bw || ih < bh) { Graphics2D g2d = bimg.createGraphics(); @@ -185,15 +252,13 @@ } } if (bimg == null) { - bimg = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_ARGB_PRE); + bimg = new BufferedImage(iw, ih, prefBimgType); } IntegerComponentRaster icr = (IntegerComponentRaster) bimg.getRaster(); int offset = icr.getDataOffset(0); int scan = icr.getScanlineStride(); int data[] = icr.getDataStorage(); - WritablePixelFormat pf = (bimg.isAlphaPremultiplied() ? - PixelFormat.getIntArgbPreInstance() : - PixelFormat.getIntArgbInstance()); + WritablePixelFormat pf = getAssociatedPixelFormat(bimg); pr.getPixels(0, 0, iw, ih, pf, data, offset, scan); return bimg; }