@@ -54,9 +54,6 @@ public class LZWFilter extends Filter
5454 * The LZW end of data code.
5555 */
5656 public static final long EOD = 257 ;
57-
58- //BEWARE: codeTable must be local to each method, because there is only
59- // one instance of each filter
6057
6158 /**
6259 * {@inheritDoc}
@@ -73,11 +70,12 @@ public DecodeResult decode(InputStream encoded, OutputStream decoded,
7370
7471 private static void doLZWDecode (InputStream encoded , OutputStream decoded , boolean earlyChange ) throws IOException
7572 {
76- List <byte []> codeTable = new ArrayList <> ();
73+ List <byte []> codeTable = createCodeTable (); // includes CLEAR/EOD handling as needed
7774 int chunk = 9 ;
7875 final MemoryCacheImageInputStream in = new MemoryCacheImageInputStream (encoded );
76+
77+ byte [] prev = null ; // no previous string yet
7978 long nextCommand ;
80- long prevCommand = -1 ;
8179
8280 try
8381 {
@@ -87,60 +85,50 @@ private static void doLZWDecode(InputStream encoded, OutputStream decoded, boole
8785 {
8886 chunk = 9 ;
8987 codeTable = createCodeTable ();
90- prevCommand = -1 ;
88+ prev = null ;
89+ continue ;
9190 }
92- else
91+
92+ byte [] curr ;
93+
94+ if (nextCommand < codeTable .size ())
9395 {
94- if (nextCommand < codeTable .size ())
95- {
96- byte [] data = codeTable .get ((int ) nextCommand );
97- byte firstByte = data [0 ];
98- decoded .write (data );
99- if (prevCommand != -1 )
100- {
101- checkIndexBounds (codeTable , prevCommand , in );
102- data = codeTable .get ((int ) prevCommand );
103- byte [] newData = Arrays .copyOf (data , data .length + 1 );
104- newData [data .length ] = firstByte ;
105- codeTable .add (newData );
106- }
107- }
108- else
96+ // Normal case: code exists
97+ curr = codeTable .get ((int ) nextCommand );
98+ decoded .write (curr );
99+
100+ if (prev != null )
109101 {
110- checkIndexBounds (codeTable , prevCommand , in );
111- byte [] data = codeTable .get ((int ) prevCommand );
112- byte [] newData = Arrays .copyOf (data , data .length + 1 );
113- newData [data .length ] = data [0 ];
114- decoded .write (newData );
115- codeTable .add (newData );
102+ // Add prev + first(curr)
103+ byte [] entry = Arrays .copyOf (prev , prev .length + 1 );
104+ entry [prev .length ] = curr [0 ];
105+ codeTable .add (entry );
116106 }
117-
118- chunk = calculateChunk (codeTable .size (), earlyChange );
119- prevCommand = nextCommand ;
120107 }
108+ else if (nextCommand == codeTable .size () && prev != null )
109+ {
110+ // KwKwK case: code equals next available index
111+ curr = Arrays .copyOf (prev , prev .length + 1 );
112+ curr [prev .length ] = prev [0 ];
113+ decoded .write (curr );
114+ codeTable .add (curr );
115+ }
116+ else
117+ {
118+ // Corrupt stream (code out of range, or KwKwK without prev)
119+ throw new EOFException ("Invalid LZW code: " + nextCommand );
120+ }
121+
122+ prev = curr ; // move forward
123+ chunk = calculateChunk (codeTable .size (), earlyChange );
121124 }
122125 }
123126 catch (EOFException ex )
124127 {
125128 LOG .warn ("Premature EOF in LZW stream, EOD code missing" , ex );
126129 }
127- decoded .flush ();
128- }
129130
130- private static void checkIndexBounds (List <byte []> codeTable , long index , MemoryCacheImageInputStream in )
131- throws IOException
132- {
133- if (index < 0 )
134- {
135- throw new IOException ("negative array index: " + index + " near offset "
136- + in .getStreamPosition ());
137- }
138- if (index >= codeTable .size ())
139- {
140- throw new IOException ("array index overflow: " + index +
141- " >= " + codeTable .size () + " near offset "
142- + in .getStreamPosition ());
143- }
131+ decoded .flush ();
144132 }
145133
146134 /**
0 commit comments