001 /*
002 * $Id: ImageRGBDisplayable.java,v 1.7 2012/02/19 17:35:40 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2012
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 *
012 * All Rights Reserved
013 *
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.
016 *
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 *
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025 * GNU Lesser Public License for more details.
026 *
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program. If not, see http://www.gnu.org/licenses.
029 */
030
031 package edu.wisc.ssec.mcidasv.data.hydra;
032
033 import ucar.visad.display.GridDisplayable;
034 import ucar.visad.display.DisplayableData;
035 import ucar.visad.display.ScalarMapSet;
036
037 import ucar.unidata.data.grid.GridUtil;
038
039 import ucar.unidata.util.Misc;
040
041 import visad.*;
042
043 import visad.bom.ImageRendererJ3D;
044 import visad.java3d.DefaultRendererJ3D;
045
046 import visad.java2d.*;
047 import visad.java2d.DefaultRendererJ2D;
048
049 import visad.java2d.DisplayRendererJ2D;
050
051
052 import java.rmi.RemoteException;
053
054
055
056 /**
057 * Provides support for a Displayable that needs a map to
058 * (Display.Red,Display.Green,Display.Blue)
059 *
060 * @author IDV development team
061 * @version $Revision: 1.7 $
062 */
063 public class ImageRGBDisplayable extends DisplayableData implements GridDisplayable {
064
065
066 /** color ScalarMaps */
067 private volatile ScalarMap[] colorMaps = { null, null, null };
068
069 /** color MathType */
070 private volatile RealTupleType colorTupleType;
071
072 /** color palette */
073 private float[][] colorPalette;
074
075 /** What do we map with */
076 private DisplayRealType mapType = Display.RGB;
077
078 /** flag for whether we use Alpha channel or not */
079 private boolean doAlpha = false;
080
081 private static int uniqueID = 0;
082
083
084 /**
085 * Constructs from a name for the Displayable and the type of the
086 * RGB parameter.
087 *
088 * @param name The name for the displayable.
089 * @throws VisADException VisAD failure.
090 * @throws RemoteException Java RMI failure.
091 */
092 public ImageRGBDisplayable(String name)
093 throws VisADException, RemoteException {
094 this(name, false);
095 }
096
097
098 /**
099 * Constructs from a name for the Displayable and the type of the
100 * RGB parameter.
101 *
102 * @param name The name for the displayable.
103 * @param doAlpha true to map to RGBA
104 * @throws VisADException VisAD failure.
105 * @throws RemoteException Java RMI failure.
106 */
107 public ImageRGBDisplayable(String name, boolean doAlpha)
108 throws VisADException, RemoteException {
109 this(name, BaseColorControl.initTableGreyWedge(new float[(doAlpha)
110 ? 4
111 : 3][255]), doAlpha);
112 }
113
114 /**
115 * Constructs from a name for the Displayable and the type of the
116 * RGB parameter.
117 *
118 * @param name The name for the displayable.
119 * @param colorPalette The color palette
120 * @param doAlpha true to map to RGBA
121 * @throws VisADException VisAD failure.
122 * @throws RemoteException Java RMI failure.
123 */
124 public ImageRGBDisplayable(String name, float[][] colorPalette,
125 boolean doAlpha)
126 throws VisADException, RemoteException {
127 this(name, colorPalette, doAlpha, null);
128 }
129
130
131 /**
132 * Constructs from another instance. The following attributes are set from
133 * the other instance: color palette, the color RealType.
134 * @param that The other instance.
135 * @throws VisADException VisAD failure.
136 * @throws RemoteException Java RMI failure.
137 */
138 protected ImageRGBDisplayable(ImageRGBDisplayable that)
139 throws VisADException, RemoteException {
140
141 super(that);
142 this.doAlpha = that.doAlpha;
143 colorTupleType = that.colorTupleType;
144 colorPalette = Set.copyFloats(that.colorPalette);
145 if (colorTupleType != null) {
146 setColorMaps();
147 }
148 }
149
150 public ImageRGBDisplayable(String name, float[][] colorPalette, boolean doAlpha, FieldImpl field)
151 throws VisADException, RemoteException {
152 super(name);
153 this.doAlpha = doAlpha;
154 if (doAlpha) {
155 mapType = Display.RGBA;
156 colorMaps = new ScalarMap[] { null, null, null, null };
157 }
158
159 addConstantMaps(new ConstantMap[] {
160 new ConstantMap(GraphicsModeControl.SUM_COLOR_MODE,
161 Display.ColorMode),
162 new ConstantMap(1.0, Display.MissingTransparent) });
163
164
165 if (field != null) {
166 TupleType tt = GridUtil.getParamType(field);
167 RealTupleType ffldType = new RealTupleType(tt.getRealComponents());
168
169 if ((getColorTupleType() == null)
170 || !ffldType.equals(getColorTupleType())) {
171 setColorTupleType(ffldType);
172 }
173 }
174 }
175
176
177
178 /**
179 * Set the data into the Displayable; set RGB Type
180 *
181 *
182 * @param field an image or sequence of images
183 * @exception VisADException from construction of VisAd objects
184 * @exception RemoteException from construction of VisAD objects
185 */
186 public void loadData(FieldImpl field)
187 throws VisADException, RemoteException {
188 setData(field);
189 }
190
191
192 /**
193 * Get the RealTupleType of the RGB parameter.
194 * @return The RealTupleType of the RGB parameters.
195 * May be <code>null</code>.
196 */
197 public RealTupleType getColorTupleType() {
198 return colorTupleType;
199 }
200
201 /**
202 * Sets the RealTupleType of the RGB parameter.
203 * @param realTupleType The RealTupleType of the RGB parameters. May
204 * not be <code>null</code>.
205 * @throws VisADException VisAD failure.
206 * @throws RemoteException Java RMI failure.
207 */
208 protected void setColorTupleType(RealTupleType realTupleType)
209 throws RemoteException, VisADException {
210
211 if ( !realTupleType.equals(colorTupleType)) {
212 RealTupleType oldValue = colorTupleType;
213 colorTupleType = realTupleType;
214 setColorMaps();
215 }
216 }
217
218
219 /**
220 * Returns the RealTupleType of the RGB parameter.
221 * @return The RealTupleType of the color parameter. May
222 * be <code>null</code>.
223 * @deprecated use getColorTupleType()
224 */
225 public RealTupleType getRGBRealTupleType() {
226 return colorTupleType;
227 }
228
229
230 /**
231 * Sets the set of ScalarMap-s of this instance. The ScalarMap-s of
232 * this instance will be added to the set before the SCALAR_MAP_SET
233 * property is set. This method fires a PropertyChangeEvent for
234 * SCALAR_MAP_SET with <code>null</code> for the old value and the new
235 * set of ScalarMap-s for the new Value. Intermediate subclasses that
236 * have their own ScalarMap-s should override this method and invoke
237 * <code>super.setScalarMaps(ScalarMapSet)</code>.
238 * @param maps The set of ScalarMap-s to be added.
239 * @throws BadMappingException The RealType of the color parameter
240 * has not been set or its ScalarMap is alread in
241 * the set.
242 */
243 protected void setScalarMaps(ScalarMapSet maps)
244 throws BadMappingException {
245
246 if (colorMaps[0] == null) {
247 throw new BadMappingException(getClass().getName()
248 + ".setScalarMaps(ScalarMapSet): "
249 + "Color not yet set");
250 }
251
252 for (int i = 0; i < colorMaps.length; i++) {
253 maps.add(colorMaps[i]);
254 }
255 super.setScalarMapSet(maps);
256 }
257
258 /**
259 * Set the alpha. Unused.
260 *
261 * @param alpha alpha
262 *
263 * @throws RemoteException On badness
264 * @throws VisADException On badness
265 */
266 public void setAlpha(float alpha) throws RemoteException, VisADException {
267 addConstantMaps(new ConstantMap[] {
268 new ConstantMap(alpha, Display.Alpha) });
269 }
270
271 /**
272 * creates the ScalarMaps for color for this Displayable.
273 *
274 * @throws VisADException VisAD failure.
275 * @throws RemoteException Java RMI failure.
276 */
277 private void setColorMaps() throws RemoteException, VisADException {
278
279 ScalarMapSet set = new ScalarMapSet();
280 for (int i = 0; i < colorMaps.length; i++) {
281 colorMaps[i] =
282 new ScalarMap((RealType) colorTupleType.getComponent(i),
283 mapType);
284 /* TODO: maybe allow user to set range. If so, just copy
285 logic from RGBDisplayable */
286 //-TDR colorMaps[i].setRange(0, 255);
287 set.add(colorMaps[i]);
288 final int colorMapIndex = i;
289 colorMaps[i].addScalarMapListener(new ScalarMapListener() {
290 public void controlChanged(ScalarMapControlEvent event)
291 throws RemoteException, VisADException {
292 int id = event.getId();
293 if ((id == event.CONTROL_ADDED)
294 || (id == event.CONTROL_REPLACED)) {
295 setColorsInControls(colorPalette, colorMapIndex);
296 }
297 }
298
299 public void mapChanged(ScalarMapEvent event)
300 throws RemoteException, VisADException {
301 }
302 });
303 }
304
305 setScalarMapSet(set);
306 setColorsInControls(colorPalette);
307 }
308
309 /**
310 * Set the display.
311 *
312 * @param display display to set this into
313 *
314 * @throws DisplayException Display type exception
315 * @throws RemoteException Java RMI error
316 * @throws VisADException problem creating VisAD object
317 */
318 public void setDisplay(LocalDisplay display)
319 throws DisplayException, VisADException, RemoteException {
320 super.setDisplay(display);
321 setColorsInControls(colorPalette);
322 }
323
324 /**
325 * This method sets the color palette
326 * according to the color table in argument;
327 * pair this method with setRange(lo,high) to get
328 * a fixed association of color table and range of values.
329 *
330 * @param colorPalette the color table or color-alpha table desired
331 * @throws VisADException if a core VisAD failure occurs.
332 * @throws RemoteException if a Java RMI failure occurs.
333 */
334 public void setColorPalette(float[][] colorPalette)
335 throws RemoteException, VisADException {
336
337 setColorsInControls(colorPalette);
338 this.colorPalette = colorPalette;
339 }
340
341 /**
342 * Return the current color palette in this Displayable
343 *
344 * @return a color table float[3][len] or color-alpha table float[4][len]
345 */
346 public float[][] getColorPalette() {
347 return colorPalette;
348 }
349
350
351 /**
352 * Set colors for the controls of all color maps.
353 *
354 * @param colorPalette The 3xN color palette array
355 *
356 * @throws RemoteException Java RMI error
357 * @throws VisADException problem creating VisAD object
358 */
359 private void setColorsInControls(float[][] colorPalette)
360 throws RemoteException, VisADException {
361
362 for (int i = 0; i < colorMaps.length; i++) {
363 setColorsInControls(colorPalette, i);
364 }
365 }
366
367
368
369
370 /**
371 * Set colors for the control defined by the given colorMapIndex (0,1 or 2).
372 *
373 * @param colorPalette The 3xN color palette array
374 * @param colorMapIndex Which of the color maps are we setting the color of.
375 *
376 * @throws RemoteException Java RMI error
377 * @throws VisADException problem creating VisAD object
378 */
379 private void setColorsInControls(float[][] colorPalette,
380 int colorMapIndex)
381 throws RemoteException, VisADException {
382 if (colorPalette == null) {
383 return;
384 }
385
386
387 if (colorMaps[colorMapIndex] == null) {
388 return;
389 }
390
391 BaseColorControl bcc =
392 (BaseColorControl) colorMaps[colorMapIndex].getControl();
393
394 if (bcc != null) {
395 float[][] table =
396 new float[colorMaps.length][colorPalette[0].length];
397 table[colorMapIndex] = colorPalette[colorMapIndex];
398 bcc.setTable(table);
399 }
400 }
401
402 protected DataRenderer getDataRenderer() throws VisADException {
403
404 ImageRendererJ3D myRenderer = new ImageRendererJ3D();
405 return myRenderer;
406
407 }
408
409
410 /**
411 * Set whether this GridDisplayable should have the data colored
412 * by another parameter. This implementation is a no-op.
413 *
414 * @param yesno true if colored by another
415 */
416 public void setColoredByAnother(boolean yesno) {}
417
418 }