1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.mylzw;
18
19 import java.io.FilterInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.nio.ByteOrder;
23
24 public class MyBitInputStream extends FilterInputStream {
25 private final ByteOrder byteOrder;
26 private final boolean tiffLZWMode;
27 private long bytesRead;
28 private int bitsInCache;
29 private int bitCache;
30
31 public MyBitInputStream(final InputStream is, final ByteOrder byteOrder, final boolean tiffLZWMode) {
32 super(is);
33 this.byteOrder = byteOrder;
34 this.tiffLZWMode = tiffLZWMode;
35 }
36
37 public void flushCache() {
38 bitsInCache = 0;
39 bitCache = 0;
40 }
41
42 public long getBytesRead() {
43 return bytesRead;
44 }
45
46 @Override
47 public int read() throws IOException {
48 return readBits(8);
49 }
50
51 public int readBits(final int sampleBits) throws IOException {
52 while (bitsInCache < sampleBits) {
53 final int next = in.read();
54
55 if (next < 0) {
56 if (tiffLZWMode) {
57
58 return 257;
59 }
60 return -1;
61 }
62
63 final int newByte = 0xff & next;
64
65 if (byteOrder == ByteOrder.BIG_ENDIAN) {
66 bitCache = bitCache << 8 | newByte;
67 } else {
68 bitCache = newByte << bitsInCache | bitCache;
69 }
70
71 bytesRead++;
72 bitsInCache += 8;
73 }
74 final int sampleMask = (1 << sampleBits) - 1;
75
76 int sample;
77
78 if (byteOrder == ByteOrder.BIG_ENDIAN) {
79 sample = sampleMask & bitCache >> bitsInCache - sampleBits;
80 } else {
81 sample = sampleMask & bitCache;
82 bitCache >>= sampleBits;
83 }
84
85 final int result = sample;
86
87 bitsInCache -= sampleBits;
88 final int remainderMask = (1 << bitsInCache) - 1;
89 bitCache &= remainderMask;
90
91 return result;
92 }
93
94 }