001 /*
002 * $Id: McIdasXDataSource.java,v 1.15 2012/02/19 17:35:45 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;
032
033 import java.awt.Image;
034 import java.rmi.RemoteException;
035 import java.util.ArrayList;
036 import java.util.Arrays;
037 import java.util.Calendar;
038 import java.util.Date;
039 import java.util.GregorianCalendar;
040 import java.util.Hashtable;
041 import java.util.Iterator;
042 import java.util.List;
043 import java.util.TimeZone;
044
045 import ucar.unidata.data.CompositeDataChoice;
046 import ucar.unidata.data.DataCategory;
047 import ucar.unidata.data.DataChoice;
048 import ucar.unidata.data.DataContext;
049 import ucar.unidata.data.DataSelection;
050 import ucar.unidata.data.DataSelectionComponent;
051 import ucar.unidata.data.DataSourceDescriptor;
052 import ucar.unidata.data.DataSourceImpl;
053 import ucar.unidata.data.DirectDataChoice;
054 import ucar.unidata.idv.IntegratedDataViewer;
055 import ucar.unidata.idv.control.DisplayControlImpl;
056 import ucar.unidata.idv.control.ImageSequenceControl;
057 import ucar.unidata.ui.colortable.ColorTableManager;
058 import ucar.unidata.util.ColorTable;
059 import ucar.unidata.util.Misc;
060 import visad.Data;
061 import visad.DateTime;
062 import visad.FlatField;
063 import visad.FunctionType;
064 import visad.Linear2DSet;
065 import visad.RealTupleType;
066 import visad.RealType;
067 import visad.VisADException;
068 import visad.data.mcidas.AREACoordinateSystem;
069 import visad.meteorology.NavigatedImage;
070 import visad.meteorology.SingleBandedImage;
071 import edu.wisc.ssec.mcidasv.control.FrameComponentInfo;
072 import edu.wisc.ssec.mcidasv.control.McIdasComponents;
073 import edu.wisc.ssec.mcidasv.control.McIdasImageSequenceControl;
074
075 /**
076 * Used to cache a data choice and its data
077 *
078 * @author IDV development team
079 * @version $Revision: 1.15 $
080 */
081 public class McIdasXDataSource extends DataSourceImpl {
082
083 /** list of frames to load */
084 private List frameNumbers = new ArrayList();
085
086 /** list of McIDAS-X frames */
087 private List frameList = new ArrayList();
088
089 /** McIDAS-X connection info */
090 private McIdasXInfo mcidasxInfo;
091
092 /** list of 2D categories */
093 private List twoDCategories;
094
095 /** list of 2D time series categories */
096 private List twoDTimeSeriesCategories;
097
098 /** image data arrays */
099 private double values[][] = new double[1][1];
100
101 //private boolean hasImagePreview = false;
102 private boolean hasImagePreview = true;
103 private Image theImage;
104 private int lastPreview = -1;
105
106 DisplayControlImpl dci;
107
108 /**
109 * Default bean constructor; does nothing
110 */
111 public McIdasXDataSource() {}
112
113 /**
114 * Create a McIdasXDataSource
115 *
116 *
117 * @param descriptor the datasource descriptor
118 * @param name my name
119 * @param properties my properties
120 */
121 public McIdasXDataSource(DataSourceDescriptor descriptor, String name,
122 Hashtable properties) {
123 super(descriptor, "McIDAS-X", "McIDAS-X", properties);
124 /*
125 System.out.println("McIdasXDataSource:");
126 System.out.println(" descriptor=" + descriptor);
127 System.out.println(" name=" + name);
128 System.out.println(" properties=" + properties);
129 */
130 if ((properties == null) || (properties.get(edu.wisc.ssec.mcidasv.chooser.FrameChooser.FRAME_NUMBERS_KEY) == null)) {
131 List frames = new ArrayList();
132 frames.add(new Integer(-1));
133 properties.put(edu.wisc.ssec.mcidasv.chooser.FrameChooser.FRAME_NUMBERS_KEY, frames);
134 }
135
136 this.frameNumbers.clear();
137 this.frameNumbers = getFrameNumbers();
138
139 String host = (String)properties.get(edu.wisc.ssec.mcidasv.chooser.FrameChooser.REQUEST_HOST);
140 String port = (String)properties.get(edu.wisc.ssec.mcidasv.chooser.FrameChooser.REQUEST_PORT);
141 String key = (String)properties.get(edu.wisc.ssec.mcidasv.chooser.FrameChooser.REQUEST_KEY);
142 mcidasxInfo = new McIdasXInfo(host, port, key);
143
144 try {
145 this.frameList = makeFrames(this.frameNumbers);
146 } catch (Exception e) {
147 System.out.println("McIdasXDataSource constructor exception: " + e);
148 }
149 }
150
151 /**
152 * Make a list of McIDAS-X frames
153 *
154 * @param frames List of frame numbers
155 *
156 * @return ImageDataset
157 */
158 public List makeFrames(List inFrameNumbers) {
159 List frames = new ArrayList();
160 Integer frmInt;
161 for (int i = 0; i < inFrameNumbers.size(); i++) {
162 frmInt = (Integer)inFrameNumbers.get(i);
163 frames.add(new McIdasFrame(frmInt.intValue(), mcidasxInfo));
164 }
165 // System.out.println("McIdasXDataSource makeFrames in: " + frameNumbers + ", out: " + frames);
166 return frames;
167 }
168
169 /**
170 * Get a frame from the frameList based on frame number
171 */
172 public McIdasFrame getFrame(int frameNumber) {
173 McIdasFrame checkFrame;
174 for (int i=0; i<this.frameList.size(); i++) {
175 checkFrame = (McIdasFrame)frameList.get(i);
176 if (checkFrame.getFrameNumber() == frameNumber) {
177 return(checkFrame);
178 }
179 }
180 return new McIdasFrame();
181 }
182
183 /**
184 * Set a frame in the framelist based on frame number
185 */
186 public void setFrame(int frameNumber, McIdasFrame inFrame) {
187 McIdasFrame checkFrame;
188 for (int i=0; i<this.frameList.size(); i++) {
189 checkFrame = (McIdasFrame)frameList.get(i);
190 if (checkFrame.getFrameNumber() == frameNumber) {
191 this.frameList.set(i, inFrame);
192 }
193 }
194 }
195
196 /**
197 * This is called after this datasource has been fully created
198 * and initialized after being unpersisted by the XmlEncoder.
199 */
200 public void initAfterUnpersistence() {
201 super.initAfterUnpersistence();
202 this.frameNumbers.clear();
203 this.frameNumbers = getFrameNumbers();
204 this.frameList = makeFrames(this.frameNumbers);
205 }
206
207 /**
208 * Gets called after creation. Initialize the connection
209 */
210 public void initAfterCreation() {
211 initConnection();
212 }
213
214 /**
215 * Initialize the connection to McIdas-X.
216 * This gets called when the data source is newly created
217 * or decoded form a bundle.
218 */
219 private void initConnection() {
220 int istat = 0;
221
222 if (istat < 0)
223 setInError(true,"Unable to connect to McIDAS-X");
224 }
225
226 protected boolean shouldCache(Data data) {
227 return false;
228 }
229
230 protected void initDataSelectionComponents(
231 List<DataSelectionComponent> components, final DataChoice dataChoice) {
232
233 getDataContext().getIdv().showWaitCursor();
234 makePreviewImage(dataChoice);
235 if (hasImagePreview) {
236 try {
237 components.add(new ImagePreviewSelection(theImage));
238 } catch (Exception e) {
239 System.out.println("Can't make preview image: "+e);
240 e.printStackTrace();
241 }
242 }
243 getDataContext().getIdv().showNormalCursor();
244 }
245
246 private void makePreviewImage(DataChoice dataChoice) {
247 int dataFrame = -1;
248 if (dataChoice.getDescription().indexOf("Frame ") >= 0) {
249 try {
250 dataFrame = Integer.parseInt(dataChoice.getDescription().substring(6));
251 }
252 catch (Exception e) {
253 hasImagePreview = false;
254 return;
255 }
256 }
257 if (dataFrame <= 0) {
258 hasImagePreview = false;
259 return;
260 }
261 if (dataFrame != lastPreview) {
262 McIdasFrame mxf = new McIdasFrame(dataFrame, mcidasxInfo);
263 theImage = mxf.getGIF();
264 }
265 hasImagePreview = true;
266 lastPreview = dataFrame;
267 }
268
269 /**
270 *
271 * @param dataChoice The data choice that identifies the requested
272 * data.
273 * @param category The data category of the request.
274 * @param dataSelection Identifies any subsetting of the data.
275 * @param requestProperties Hashtable that holds any detailed request
276 * properties.
277 *
278 * @return The data
279 *
280 * @throws RemoteException Java RMI problem
281 * @throws VisADException VisAD problem
282 */
283 protected Data getDataInner(DataChoice dataChoice, DataCategory category,
284 DataSelection dataSelection, Hashtable requestProperties)
285 throws VisADException, RemoteException {
286 /*
287 System.out.println("McIdasXDataSource getDataInner:");
288 System.out.println(" dataChoice=" + dataChoice);
289 System.out.println(" category=" + category);
290 System.out.println(" dataSelection=" + dataSelection);
291 System.out.println(" requestProperties=" + requestProperties);
292 */
293
294 // Read the properties to decide which frame components should be requested
295 FrameComponentInfo frameComponentInfo = new FrameComponentInfo();
296 Boolean mc;
297 mc = (Boolean)(requestProperties.get(McIdasComponents.IMAGE));
298 if (mc == null) mc=Boolean.TRUE;
299 frameComponentInfo.setIsImage(mc.booleanValue());
300 mc = (Boolean)(requestProperties.get(McIdasComponents.GRAPHICS));
301 if (mc == null) mc=Boolean.TRUE;
302 frameComponentInfo.setIsGraphics(mc.booleanValue());
303 mc = (Boolean)(requestProperties.get(McIdasComponents.COLORTABLE));
304 if (mc == null) mc=Boolean.TRUE;
305 frameComponentInfo.setIsColorTable(mc.booleanValue());
306 mc = (Boolean)(requestProperties.get(McIdasComponents.ANNOTATION));
307 if (mc == null) mc=Boolean.TRUE;
308 frameComponentInfo.setIsAnnotation(mc.booleanValue());
309 mc = (Boolean)(requestProperties.get(McIdasComponents.FAKEDATETIME));
310 if (mc == null) mc=Boolean.TRUE;
311 frameComponentInfo.setFakeDateTime(mc.booleanValue());
312
313 List defList = null;
314 frameNumbers = (List)getProperty(edu.wisc.ssec.mcidasv.chooser.FrameChooser.FRAME_NUMBERS_KEY, defList);
315
316 // Read the properties to decide which frame components need to be requested
317 FrameDirtyInfo frameDirtyInfo = new FrameDirtyInfo();
318 List frameDirtyInfoList = new ArrayList();
319 frameDirtyInfoList = (ArrayList)(requestProperties.get(McIdasComponents.DIRTYINFO));
320
321 if (frameDirtyInfoList == null) {
322 frameDirtyInfoList = new ArrayList();
323 for (int i=0; i<frameNumbers.size(); i++) {
324 frameDirtyInfo = new FrameDirtyInfo((Integer)frameNumbers.get(i), true, true, true);
325 frameDirtyInfoList.add(frameDirtyInfo);
326 }
327 }
328
329 Data data=null;
330 if (frameNumbers.size() < 1) {
331 return data;
332 }
333 if (frameNumbers.size() < 2) {
334 for (int i=0; i<frameDirtyInfoList.size(); i++) {
335 frameDirtyInfo = (FrameDirtyInfo)frameDirtyInfoList.get(i);
336 if (frameDirtyInfo.getFrameNumber() == (Integer)frameNumbers.get(0)) {
337 // System.out.println("frameDirtyInfo: " + frameDirtyInfo);
338 data = (Data) getMcIdasSequence((Integer)frameNumbers.get(0), frameComponentInfo, frameDirtyInfo);
339 }
340 }
341 } else {
342 String dc="";
343 String fd="";
344 for (int i=0; i<frameNumbers.size(); i++) {
345 dc = dataChoice.toString();
346 fd = (this.frameList.get(i)).toString();
347 if (dc.compareTo(fd) == 0) {
348 if (i > 0) {
349 frameComponentInfo.setIsColorTable(false);
350 }
351 for (int j=0; j<frameDirtyInfoList.size(); j++) {
352 frameDirtyInfo = (FrameDirtyInfo)frameDirtyInfoList.get(j);
353 if (frameDirtyInfo.getFrameNumber() == (Integer)frameNumbers.get(i)) {
354 // System.out.println("frameDirtyInfo: " + frameDirtyInfo);
355 data = (Data) getMcIdasSequence((Integer)frameNumbers.get(i), frameComponentInfo, frameDirtyInfo);
356 }
357 }
358 }
359 }
360 }
361 return data;
362 }
363
364 /**
365 * make a time series from selected McIdas-X frames
366 */
367 private SingleBandedImage getMcIdasSequence(int frameNumber,
368 FrameComponentInfo frameComponentInfo,
369 FrameDirtyInfo frameDirtyInfo)
370 throws VisADException, RemoteException {
371 /*
372 System.out.println("McIdasXDataSource getMcIdasSequence:");
373 System.out.println(" frmNo=" + frmNo);
374 System.out.println(" frameComponentInfo=" + frameComponentInfo);
375 */
376 SingleBandedImage image = getMcIdasFrame(frameNumber, frameComponentInfo, frameDirtyInfo);
377 if (image != null) {
378 if (shouldCache((Data)image)) {
379 Integer fo = new Integer(frameNumber);
380 putCache(fo,image);
381 }
382 }
383 return image;
384 }
385
386 private DisplayControlImpl getDisplayControlImpl() {
387 dci = null;
388 List dcl = getDataChangeListeners();
389 if (dcl != null) {
390 for (int i=0; i< dcl.size(); i++) {
391 if (dcl.get(i) instanceof McIdasImageSequenceControl) {
392 dci= (DisplayControlImpl)(dcl.get(i));
393 break;
394 }
395 }
396 }
397 return dci;
398 }
399
400 /**
401 * Get frame numbers
402 *
403 * @return frame numbers
404 */
405 public List getFrameNumbers() {
406 List defList = null;
407 List gotFrameNumbers = (List)getProperty(edu.wisc.ssec.mcidasv.chooser.FrameChooser.FRAME_NUMBERS_KEY, defList);
408 return gotFrameNumbers;
409 }
410
411 /**
412 * Get the name for the main data object
413 *
414 * @return name of main data object
415 */
416 public String getDataName() {
417 String dataName = (String) getProperty(edu.wisc.ssec.mcidasv.chooser.FrameChooser.DATA_NAME_KEY, "Frame Sequence");
418 if (dataName.equals("")) {
419 dataName = "Frame Sequence";
420 }
421 return dataName;
422 }
423
424 /**
425 * Get McIdasXInfo object
426 *
427 * @return mcidasxInfo
428 */
429 public McIdasXInfo getMcIdasXInfo() {
430 return mcidasxInfo;
431 }
432
433 /**
434 * Initialize the {@link ucar.unidata.data.DataCategory} objects that
435 * this data source uses.
436 */
437 private void makeCategories() {
438 twoDTimeSeriesCategories = DataCategory.parseCategories("MCIDASX;", false);
439 twoDCategories = DataCategory.parseCategories("MCIDASX;", false);
440 }
441
442 /**
443 * Return the list of {@link ucar.unidata.data.DataCategory} used for
444 * single time step data.
445 *
446 * @return A list of categories.
447 */
448 public List getTwoDCategories() {
449 if (twoDCategories == null) {
450 makeCategories();
451 }
452 return twoDCategories;
453 }
454
455 /**
456 * Return the list of {@link ucar.unidata.data.DataCategory} used for
457 * multiple time step data.
458 *
459 * @return A list of categories.
460 */
461
462 public List getTwoDTimeSeriesCategories() {
463 if (twoDCategories == null) {
464 makeCategories();
465 }
466 return twoDTimeSeriesCategories;
467 }
468
469
470 /**
471 * Create the set of {@link ucar.unidata.data.DataChoice} that represent
472 * the data held by this data source. We create one top-level
473 * {@link ucar.unidata.data.CompositeDataChoice} that represents
474 * all of the image time steps. We create a set of children
475 * {@link ucar.unidata.data.DirectDataChoice}, one for each time step.
476 */
477 public void doMakeDataChoices() {
478 if (this.frameList == null) return;
479 CompositeDataChoice composite = new CompositeDataChoice(this,
480 getFrameNumbers(), getName(),
481 getDataName(),
482 (this.frameList.size() > 1)
483 ? getTwoDTimeSeriesCategories()
484 : getTwoDCategories()) {
485 public List getSelectedDateTimes() {
486 return dataSource.getSelectedDateTimes();
487 }
488 };
489 addDataChoice(composite);
490 doMakeDataChoices(composite);
491 }
492
493 /**
494 * Make the data choices and add them to the given composite
495 *
496 * @param composite The parent data choice to add to
497 */
498 private void doMakeDataChoices(CompositeDataChoice composite) {
499 int cnt = 0;
500 List frameNos = new ArrayList();
501 List frameChoices = new ArrayList();
502 for (Iterator iter = frameList.iterator(); iter.hasNext(); ) {
503 Object object = iter.next();
504 McIdasFrame frame = getFrame(object);
505 String name = frame.toString();
506 DataSelection frameSelect = null;
507 Integer frameNo = frame.getFrameNumber();
508 if (frameNo != null) {
509 frameNos.add(frameNo);
510 //We will create the data choice with an index, not with the actual frame number.
511 frameSelect = new DataSelection(Misc.newList(new Integer(cnt)));
512 }
513 frameSelect = null;
514 DataChoice choice =
515 new DirectDataChoice(this, new FrameDataInfo(cnt, frame),
516 composite.getName(), name,
517 getTwoDCategories(), frameSelect);
518 cnt++;
519 frameChoices.add(choice);
520 }
521
522 //Sort the data choices.
523 composite.replaceDataChoices(sortChoices(frameChoices));
524 }
525
526 /**
527 * Sort the list of data choices on their frame numbers
528 *
529 * @param choices The data choices
530 *
531 * @return The data choices sorted
532 */
533 private List sortChoices(List choices) {
534 Object[] choicesArray = choices.toArray();
535 /*
536 Comparator comp = new Comparator() {
537 public int compare(Object o1, Object o2) {
538 McIdasFrameDescriptor fd1 = getDescriptor(o1);
539 McIdasFrameDescriptor fd2 = getDescriptor(o2);
540 return fd1.getFrameNumber().compareTo(fd2.getFrameNumber());
541 }
542 };
543 Arrays.sort(choicesArray, comp);
544 */
545 return new ArrayList(Arrays.asList(choicesArray));
546 }
547
548 /**
549 * A utility method that helps us deal with legacy bundles that used to
550 * have String file names as the id of a data choice.
551 *
552 * @param object May be an AddeImageDescriptor (for new bundles) or a
553 * String that is converted to an image descriptor.
554 * @return The image descriptor.
555 */
556 private McIdasFrame getFrame(Object object) {
557 if (object == null) {
558 return null;
559 }
560
561 if (object instanceof McIdasFrame) {
562 return (McIdasFrame) object;
563 }
564
565 return new McIdasFrame();
566 }
567
568 /**
569 * Class FrameDataInfo Holds an index and a McIdasFrame
570 */
571 public class FrameDataInfo {
572
573 /** The index */
574 private int index;
575
576 /** The FD */
577 private McIdasFrame frame;
578
579 /**
580 * Ctor for xml encoding
581 */
582 public FrameDataInfo() {}
583
584 /**
585 * CTOR
586 *
587 * @param index The index
588 * @param fd The fd
589 */
590 public FrameDataInfo(int index, McIdasFrame frame) {
591 this.index = index;
592 this.frame = frame;
593 }
594
595 /**
596 * Get the index
597 *
598 * @return The index
599 */
600 public int getIndex() {
601 return index;
602 }
603
604 /**
605 * Set the index
606 *
607 * @param v The index
608 */
609 public void setIndex(int v) {
610 index = v;
611 }
612
613 /**
614 * Get the frame
615 *
616 * @return The frame
617 */
618 public McIdasFrame getFrame() {
619 return frame;
620 }
621
622 /**
623 * Set the frame
624 *
625 * @param v The frame
626 */
627 public void setFrame(McIdasFrame v) {
628 frame = v;
629 }
630
631 /**
632 * toString
633 *
634 * @return toString
635 */
636 public String toString() {
637 return "index: " + index + ", frame: " + frame.getFrameNumber();
638 }
639
640 }
641
642 public SingleBandedImage getMcIdasFrame(int frameNumber,
643 FrameComponentInfo frameComponentInfo,
644 FrameDirtyInfo frameDirtyInfo)
645 throws VisADException, RemoteException {
646 /*
647 System.out.println("McIdasXDataSource getMcIdasFrame:");
648 System.out.println(" frameNumber=" + frameNumber);
649 System.out.println(" frameComponentInfo=" + frameComponentInfo);
650 System.out.println(" frameDirtyInfo=" + frameDirtyInfo);
651 */
652 FlatField image_data = null;
653 SingleBandedImage field = null;
654
655 if (frameNumber < 1) return field;
656
657 // Get the appropriate frame out of the list
658 McIdasFrame frm = getFrame(frameNumber);
659
660 // Tell the frame once whether or not to refresh cached data
661 frm.setRefreshData(frameDirtyInfo.getDirtyImage() || frameDirtyInfo.getDirtyColorTable());
662
663 FrameDirectory fd = frm.getFrameDirectory(frameDirtyInfo.getDirtyImage());
664 int[] nav = fd.getFrameNav();
665 int[] aux = fd.getFrameAux();
666
667 if (nav[0] == 0) return field;
668
669 // Set the time of the frame. Because IDV uses time-based ordering, give the user the option
670 // of "faking" the date/time by using frame number for year. This preserves -X frame ordering.
671 Date nominal_time;
672 if (!frameComponentInfo.getFakeDateTime()) {
673 nominal_time = fd.getNominalTime();
674 }
675 else {
676 Calendar calendarDate = new GregorianCalendar(frameNumber, Calendar.JANUARY, 1, 0, 0, 0);
677 calendarDate.setTimeZone(TimeZone.getTimeZone("UTC"));
678 nominal_time = calendarDate.getTime();
679 }
680
681 int height = frm.getLineSize(frameDirtyInfo.getDirtyImage());
682 if (height < 0) return field;
683 int width = frm.getElementSize(frameDirtyInfo.getDirtyImage());
684 if (width < 0) return field;
685
686 // check for frameComponentInfo.isColorTable == true
687 if (frameComponentInfo.getIsColorTable()) {
688 DataContext dataContext = getDataContext();
689 ColorTableManager colorTableManager = ((IntegratedDataViewer)dataContext).getColorTableManager();
690 List dcl = ((IntegratedDataViewer)dataContext).getDisplayControls();
691 DisplayControlImpl dc = null;
692 for (int i=dcl.size()-1; i>=0; i--) {
693 DisplayControlImpl dci = (DisplayControlImpl)dcl.get(i);
694 if (dci instanceof ImageSequenceControl) {
695 dc = dci;
696 break;
697 }
698 }
699 ColorTable mcidasXColorTable = frm.getColorTable(frameDirtyInfo.getDirtyColorTable());
700 // TODO: Add a transparent value to the color table when only graphics were requested
701 /*
702 // if image wasn't requested, make color table with entry 0 as transparent
703 if (!frameComponentInfo.getIsImage()) {
704 float[][] mcidasXColorTableAlpha = mcidasXColorTable.getAlphaTable();
705 mcidasXColorTableAlpha[3][0] = 0.0f;
706 mcidasXColorTable.setTable(mcidasXColorTableAlpha);
707 }
708 */
709 colorTableManager.addUsers(mcidasXColorTable);
710 dc.setColorTable("default", mcidasXColorTable);
711 }
712
713 // check for frameComponentInfo.isAnnotation == true
714 int skip = 0;
715 if (!frameComponentInfo.getIsAnnotation()) {
716 skip = 12;
717 }
718 height = height - skip;
719
720 values = new double[1][width*height];
721
722 // check for frameComponentInfo.isImage == true
723 if (frameComponentInfo.getIsImage()) {
724 byte[] image = frm.getImageData(frameDirtyInfo.getDirtyImage());
725 double pixel;
726 for (int i=0; i<width*height; i++) {
727 pixel = (double)image[i];
728 if (pixel < 0.0) pixel += 256.0;
729 values[0][i] = pixel;
730 }
731 }
732 else {
733 for (int i=0; i<width*height; i++) {
734 // TODO: Use a special value that is transparent in the color table
735 values[0][i] = 0.0;
736 }
737 }
738
739 // check for frameComponentInfo.isGraphics == true
740 if (frameComponentInfo.getIsGraphics()) {
741 byte[] graphics = frm.getGraphicsData(frameDirtyInfo.getDirtyGraphics());
742 for (int i=0; i<width*height; i++) {
743 if (graphics[i] != (byte)255) {
744 values[0][i] = (double)graphics[i];
745 }
746 }
747 }
748
749 // Done working with the frame, put it back in the list
750 setFrame(frameNumber, frm);
751
752 // fake an area directory
753 int[] adir = new int[64];
754 adir[5] = fd.getULLine();
755 adir[6] = fd.getULEle();
756 adir[8] = height;
757 adir[9] = width;
758 adir[11] = fd.getLineRes();
759 adir[12] = fd.getEleRes();
760
761 AREACoordinateSystem cs;
762 try {
763 cs = new AREACoordinateSystem( adir, nav, aux);
764 } catch (Exception e) {
765 System.out.println("AREACoordinateSystem exception: " + e);
766 return field;
767 }
768
769 /*
770 double[][] linele = new double[2][4];
771 double[][] latlon = new double[2][4];
772 // LR
773 linele[0][0] = (double)(width-1);
774 linele[1][0] = 0.0;
775 // UL
776 linele[0][1] = 0.0;
777 linele[1][1] = (double)(height-1);
778 // LL
779 linele[0][2] = 0.0;
780 linele[1][2] = 0.0;
781 // UR
782 linele[0][3] = (double)(width-1);
783 linele[1][3] = (double)(height-1);
784
785 latlon = cs.toReference(linele);
786 System.out.println("linele: " + linele[0][0] + " " + linele[1][0] + " " +
787 linele[0][1] + " " + linele[1][1] + " " +
788 linele[0][2] + " " + linele[1][2] + " " +
789 linele[0][3] + " " + linele[1][3]);
790 System.out.println("latlon: " + latlon[0][0] + " " + latlon[1][0] + " " +
791 latlon[0][1] + " " + latlon[1][1] + " " +
792 latlon[0][2] + " " + latlon[1][2] + " " +
793 latlon[0][3] + " " + latlon[1][3]);
794 */
795
796 RealType[] domain_components = {RealType.getRealType("ImageElement", null, null),
797 RealType.getRealType("ImageLine", null, null)};
798 RealTupleType image_domain =
799 new RealTupleType(domain_components, cs, null);
800
801 // Image numbering is usually the first line is at the "top"
802 // whereas in VisAD, it is at the bottom. So define the
803 // domain set of the FlatField to map the Y axis accordingly
804 Linear2DSet domain_set = new Linear2DSet(image_domain,
805 0, (width - 1), width,
806 (height - 1), 0, height );
807 RealType range = RealType.getRealType("brightness");
808
809 FunctionType image_func = new FunctionType(image_domain, range);
810
811 // now, define the Data objects
812 image_data = new FlatField(image_func, domain_set);
813 DateTime date = new DateTime(nominal_time);
814 image_data = new NavigatedImage(image_data, date, "McIdas Image");
815
816 // put the data values into the FlatField image_data
817 image_data.setSamples(values,false);
818 field = (SingleBandedImage) image_data;
819
820 return field;
821 }
822
823 }