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