+ private void encodeChannel(final Table table, final Channel channel,
+ final int averageDecodedValue, final int index, final int value,
+ final int range, final int parentIndex) throws IOException {
+
+ final byte[] decodedRangeMap = channel.decodedRangeMap;
+ final byte[] decodedMap = channel.decodedMap;
+
+ final int inheritedRange = byteToInt(decodedRangeMap[parentIndex]);
+
+ final int inheritedBitCount = table
+ .proposeBitcountForRange(inheritedRange);
+
+ if (inheritedBitCount > 0) {
+ int computedRange;
+ computedRange = table.proposeRangeForRange(range, inheritedRange);
+ decodedRangeMap[index] = (byte) computedRange;
+
+ channel.bitCount++;
+ if (computedRange != inheritedRange) {
+ // brightness range shrinked
+ bitOutputStream.storeBits(1, 1);
+ } else {
+ // brightness range stayed the same
+ bitOutputStream.storeBits(0, 1);
+ }
+
+ // encode brightness into available amount of bits
+ final int computedBitCount = table
+ .proposeBitcountForRange(computedRange);
+
+ if (computedBitCount > 0) {
+
+ final int differenceToEncode = -(value - averageDecodedValue);
+ final int bitEncodedDifference = encodeValueIntoGivenBits(
+ differenceToEncode, computedRange, computedBitCount);
+
+ channel.bitCount = channel.bitCount + computedBitCount;
+ bitOutputStream.storeBits(bitEncodedDifference,
+ computedBitCount);
+
+ final int decodedDifference = decodeValueFromGivenBits(
+ bitEncodedDifference, computedRange, computedBitCount);
+ int decodedValue = averageDecodedValue - decodedDifference;
+ if (decodedValue > 255)
+ decodedValue = 255;
+ if (decodedValue < 0)
+ decodedValue = 0;
+
+ decodedMap[index] = (byte) decodedValue;
+ } else {
+ decodedMap[index] = (byte) averageDecodedValue;
+ }
+
+ } else {
+ decodedRangeMap[index] = (byte) inheritedRange;
+ decodedMap[index] = (byte) averageDecodedValue;
+ }
+ }
+
+ public void printStatistics() {