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 }