public int decodeHorizontal(byte[] tmp, int i) {

    do {
      int j = i / 8;
      int shift = (i % 8);

      copyBits(bytesArray, tmp, j, shift);

      if (whiteRun) node = WhiteTree.Find(Converter.bytesToInt(tmp));
      else node = BlackTree.Find(Converter.bytesToInt(tmp));
      if (node != null) code = node.code;

      if (code.runLength >= 0) {

        // DEBUG System.out.print( (whiteRun?"W":"B") + code.runLength
        // );

        if (code.runLength < 64) {
          addRun(code.runLength + longHoriztonalRun);
          whiteRun = !whiteRun;
          longHoriztonalRun = 0;
        } else longHoriztonalRun += code.runLength;

      } else if (code.runLength == T4Code.EOF) {
        lines--;
        System.out.print("---" + code);
        return T4Code.EOF; // reached the end of the image!
      } else {
        addRun(code.runLength);
        System.out.print(code + "~~");
        System.out.print((whiteRun ? "W" : "B") + code.runLength);
        System.out.print("~~");
      }

      i += code.bitLength;

      if (nPixels > 0 && code.runLength == T4Code.EOL) // end of the
      // line
      {
        whiteRun = true; // always start with white
        lines++;
        resetRuns();
      }

    } while (code.runLength >= 64);
    return i;
  }
  public int readMode(int i) {
    int j = i / 8;
    int shift = (i % 8);

    // DEBUG System.out.println("Loop start i="+i);

    copyBits(bytesArray, tmp, j, shift);

    node = ModeTree.Find(Converter.bytesToInt(tmp));
    if (node != null) code = node.code;

    i += code.bitLength;
    return i;
  }
  void init() {
    // setup trees
    WhiteTree = new T4Node();
    BlackTree = new T4Node();
    ModeTree = new T4Node();

    if (hiloBitOrder) {
      for (i = 0; i < ModeCodes.length; i++) {
        code = new T4Code(ModeCodes[i]);
        if (code.bitLength <= 8) {
          int lo = Converter.reverseByte(Converter.getLoByte(code.codeWord)); // & 0xff);
          code.codeWord = (lo >>> (8 - code.bitLength));
        } else {
          code.codeWord = (Converter.reverseInt(code.codeWord) >>> (16 - code.bitLength));
        }
        ModeTree.ReversedAdd(0, code);
      }

      for (i = 0; i < T4Tables.WhiteCodes.length; i++) {
        code = new T4Code(T4Tables.WhiteCodes[i]);
        if (code.bitLength <= 8) {
          int lo = Converter.reverseByte(Converter.getLoByte(code.codeWord)); // & 0xff);
          code.codeWord = (lo >>> (8 - code.bitLength));
        } else {
          code.codeWord = (Converter.reverseInt(code.codeWord) >>> (16 - code.bitLength));
        }
        WhiteTree.ReversedAdd(0, code);
      }

      for (i = 0; i < T4Tables.BlackCodes.length; i++) {
        code = new T4Code(T4Tables.BlackCodes[i]);
        if (code.bitLength <= 8) {
          int lo = Converter.reverseByte(Converter.getLoByte(code.codeWord)); // & 0xff);
          code.codeWord = (lo >>> (8 - code.bitLength));
        } else {
          code.codeWord = (Converter.reverseInt(code.codeWord) >>> (16 - code.bitLength));
        }
        BlackTree.ReversedAdd(0, code);
      }
    } else {
      for (i = 0; i < ModeCodes.length; i++) {
        code = new T4Code(ModeCodes[i]);
        ModeTree.Add(0, code);
      }

      for (i = 0; i < T4Tables.WhiteCodes.length; i++) {
        code = new T4Code(T4Tables.WhiteCodes[i]);
        WhiteTree.Add(0, code);
      }

      for (i = 0; i < T4Tables.BlackCodes.length; i++) {
        code = new T4Code(T4Tables.BlackCodes[i]);
        BlackTree.Add(0, code);
      }
    }
    // setup runs
    WhiteRun = new byte[imageWidth + 2];
    BlackRun = new byte[imageWidth + 2];

    for (i = 0; i < imageWidth + 1; i++) {
      WhiteRun[i] = (byte) 0xff;
      BlackRun[i] = 0;
    }
  }