001/* 002 * $Id: RGBCompositeControl.java,v 1.10 2011/03/24 16:06:32 davep Exp $ 003 * 004 * This file is part of McIDAS-V 005 * 006 * Copyright 2007-2011 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 */ 030package edu.wisc.ssec.mcidasv.control; 031 032import java.awt.BorderLayout; 033import java.awt.Container; 034import java.awt.FlowLayout; 035import java.awt.GridLayout; 036import java.awt.event.ActionEvent; 037import java.awt.event.ActionListener; 038import java.rmi.RemoteException; 039import java.util.Iterator; 040 041import javax.swing.JButton; 042import javax.swing.JLabel; 043import javax.swing.JPanel; 044import javax.swing.JTextField; 045 046import visad.BaseColorControl; 047import visad.FieldImpl; 048import visad.FlatField; 049import visad.FunctionType; 050import visad.ScalarMap; 051import visad.ScalarMapControlEvent; 052import visad.ScalarMapEvent; 053import visad.ScalarMapListener; 054import visad.VisADException; 055import visad.Data; 056import visad.CoordinateSystem; 057 058import visad.georef.MapProjection; 059 060import ucar.unidata.data.DataChoice; 061import ucar.unidata.data.DataSelection; 062import ucar.unidata.data.grid.GridDataInstance; 063import ucar.unidata.idv.control.DisplayControlImpl; 064import ucar.unidata.util.ColorTable; 065import ucar.unidata.util.LogUtil; 066import ucar.unidata.util.Range; 067import ucar.visad.display.DisplayMaster; 068 069import edu.wisc.ssec.mcidasv.data.hydra.ImageRGBDisplayable; 070 071 072public class RGBCompositeControl extends DisplayControlImpl { 073 074 /** Displayable for the data */ 075 private ImageRGBDisplayable imageDisplay; 076 077 private DisplayMaster displayMaster; 078 079 private ScalarMap redMap = null; 080 private ScalarMap grnMap = null; 081 private ScalarMap bluMap = null; 082 083 float[][] redTable = null; 084 float[][] grnTable = null; 085 float[][] bluTable = null; 086 087 final private double[] redRange = new double[] {Double.NaN, Double.NaN}; 088 final private double[] grnRange = new double[] {Double.NaN, Double.NaN}; 089 final private double[] bluRange = new double[] {Double.NaN, Double.NaN}; 090 091 final double[] initRedRange = new double[] {Double.NaN, Double.NaN}; 092 final double[] initGrnRange = new double[] {Double.NaN, Double.NaN}; 093 final double[] initBluRange = new double[] {Double.NaN, Double.NaN}; 094 095 private FieldImpl imageField = null; 096 private MapProjection mapProjection = null; 097 098 099 private double gamma = 1.0; 100 101 private double redGamma = 1.0; 102 private double grnGamma = 1.0; 103 private double bluGamma = 1.0; 104 105 private boolean hasRange = false; 106 107 private final JTextField gammaTxtFld = 108 new JTextField(Float.toString(1f), 4); 109 private final JTextField redGammaTxtFld = 110 new JTextField(Float.toString(1f), 4); 111 private final JTextField grnGammaTxtFld = 112 new JTextField(Float.toString(1f), 4); 113 private final JTextField bluGammaTxtFld = 114 new JTextField(Float.toString(1f), 4); 115 116 private final JTextField redLowTxtFld = 117 new JTextField(Float.toString(1f), 10); 118 private final JTextField redHighTxtFld = 119 new JTextField(Float.toString(1f), 10); 120 private final JTextField grnLowTxtFld = 121 new JTextField(Float.toString(1f), 10); 122 private final JTextField grnHighTxtFld = 123 new JTextField(Float.toString(1f), 10); 124 private final JTextField bluLowTxtFld = 125 new JTextField(Float.toString(1f), 10); 126 private final JTextField bluHighTxtFld = 127 new JTextField(Float.toString(1f), 10); 128 129 public RGBCompositeControl() { 130 super(); 131 } 132 133 public boolean init(DataChoice dataChoice) throws VisADException, RemoteException { 134 displayMaster = getViewManager().getMaster(); 135 DataSelection dataSelection = getDataSelection(); 136 imageField = (FieldImpl) dataChoice.getData(dataSelection); 137 138 139 imageDisplay = new ImageRGBDisplayable("rgb composite", null, false, imageField); 140 141 Iterator iter = imageDisplay.getScalarMapSet().iterator(); 142 while (iter.hasNext()) { 143 ScalarMap map = (ScalarMap) iter.next(); 144 double[] datRng = map.getRange(); 145 if (map.getScalarName().startsWith("redimage")) { 146 redMap = map; 147 } 148 if (map.getScalarName().startsWith("greenimage")) { 149 grnMap = map; 150 } 151 if (map.getScalarName().startsWith("blueimage")) { 152 bluMap = map; 153 } 154 } 155 156 if (checkRange()) { //- from unpersistence if true, initialize gui, ScalarMaps 157 double[] redRange = getRedRange(); 158 double[] grnRange = getGrnRange(); 159 double[] bluRange = getBluRange(); 160 161 initRedRange[0] = redRange[0]; 162 initRedRange[1] = redRange[1]; 163 initGrnRange[0] = grnRange[0]; 164 initGrnRange[1] = grnRange[1]; 165 initBluRange[0] = bluRange[0]; 166 initBluRange[1] = bluRange[1]; 167 168 redLowTxtFld.setText(Float.toString((float)redRange[0])); 169 redHighTxtFld.setText(Float.toString((float)redRange[1])); 170 grnLowTxtFld.setText(Float.toString((float)grnRange[0])); 171 grnHighTxtFld.setText(Float.toString((float)grnRange[1])); 172 bluLowTxtFld.setText(Float.toString((float)bluRange[0])); 173 bluHighTxtFld.setText(Float.toString((float)bluRange[1])); 174 175 gammaTxtFld.setText(Float.toString((float)gamma)); 176 redGammaTxtFld.setText(Float.toString((float)redGamma)); 177 grnGammaTxtFld.setText(Float.toString((float)grnGamma)); 178 bluGammaTxtFld.setText(Float.toString((float)bluGamma)); 179 180 redMap.setRange(redRange[0], redRange[1]); 181 grnMap.setRange(grnRange[0], grnRange[1]); 182 bluMap.setRange(bluRange[0], bluRange[1]); 183 } 184 else { 185 redMap.resetAutoScale(); 186 grnMap.resetAutoScale(); 187 bluMap.resetAutoScale(); 188 189 redMap.addScalarMapListener(new ColorMapListener(redMap, initRedRange, redRange, redLowTxtFld, redHighTxtFld)); 190 grnMap.addScalarMapListener(new ColorMapListener(grnMap, initGrnRange, grnRange, grnLowTxtFld, grnHighTxtFld)); 191 bluMap.addScalarMapListener(new ColorMapListener(bluMap, initBluRange, bluRange, bluLowTxtFld, bluHighTxtFld)); 192 } 193 194 setShowInDisplayList(true); 195 196 addDisplayable(imageDisplay, FLAG_COLORTABLE); 197 198 return true; 199 } 200 201 public void initDone() { 202 redTable = ((BaseColorControl)redMap.getControl()).getTable(); 203 grnTable = ((BaseColorControl)grnMap.getControl()).getTable(); 204 bluTable = ((BaseColorControl)bluMap.getControl()).getTable(); 205 206 float[][] newRedTbl = getZeroOutArray(redTable); 207 float[][] newGrnTbl = getZeroOutArray(grnTable); 208 float[][] newBluTbl = getZeroOutArray(bluTable); 209 210 for (int k=0; k<redTable[0].length; k++) { 211 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], redGamma); 212 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], grnGamma); 213 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], bluGamma); 214 } 215 216 try { 217 displayMaster.setDisplayInactive(); 218 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 219 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 220 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 221 imageDisplay.loadData(imageField); 222 displayMaster.setDisplayActive(); 223 } catch(Exception ex) { 224 LogUtil.logException("setDisplayInactive", ex); 225 } 226 } 227 228 public MapProjection getDataProjection() { 229 CoordinateSystem cs = null; 230 try { 231 if (imageField instanceof FlatField) { 232 cs = ((FunctionType)imageField.getType()).getDomain().getCoordinateSystem(); 233 } 234 else if (imageField instanceof FieldImpl) { 235 Data dat = imageField.getSample(0, false); 236 if (dat instanceof FlatField) { 237 FlatField img = (FlatField) dat; 238 cs = ((FunctionType)img.getType()).getDomain().getCoordinateSystem(); 239 } 240 } 241 } 242 catch (Exception ex) { 243 LogUtil.logException("problem accessing data", ex); 244 } 245 246 if (cs instanceof MapProjection) mapProjection = (MapProjection) cs; 247 248 return mapProjection; 249 } 250 251 boolean checkRange() { 252 if (Double.isNaN(redRange[0]) || Double.isNaN(grnRange[0]) || Double.isNaN(bluRange[0])) { 253 return false; 254 } 255 else { 256 return true; 257 } 258 } 259 260 private void updateRedRange(double lo, double hi) { 261 redRange[0] = lo; 262 redRange[1] = hi; 263 try { 264 redMap.setRange(lo, hi); 265 } catch (VisADException ex) { 266 LogUtil.logException("redMap.setRange", ex); 267 } catch (RemoteException ex) { 268 LogUtil.logException("redMap.setRange", ex); 269 } 270 } 271 272 public void setRedRange(double[] range) { 273 redRange[0] = range[0]; 274 redRange[1] = range[1]; 275 } 276 277 public double[] getRedRange() { 278 return new double[] {redRange[0], redRange[1]}; 279 } 280 281 private void updateGrnRange(double lo, double hi) { 282 grnRange[0] = lo; 283 grnRange[1] = hi; 284 try { 285 grnMap.setRange(lo, hi); 286 } catch (VisADException ex) { 287 LogUtil.logException("grnMap.setRange", ex); 288 } catch (RemoteException ex) { 289 LogUtil.logException("grnMap.setRange", ex); 290 } 291 } 292 293 public void setGrnRange(double[] range) { 294 grnRange[0] = range[0]; 295 grnRange[1] = range[1]; 296 } 297 298 public double[] getGrnRange() { 299 return new double[] {grnRange[0], grnRange[1]}; 300 } 301 302 private void updateBluRange(double lo, double hi) { 303 bluRange[0] = lo; 304 bluRange[1] = hi; 305 try { 306 bluMap.setRange(lo, hi); 307 } catch (VisADException ex) { 308 LogUtil.logException("bluMap.setRange", ex); 309 } catch (RemoteException ex) { 310 LogUtil.logException("bluMap.setRange", ex); 311 } 312 } 313 314 public void setBluRange(double[] range) { 315 bluRange[0] = range[0]; 316 bluRange[1] = range[1]; 317 } 318 319 public double[] getBluRange() { 320 return new double[] {bluRange[0], bluRange[1]}; 321 } 322 323 public void setRedGamma(double gamma) { 324 redGamma = gamma; 325 } 326 327 public double getRedGamma() { 328 return redGamma; 329 } 330 331 public void setGrnGamma(double gamma) { 332 grnGamma = gamma; 333 } 334 335 public double getGrnGamma() { 336 return grnGamma; 337 } 338 339 public void setBluGamma(double gamma) { 340 bluGamma = gamma; 341 } 342 343 public double getBluGamma() { 344 return bluGamma; 345 } 346 347 public void setGamma(double gamma) { 348 this.gamma = gamma; 349 } 350 351 public double getGamma() { 352 return gamma; 353 } 354 355 private void updateGamma(double gamma) { 356 setGamma(gamma); 357 setRedGamma(gamma); 358 setGrnGamma(gamma); 359 setBluGamma(gamma); 360 redGammaTxtFld.setText(Float.toString((float)gamma)); 361 grnGammaTxtFld.setText(Float.toString((float)gamma)); 362 bluGammaTxtFld.setText(Float.toString((float)gamma)); 363 364 float[][] newRedTbl = getZeroOutArray(redTable); 365 float[][] newGrnTbl = getZeroOutArray(grnTable); 366 float[][] newBluTbl = getZeroOutArray(bluTable); 367 368 for (int k=0; k<redTable[0].length; k++) { 369 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma); 370 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma); 371 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma); 372 } 373 try { 374 displayMaster.setDisplayInactive(); 375 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 376 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 377 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 378 displayMaster.setDisplayActive(); 379 } catch(Exception ex) { 380 LogUtil.logException("setDisplayInactive", ex); 381 } 382 } 383 384 private void updateRedGamma(double gamma) { 385 setRedGamma(gamma); 386 387 float[][] newRedTbl = getZeroOutArray(redTable); 388 389 for (int k=0; k<redTable[0].length; k++) { 390 newRedTbl[0][k] = (float) Math.pow(redTable[0][k], gamma); 391 } 392 393 try { 394 displayMaster.setDisplayInactive(); 395 ((BaseColorControl)redMap.getControl()).setTable(newRedTbl); 396 displayMaster.setDisplayActive(); 397 } catch(Exception ex) { 398 LogUtil.logException("setDisplayInactive", ex); 399 } 400 } 401 402 private void updateGrnGamma(double gamma) { 403 setGrnGamma(gamma); 404 405 float[][] newGrnTbl = getZeroOutArray(grnTable); 406 for (int k=0; k<grnTable[0].length; k++) { 407 newGrnTbl[1][k] = (float) Math.pow(grnTable[1][k], gamma); 408 } 409 410 try { 411 displayMaster.setDisplayInactive(); 412 ((BaseColorControl)grnMap.getControl()).setTable(newGrnTbl); 413 displayMaster.setDisplayActive(); 414 } catch(Exception ex) { 415 LogUtil.logException("setDisplayInactive", ex); 416 } 417 } 418 419 private void updateBluGamma(double gamma) { 420 setBluGamma(gamma); 421 422 float[][] newBluTbl = getZeroOutArray(bluTable); 423 for (int k=0; k<bluTable[0].length; k++) { 424 newBluTbl[2][k] = (float) Math.pow(bluTable[2][k], gamma); 425 } 426 427 try { 428 displayMaster.setDisplayInactive(); 429 ((BaseColorControl)bluMap.getControl()).setTable(newBluTbl); 430 displayMaster.setDisplayActive(); 431 } catch(Exception ex) { 432 LogUtil.logException("setDisplayInactive", ex); 433 } 434 } 435 436 public float[][] getZeroOutArray(float[][] array) { 437 float[][] newArray = new float[array.length][array[0].length]; 438 for (int i=0; i<newArray.length; i++) { 439 for (int j=0; j<newArray[0].length; j++) { 440 newArray[i][j] = 0f; 441 } 442 } 443 return newArray; 444 } 445 446 protected ColorTable getInitialColorTable() { 447 return getDisplayConventions().getParamColorTable("image"); 448 } 449 450 public Container doMakeContents() { 451 452 JPanel bigPanel = new JPanel(new BorderLayout()); 453 JPanel subPanel = new JPanel(new GridLayout(4,1)); 454 455 JPanel gammaPanel = new JPanel(new FlowLayout()); 456 final JLabel nameLabel = new JLabel("Gamma: "); 457 458 gammaTxtFld.addActionListener(new ActionListener() { 459 public void actionPerformed(ActionEvent e) { 460 String tmp = gammaTxtFld.getText().trim(); 461 updateGamma(Double.valueOf(tmp)); 462 } 463 }); 464 465 gammaPanel.add(nameLabel); 466 gammaPanel.add(gammaTxtFld); 467 468 JPanel redPanel = new JPanel(new FlowLayout()); 469 redPanel.add(new JLabel("Red range: ")); 470 471 redLowTxtFld.addActionListener(new ActionListener() { 472 public void actionPerformed(ActionEvent e) { 473 String tmp = redLowTxtFld.getText().trim(); 474 updateRedRange(Double.valueOf(tmp), redRange[1]); 475 } 476 }); 477 redPanel.add(redLowTxtFld); 478 redHighTxtFld.addActionListener(new ActionListener() { 479 public void actionPerformed(ActionEvent e) { 480 String tmp = redHighTxtFld.getText().trim(); 481 updateRedRange(redRange[0], Double.valueOf(tmp)); 482 } 483 }); 484 redPanel.add(redHighTxtFld); 485 486 redGammaTxtFld.addActionListener(new ActionListener() { 487 public void actionPerformed(ActionEvent e) { 488 String tmp = redGammaTxtFld.getText().trim(); 489 updateRedGamma(Double.valueOf(tmp)); 490 } 491 }); 492 redPanel.add(new JLabel("Gamma:")); 493 redPanel.add(redGammaTxtFld); 494 495 JButton button = new JButton("reset"); 496 redPanel.add(button); 497 button.addActionListener(new ActionListener() { 498 public void actionPerformed(ActionEvent e) { 499 updateRedRange(initRedRange[0], initRedRange[1]); 500 redRange[0] = initRedRange[0]; 501 redRange[1] = initRedRange[1]; 502 redLowTxtFld.setText(Float.toString((float)redRange[0])); 503 redHighTxtFld.setText(Float.toString((float)redRange[1])); 504 } 505 }); 506 507 JPanel grnPanel = new JPanel(new FlowLayout()); 508 grnPanel.add(new JLabel("Green range: ")); 509 510 grnLowTxtFld.addActionListener(new ActionListener() { 511 public void actionPerformed(ActionEvent e) { 512 String tmp = grnLowTxtFld.getText().trim(); 513 updateGrnRange(Double.valueOf(tmp), grnRange[1]); 514 } 515 }); 516 grnPanel.add(grnLowTxtFld); 517 grnHighTxtFld.addActionListener(new ActionListener() { 518 public void actionPerformed(ActionEvent e) { 519 String tmp = grnHighTxtFld.getText().trim(); 520 updateGrnRange(grnRange[0], Double.valueOf(tmp)); 521 } 522 }); 523 grnPanel.add(grnHighTxtFld); 524 525 grnGammaTxtFld.addActionListener(new ActionListener() { 526 public void actionPerformed(ActionEvent e) { 527 String tmp = grnGammaTxtFld.getText().trim(); 528 updateGrnGamma(Double.valueOf(tmp)); 529 } 530 }); 531 grnPanel.add(new JLabel("Gamma:")); 532 grnPanel.add(grnGammaTxtFld); 533 534 535 button = new JButton("reset"); 536 grnPanel.add(button); 537 button.addActionListener(new ActionListener() { 538 public void actionPerformed(ActionEvent e) { 539 updateGrnRange(initGrnRange[0], initGrnRange[1]); 540 grnRange[0] = initGrnRange[0]; 541 grnRange[1] = initGrnRange[1]; 542 grnLowTxtFld.setText(Float.toString((float)grnRange[0])); 543 grnHighTxtFld.setText(Float.toString((float)grnRange[1])); 544 } 545 }); 546 547 548 549 JPanel bluPanel = new JPanel(new FlowLayout()); 550 bluPanel.add(new JLabel("Blue range: ")); 551 552 bluLowTxtFld.addActionListener(new ActionListener() { 553 public void actionPerformed(ActionEvent e) { 554 String tmp = bluLowTxtFld.getText().trim(); 555 updateBluRange(Double.valueOf(tmp), bluRange[1]); 556 } 557 }); 558 bluPanel.add(bluLowTxtFld); 559 bluHighTxtFld.addActionListener(new ActionListener() { 560 public void actionPerformed(ActionEvent e) { 561 String tmp = bluHighTxtFld.getText().trim(); 562 updateBluRange(bluRange[0], Double.valueOf(tmp)); 563 } 564 }); 565 bluPanel.add(bluHighTxtFld); 566 567 bluGammaTxtFld.addActionListener(new ActionListener() { 568 public void actionPerformed(ActionEvent e) { 569 String tmp = bluGammaTxtFld.getText().trim(); 570 updateBluGamma(Double.valueOf(tmp)); 571 } 572 }); 573 bluPanel.add(new JLabel("Gamma:")); 574 bluPanel.add(bluGammaTxtFld); 575 576 button = new JButton("reset"); 577 bluPanel.add(button); 578 button.addActionListener(new ActionListener() { 579 public void actionPerformed(ActionEvent e) { 580 updateBluRange(initBluRange[0], initBluRange[1]); 581 bluRange[0] = initBluRange[0]; 582 bluRange[1] = initBluRange[1]; 583 bluLowTxtFld.setText(Float.toString((float)bluRange[0])); 584 bluHighTxtFld.setText(Float.toString((float)bluRange[1])); 585 } 586 }); 587 588 589 subPanel.add(redPanel); 590 subPanel.add(grnPanel); 591 subPanel.add(bluPanel); 592 subPanel.add(gammaPanel); 593 594 bigPanel.add(subPanel, BorderLayout.NORTH); 595 596 return bigPanel; 597 } 598 599 private class ColorMapListener implements ScalarMapListener 600 { 601 ScalarMap clrMap; 602 603 double[] range = null; 604 double[] initRange = null; 605 606 JTextField lowTxtFld; 607 JTextField highTxtFld; 608 609 ColorMapListener(ScalarMap clrMap, double[] initRange, double[] range, JTextField lowTxtFld, JTextField highTxtFld) { 610 this.clrMap = clrMap; 611 this.lowTxtFld = lowTxtFld; 612 this.highTxtFld = highTxtFld; 613 this.range = range; 614 this.initRange = initRange; 615 } 616 617 618 public void controlChanged(ScalarMapControlEvent event) throws RemoteException, VisADException { 619 } 620 621 public void mapChanged(ScalarMapEvent event) throws RemoteException, VisADException { 622 if (event.getId() == event.AUTO_SCALE) { 623 double[] rng = clrMap.getRange(); 624 boolean shouldRemove = false; 625 //Ghansham: decide whether it is first time. The cleaner way 626 if (!Double.isNaN(rng[0]) && !Double.isNaN(rng[1]) && Double.isNaN(initRange[0]) && Double.isNaN(initRange[1])) { 627 shouldRemove = true; 628 } 629 range[0] = rng[0]; 630 range[1] = rng[1]; 631 initRange[0] = rng[0]; 632 initRange[1] = rng[1]; 633 lowTxtFld.setText(Float.toString((float)rng[0])); 634 highTxtFld.setText(Float.toString((float)rng[1])); 635 //Ghansham:If its first time remove the scalarmaplistener and setRange manually to disable autscaling of the scalarmap 636 if(shouldRemove) { 637 clrMap.removeScalarMapListener(this); 638 //-Lock out auto-scaling 639 clrMap.disableAutoScale(); 640 } 641 } 642 else if (event.getId() == event.MANUAL) { 643 double[] rng = clrMap.getRange(); 644 range[0] = rng[0]; 645 range[1] = rng[1]; 646 } 647 } 648 } 649 650 651}