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