blob: ea4a4dde2b70d11843dccf28eaf1d566979e2334 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.pdfbox.jbig2.decoder.huffman;
import java.io.IOException;
import javax.imageio.stream.ImageInputStream;
import org.apache.pdfbox.jbig2.JBIG2ImageReader;
import org.apache.pdfbox.jbig2.decoder.huffman.HuffmanTable.Code;
/**
* This class represents an internal node of a huffman tree. It contains two child nodes.
*/
class InternalNode extends Node {
private final int depth;
private Node zero;
private Node one;
protected InternalNode() {
depth = 0;
}
protected InternalNode(int depth) {
this.depth = depth;
}
protected void append(Code c) {
if (JBIG2ImageReader.DEBUG)
System.out.println("I'm working on " + c.toString());
// ignore unused codes
if (c.prefixLength == 0)
return;
int shift = c.prefixLength - 1 - depth;
if (shift < 0)
throw new IllegalArgumentException("Negative shifting is not possible.");
int bit = (c.code >> shift) & 1;
if (shift == 0) {
if (c.rangeLength == -1) {
// the child will be a OutOfBand
if (bit == 1) {
if (one != null)
throw new IllegalStateException("already have a OOB for " + c);
one = new OutOfBandNode(c);
} else {
if (zero != null)
throw new IllegalStateException("already have a OOB for " + c);
zero = new OutOfBandNode(c);
}
} else {
// the child will be a ValueNode
if (bit == 1) {
if (one != null)
throw new IllegalStateException("already have a ValueNode for " + c);
one = new ValueNode(c);
} else {
if (zero != null)
throw new IllegalStateException("already have a ValueNode for " + c);
zero = new ValueNode(c);
}
}
} else {
// the child will be an InternalNode
if (bit == 1) {
if (one == null)
one = new InternalNode(depth + 1);
((InternalNode) one).append(c);
} else {
if (zero == null)
zero = new InternalNode(depth + 1);
((InternalNode) zero).append(c);
}
}
}
@Override
protected long decode(ImageInputStream iis) throws IOException {
int b = iis.readBit();
Node n = b == 0 ? zero : one;
return n.decode(iis);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("\n");
pad(sb);
sb.append("0: ").append(zero).append("\n");
pad(sb);
sb.append("1: ").append(one).append("\n");
return sb.toString();
}
private void pad(StringBuilder sb) {
for (int i = 0; i < depth; i++)
sb.append(" ");
}
}