1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.common.mylzw;
18
19 import java.io.IOException;
20 import java.io.OutputStream;
21 import java.nio.ByteOrder;
22
23 public class MyBitOutputStream extends OutputStream {
24 private final OutputStream os;
25 private final ByteOrder byteOrder;
26 private int bitsInCache;
27 private int bitCache;
28 private int bytesWritten;
29
30 public MyBitOutputStream(final OutputStream os, final ByteOrder byteOrder) {
31 this.byteOrder = byteOrder;
32 this.os = os;
33 }
34
35 @Override
36 public void write(final int value) throws IOException {
37 writeBits(value, 8);
38 }
39
40
41
42 public void writeBits(int value, final int sampleBits) throws IOException {
43 final int sampleMask = (1 << sampleBits) - 1;
44 value &= sampleMask;
45
46 if (byteOrder == ByteOrder.BIG_ENDIAN) {
47
48 bitCache = (bitCache << sampleBits) | value;
49 } else {
50
51 bitCache = bitCache | (value << bitsInCache);
52 }
53 bitsInCache += sampleBits;
54
55 while (bitsInCache >= 8) {
56 if (byteOrder == ByteOrder.BIG_ENDIAN) {
57
58 final int b = 0xff & (bitCache >> (bitsInCache - 8));
59 actualWrite(b);
60
61 bitsInCache -= 8;
62 } else {
63
64 final int b = 0xff & bitCache;
65 actualWrite(b);
66
67 bitCache >>= 8;
68 bitsInCache -= 8;
69 }
70 final int remainderMask = (1 << bitsInCache) - 1;
71 bitCache &= remainderMask;
72 }
73
74 }
75
76 private void actualWrite(final int value) throws IOException {
77 os.write(value);
78 bytesWritten++;
79 }
80
81 public void flushCache() throws IOException {
82 if (bitsInCache > 0) {
83 final int bitMask = (1 << bitsInCache) - 1;
84 int b = bitMask & bitCache;
85
86 if (byteOrder == ByteOrder.BIG_ENDIAN) {
87
88 b <<= 8 - bitsInCache;
89 os.write(b);
90 } else {
91
92 os.write(b);
93 }
94 }
95
96 bitsInCache = 0;
97 bitCache = 0;
98 }
99
100 public int getBytesWritten() {
101 return bytesWritten + ((bitsInCache > 0) ? 1 : 0);
102 }
103
104 }