1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.formats.tiff.datareaders;
18
19 import java.io.FilterInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.nio.ByteOrder;
23
24 import org.apache.commons.imaging.ImagingException;
25
26
27
28
29
30 final class BitInputStream extends FilterInputStream {
31 private final ByteOrder byteOrder;
32 private int cache;
33 private int cacheBitsRemaining;
34 private long bytesRead;
35
36 BitInputStream(final InputStream is, final ByteOrder byteOrder) {
37 super(is);
38 this.byteOrder = byteOrder;
39 }
40
41 public void flushCache() {
42 cacheBitsRemaining = 0;
43 }
44
45 public long getBytesRead() {
46 return bytesRead;
47 }
48
49 @Override
50 public int read() throws IOException {
51 if (cacheBitsRemaining > 0) {
52 throw new ImagingException("BitInputStream: incomplete bit read");
53 }
54 return in.read();
55 }
56
57 public int readBits(final int count) throws IOException {
58 if (count < 8) {
59 if (cacheBitsRemaining == 0) {
60
61 cache = in.read();
62 cacheBitsRemaining = 8;
63 bytesRead++;
64 }
65 if (count > cacheBitsRemaining) {
66 throw new ImagingException("BitInputStream: can't read bit fields across bytes");
67 }
68
69
70 cacheBitsRemaining -= count;
71 final int bits = cache >> cacheBitsRemaining;
72
73 switch (count) {
74 case 1:
75 return bits & 1;
76 case 2:
77 return bits & 3;
78 case 3:
79 return bits & 7;
80 case 4:
81 return bits & 15;
82 case 5:
83 return bits & 31;
84 case 6:
85 return bits & 63;
86 case 7:
87 return bits & 127;
88 }
89
90 }
91 if (cacheBitsRemaining > 0) {
92 throw new ImagingException("BitInputStream: incomplete bit read");
93 }
94
95 if (count == 8) {
96 bytesRead++;
97 return in.read();
98 }
99
100
101
102
103
104 if (byteOrder == ByteOrder.BIG_ENDIAN) {
105 switch (count) {
106 case 16:
107 bytesRead += 2;
108 return in.read() << 8 | in.read() << 0;
109 case 24:
110 bytesRead += 3;
111 return in.read() << 16 | in.read() << 8 | in.read() << 0;
112 case 32:
113 bytesRead += 4;
114 return in.read() << 24 | in.read() << 16 | in.read() << 8 | in.read() << 0;
115 default:
116 break;
117 }
118 } else {
119 switch (count) {
120 case 16:
121 bytesRead += 2;
122 return in.read() << 0 | in.read() << 8;
123 case 24:
124 bytesRead += 3;
125 return in.read() << 0 | in.read() << 8 | in.read() << 16;
126 case 32:
127 bytesRead += 4;
128 return in.read() << 0 | in.read() << 8 | in.read() << 16 | in.read() << 24;
129 default:
130 break;
131 }
132 }
133
134 throw new ImagingException("BitInputStream: unknown error");
135 }
136 }