001 /*
002 * $Id: RGBCompositeControl.java,v 1.11 2012/02/19 17:35:38 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 package edu.wisc.ssec.mcidasv.control;
031
032 import java.awt.BorderLayout;
033 import java.awt.Container;
034 import java.awt.FlowLayout;
035 import java.awt.GridLayout;
036 import java.awt.event.ActionEvent;
037 import java.awt.event.ActionListener;
038 import java.rmi.RemoteException;
039 import java.util.Iterator;
040
041 import javax.swing.JButton;
042 import javax.swing.JLabel;
043 import javax.swing.JPanel;
044 import javax.swing.JTextField;
045
046 import visad.BaseColorControl;
047 import visad.FieldImpl;
048 import visad.FlatField;
049 import visad.FunctionType;
050 import visad.ScalarMap;
051 import visad.ScalarMapControlEvent;
052 import visad.ScalarMapEvent;
053 import visad.ScalarMapListener;
054 import visad.VisADException;
055 import visad.Data;
056 import visad.CoordinateSystem;
057
058 import visad.georef.MapProjection;
059
060 import ucar.unidata.data.DataChoice;
061 import ucar.unidata.data.DataSelection;
062 import ucar.unidata.data.grid.GridDataInstance;
063 import ucar.unidata.idv.control.DisplayControlImpl;
064 import ucar.unidata.util.ColorTable;
065 import ucar.unidata.util.LogUtil;
066 import ucar.unidata.util.Range;
067 import ucar.visad.display.DisplayMaster;
068
069 import edu.wisc.ssec.mcidasv.data.hydra.ImageRGBDisplayable;
070
071
072 public 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 }