All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ucar.nc2.iosp.gini.Giniiosp Maven / Gradle / Ivy

Go to download

The NetCDF-Java Library is a Java interface to NetCDF files, as well as to many other types of scientific data formats.

There is a newer version: 4.3.22
Show newest version
/*
 * Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
 *
 * Portions of this software were developed by the Unidata Program at the
 * University Corporation for Atmospheric Research.
 *
 * Access and use of this software shall impose the following obligations
 * and understandings on the user. The user is granted the right, without
 * any fee or cost, to use, copy, modify, alter, enhance and distribute
 * this software, and any derivative works thereof, and its supporting
 * documentation for any purpose whatsoever, provided that this entire
 * notice appears in all copies of the software, derivative works and
 * supporting documentation.  Further, UCAR requests that the user credit
 * UCAR/Unidata in any publications that result from the use of this
 * software or in any product that includes this software. The names UCAR
 * and/or Unidata, however, may not be used in any advertising or publicity
 * to endorse or promote any products or commercial entity unless specific
 * written permission is obtained from UCAR/Unidata. The user also
 * understands that UCAR/Unidata is not obligated to provide the user with
 * any support, consulting, training or assistance of any kind with regard
 * to the use, operation and performance of this software nor to provide
 * the user with any updates, revisions, new versions or "bug fixes."
 *
 * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
 */
package ucar.nc2.iosp.gini;

import ucar.ma2.*;
import ucar.nc2.Variable;
import ucar.nc2.iosp.AbstractIOServiceProvider;

import java.io.*;
import java.awt.image.*;
import java.util.*;
import java.util.zip.Inflater;
import java.util.zip.DataFormatException;

/**
 * IOServiceProvider for GINI files.
 */

public class Giniiosp extends AbstractIOServiceProvider {

  protected boolean readonly;
  private ucar.nc2.NetcdfFile ncfile;
  private ucar.unidata.io.RandomAccessFile myRaf;
  protected Giniheader headerParser;

  final static int Z_DEFLATED = 8;
  final static int DEF_WBITS = 15;

  // used for writing
  protected int fileUsed = 0; // how much of the file is written to ?
  protected int recStart = 0; // where the record data starts

  protected boolean debug = false, debugSize = false, debugSPIO = false;
  protected boolean showHeaderBytes = false;

  public ucar.ma2.Array readNestedData(ucar.nc2.Variable v2, java.util.List section)
          throws java.io.IOException, ucar.ma2.InvalidRangeException {

    throw new UnsupportedOperationException("Gini IOSP does not support nested variables");
  }

  public boolean isValidFile(ucar.unidata.io.RandomAccessFile raf) {
    Giniheader localHeader = new Giniheader();
    return (localHeader.isValidFile(raf));
  }

  /////////////////////////////////////////////////////////////////////////////
  // reading

  public void open(ucar.unidata.io.RandomAccessFile raf, ucar.nc2.NetcdfFile file,
                   ucar.nc2.util.CancelTask cancelTask) throws IOException {

    ncfile = file;
    myRaf = raf;

    headerParser = new Giniheader();
    headerParser.read(myRaf, ncfile, null);

    ncfile.finish();


  }

  public Array readData(ucar.nc2.Variable v2, Section section) throws IOException, InvalidRangeException {
    // subset
    int[] origin = section.getOrigin();
    int[] shape = section.getShape();
    int[] stride = section.getStride();
    Giniheader.Vinfo vinfo = (Giniheader.Vinfo) v2.getSPobject();
    int[] levels = vinfo.levels;

    if (headerParser.gini_GetCompressType() == 0)
      return readData(v2, vinfo.begin, origin, shape, stride, levels);
    else if (headerParser.gini_GetCompressType() == 2)
      return readCompressedData(v2, vinfo.begin, origin, shape, stride, levels);
    else if (headerParser.gini_GetCompressType() == 1)
      return readCompressedZlib(v2, vinfo.begin, vinfo.nx, vinfo.ny, origin, shape, stride, levels);
    else
      return null;
  }

  // all the work is here, so can be called recursively
  private Array readData(ucar.nc2.Variable v2, long dataPos, int[] origin, int[] shape, int[] stride,
                         int[] levels) throws IOException, InvalidRangeException {

    long length = myRaf.length();
    myRaf.seek(dataPos);

    int data_size = (int) (length - dataPos);
    byte[] data = new byte[data_size];
    myRaf.read(data);

    if (levels == null) {
      Array array = Array.factory(DataType.BYTE.getPrimitiveClassType(), v2.getShape(), data);

      return array.sectionNoReduce(origin, shape, stride);
    } else {
      int level = levels[0];
      float[] a = new float[level];
      float[] b = new float[level];
      float[] fdata = new float[data_size];
      int scale = 1;

      for (int i = 0; i < level; i++) {
        int numer = levels[1 + 5 * i] - levels[2 + 5 * i];
        int denom = levels[3 + 5 * i] - levels[4 + 5 * i];
        a[i] = (numer * 1.f) / (1.f * denom);
        b[i] = levels[1 + 5 * i] - a[i] * levels[3 + 5 * i];
      }

      int k;
      for (int i = 0; i < data_size; i++) {
        int ival = convertUnsignedByte2Short(data[i]);
        k = -1;
        for (int j = 0; j < level; j++) {
          if (levels[3 + (j * 5)] <= ival && ival <= levels[4 + (j * 5)]) {
            k = j;
            scale = levels[5 + j * 5];
          }
        }

        if (k >= 0)
          fdata[i] = (a[k] * ival + b[k]) / scale;
        else
          fdata[i] = 0;

      }
      Array array = Array.factory(DataType.FLOAT.getPrimitiveClassType(), v2.getShape(), fdata);

      return array.sectionNoReduce(origin, shape, stride);
    }
  }

  public Array readDataOld(ucar.nc2.Variable v2, long dataPos, int[] origin, int[] shape, int[] stride) throws IOException, InvalidRangeException {
    int start_l, stride_l, stop_l;
    int start_p, stride_p, stop_p;
    if (origin == null) origin = new int[v2.getRank()];
    if (shape == null) shape = v2.getShape();

    Giniheader.Vinfo vinfo = (Giniheader.Vinfo) v2.getSPobject();
    ucar.ma2.DataType dataType = v2.getDataType();

    int nx = vinfo.nx;
    int ny = vinfo.ny;
    start_l = origin[0];
    stride_l = stride[0];
    stop_l = origin[0] + shape[0] - 1;
    // Get data values from GINI
    // Loop over number of lines (slower dimension) for actual data Array
    start_p = origin[1];
    stride_p = stride[1];
    stop_p = origin[1] + shape[1] - 1;

    if (start_l + stop_l + stride_l == 0) { //default lines
      start_l = 0;
      stride_l = 1;
      stop_l = ny - 1;
    }
    if (start_p + stop_p + stride_p == 0) { //default pixels
      start_p = 0;
      stride_p = 1;
      stop_p = nx - 1;
    }

    int Len = shape[1]; // length of pixels read each line
    ucar.ma2.DataType ConvertFrom = ucar.ma2.DataType.BYTE;
    ArrayByte adata = new ArrayByte(new int[]{shape[0], shape[1]});
    Index indx = adata.getIndex();
    long doff = dataPos + start_p;
    // initially no data conversion is needed.
    if (ConvertFrom == ucar.ma2.DataType.BYTE) {
      for (int iline = start_l; iline <= stop_l; iline += stride_l) {
        /* read 1D byte[] */
        byte[] buf = getGiniLine(nx, ny, doff, iline, Len, stride_p);
        /* write into 2D array */
        for (int i = 0; i < Len; i++) {
          adata.setByte(indx.set(iline - start_l, i), buf[i]);
        }
      }
    }
    return adata;
  }
  // for the compressed data read all out into a array and then parse into requested


  // for the compressed data read all out into a array and then parse into requested

  public Array readCompressedData(ucar.nc2.Variable v2, long dataPos, int[] origin,
                                  int[] shape, int[] stride, int[] levels) throws IOException, InvalidRangeException {

    long length = myRaf.length();

    myRaf.seek(dataPos);

    int data_size = (int) (length - dataPos);
    byte[] data = new byte[data_size];
    myRaf.read(data);
    ByteArrayInputStream ios = new ByteArrayInputStream(data);

    BufferedImage image = javax.imageio.ImageIO.read(ios);
    Raster raster = image.getData();
    DataBuffer db = raster.getDataBuffer();

    if (db instanceof DataBufferByte) {
      DataBufferByte dbb = (DataBufferByte) db;
      int t = dbb.getNumBanks();
      byte[] udata = dbb.getData();

      if (levels == null) {
        Array array = Array.factory(DataType.BYTE.getPrimitiveClassType(), v2.getShape(), udata);
        v2.setCachedData(array, false);
        return array.sectionNoReduce(origin, shape, stride);
      } else {
        data_size = udata.length;
        int level = levels[0];
        float[] a = new float[level];
        float[] b = new float[level];
        float[] fdata = new float[data_size];
        int scale = 1;

        for (int i = 0; i < level; i++) {
          int numer = levels[1 + 5 * i] - levels[2 + 5 * i];
          int denom = levels[3 + 5 * i] - levels[4 + 5 * i];
          a[i] = (numer * 1.f) / (1.f * denom);
          b[i] = levels[1 + 5 * i] - a[i] * levels[3 + 5 * i];
        }

        int k;
        for (int i = 0; i < data_size; i++) {
          int ival = convertUnsignedByte2Short(udata[i]);
          k = -1;
          for (int j = 0; j < level; j++) {
            if (levels[3 + (j * 5)] <= ival && ival <= levels[4 + (j * 5)]) {
              k = j;
              scale = levels[5 + j * 5];
            }
          }

          if (k >= 0)
            fdata[i] = (a[k] * ival + b[k]) / scale;
          else
            fdata[i] = 0;

        }
        Array array = Array.factory(DataType.FLOAT.getPrimitiveClassType(), v2.getShape(), fdata);

        return array.sectionNoReduce(origin, shape, stride);
      }

    }

    return null;
  }

  public Array readCompressedZlib(ucar.nc2.Variable v2, long dataPos, int nx, int ny, int[] origin,
                                  int[] shape, int[] stride, int[] levels) throws IOException, InvalidRangeException {

    long length = myRaf.length();

    myRaf.seek(dataPos);

    int data_size = (int) (length - dataPos);     //  or 5120 as read buffer size
    byte[] data = new byte[data_size];
    myRaf.read(data);

    // decompress the bytes
    int resultLength = 0;
    int result = 0;
    byte[] inflateData = new byte[nx * (ny)];
    byte[] tmp;
    int uncompLen;        /* length of decompress space    */
    byte[] uncomp = new byte[nx * (ny + 1) + 4000];
    Inflater inflater = new Inflater(false);

    inflater.setInput(data, 0, data_size);
    int offset = 0;
    int limit = nx * ny + nx;

    while (inflater.getRemaining() > 0) {
      try {
        resultLength = inflater.inflate(uncomp, offset, 4000);
      }
      catch (DataFormatException ex) {
        System.out.println("ERROR on inflation " + ex.getMessage());
        ex.printStackTrace();
        throw new IOException(ex.getMessage());
      }
      offset = offset + resultLength;
      result = result + resultLength;
      if ((result) > limit) {
        // when uncomp data larger then limit, the uncomp need to increase size
        tmp = new byte[result];
        System.arraycopy(uncomp, 0, tmp, 0, result);
        uncompLen = result + 4000;
        uncomp = new byte[uncompLen];
        System.arraycopy(tmp, 0, uncomp, 0, result);
      }
      if (resultLength == 0) {
        int tt = inflater.getRemaining();
        byte[] b2 = new byte[2];
        System.arraycopy(data, (int) data_size - tt, b2, 0, 2);
        if (isZlibHed(b2) == 0) {
          System.arraycopy(data, (int) data_size - tt, uncomp, result, tt);
          result = result + tt;
          break;
        }
        inflater.reset();
        inflater.setInput(data, (int) data_size - tt, tt);
      }

    }

    inflater.end();

    System.arraycopy(uncomp, 0, inflateData, 0, nx * ny);
    if (data != null) {

      if (levels == null) {
        Array array = Array.factory(DataType.BYTE.getPrimitiveClassType(), v2.getShape(), uncomp);
        if (array.getSize() < Variable.defaultSizeToCache)
          v2.setCachedData(array, false);
        return array.sectionNoReduce(origin, shape, stride);
      } else {
        data_size = uncomp.length;
        int level = levels[0];
        float[] a = new float[level];
        float[] b = new float[level];
        float[] fdata = new float[data_size];
        int scale = 1;

        for (int i = 0; i < level; i++) {
          int numer = levels[1 + 5 * i] - levels[2 + 5 * i];
          int denom = levels[3 + 5 * i] - levels[4 + 5 * i];
          a[i] = (numer * 1.f) / (1.f * denom);
          b[i] = levels[1 + 5 * i] - a[i] * levels[3 + 5 * i];
        }

        int k;
        for (int i = 0; i < data_size; i++) {
          int ival = convertUnsignedByte2Short(uncomp[i]);
          k = -1;
          for (int j = 0; j < level; j++) {
            if (levels[3 + (j * 5)] <= ival && ival <= levels[4 + (j * 5)]) {
              k = j;
              scale = levels[5 + j * 5];
            }
          }

          if (k >= 0)
            fdata[i] = (a[k] * ival + b[k]) / scale;
          else
            fdata[i] = 0;

        }
        Array array = Array.factory(DataType.FLOAT.getPrimitiveClassType(), v2.getShape(), fdata);

        return array.sectionNoReduce(origin, shape, stride);
      }
    }

    return null;
  }

  /*
  ** Name:       GetGiniLine
  **
  ** Purpose:    Extract a line of data from a GINI image
  **
  ** Parameters:
  **             buf     - buffer containing image data
  **
  ** Returns:
  **             SUCCESS == 1
  **             FAILURE == 0
  **
  **
  */
  private byte[] getGiniLine(int nx, int ny, long doff, int lineNumber, int len, int stride) throws IOException {

    byte[] data = new byte[len];

    /*
    ** checking image file and set location of first line in file
    */
    myRaf.seek(doff);

    if (lineNumber >= ny)
      throw new IOException("Try to access the file at line number= " + lineNumber + " larger then last line number = " + ny);

    /*
    ** Read in the requested line
    */

    int offset = lineNumber * nx + (int) doff;

    //myRaf.seek ( offset );
    for (int i = 0; i < len; i++) {
      myRaf.seek(offset);
      data[i] = myRaf.readByte();
      offset = offset + stride;
      //myRaf.seek(offset);
    }
    //myRaf.read( data, 0, len);

    return data;

  }

  /*
  ** Name:       IsZlibed
  **
  ** Purpose:    Check a two-byte sequence to see if it indicates the start of
  **             a zlib-compressed buffer
  **
  ** Parameters:
  **             buf     - buffer containing at least two bytes
  **
  ** Returns:
  **             SUCCESS 1
  **             FAILURE 0
  **
  */
  int issZlibed(byte[] buf) {

    if ((buf[0] & 0xf) == Z_DEFLATED) {
      if ((buf[0] >> 4) + 8 <= DEF_WBITS) {
        if ((((buf[0] << 8) + (buf[1])) % 31) == 0) {
          return 1;
        }
      }
    }

    return 0;
  }

  protected boolean fill;
  protected HashMap dimHash = new HashMap(50);

  public void flush() throws java.io.IOException {
    myRaf.flush();
  }

  public void close() throws java.io.IOException {
    myRaf.close();
  }

  // get this to inline for performance
  private final short convertUnsignedByte2Short(byte b) {
    return (short) ((b < 0) ? (short) b + 256 : (short) b);
  }

  private int isZlibHed(byte[] buf) {
    short b0 = convertUnsignedByte2Short(buf[0]);
    short b1 = convertUnsignedByte2Short(buf[1]);

    if ((b0 & 0xf) == Z_DEFLATED) {
      if ((b0 >> 4) + 8 <= DEF_WBITS) {
        if ((((b0 << 8) + b1) % 31) == 0) {
          return 1;
        }
      }
    }

    return 0;

  }

  public String getFileTypeId() {
    return "GINI";
  }

  public String getFileTypeDescription() {
    return "GOES Ingest and NOAAPORT Interface";
  }


  public static void main(String args[]) throws Exception, IOException, InstantiationException, IllegalAccessException {
    //String fileIn = "/home/yuanho/dev/netcdf-java-2.2/src/ucar/nc2/n0r_20040823_2215";    // uncompressed
    String fileIn = "c:/data/image/gini/n0r_20041013_1852";
    ucar.nc2.NetcdfFile.registerIOProvider(ucar.nc2.iosp.gini.Giniiosp.class);
    ucar.nc2.NetcdfFile ncf = ucar.nc2.NetcdfFile.open(fileIn);

    List alist = ncf.getGlobalAttributes();

    ucar.nc2.Variable v = ncf.findVariable("BaseReflectivity");

    int[] origin = {0, 0};
    int[] shape = {3000, 4736};

    ArrayByte data = (ArrayByte) v.read(origin, shape);

    ncf.close();


  }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy