001/* An AWT and Swing implementation of the the ImageDisplayInterface
002 that displays a Black and White image on the screen using the Picture class.
003
004 @Copyright (c) 1998-2014 The Regents of the University of California.
005 All rights reserved.
006
007 Permission is hereby granted, without written agreement and without
008 license or royalty fees, to use, copy, modify, and distribute this
009 software and its documentation for any purpose, provided that the
010 above copyright notice and the following two paragraphs appear in all
011 copies of this software.
012
013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
017 SUCH DAMAGE.
018
019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
024 ENHANCEMENTS, OR MODIFICATIONS.
025
026 PT_COPYRIGHT_VERSION 2
027 COPYRIGHTENDKEY
028 */
029package ptolemy.domains.sdf.lib.vq;
030
031import java.awt.Container;
032import java.awt.Image;
033import java.awt.image.ColorModel;
034import java.awt.image.MemoryImageSource;
035
036import javax.swing.JFrame;
037import javax.swing.SwingUtilities;
038
039import ptolemy.data.AWTImageToken;
040import ptolemy.data.IntMatrixToken;
041import ptolemy.data.Token;
042import ptolemy.kernel.util.IllegalActionException;
043import ptolemy.kernel.util.InternalErrorException;
044import ptolemy.media.Picture;
045
046///////////////////////////////////////////////////////////////////
047////ImageDisplayJavaSE
048
049/**
050<p>
051ImageDisplayJavaSE is the implementation of the ImageDisplayInterface that uses AWT and Swing
052classes.</p>
053
054@author Jianwu Wang, Based on code by James Yeh, Edward A. Lee
055@version $Id$
056@since Ptolemy II 10.0
057@Pt.ProposedRating
058@Pt.AcceptedRating
059 */
060
061public class ImageDisplayJavaSE
062        extends ptolemy.actor.lib.image.ImageDisplayJavaSE
063        implements ptolemy.domains.sdf.lib.vq.ImageDisplayInterface {
064
065    ///////////////////////////////////////////////////////////////////
066    ////                         public methods                    ////
067
068    /** Display the specified token. This must be called in the Swing
069     *  event thread.
070     *  @param in The token to display
071     */
072    @Override
073    public void display(final Token in) {
074        // Display probably to be done in the Swing event thread.
075        Runnable doDisplay = new Runnable() {
076            @Override
077            public void run() {
078                _display(in);
079            }
080        };
081
082        SwingUtilities.invokeLater(doDisplay);
083    }
084
085    ///////////////////////////////////////////////////////////////////
086    ////                         private methods                   ////
087
088    /** Convert an IntMatrixToken to a Packed RGB Image.
089     *  @param token An IntMatrixToken defining the black and white image.
090     *  @return A packed RGB array of integers
091     */
092    private int[] _convertBWImageToPackedRGBImage(IntMatrixToken token) {
093        int[][] frame = token.intMatrix();
094        int xSize = token.getColumnCount();
095        int ySize = token.getRowCount();
096
097        int[] RGBbuffer = new int[xSize * ySize];
098
099        // convert the B/W image to a packed RGB image.  This includes
100        // flipping the image upside down.  (When it is drawn, it gets
101        // drawn from bottom up).
102        int i;
103
104        // convert the B/W image to a packed RGB image.  This includes
105        // flipping the image upside down.  (When it is drawn, it gets
106        // drawn from bottom up).
107        int j;
108
109        // convert the B/W image to a packed RGB image.  This includes
110        // flipping the image upside down.  (When it is drawn, it gets
111        // drawn from bottom up).
112        int index = 0;
113
114        for (j = ySize - 1; j >= 0; j--) {
115            for (i = 0; i < xSize; i++, index++) {
116                RGBbuffer[index] = 255 << 24 | (frame[j][i] & 255) << 16
117                        | (frame[j][i] & 255) << 8 | frame[j][i] & 255;
118            }
119        }
120
121        return RGBbuffer;
122    }
123
124    /** Display the specified token. This must be called in the Swing
125     *  event thread.
126     *  @param in The token to display.
127     */
128    private void _display(Token in) {
129        // FIXME: lots of code duplication with parent and
130        // with ptolemy/actor/lib/image/ImageTableau.java
131        // We could try to refactor this, but it would get tricky
132        int xSize = ((IntMatrixToken) in).getColumnCount();
133        int ySize = ((IntMatrixToken) in).getRowCount();
134
135        if (_imageWindowFrame != null) {
136            // We have a frame already, so just create an AWTImageToken
137            // and tell the effigy about it.
138            MemoryImageSource imageSource = new MemoryImageSource(xSize, ySize,
139                    ColorModel.getRGBdefault(),
140                    _convertBWImageToPackedRGBImage((IntMatrixToken) in), 0,
141                    xSize);
142            imageSource.setAnimated(true);
143
144            // Sadly, we can't easily create an image without some sort
145            // of graphical context here.  This is a huge shortcoming of
146            // awt.  Just because I'm operating on images, I should not
147            // need a frame.
148            Image image = _imageWindowFrame.getContentPane()
149                    .createImage(imageSource);
150
151            AWTImageToken token = new AWTImageToken(image);
152
153            try {
154                _effigy.setImage(token);
155            } catch (IllegalActionException e) {
156                throw new InternalErrorException(e);
157            }
158        } else if (_picture != null) {
159            // If the size has changed, have to recreate the Picture object.
160            if (_oldXSize != xSize || _oldYSize != ySize) {
161                _oldXSize = xSize;
162                _oldYSize = ySize;
163
164                Container container = _picture.getParent();
165
166                container.remove(_picture);
167
168                _picture = new Picture(xSize, ySize);
169
170                //_picture.setImage(image);
171                _picture.setImage(
172                        _convertBWImageToPackedRGBImage((IntMatrixToken) in));
173                _picture.setBackground(null);
174                container.add("Center", _picture);
175                container.validate();
176                container.invalidate();
177                container.repaint();
178                container.doLayout();
179
180                Container c = container.getParent();
181
182                while (c.getParent() != null) {
183                    c.invalidate();
184                    c.validate();
185                    c = c.getParent();
186
187                    if (c instanceof JFrame) {
188                        ((JFrame) c).pack();
189                    }
190                }
191            } else {
192                // The _imageWindowFrame is null, the size has not changed, set the image.
193                _picture.setImage(
194                        _convertBWImageToPackedRGBImage((IntMatrixToken) in));
195                _picture.displayImage();
196                _picture.repaint();
197            }
198        }
199    }
200
201}