private Point hilbertOrderData(ImageData id, byte pixData[]) {

    int order = 0;
    for (int n = 1; n < id.width; n *= 2) {
      order++;
    }
    /* Skanky; use an otherwise-unused ImageData field
     * to keep track of maxX.
     */
    Point p = new Point(0, 0);
    int oldIdX = id.x;
    int oldIdY = id.y;
    id.x = id.y = 0;
    try {
      hilbertWalk(id, new ByteArrayInputStream(pixData), order, 0, 0, HILBERT_DIR_E);
      p.x = id.x;
      p.y = id.y;
    } catch (IOException ex) {
      System.err.println("Exception during hilbertWalk()");
      p.x = id.height;
      p.y = id.width;
    }
    id.x = oldIdX;
    id.y = oldIdY;
    return p;
  }
  private void hilbertWalk(ImageData id, InputStream pixData, int order, int x, int y, int dir)
      throws IOException {
    if (x >= id.width || y >= id.height) {
      return;
    } else if (order == 0) {
      try {
        int p = pixData.read();
        if (p >= 0) {
          // flip along x=y axis;  assume width == height
          id.setPixel(y, x, p);

          /* Skanky; use an otherwise-unused ImageData field
           * to keep track of the max x,y used. Note that x and y are inverted.
           */
          if (y > id.x) {
            id.x = y;
          }
          if (x > id.y) {
            id.y = x;
          }
        }
        // xxx just give up; don't bother walking the rest of the image
      } catch (IllegalArgumentException ex) {
        System.out.println(
            "bad pixels: order "
                + order
                + ", dir "
                + dir
                + ", w "
                + id.width
                + ", h "
                + id.height
                + ", x "
                + x
                + ", y "
                + y);
        throw ex;
      }
    } else {
      order--;
      int delta = 1 << order;
      int nextX = x + delta;
      int nextY = y + delta;

      switch (dir) {
        case HILBERT_DIR_E:
          hilbertWalk(id, pixData, order, x, y, HILBERT_DIR_N);
          hilbertWalk(id, pixData, order, x, nextY, HILBERT_DIR_E);
          hilbertWalk(id, pixData, order, nextX, nextY, HILBERT_DIR_E);
          hilbertWalk(id, pixData, order, nextX, y, HILBERT_DIR_S);
          break;
        case HILBERT_DIR_N:
          hilbertWalk(id, pixData, order, x, y, HILBERT_DIR_E);
          hilbertWalk(id, pixData, order, nextX, y, HILBERT_DIR_N);
          hilbertWalk(id, pixData, order, nextX, nextY, HILBERT_DIR_N);
          hilbertWalk(id, pixData, order, x, nextY, HILBERT_DIR_W);
          break;
        case HILBERT_DIR_S:
          hilbertWalk(id, pixData, order, nextX, nextY, HILBERT_DIR_W);
          hilbertWalk(id, pixData, order, x, nextY, HILBERT_DIR_S);
          hilbertWalk(id, pixData, order, x, y, HILBERT_DIR_S);
          hilbertWalk(id, pixData, order, nextX, y, HILBERT_DIR_E);
          break;
        case HILBERT_DIR_W:
          hilbertWalk(id, pixData, order, nextX, nextY, HILBERT_DIR_S);
          hilbertWalk(id, pixData, order, nextX, y, HILBERT_DIR_W);
          hilbertWalk(id, pixData, order, x, y, HILBERT_DIR_W);
          hilbertWalk(id, pixData, order, x, nextY, HILBERT_DIR_N);
          break;
        default:
          throw new RuntimeException("Unexpected Hilbert direction " + dir);
      }
    }
  }