Skip to content

Commit

Permalink
added jpeg decoder, wip
Browse files Browse the repository at this point in the history
  • Loading branch information
wizzardo committed Nov 25, 2023
1 parent f7a4421 commit ba36e4e
Show file tree
Hide file tree
Showing 56 changed files with 6,916 additions and 0 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ dependencies {

testImplementation "org.testcontainers:oracle-xe:1.17.5"
testImplementation "com.oracle.database.jdbc:ojdbc11-production:21.7.0.0"
testImplementation 'org.apache.commons:commons-imaging:1.0-alpha3'
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.wizzardo.tools.image;

import java.io.IOException;
import java.util.Arrays;

public interface BitStream {

boolean ensureEnoughLength(int length) throws IOException;

int readByte() throws IOException;

int readBit() throws IOException;

int readByteUnsafe();

int readByteUnsafe(boolean ignoreByteStuffing);

int readBitUnsafe();

int readBits(int n) throws IOException;

int readBitsUnsafe(int n);

void skip(int length) throws IOException;

void unread(int offset);

int getBitsRemaining();

void setBitsRemaining(int bitsRemaining);

int getBitsBuffer();

void setBitsBuffer(int bitsBuffer);

boolean isSeekable();

int indexOf(byte[] bytes, int from);

BitStream shallowCopy(int offset);

default int readIntUnsafe() {
return (readByteUnsafe() << 24) + (readByteUnsafe() << 16) + (readByteUnsafe() << 8) + readByteUnsafe();
}

default int readIntUnsafe(boolean ignoreByteStuffing) {
return (readByteUnsafe(ignoreByteStuffing) << 24) + (readByteUnsafe(ignoreByteStuffing) << 16) + (readByteUnsafe(ignoreByteStuffing) << 8) + readByteUnsafe(ignoreByteStuffing);
}

default int readShortUnsafe() {
return (readByteUnsafe() << 8) + readByteUnsafe();
}

default int readShortUnsafe(boolean ignoreByteStuffing) {
return (readByteUnsafe(ignoreByteStuffing) << 8) + readByteUnsafe(ignoreByteStuffing);
}

default int readInt() throws IOException {
return (readByte() << 24) + (readByte() << 16) + (readByte() << 8) + readByte();
}

default int readShort() throws IOException {
return (readByte() << 8) + readByte();
}

default byte[] readBytes(byte[] block) throws IOException {
ensureEnoughLength(block.length);
for (int i = 0; i < block.length; i++) {
block[i] = (byte) readByteUnsafe(true);
}
return block;
}

default byte[] readBytesUnsafe(byte[] block) {
for (int i = 0; i < block.length; i++) {
block[i] = (byte) readByteUnsafe(true);
}
return block;
}

// int[] debugData = new int[4];
default int fillBitsBuffer() {
int result = 0;
int i = 0;
// Arrays.fill(debugData, -1);
do {
int value = readByteUnsafe(true);
if (value == 255) {
int next = readByteUnsafe(true);
if (next != 0) {
if (next >= 0xD0 && next <= 0xD7) {
setBitsBuffer(result);
setBitsRemaining(i * 8);
unread(2);
if (i == 0) {
// return fillBitsBuffer();
throw new IllegalStateException();
}

return i * 8;
}
throw new IllegalStateException();
}
}
result = (result << 8) + value;
// debugData[i]=value;
} while (++i < 4);
setBitsBuffer(result);
setBitsRemaining(32);
return 32;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package com.wizzardo.tools.image;

import java.io.IOException;

class BitStreamBuffered implements BitStream {
int partSize = 1024 * 64;
byte[][] parts;
int offset;
int read;
int bitsBuffer;
int bitsRemaining;

BitStreamBuffered(BitStreamInputStream inputStream) throws IOException {
this.parts = new byte[1][];

buffer(inputStream);
}

BitStreamBuffered(BitStreamBuffered stream) {
this.parts = stream.parts;
this.read = stream.read;
}

void buffer(BitStreamInputStream inputStream) throws IOException {
byte[] part = new byte[partSize];
int r = inputStream.read - inputStream.offset;
System.arraycopy(inputStream.buf, inputStream.offset, part, 0, r);
parts[0] = part;
this.read += r;

do {
int read = inputStream.in.read(part, r, part.length - r);
if (read == -1) {
break;
} else {
r += read;
this.read += read;
if (r == part.length) {
part = new byte[partSize];
byte[][] nextParts = new byte[parts.length + 1][];
System.arraycopy(parts, 0, nextParts, 0, parts.length);
parts = nextParts;
parts[parts.length - 1] = part;
r = 0;
}
}
} while (true);
}

@Override
public boolean ensureEnoughLength(int length) throws IOException {
int left = read - offset;
return left >= length;
}

@Override
public void skip(int length) throws IOException {
offset += length;
}

@Override
public void unread(int offset) {
this.offset -= offset;
}


@Override
public int getBitsRemaining() {
return bitsRemaining;
}

@Override
public void setBitsRemaining(int bitsRemaining) {
this.bitsRemaining = bitsRemaining;
}

@Override
public int getBitsBuffer() {
return bitsBuffer;
}

@Override
public void setBitsBuffer(int bitsBuffer) {
this.bitsBuffer = bitsBuffer;
}

@Override
public int readByte() throws IOException {
if (!ensureEnoughLength(2))
return -1;

byte[] buf = parts[offset >> 16];
byte b = buf[(offset++) & 0xFFFF];
int result = b & 0xFF;
if (result == 0xFF) {
buf = parts[offset >> 16];
if (buf[(offset++) & 0xFFFF] != 0)
throw new IllegalStateException();
}
return result;
}

@Override
public int readBit() throws IOException {
if (bitsRemaining == 0) {
bitsBuffer = readByte();
if (bitsBuffer == -1) {
return -1;
}
bitsRemaining = 8;
}
bitsRemaining--;
return (bitsBuffer >>> bitsRemaining) & 1;
}

@Override
public int readByteUnsafe() {
byte[] buf = parts[offset >> 16];
byte b = buf[((offset++) & 0xFFFF) & 0xFFFF];
int result = b & 0xFF;
if (result == 0xFF) {
buf = parts[offset >> 16];
if (buf[((offset++) & 0xFFFF) & 0xFFFF] != 0)
throw new IllegalStateException();
}
return result;
}

@Override
public int readByteUnsafe(boolean ignoreByteStuffing) {
if (!ignoreByteStuffing)
return readByteUnsafe();

byte[] buf = parts[offset >> 16];
byte b = buf[((offset++) & 0xFFFF) & 0xFFFF];
return b & 0xFF;
}

@Override
public int readBitUnsafe() {
if (bitsRemaining == 0) {
bitsBuffer = readByteUnsafe();
bitsRemaining = 8;
}
bitsRemaining--;
return (bitsBuffer >>> bitsRemaining) & 1;
}

@Override
public int readBits(int n) throws IOException {
int result = 0;
while (n > 0) {
if (bitsRemaining == 0) {
bitsBuffer = readByte();
if (bitsBuffer == -1) {
return -1;
}
bitsRemaining = 8;
}
int bitsToRead = Math.min(n, bitsRemaining);
n -= bitsToRead;
bitsRemaining -= bitsToRead;
result <<= bitsToRead;
result |= (bitsBuffer >>> bitsRemaining) & ((1 << bitsToRead) - 1);
}
return result;
}

@Override
public int readBitsUnsafe(int n) {
int result = 0;
while (n > 0) {
if (bitsRemaining == 0) {
bitsBuffer = readByteUnsafe();
if (bitsBuffer == -1) {
return -1;
}
bitsRemaining = 8;
}
int bitsToRead = Math.min(n, bitsRemaining);
n -= bitsToRead;
bitsRemaining -= bitsToRead;
result <<= bitsToRead;
result |= (bitsBuffer >>> bitsRemaining) & ((1 << bitsToRead) - 1);
}
return result;
}

@Override
public boolean isSeekable() {
return true;
}

byte getByte(int offset) {
return parts[offset >> 16][(offset & 0xFFFF) & 0xFFFF];
}

@Override
public int indexOf(byte[] bytes, int from) {
byte first = bytes[0];
outer:
for (int i = from; i < read; i++) {
if (getByte(i) == first) {
for (int j = 1; j < bytes.length; j++) {
if (getByte(i + j) != bytes[j])
continue outer;
}
return i;
}
}
return -1;
}

@Override
public BitStream shallowCopy(int offset) {
BitStreamBuffered stream = new BitStreamBuffered(this);
stream.offset = offset;
return stream;
}
}
Loading

0 comments on commit ba36e4e

Please sign in to comment.