/** * Utility method for decoding an LZW-compressed image strip. Adapted from the TIFF 6.0 * Specification: http://partners.adobe.com/asn/developer/pdfs/tn/TIFF6.pdf (page 61) Author: * Curtis Rueden (ctrueden at wisc.edu) */ public byte[] lzwUncompress(byte[] input) { if (input == null || input.length == 0) return input; byte[][] symbolTable = new byte[4096][1]; int bitsToRead = 9; int nextSymbol = 258; int code; int oldCode = -1; ByteVector out = new ByteVector(8192); BitBuffer bb = new BitBuffer(input); byte[] byteBuffer1 = new byte[16]; byte[] byteBuffer2 = new byte[16]; while (out.size() < byteCount) { code = bb.getBits(bitsToRead); if (code == EOI_CODE || code == -1) break; if (code == CLEAR_CODE) { // initialize symbol table for (int i = 0; i < 256; i++) symbolTable[i][0] = (byte) i; nextSymbol = 258; bitsToRead = 9; code = bb.getBits(bitsToRead); if (code == EOI_CODE || code == -1) break; out.add(symbolTable[code]); oldCode = code; } else { if (code < nextSymbol) { // code is in table out.add(symbolTable[code]); // add string to table ByteVector symbol = new ByteVector(byteBuffer1); symbol.add(symbolTable[oldCode]); symbol.add(symbolTable[code][0]); symbolTable[nextSymbol] = symbol.toByteArray(); // ** oldCode = code; nextSymbol++; } else { // out of table ByteVector symbol = new ByteVector(byteBuffer2); symbol.add(symbolTable[oldCode]); symbol.add(symbolTable[oldCode][0]); byte[] outString = symbol.toByteArray(); out.add(outString); symbolTable[nextSymbol] = outString; // ** oldCode = code; nextSymbol++; } if (nextSymbol == 511) { bitsToRead = 10; } if (nextSymbol == 1023) { bitsToRead = 11; } if (nextSymbol == 2047) { bitsToRead = 12; } } } return out.toByteArray(); }
/** Based on the Bio-Formats PackbitsCodec written by Melissa Linkert. */ public byte[] packBitsUncompress(byte[] input, int expected) { if (expected == 0) expected = Integer.MAX_VALUE; ByteVector output = new ByteVector(1024); int index = 0; while (output.size() < expected && index < input.length) { byte n = input[index++]; if (n >= 0) { // 0 <= n <= 127 byte[] b = new byte[n + 1]; for (int i = 0; i < n + 1; i++) b[i] = input[index++]; output.add(b); b = null; } else if (n != -128) { // -127 <= n <= -1 int len = -n + 1; byte inp = input[index++]; for (int i = 0; i < len; i++) output.add(inp); } } return output.toByteArray(); }