You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.0 KiB
141 lines
3.0 KiB
package com.jotuntech.sketcher.client;
|
|
|
|
import java.io.DataOutput;
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
|
|
public class PackBitsOutputStream extends OutputStream {
|
|
private DataOutput mdo;
|
|
|
|
private final static int IN_BUFFER_SIZE = 2048;
|
|
private final static int IN_BUFFER_MASK = IN_BUFFER_SIZE - 1;
|
|
private final static int OUT_BUFFER_SIZE = 4096;
|
|
|
|
private int[] inBuffer;
|
|
private int inBufferWritePos, inBufferReadPos, inBufferMark;
|
|
private byte[] outBuffer;
|
|
private int outBufferWritePos;
|
|
|
|
public PackBitsOutputStream(DataOutput mdo) {
|
|
this.mdo = mdo;
|
|
this.inBuffer = new int[IN_BUFFER_SIZE];
|
|
this.inBufferWritePos = 0;
|
|
this.inBufferReadPos = 0;
|
|
this.inBufferMark = 0;
|
|
this.outBuffer = new byte[OUT_BUFFER_SIZE];
|
|
this.outBufferWritePos = 0;
|
|
}
|
|
|
|
public void write(int b) throws IOException {
|
|
inBuffer[inBufferWritePos++ & IN_BUFFER_MASK] = b;
|
|
|
|
if(inBufferWritePos - inBufferReadPos == IN_BUFFER_SIZE) {
|
|
pack();
|
|
}
|
|
}
|
|
|
|
public void write(byte[] b) throws IOException {
|
|
for(int i = 0; i < b.length; i++) {
|
|
inBuffer[inBufferWritePos++ & IN_BUFFER_MASK] = b[i];
|
|
|
|
if(inBufferWritePos - inBufferReadPos == IN_BUFFER_SIZE) {
|
|
pack();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void write(byte[] b, int off, int len) throws IOException {
|
|
for(int i = off; i < off + len; i++) {
|
|
inBuffer[inBufferWritePos++ & IN_BUFFER_MASK] = b[i];
|
|
|
|
if(inBufferWritePos - inBufferReadPos == IN_BUFFER_SIZE) {
|
|
pack();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void flush() throws IOException {
|
|
pack();
|
|
}
|
|
|
|
private void output(int b) {
|
|
outBuffer[outBufferWritePos++] = (byte) b;
|
|
}
|
|
|
|
private void pack() throws IOException {
|
|
outBufferWritePos = 0;
|
|
|
|
while(available() > 0) {
|
|
int b = read();
|
|
int repeat = 1;
|
|
while(available() > 0 && peek() == b && repeat < 128) {
|
|
++repeat;
|
|
skip();
|
|
}
|
|
|
|
if(repeat == 1) {
|
|
mark();
|
|
int b2 = read();
|
|
int literal = 0;
|
|
while(available() > 0 && peek() != b2 && literal < 127) {
|
|
b2 = read();
|
|
++literal;
|
|
}
|
|
|
|
if(available() == 0 && literal < 127) {
|
|
++literal;
|
|
}
|
|
|
|
if(literal == 0) {
|
|
reset();
|
|
output(0);
|
|
output(b);
|
|
} else {
|
|
reset();
|
|
output(literal);
|
|
output(b);
|
|
for(int i = 0; i < literal; i++) {
|
|
output(read());
|
|
}
|
|
}
|
|
} else if(repeat == 2) {
|
|
output(1);
|
|
output(b);
|
|
output(b);
|
|
} else {
|
|
output(1 - repeat);
|
|
output(b);
|
|
}
|
|
}
|
|
|
|
mdo.write(outBuffer, 0, outBufferWritePos);
|
|
}
|
|
|
|
public void close() throws IOException {
|
|
pack();
|
|
}
|
|
|
|
private int available() {
|
|
return inBufferWritePos - inBufferReadPos;
|
|
}
|
|
|
|
private int peek() {
|
|
return inBuffer[inBufferReadPos & IN_BUFFER_MASK];
|
|
}
|
|
|
|
private int read() {
|
|
return inBuffer[inBufferReadPos++ & IN_BUFFER_MASK];
|
|
}
|
|
|
|
private void skip() {
|
|
++inBufferReadPos;
|
|
}
|
|
|
|
private void mark() {
|
|
inBufferMark = inBufferReadPos;
|
|
}
|
|
|
|
private void reset() {
|
|
inBufferReadPos = inBufferMark;
|
|
}
|
|
}
|
|
|