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 package edu.wisc.ssec.mcidasv.data; 029 030 import java.awt.Image; 031 import java.awt.Toolkit; 032 import java.io.*; 033 import java.rmi.RemoteException; 034 035 import ucar.unidata.data.BadDataException; 036 import ucar.unidata.data.grid.GridUtil; 037 import ucar.unidata.util.IOUtil; 038 import visad.CoordinateSystem; 039 import visad.Data; 040 import visad.FlatField; 041 import visad.FunctionType; 042 import visad.Gridded2DSet; 043 import visad.Linear2DSet; 044 import visad.RealTupleType; 045 import visad.RealType; 046 import visad.VisADException; 047 import visad.util.ImageHelper; 048 049 import edu.wisc.ssec.mcidasv.data.HeaderInfo; 050 import edu.wisc.ssec.mcidasv.data.hydra.LongitudeLatitudeCoordinateSystem; 051 import edu.wisc.ssec.mcidasv.data.hydra.SwathNavigation; 052 053 public class FlatFileReader { 054 055 /** The url */ 056 private String url = null; 057 058 /** The dimensions */ 059 private int lines = 0; 060 private int elements = 0; 061 private int strideLines = 0; 062 private int strideElements = 0; 063 private int band = 1; 064 private int bandCount = 1; 065 private String unit = ""; 066 private int stride = 1; 067 068 /** The nav dimensions */ 069 private int navLines = 0; 070 private int navElements = 0; 071 072 /** The data parameters */ 073 private String interleave = HeaderInfo.kInterleaveSequential; 074 private boolean bigEndian = false; 075 private int offset = 0; 076 private String delimiter = "\\s+"; 077 private int dataScale = 1; 078 079 /** The nav parameters */ 080 private double ulLat = Double.NaN; 081 private double ulLon = Double.NaN; 082 private double lrLat = Double.NaN; 083 private double lrLon = Double.NaN; 084 private String latFile = null; 085 private String lonFile = null; 086 private int latlonScale = 1; 087 private boolean eastPositive = false; 088 089 /** which format this object is representing */ 090 private int myFormat = HeaderInfo.kFormatUnknown; 091 private int myNavigation = HeaderInfo.kNavigationUnknown; 092 093 /** the actual floats read from the file */ 094 private float[] floatData = null; 095 096 /** cache the nav info when possible */ 097 Gridded2DSet navigationSet = null; 098 CoordinateSystem navigationCoords = null; 099 100 /** 101 * Ctor for xml encoding 102 */ 103 public FlatFileReader() { 104 this.floatData = null; 105 } 106 107 /** 108 * CTOR 109 * 110 * @param filename The filename 111 */ 112 public FlatFileReader(String filename) { 113 this.floatData = null; 114 this.url = filename; 115 } 116 117 /** 118 * CTOR 119 * 120 * @param filename The filename 121 * @param lines The number of lines 122 * @param elements The number of elements 123 * @param band The band 124 */ 125 public FlatFileReader(String filename, int lines, int elements) { 126 this.floatData = null; 127 this.url = filename; 128 this.lines = lines; 129 this.elements = elements; 130 setStride(1); 131 } 132 133 /** 134 * @param delimiter The data value delimiter 135 * @param dataScale The data scale factor 136 */ 137 public void setBinaryInfo(int format, String interleave, boolean bigEndian, int offset, int band, int bandCount) { 138 this.myFormat = format; 139 this.interleave = interleave; 140 this.bigEndian = bigEndian; 141 this.offset = offset; 142 this.band = band; 143 this.bandCount = bandCount; 144 } 145 146 /** 147 * @param delimiter The data value delimiter 148 * @param dataScale The data scale factor 149 */ 150 public void setAsciiInfo(String delimiter, int dataScale) { 151 this.myFormat = HeaderInfo.kFormatASCII; 152 if (delimiter == null || delimiter.trim().length() == 0) delimiter="\\s+"; 153 this.delimiter = delimiter; 154 this.dataScale = dataScale; 155 } 156 157 /** 158 * @param delimiter The data value delimiter 159 * @param dataScale The data scale factor 160 */ 161 public void setImageInfo() { 162 this.myFormat = HeaderInfo.kFormatImage; 163 } 164 165 /** 166 * @param ulLat The upper left latitude 167 * @param ulLon The upper left longitude 168 * @param lrLat The lower right latitude 169 * @param lrLon The lower right longitude 170 */ 171 public void setNavBounds(double ulLat, double ulLon, double lrLat, double lrLon) { 172 this.myNavigation = HeaderInfo.kNavigationBounds; 173 this.ulLat = ulLat; 174 this.ulLon = ulLon; 175 this.lrLat = lrLat; 176 this.lrLon = lrLon; 177 this.latlonScale = 1; 178 } 179 180 /** 181 * @param ulLat The latitude file 182 * @param ulLon The longitude file 183 * @param latlonScale The navigation value scaling 184 */ 185 public void setNavFiles(String latFile, String lonFile, int latlonScale) { 186 this.myNavigation = HeaderInfo.kNavigationFiles; 187 this.latFile = latFile; 188 this.lonFile = lonFile; 189 this.latlonScale = latlonScale; 190 } 191 192 /** 193 * @param eastPositive 194 */ 195 public void setEastPositive(boolean eastPositive) { 196 this.eastPositive = eastPositive; 197 } 198 199 /** 200 * @param stride 201 */ 202 public void setStride(int stride) { 203 if (stride < 1) stride=1; 204 this.stride = stride; 205 this.strideElements = (int)Math.ceil((float)this.elements/(float)stride); 206 this.strideLines = (int)Math.ceil((float)this.lines/(float)stride); 207 } 208 209 /** 210 * @param unit 211 */ 212 public void setUnit(String unit) { 213 if (unit.trim().equals("")) unit=""; 214 this.unit = unit; 215 } 216 217 /** 218 * Read floats from a binary file 219 */ 220 private void readFloatsFromBinary() { 221 System.out.println("FlatFileInfo.readFloatsFromBinary()"); 222 223 int bytesEach = 1; 224 switch (this.myFormat) { 225 case HeaderInfo.kFormat1ByteUInt: 226 bytesEach = 1; 227 break; 228 case HeaderInfo.kFormat2ByteUInt: 229 bytesEach = 2; 230 break; 231 case HeaderInfo.kFormat2ByteSInt: 232 bytesEach = 2; 233 break; 234 case HeaderInfo.kFormat4ByteSInt: 235 bytesEach = 4; 236 break; 237 case HeaderInfo.kFormat4ByteFloat: 238 bytesEach = 4; 239 break; 240 default: 241 System.err.println("FlatFileReader: Unrecognized binary format: " + this.myFormat); 242 return; 243 } 244 245 int curPixel = 0; 246 int curElement = 0; 247 int curLine = 0; 248 int lastRead = 0; 249 int readEach = 8192; 250 int startPointer = 0; 251 int endPointer = -1; 252 int pixelPointer = 0; 253 254 int readPixels = this.strideElements * this.strideLines; 255 this.floatData = new float[readPixels]; 256 byte[] readBytes = new byte[readEach]; 257 258 try { 259 FileInputStream fis = new FileInputStream(url); 260 261 // byte boundaries 262 assert(readEach % 64 == 0); 263 264 // assure we read the first time 265 assert(endPointer < 0); 266 267 while ((curPixel < readPixels && curLine < lines && lastRead > 0) || curPixel == 0) { 268 269 pixelPointer = this.offset; 270 if (this.interleave.equals(HeaderInfo.kInterleaveSequential)) { 271 // Skip to the right band 272 pixelPointer += (this.band - 1) * (this.lines * this.elements * bytesEach); 273 // Skip into the band 274 pixelPointer += (curLine * this.elements * bytesEach) + (curElement * bytesEach); 275 } 276 else if (this.interleave.equals(HeaderInfo.kInterleaveByLine)) { 277 // Skip to the right line 278 pixelPointer += curLine * (this.bandCount * this.elements * bytesEach); 279 // Skip into the line 280 pixelPointer += ((this.band - 1) * this.elements * bytesEach) + (curElement * bytesEach); 281 } 282 else if (this.interleave.equals(HeaderInfo.kInterleaveByPixel)) { 283 // Skip to the right line 284 pixelPointer += curLine * (this.bandCount * this.elements * bytesEach); 285 // Skip into the line 286 pixelPointer += (curElement * bandCount * bytesEach) + ((this.band - 1) * bytesEach); 287 } 288 else { 289 System.err.println("FlatFileReader: Unrecognized interleave type: " + this.interleave); 290 } 291 292 // We need data outside of our buffer 293 if (pixelPointer > endPointer) { 294 295 // Skip ahead to useful data 296 int skipBytes = pixelPointer - endPointer - 1; 297 if (skipBytes > 0) { 298 // System.out.println(" Skipping " + skipBytes + " bytes"); 299 startPointer += lastRead + fis.skip(skipBytes); 300 endPointer = startPointer; 301 } 302 303 // Read more bytes 304 lastRead = fis.read(readBytes); 305 if (startPointer != endPointer) 306 startPointer = endPointer + 1; 307 endPointer = startPointer + lastRead - 1; 308 // System.out.println(" Read " + lastRead + " bytes, from " + startPointer); 309 310 } 311 312 int readOffset = pixelPointer - startPointer; 313 switch (this.myFormat) { 314 case HeaderInfo.kFormat1ByteUInt: 315 this.floatData[curPixel++] = (float)bytesTo1ByteUInt(readBytes, readOffset); 316 break; 317 case HeaderInfo.kFormat2ByteUInt: 318 this.floatData[curPixel++] = (float)bytesTo2ByteUInt(readBytes, readOffset); 319 break; 320 case HeaderInfo.kFormat2ByteSInt: 321 this.floatData[curPixel++] = (float)bytesTo2ByteSInt(readBytes, readOffset); 322 break; 323 case HeaderInfo.kFormat4ByteSInt: 324 this.floatData[curPixel++] = (float)bytesTo4ByteSInt(readBytes, readOffset); 325 break; 326 case HeaderInfo.kFormat4ByteFloat: 327 this.floatData[curPixel++] = (float)bytesTo4ByteFloat(readBytes, readOffset); 328 break; 329 } 330 331 curElement+=stride; 332 if (curElement >= elements) { 333 curElement = 0; 334 curLine+=stride; 335 } 336 } 337 338 fis.close(); 339 340 System.out.println(" read " + curPixel + " floats (expected " + readPixels + ")"); 341 342 } catch (NumberFormatException exc) { 343 throw new BadDataException("Error parsing binary file"); 344 } catch (Exception e) { 345 throw new BadDataException("Error reading binary file: " + url + "\n" + e); 346 } 347 } 348 349 /** 350 * Read floats from an ASCII file 351 */ 352 private void readFloatsFromAscii() { 353 System.out.println("FlatFileInfo.readFloatsFromAscii()"); 354 355 int curPixel = 0; 356 int curElement = 0; 357 int curLine = 0; 358 359 int readPixels = this.strideElements * this.strideLines; 360 this.floatData = new float[readPixels]; 361 362 try { 363 InputStream is = IOUtil.getInputStream(url, getClass()); 364 BufferedReader in = new BufferedReader(new InputStreamReader(is)); 365 String aLine; 366 367 while ((aLine = in.readLine()) != null) { 368 aLine = aLine.trim(); 369 String[] words = aLine.split(delimiter); 370 for (int i=0; i<words.length; i++) { 371 372 if (curLine % stride == 0 && curElement % stride == 0) { 373 this.floatData[curPixel++] = Float.parseFloat(words[i]); 374 } 375 376 // Keep track of what element/line we are reading so we can stride appropriately 377 curElement++; 378 if (curElement >= elements) { 379 curElement = 0; 380 curLine++; 381 } 382 if (curLine > lines || curPixel > readPixels) { 383 throw new BadDataException("Error parsing ASCII file: Bad dimensions"); 384 } 385 386 } 387 } 388 in.close(); 389 390 System.out.println(" read " + curPixel + " floats (expected " + readPixels + ")"); 391 392 } catch (NumberFormatException exc) { 393 throw new BadDataException("Error parsing ASCII file"); 394 } catch (Exception e) { 395 throw new BadDataException("Error reading ASCII file: " + url + "\n" + e); 396 } 397 } 398 399 /** 400 * Make a FlatField from an Image 401 */ 402 private Data getDataFromImage() { 403 System.out.println("FlatFileInfo.getDataFromImage()"); 404 try { 405 this.floatData = new float[0]; 406 InputStream is = IOUtil.getInputStream(url, getClass()); 407 byte[] imageContent = IOUtil.readBytes(is); 408 Image image = Toolkit.getDefaultToolkit().createImage(imageContent); 409 ImageHelper ih = new ImageHelper(); 410 image.getWidth(ih); 411 if (ih.badImage) { 412 throw new IllegalStateException("Bad image: " + url); 413 } 414 415 makeCoordinateSystem(); 416 417 FlatField field = (FlatField) ucar.visad.Util.makeField(image,true); 418 return GridUtil.setSpatialDomain(field, navigationSet); 419 420 } catch (Exception e) { 421 throw new BadDataException("Error reading image file: " + url + "\n" + e); 422 } 423 } 424 425 /** 426 * Make a Gridded2DSet from bounds 427 */ 428 private Gridded2DSet getNavigationSetFromBounds() { 429 System.out.println("FlatFileInfo.getNavigationSetFromBounds()"); 430 try { 431 this.navElements = this.strideElements; 432 this.navLines = this.strideLines; 433 int lonScale = this.latlonScale; 434 int latScale = this.latlonScale; 435 if (eastPositive) lonScale *= -1; 436 return new Linear2DSet(RealTupleType.SpatialEarth2DTuple, 437 ulLon / lonScale, lrLon / lonScale, navElements, 438 ulLat / latScale, lrLat / latScale, navLines); 439 } catch (Exception e) { 440 throw new BadDataException("Error setting navigation bounds:\n" + e); 441 } 442 } 443 444 /** 445 * Make a Gridded2DSet from files 446 */ 447 private Gridded2DSet getNavigationSetFromFiles() { 448 System.out.println("FlatFileInfo.getNavigationSetFromFiles()"); 449 try { 450 float[][] lalo = new float[0][0]; 451 452 FlatFileReader lonData, latData; 453 454 // ASCII nav files 455 if (this.myFormat == HeaderInfo.kFormatASCII) { 456 System.out.println(" ASCII nav file"); 457 458 this.navElements = this.elements; 459 this.navLines = this.lines; 460 lalo = new float[2][navElements * navLines]; 461 462 // Longitude band 463 lonData = new FlatFileReader(lonFile, navLines, navElements); 464 lonData.setAsciiInfo(delimiter, 1); 465 466 // Latitude band 467 latData = new FlatFileReader(latFile, navLines, navElements); 468 latData.setAsciiInfo(delimiter, 1); 469 470 } 471 472 // Binary nav files 473 else { 474 475 System.out.println(" Binary nav file"); 476 477 // ENVI header for nav 478 EnviInfo enviLat = new EnviInfo(latFile); 479 EnviInfo enviLon = new EnviInfo(lonFile); 480 if (enviLat.isNavHeader() && enviLon.isNavHeader()) { 481 System.out.println(" ENVI nav file"); 482 483 this.navElements = enviLat.getParameter(HeaderInfo.ELEMENTS, 0); 484 this.navLines = enviLat.getParameter(HeaderInfo.LINES, 0); 485 lalo = new float[2][navElements * navLines]; 486 487 // Longitude band 488 lonData = new FlatFileReader(enviLon.getLonBandFile(), 489 enviLon.getParameter(HeaderInfo.LINES, 0), 490 enviLon.getParameter(HeaderInfo.ELEMENTS, 0)); 491 lonData.setBinaryInfo( 492 enviLon.getParameter(HeaderInfo.DATATYPE, HeaderInfo.kFormatUnknown), 493 enviLon.getParameter(HeaderInfo.INTERLEAVE, HeaderInfo.kInterleaveSequential), 494 enviLon.getParameter(HeaderInfo.BIGENDIAN, false), 495 enviLon.getParameter(HeaderInfo.OFFSET, 0), 496 enviLon.getLonBandNum(), 497 enviLon.getBandCount()); 498 499 // Latitude band 500 latData = new FlatFileReader(enviLat.getLatBandFile(), 501 enviLat.getParameter(HeaderInfo.LINES, 0), 502 enviLat.getParameter(HeaderInfo.ELEMENTS, 0)); 503 latData.setBinaryInfo( 504 enviLat.getParameter(HeaderInfo.DATATYPE, HeaderInfo.kFormatUnknown), 505 enviLat.getParameter(HeaderInfo.INTERLEAVE, HeaderInfo.kInterleaveSequential), 506 enviLat.getParameter(HeaderInfo.BIGENDIAN, false), 507 enviLat.getParameter(HeaderInfo.OFFSET, 0), 508 enviLat.getLatBandNum(), 509 enviLat.getBandCount()); 510 511 } 512 513 else { 514 System.out.println(" AXFORM nav file"); 515 516 this.navElements = this.elements; 517 this.navLines = this.lines; 518 lalo = new float[2][navElements * navLines]; 519 520 // Longitude band 521 lonData = new FlatFileReader(lonFile, navLines, navElements); 522 lonData.setBinaryInfo(HeaderInfo.kFormat2ByteUInt, HeaderInfo.kInterleaveSequential, bigEndian, offset, 1, 1); 523 524 // Latitude band 525 latData = new FlatFileReader(latFile, navLines, navElements); 526 latData.setBinaryInfo(HeaderInfo.kFormat2ByteUInt, HeaderInfo.kInterleaveSequential, bigEndian, offset, 1, 1); 527 528 } 529 530 } 531 532 // Set the stride if the dimensions are the same and read the floats 533 if (this.lines == this.navLines && this.elements == this.navElements && stride != 1) { 534 System.out.println("Setting stride for nav files: " + stride); 535 lonData.setStride(this.stride); 536 latData.setStride(this.stride); 537 this.navElements = this.strideElements; 538 this.navLines = this.strideLines; 539 lalo = new float[2][this.navElements * this.navLines]; 540 } 541 lalo[0] = lonData.getFloats(); 542 lalo[1] = latData.getFloats(); 543 544 // Take into account scaling and east positive 545 int latScale = this.latlonScale; 546 int lonScale = this.latlonScale; 547 if (eastPositive) lonScale = -1 * lonScale; 548 for (int i=0; i<lalo[0].length; i++) { 549 lalo[0][i] = lalo[0][i] / (float)lonScale; 550 } 551 for (int i=0; i<lalo[1].length; i++) { 552 lalo[1][i] = lalo[1][i] / (float)latScale; 553 } 554 555 return new Gridded2DSet(RealTupleType.SpatialEarth2DTuple, 556 lalo, navElements, navLines, 557 null, null, null, 558 false, false); 559 560 } catch (NumberFormatException exc) { 561 throw new BadDataException("Error parsing ASCII navigation file"); 562 } catch (Exception e) { 563 throw new BadDataException("Error setting navigation from file: " + url + "\n" + e); 564 } 565 } 566 567 /** 568 * Create navigation info if it hasn't been built 569 */ 570 private void makeCoordinateSystem() { 571 System.out.println("FlatFileInfo.makeCoordinateSystem()"); 572 573 if (navigationSet != null && navigationCoords != null) return; 574 575 switch (this.myNavigation) { 576 case HeaderInfo.kNavigationBounds: 577 navigationSet = getNavigationSetFromBounds(); 578 break; 579 case HeaderInfo.kNavigationFiles: 580 navigationSet = getNavigationSetFromFiles(); 581 break; 582 default: 583 System.err.println("Unknown navigation format"); 584 } 585 586 // myElements, myLines: Nav dimensions 587 // this.elements, this.lines: Data dimensions 588 float ratioElements = (float)this.strideElements / (float)this.navElements; 589 float ratioLines = (float)this.strideLines / (float)this.navLines; 590 int[] geo_start = new int[2]; 591 int[] geo_count = new int[2]; 592 int[] geo_stride = new int[2]; 593 try { 594 Linear2DSet domainSet = SwathNavigation.getNavigationDomain( 595 0, strideElements-1, 1, 596 0, strideLines-1, 1, 597 ratioElements, ratioLines, 0, 0, 598 geo_start, geo_count, geo_stride); 599 600 // System.out.println("makeCoordinateSystem stats for " + url + ":"); 601 // System.out.println(" Elements: " + strideElements + ", Lines: " + strideLines); 602 // System.out.println(" navElements: " + navElements + ", navLines: " + navLines); 603 // System.out.println(" ratioElements: " + ratioElements + ", ratioLines: " + ratioLines); 604 // System.out.println(" navigationSet: " + navigationSet.getLength(0) + " x " + navigationSet.getLength(1)); 605 // System.out.println(" geo_start: " + geo_start[0] + ", " + geo_start[1]); 606 // System.out.println(" geo_count: " + geo_count[0] + ", " + geo_count[1]); 607 // System.out.println(" geo_stride: " + geo_stride[0] + ", " + geo_stride[1]); 608 // System.out.println(" domainSet: " + domainSet.getLength(0) + " x " + domainSet.getLength(1)); 609 // System.out.println(" domainSet.toString(): " + domainSet.toString()); 610 611 navigationCoords = new LongitudeLatitudeCoordinateSystem(domainSet, navigationSet); 612 } catch (Exception e) { 613 // TODO Auto-generated catch block 614 e.printStackTrace(); 615 } 616 } 617 618 /** 619 * Return a valid data object for a DataSource 620 */ 621 public Data getData() { 622 System.out.println("FlatFileInfo.getData()"); 623 624 Data d = null; 625 FlatField field; 626 627 try { 628 629 switch (this.myFormat) { 630 case HeaderInfo.kFormatImage: 631 d = getDataFromImage(); 632 break; 633 default: 634 this.floatData = getFloats(); 635 field = getFlatField(); 636 // d = GridUtil.setSpatialDomain(field, navigationSet); 637 d = field; 638 break; 639 } 640 641 } catch (IOException e) { 642 // TODO Auto-generated catch block 643 e.printStackTrace(); 644 } catch (VisADException e) { 645 // TODO Auto-generated catch block 646 e.printStackTrace(); 647 } 648 649 return d; 650 } 651 652 /** 653 * Return the array of floats making up the data 654 */ 655 public float[] getFloats() { 656 System.out.println("FlatFileInfo.getFloats()"); 657 658 if (this.floatData != null) return this.floatData; 659 660 switch (this.myFormat) { 661 case HeaderInfo.kFormatImage: 662 break; 663 case HeaderInfo.kFormatASCII: 664 readFloatsFromAscii(); 665 break; 666 default: 667 readFloatsFromBinary(); 668 break; 669 } 670 671 672 673 // DEBUG! 674 // File justName = new File(url); 675 // try { 676 // BufferedWriter out = new BufferedWriter(new FileWriter("/tmp/mcv/" + justName.getName())); 677 // for (int i=0; i<this.floatData.length; i++) { 678 // if (i%strideElements==0) out.write("New line " + (i/strideElements) + " at element " + i + "\n"); 679 // out.write(this.floatData[i] + "\n"); 680 // } 681 // out.close(); 682 // } 683 // catch (IOException e) { 684 // System.out.println("Exception "); 685 // } 686 687 688 689 return this.floatData; 690 } 691 692 /** 693 * float array -> flatfield 694 */ 695 private FlatField getFlatField() 696 throws IOException, VisADException { 697 698 makeCoordinateSystem(); 699 700 // RealType[] unit = new RealType[] { RealType.Generic }; 701 // RealTupleType unitType = new RealTupleType(unit); 702 703 RealType unitType = RealType.getRealType(unit); 704 705 RealType line = RealType.getRealType("ImageLine"); 706 RealType element = RealType.getRealType("ImageElement"); 707 RealType[] domain_components = { element, line }; 708 RealTupleType image_domain = new RealTupleType(domain_components, navigationCoords, null); 709 FunctionType image_type = new FunctionType(image_domain, unitType); 710 Linear2DSet domain_set = new Linear2DSet(image_domain, 711 0.0, (float) (strideElements - 1.0), strideElements, 712 0.0, (float) (strideLines - 1.0), strideLines); 713 714 FlatField field = new FlatField(image_type, domain_set); 715 716 float[][] samples = new float[][] { this.floatData }; 717 try { 718 field.setSamples(samples, false); 719 } catch (RemoteException e) { 720 throw new VisADException("Couldn't finish FlatField initialization"); 721 } 722 723 return field; 724 } 725 726 /** 727 * toString 728 * 729 * @return toString 730 */ 731 public String toString() { 732 return "url: " + url + ", lines: " + lines + ", elements: " + elements; 733 } 734 735 // byte[] conversion functions 736 // TODO: are these replicated elsewhere in McV? 737 738 private static int bytesTo1ByteUInt (byte[] bytes, int offset) { 739 return (int) ( bytes[offset] & 0xff ); 740 } 741 742 private static int bytesTo2ByteUInt (byte[] bytes, int offset) { 743 int accum = 0; 744 for ( int shiftBy = 0; shiftBy < 16; shiftBy += 8 ) { 745 accum |= ( (long)( bytes[offset] & 0xff ) ) << shiftBy; 746 offset++; 747 } 748 return (int)( accum ); 749 } 750 751 private static int bytesTo2ByteSInt (byte[] bytes, int offset) { 752 return (bytesTo2ByteUInt(bytes, offset)) - 32768; 753 } 754 755 private static int bytesTo4ByteSInt (byte[] bytes, int offset) { 756 int accum = 0; 757 for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 ) { 758 accum |= ( (long)( bytes[offset] & 0xff ) ) << shiftBy; 759 offset++; 760 } 761 return (int)( accum ); 762 } 763 764 private static float bytesTo4ByteFloat (byte[] bytes, int offset) { 765 int accum = 0; 766 for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 ) { 767 accum |= ( (long)( bytes[offset] & 0xff ) ) << shiftBy; 768 offset++; 769 } 770 return Float.intBitsToFloat(accum); 771 } 772 773 private static long bytesToLong (byte[] bytes) { 774 if (bytes.length != 4) return 0; 775 long accum = 0; 776 int i = 0; 777 for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 ) { 778 accum |= ( (long)( bytes[i] & 0xff ) ) << shiftBy; 779 i++; 780 } 781 return accum; 782 } 783 784 private static double bytesToDouble (byte[] bytes) { 785 if (bytes.length != 8) return 0; 786 long accum = 0; 787 int i = 0; 788 for ( int shiftBy = 0; shiftBy < 64; shiftBy += 8 ) { 789 accum |= ( (long)( bytes[i] & 0xff ) ) << shiftBy; 790 i++; 791 } 792 return Double.longBitsToDouble(accum); 793 } 794 795 }