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