Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.embed.swing;
027
028import java.awt.AlphaComposite;
029import java.awt.Graphics2D;
030import java.awt.image.BufferedImage;
031import java.nio.IntBuffer;
032import javafx.scene.image.Image;
033import javafx.scene.image.PixelFormat;
034import javafx.scene.image.PixelReader;
035import javafx.scene.image.PixelWriter;
036import javafx.scene.image.WritableImage;
037import javafx.scene.image.WritablePixelFormat;
038import sun.awt.image.IntegerComponentRaster;
039
040/**
041 * This class provides utility methods for converting data types between
042 * Swing/AWT and JavaFX formats.
043 */
044public class SwingFXUtils {
045    private SwingFXUtils() {} // no instances
046
047    /**
048     * Snapshots the specified {@link BufferedImage} and stores a copy of
049     * its pixels into a JavaFX {@link Image} object, creating a new
050     * object if needed.
051     * The returned {@code Image} will be a static snapshot of the state
052     * of the pixels in the {@code BufferedImage} at the time the method
053     * completes.  Further changes to the {@code BufferedImage} will not
054     * be reflected in the {@code Image}.
055     * <p>
056     * The optional JavaFX {@link WritableImage} parameter may be reused
057     * to store the copy of the pixels.
058     * A new {@code Image} will be created if the supplied object is null,
059     * is too small or of a type which the image pixels cannot be easily
060     * converted into.
061     * 
062     * @param bimg the {@code BufferedImage} object to be converted
063     * @param wimg an optional {@code WritableImage} object that can be
064     *        used to store the returned pixel data
065     * @return an {@code Image} object representing a snapshot of the
066     *         current pixels in the {@code BufferedImage}.
067     * @since 2.2
068     */
069    public static WritableImage toFXImage(BufferedImage bimg, WritableImage wimg) {
070        int bw = bimg.getWidth();
071        int bh = bimg.getHeight();
072        switch (bimg.getType()) {
073            case BufferedImage.TYPE_INT_ARGB:
074            case BufferedImage.TYPE_INT_ARGB_PRE:
075                break;
076            default:
077                BufferedImage converted =
078                    new BufferedImage(bw, bh, BufferedImage.TYPE_INT_ARGB_PRE);
079                Graphics2D g2d = converted.createGraphics();
080                g2d.drawImage(bimg, 0, 0, null);
081                g2d.dispose();
082                bimg = converted;
083                break;
084        }
085        // assert(bimg.getType == TYPE_INT_ARGB[_PRE]);
086        if (wimg != null) {
087            int iw = (int) wimg.getWidth();
088            int ih = (int) wimg.getHeight();
089            if (iw < bw || ih < bh) {
090                wimg = null;
091            } else if (bw < iw || bh < ih) {
092                int empty[] = new int[iw];
093                PixelWriter pw = wimg.getPixelWriter();
094                PixelFormat pf = PixelFormat.getIntArgbPreInstance();
095                if (bw < iw) {
096                    pw.setPixels(bw, 0, iw-bw, bh, pf, empty, 0, 0);
097                }
098                if (bh < ih) {
099                    pw.setPixels(0, bh, iw, ih-bh, pf, empty, 0, 0);
100                }
101            }
102        }
103        if (wimg == null) {
104            wimg = new WritableImage(bw, bh);
105        }
106        PixelWriter pw = wimg.getPixelWriter();
107        IntegerComponentRaster icr = (IntegerComponentRaster) bimg.getRaster();
108        int data[] = icr.getDataStorage();
109        int offset = icr.getDataOffset(0);
110        int scan = icr.getScanlineStride();
111        PixelFormat<IntBuffer> pf = (bimg.isAlphaPremultiplied() ?
112                                     PixelFormat.getIntArgbPreInstance() :
113                                     PixelFormat.getIntArgbInstance());
114        pw.setPixels(0, 0, bw, bh, pf, data, offset, scan);
115        return wimg;
116    }
117
118    /**
119     * Snapshots the specified JavaFX {@link Image} object and stores a
120     * copy of its pixels into a {@link BufferedImage} object, creating
121     * a new object if needed.
122     * The method will only convert a JavaFX {@code Image} that is readable
123     * as per the conditions on the
124     * {@link Image#getPixelReader() Image.getPixelReader()}
125     * method.
126     * If the {@code Image} is not readable, as determined by its
127     * {@code getPixelReader()} method, then this method will return null.
128     * If the {@code Image} is a writable, or other dynamic image, then
129     * the {@code BufferedImage} will only be set to the current state of
130     * the pixels in the image as determined by its {@link PixelReader}.
131     * Further changes to the pixels of the {@code Image} will not be
132     * reflected in the returned {@code BufferedImage}.
133     * <p>
134     * The optional {@code BufferedImage} parameter may be reused to store
135     * the copy of the pixels.
136     * A new {@code BufferedImage} will be created if the supplied object
137     * is null, is too small or of a type which the image pixels cannot
138     * be easily converted into.
139     * 
140     * @param img the JavaFX {@code Image} to be converted
141     * @param bimg an optional {@code BufferedImage} object that may be
142     *        used to store the returned pixel data
143     * @return a {@code BufferedImage} containing a snapshot of the JavaFX
144     *         {@code Image}, or null if the {@code Image} is not readable.
145     * @since 2.2
146     */
147    public static BufferedImage fromFXImage(Image img, BufferedImage bimg) {
148        PixelReader pr = img.getPixelReader();
149        if (pr == null) {
150            return null;
151        }
152        int iw = (int) img.getWidth();
153        int ih = (int) img.getHeight();
154        if (bimg != null) {
155            int type = bimg.getType();
156            int bw = bimg.getWidth();
157            int bh = bimg.getHeight();
158            if (bw < iw || bh < ih ||
159                (type != BufferedImage.TYPE_INT_ARGB &&
160                 type != BufferedImage.TYPE_INT_ARGB_PRE))
161            {
162                bimg = null;
163            } else if (iw < bw || ih < bh) {
164                Graphics2D g2d = bimg.createGraphics();
165                g2d.setComposite(AlphaComposite.Clear);
166                g2d.fillRect(0, 0, bw, bh);
167                g2d.dispose();
168            }
169        }
170        if (bimg == null) {
171            bimg = new BufferedImage(iw, ih, BufferedImage.TYPE_INT_ARGB_PRE);
172        }
173        IntegerComponentRaster icr = (IntegerComponentRaster) bimg.getRaster();
174        int offset = icr.getDataOffset(0);
175        int scan = icr.getScanlineStride();
176        int data[] = icr.getDataStorage();
177        WritablePixelFormat<IntBuffer> pf = (bimg.isAlphaPremultiplied() ?
178                                             PixelFormat.getIntArgbPreInstance() :
179                                             PixelFormat.getIntArgbInstance());
180        pr.getPixels(0, 0, iw, ih, pf, data, offset, scan);
181        return bimg;
182    }
183}