package com.bytezone.diskbrowser; import java.util.Objects; import com.bytezone.common.Utility; class LZW1 extends LZW { public LZW1 (byte[] buffer) { bytes = Objects.requireNonNull (buffer); crc = Utility.getWord (buffer, 0); crcBase = 0; volume = buffer[2] & 0xFF; runLengthChar = (byte) (buffer[3] & 0xFF); int ptr = 4; while (ptr < buffer.length - 1) // what is in the last byte? { int rleLength = Utility.getWord (buffer, ptr); int lzwPerformed = buffer[ptr + 2] & 0xFF; ptr += 3; if (lzwPerformed != 0) { setBuffer (buffer, ptr); // prepare to read n-bit integers byte[] lzwBuffer = undoLZW (rleLength); if (rleLength == TRACK_LENGTH) // no run length encoding chunks.add (lzwBuffer); else chunks.add (undoRLE (lzwBuffer, 0, lzwBuffer.length)); ptr += bytesRead (); // since the setBuffer() } else { if (rleLength == TRACK_LENGTH) // no run length encoding { byte[] originalBuffer = new byte[TRACK_LENGTH]; System.arraycopy (buffer, ptr, originalBuffer, 0, originalBuffer.length); chunks.add (originalBuffer); } else chunks.add (undoRLE (buffer, ptr, rleLength)); ptr += rleLength; } } } protected byte[] undoLZW (int rleLength) { byte[] lzwBuffer = new byte[rleLength]; // must fill this array from input int ptr = 0; int nextEntry = 0x100; // always start with a fresh table String prev = ""; while (ptr < rleLength) { int codeWord = readInt (width (nextEntry + 1)); String s = (nextEntry == codeWord) ? prev + prev.charAt (0) : st[codeWord]; if (nextEntry < st.length) st[nextEntry++] = prev + s.charAt (0); for (int i = 0; i < s.length (); i++) lzwBuffer[ptr++] = (byte) s.charAt (i); prev = s; } return lzwBuffer; } @Override public String toString () { StringBuilder text = new StringBuilder (); text.append (String.format (" crc ............... %,d (%04X)%n", crc, crc)); text.append (String.format (" volume ............ %,d%n", volume)); text.append (String.format (" RLE char .......... $%02X", runLengthChar)); return text.toString (); } }