Ejemplo n.º 1
0
  /**
   * Loads PNG files and returns the result as an int[][]. The only PNG formats permitted are those
   * with up to 256 grays (including simple black and white) or indexed colors from an up to
   * 256-sized color table. Each integer value represents the gray level or the color table index
   * value of the pixel. The Y dimension is not flipped.
   */
  public static int[][] loadPNGFile(InputStream str) throws IOException {
    // read the bytes into a byte array
    BufferedInputStream stream = new BufferedInputStream(str);
    ArrayList list = new ArrayList();
    int count = 0;
    while (true) {
      byte[] buffer = new byte[16384 * 16];
      int len = stream.read(buffer);
      if (len <= 0) // all done
      break;
      else if (len < buffer.length) {
        byte[] buf2 = new byte[len];
        System.arraycopy(buffer, 0, buf2, 0, len);
        buffer = buf2;
      }
      count += len;
      list.add(buffer);
    }
    byte[] data = new byte[count];
    int cur = 0;
    for (int i = 0; i < list.size(); i++) {
      byte[] b = (byte[]) (list.get(i));
      System.arraycopy(b, 0, data, cur, b.length);
      cur += b.length;
    }

    // Next convert the byte array to a buffered image
    BufferedImage image = ((ToolkitImage) (new ImageIcon(data).getImage())).getBufferedImage();

    // Is the color model something we can use?
    int type = image.getType();
    if (type == BufferedImage.TYPE_BYTE_BINARY || type == BufferedImage.TYPE_BYTE_GRAY) {
      int w = image.getWidth();
      int h = image.getHeight();
      int[][] result = new int[w][h];
      // obviously this could be done more efficiently
      for (int i = 0; i < w; i++)
        for (int j = 0; j < h; j++) result[i][j] = (image.getRGB(i, j) & 0xFF);
      return result;
    } else if (type == BufferedImage.TYPE_BYTE_INDEXED) {
      Raster raster = image.getRaster();
      if (raster.getTransferType() != DataBuffer.TYPE_BYTE) // uh oh
      throw new IOException("Input Stream must contain an image with byte data if indexed.");
      byte[] pixel = new byte[1];
      int w = image.getWidth();
      int h = image.getHeight();
      int[][] result = new int[w][h];
      // obviously this could be done more efficiently
      for (int i = 0; i < w; i++)
        for (int j = 0; j < h; j++) {
          result[i][j] = ((byte[]) (raster.getDataElements(i, j, pixel)))[0];
          if (result[i][j] < 0) result[i][j] += 256;
        }
      return result;
    }
    // else if (type == TYPE_USHORT_GRAY)   // at present we don't handle shorts
    //    {
    //    }
    else
      throw new IOException(
          "Input Stream must contain a binary, byte-sized grayscale, or byte-sized indexed color scheme: "
              + image);
  }