001    /* EVolve - an Extensible Software Visualization Framework
002     * Copyright (C) 2001-2002 Qin Wang
003     *
004     * This library is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU Library General Public
006     * License as published by the Free Software Foundation; either
007     * version 2 of the License, or (at your option) any later version.
008     *
009     * This library is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012     * Library General Public License for more details.
013     *
014     * You should have received a copy of the GNU Library General Public
015     * License along with this library; if not, write to the
016     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017     * Boston, MA 02111-1307, USA.
018     */
019    
020    /*
021     * EVolve is distributed at http://www.sable.mcgill.ca/EVolve/
022     */
023    
024    package EVolve.visualization;
025    
026    import java.awt.Color;
027    import java.awt.Graphics2D;
028    import java.awt.image.BufferedImage;
029    import java.util.ArrayList;
030    import java.util.HashMap;
031    import java.util.Iterator;
032    
033    import EVolve.exceptions.NoDataPlotException;
034    
035    /**
036     * Automatic expanding image.
037     */
038    public class AutoImage implements Cloneable{
039        protected short[][] image; // the image
040        protected int w, h; // width and height of the content
041        protected int wMax, hMax; // width and height of the image
042        protected int imageWidth, imageHeight;
043    
044        protected HashMap object2Int,Int2Object;
045    
046        private ArrayList phases;
047        private Color gray;
048    
049        /**
050         * Creates an auto-image.
051         */
052        public AutoImage() {
053            w = 0;
054            h = 0;
055            wMax = 200;
056            hMax = 200;
057            image = new short[wMax][hMax];
058            for (int i = 0; i < wMax; i++) {
059                for (int j = 0; j < hMax; j++) {
060                    image[i][j] = 0;
061                }
062            }
063            object2Int = new HashMap();
064            Int2Object = new HashMap();
065            object2Int.put(null,new Integer(0));
066            Int2Object.put(new Integer(0),null);
067            gray = new Color(234,234,234);
068        }
069    
070        /**
071         * Sets the color of a pixel.
072         *
073         * @param   x position on X-axis
074         * @param   y position on Y-axis
075         * @param   color the color
076         */
077        public void setColor(int x, int y, Object color) {
078            if ((x >= wMax) || (y >= hMax)) {
079                while (x >= wMax) {
080                    wMax += 200;
081                }
082                while (y >= hMax) {
083                    hMax += 200;
084                }
085    
086                short[][] newImage = new short[wMax][hMax];
087                for (int i = 0; i < wMax; i++) {
088                    for (int j = 0; j < hMax; j++) {
089                        newImage[i][j] = 0;
090                    }
091                }
092                for (int i = 0; i < w; i++) {
093                    for (int j = 0; j < h; j++) {
094                        newImage[i][j] = image[i][j];
095                    }
096                }
097                image = newImage;
098            }
099    
100            if (object2Int.containsKey(color)) {
101                image[x][y] = ((Integer)object2Int.get(color)).shortValue();
102            } else {
103                short size = (short)object2Int.size();
104                object2Int.put(color,new Integer(size));
105                Int2Object.put(new Integer(size),color);
106                image[x][y] = size;
107            }
108    
109            if (x >= w) {
110                w = x + 1;
111            }
112            if (y >= h) {
113                h = y + 1;
114            }
115        }
116    
117        /**
118         * Gets the color of a pixel.
119         *
120         * @param   x position on X-axis
121         * @param   y position on Y-axis
122         * @return  the color
123         */
124        public Object getColor(int x, int y) {
125            if ((image!=null) && ((x < 0) || (y < 0) || (x >= image.length) || (y >= image[0].length))) {
126                return null;
127            } else {
128                int index = image[x][y];
129                return Int2Object.get(new Integer(index));
130            }
131        }
132    
133        public Object getSortedColor(ReferenceDimension xAxis, ReferenceDimension yAxis,int x,int y) {
134            int xMappedId,yMappedId;
135            xMappedId = (xAxis == null) ? x : xAxis.getOriginMappedId(x);
136            yMappedId = (yAxis == null) ? y : yAxis.getOriginMappedId(y);
137    
138            if ((xMappedId >= wMax) || (yMappedId >= hMax) || (xMappedId < 0) || (yMappedId < 0))
139                return null;
140            else {
141                int index = image[xMappedId][yMappedId];
142                if (index == 0)
143                    return null;
144                else
145                    return (Color)Int2Object.get(new Integer(index));
146            }
147        }
148    
149        /**
150         * Gets the buffered-image.
151         *
152         * @return  buffered-image
153         */
154        public BufferedImage getImage() throws NoDataPlotException {
155    
156            if (w*h == 0) throw new NoDataPlotException();
157    
158            BufferedImage returnVal = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
159            Graphics2D g2 = (Graphics2D)returnVal.getGraphics();
160    
161            g2.setColor(Color.white);
162            g2.fillRect(0, 0, w, h);
163    
164            if ((phases != null)&&(phases.size()!=0)) {
165                int lastX = 0;
166    
167                for (int i=0; i<phases.size(); i++) {
168                    int phaseEnd = ((Integer)phases.get(i)).intValue();
169    
170                    if ((phaseEnd <= 0)||(phaseEnd>=w)) continue;
171    
172                    g2.setColor(i%2 == 0 ? gray : Color.white);
173                    g2.fillRect(lastX,0,phaseEnd,h);
174                    lastX = phaseEnd;
175                }
176                g2.setColor(phases.size()%2 == 0 ? gray : Color.white);
177                g2.fillRect(lastX,0,w,h);
178            }
179    
180            for (int i = 0; i < w; i++) {
181                for (int j = 0; j < h; j++) {
182                    if (image[i][j] != 0) {
183                        returnVal.setRGB(i, j, ((Color)Int2Object.get(new Integer(image[i][j]))).getRGB());
184                    }
185                }
186            }
187    
188            return returnVal;
189        }
190    
191        /**
192         * Sorts the image.
193         *
194         * @param   xAxis dimension that represents the X-axis, null if doesn't need to be sorted
195         * @param   yAxis dimension that represents the Y-axis, null if doesn't need to be sorted
196         * @return  sorted image
197         */
198        public AutoImage getSortedImage(ReferenceDimension xAxis, ReferenceDimension yAxis) {
199            AutoImage returnVal = new AutoImage();
200            for (int i = 0; i < w; i++) {
201                for (int j = 0; j < h; j++) {
202                    int x, y;
203                    if (xAxis == null) {
204                        x = i;
205                    } else {
206                        x = xAxis.getSortedIndex(i);
207                    }
208                    if (yAxis == null) {
209                        y = j;
210                    } else {
211                        y = yAxis.getSortedIndex(j);
212                    }
213                    if ((x != -1) && (y != -1)) {
214                        returnVal.setColor(x, y, Int2Object.get(new Integer(image[i][j])));
215                    }
216                }
217            }
218            return returnVal;
219        }
220    
221        public int getDimension(int dim) {
222            if (dim == -1) return image.length;
223    
224            return image[dim].length;
225        }
226    
227        public int getW() {
228            return w;
229        }
230    
231        public int getH() {
232            return h;
233        }
234    
235        public void setImageSize(int width, int height) {
236            imageWidth = w;
237            imageHeight = h;
238        }
239    
240        public short[][] getImageDataArray() {
241            return image;
242        }
243    
244        public void setPhases(ArrayList phases) {
245            this.phases = phases;
246        }
247    
248        public Object clone() {
249            AutoImage o = null;
250            try {
251                o = (AutoImage)super.clone();
252            } catch (CloneNotSupportedException e) {
253                e.printStackTrace();
254                return o;
255            }
256    
257            o.Int2Object = new HashMap();
258            o.object2Int = new HashMap();
259            o.object2Int.put(null,new Integer(0));
260            o.Int2Object.put(new Integer(0),null);
261            o.image = new short[image.length][];
262            for (int i=0; i<image.length; i++) {
263                o.image[i] = new short[image[i].length];
264                for (int j=0; j<image[i].length; j++) {
265                    o.image[i][j] = image[i][j];
266                }
267            }
268            Iterator it = object2Int.keySet().iterator();
269            while (it.hasNext()) {
270                Object key = it.next();
271                o.object2Int.put(key, object2Int.get(key));
272            }
273            it = Int2Object.keySet().iterator();
274            while (it.hasNext()) {
275                Object key = it.next();
276                o.Int2Object.put(key, Int2Object.get(key));
277            }
278            return o;
279        }
280    }