public static BufferedImage convertImageData(ImageData data) {
    BufferedImage bimg = null;
    int height = data.getHeight(), width = data.getWidth();
    Object pixels = data.getData();
    if (pixels instanceof int[] && data.getElementWidth() == 1) {
      int[] arr = (int[]) pixels;
      byte[] barray = new byte[arr.length * 3];
      int k = 0;
      for (int j = 0; j < arr.length; j++) {
        int l = arr[j];
        barray[k++] = (byte) (l & 0xFF);
        barray[k++] = (byte) ((l >>> 8) & 0xFF);
        barray[k++] = (byte) ((l >>> 16) & 0xFF);
      }
      ColorModel ccm =
          new ComponentColorModel(
              ICC_ColorSpace.getInstance(ICC_ColorSpace.CS_sRGB),
              new int[] {8, 8, 8},
              false,
              false,
              Transparency.OPAQUE,
              DataBuffer.TYPE_BYTE);
      DataBuffer bbuf = new DataBufferByte(barray, barray.length);
      SampleModel bmodel =
          new PixelInterleavedSampleModel(
              DataBuffer.TYPE_BYTE, width, height, 3, 3 * width, new int[] {2, 1, 0});

      WritableRaster raster = Raster.createWritableRaster(bmodel, bbuf, new Point(0, 0));
      bimg = new BufferedImage(ccm, raster, false, new Hashtable());
    } else if (pixels instanceof byte[]
        && data.getElementWidth() == 1) { // Assume gray scale model?
      byte[] arr = (byte[]) pixels;
      byte[] barray = new byte[arr.length * 3];
      int k = 0;
      for (int j = 0; j < arr.length; j++) {
        byte l = arr[j];
        barray[k++] = l;
        barray[k++] = l;
        barray[k++] = l;
      }
      ColorModel ccm =
          new ComponentColorModel(
              ICC_ColorSpace.getInstance(ICC_ColorSpace.CS_sRGB),
              new int[] {8, 8, 8},
              false,
              false,
              Transparency.OPAQUE,
              DataBuffer.TYPE_BYTE);
      DataBuffer bbuf = new DataBufferByte(barray, barray.length);
      SampleModel bmodel =
          new PixelInterleavedSampleModel(
              DataBuffer.TYPE_BYTE, width, height, 3, 3 * width, new int[] {2, 1, 0});

      WritableRaster raster = Raster.createWritableRaster(bmodel, bbuf, new Point(0, 0));
      bimg = new BufferedImage(ccm, raster, false, new Hashtable());
    } else {
      throw new RuntimeException("Unexpected data.");
    }
    return bimg;
  }
  /** Convert standard img to a buffered image. */
  public static BufferedImage convertImage(Image img) {
    int height = img.getHeight(null), width = img.getWidth(null);
    // FloatMatrix fm = new FloatMatrix( height, width ) ;
    PixelGrabber grabber = new PixelGrabber(img, 0, 0, width, height, false);
    try {
      grabber.grabPixels();
    } catch (InterruptedException e) {
      System.out.println(e);
    }
    Object pixels = grabber.getPixels();
    ColorModel cm = grabber.getColorModel();

    BufferedImage bimg = null;

    // REVISIT  Makes some unwarranted assumptions about the layout of the PixelGrabber data
    // as being either int (ARGB?) or byte (gray scale?)
    if (pixels instanceof int[]) {
      int[] arr = (int[]) pixels;
      byte[] barray = new byte[arr.length * 3];
      int k = 0;
      for (int j = 0; j < arr.length; j++) {
        int l = arr[j];
        barray[k++] = (byte) (l & 0xFF);
        barray[k++] = (byte) ((l >>> 8) & 0xFF);
        barray[k++] = (byte) ((l >>> 16) & 0xFF);
      }
      ColorModel ccm =
          new ComponentColorModel(
              ICC_ColorSpace.getInstance(ICC_ColorSpace.CS_sRGB),
              new int[] {8, 8, 8},
              false,
              false,
              Transparency.OPAQUE,
              DataBuffer.TYPE_BYTE);
      DataBuffer bbuf = new DataBufferByte(barray, barray.length);
      SampleModel bmodel =
          new PixelInterleavedSampleModel(
              DataBuffer.TYPE_BYTE, width, height, 3, 3 * width, new int[] {2, 1, 0});

      WritableRaster raster = Raster.createWritableRaster(bmodel, bbuf, new Point(0, 0));
      bimg = new BufferedImage(ccm, raster, false, new Hashtable());
    } else if (pixels instanceof byte[]) { // Assume gray scale model?
      byte[] arr = (byte[]) pixels;
      byte[] barray = new byte[arr.length * 3];
      int k = 0;
      for (int j = 0; j < arr.length; j++) {
        byte l = arr[j];
        barray[k++] = l;
        barray[k++] = l;
        barray[k++] = l;
      }
      ColorModel ccm =
          new ComponentColorModel(
              ICC_ColorSpace.getInstance(ICC_ColorSpace.CS_sRGB),
              new int[] {8, 8, 8},
              false,
              false,
              Transparency.OPAQUE,
              DataBuffer.TYPE_BYTE);
      DataBuffer bbuf = new DataBufferByte(barray, barray.length);
      SampleModel bmodel =
          new PixelInterleavedSampleModel(
              DataBuffer.TYPE_BYTE, width, height, 3, 3 * width, new int[] {2, 1, 0});

      WritableRaster raster = Raster.createWritableRaster(bmodel, bbuf, new Point(0, 0));
      bimg = new BufferedImage(ccm, raster, false, new Hashtable());
    } else {
      throw new RuntimeException("Unexpected data.");
    }
    return bimg;
  }
  public BufferedImage read(int imageIndex, ImageReadParam param) throws IOException {
    checkIndex(imageIndex);
    readHeader();

    if (iis == null) throw new IllegalStateException("input is null");

    BufferedImage img;

    clearAbortRequest();
    processImageStarted(imageIndex);

    if (param == null) param = getDefaultReadParam();

    sourceRegion = new Rectangle(0, 0, 0, 0);
    destinationRegion = new Rectangle(0, 0, 0, 0);

    computeRegions(
        param, this.width, this.height, param.getDestination(), sourceRegion, destinationRegion);

    scaleX = param.getSourceXSubsampling();
    scaleY = param.getSourceYSubsampling();

    // If the destination band is set used it
    sourceBands = param.getSourceBands();
    destBands = param.getDestinationBands();

    seleBand = (sourceBands != null) && (destBands != null);
    noTransform = destinationRegion.equals(new Rectangle(0, 0, width, height)) || seleBand;

    if (!seleBand) {
      sourceBands = new int[colorPlanes];
      destBands = new int[colorPlanes];
      for (int i = 0; i < colorPlanes; i++) destBands[i] = sourceBands[i] = i;
    }

    // If the destination is provided, then use it.  Otherwise, create new one
    bi = param.getDestination();

    // Get the image data.
    WritableRaster raster = null;

    if (bi == null) {
      if (sampleModel != null && colorModel != null) {
        sampleModel =
            sampleModel.createCompatibleSampleModel(
                destinationRegion.width + destinationRegion.x,
                destinationRegion.height + destinationRegion.y);
        if (seleBand) sampleModel = sampleModel.createSubsetSampleModel(sourceBands);
        raster = Raster.createWritableRaster(sampleModel, new Point(0, 0));
        bi = new BufferedImage(colorModel, raster, false, null);
      }
    } else {
      raster = bi.getWritableTile(0, 0);
      sampleModel = bi.getSampleModel();
      colorModel = bi.getColorModel();

      noTransform &= destinationRegion.equals(raster.getBounds());
    }

    byte bdata[] = null; // buffer for byte data

    if (sampleModel.getDataType() == DataBuffer.TYPE_BYTE)
      bdata = (byte[]) ((DataBufferByte) raster.getDataBuffer()).getData();

    readImage(bdata);

    if (abortRequested()) processReadAborted();
    else processImageComplete();

    return bi;
  }