KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > pdfbox > filter > LZWFilter


1 /**
2  * Copyright (c) 2003-2005, www.pdfbox.org
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  * 3. Neither the name of pdfbox; nor the names of its
14  * contributors may be used to endorse or promote products derived from this
15  * software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * http://www.pdfbox.org
29  *
30  */

31 package org.pdfbox.filter;
32
33 import java.io.ByteArrayOutputStream JavaDoc;
34 import java.io.IOException JavaDoc;
35 import java.io.InputStream JavaDoc;
36 import java.io.OutputStream JavaDoc;
37 import java.io.PushbackInputStream JavaDoc;
38 import java.io.StreamCorruptedException JavaDoc;
39
40 import org.pdfbox.cos.COSDictionary;
41
42 import org.pdfbox.io.NBitInputStream;
43 import org.pdfbox.io.NBitOutputStream;
44
45 /**
46  * This is the used for the LZWDecode filter.
47  *
48  * @author <a HREF="mailto:ben@benlitchfield.com">Ben Litchfield</a>
49  * @version $Revision: 1.14 $
50  */

51 public class LZWFilter implements Filter
52 {
53
54     /**
55      * The LZW clear table code.
56      */

57     public static final long CLEAR_TABLE = 256;
58     /**
59      * The LZW end of data code.
60      */

61     public static final long EOD = 257;
62
63     /**
64      * This will decode some compressed data.
65      *
66      * @param compressedData The compressed byte stream.
67      * @param result The place to write the uncompressed byte stream.
68      * @param options The options to use to encode the data.
69      *
70      * @throws IOException If there is an error decompressing the stream.
71      */

72     public void decode( InputStream JavaDoc compressedData, OutputStream JavaDoc result, COSDictionary options ) throws IOException JavaDoc
73     {
74         //log.debug("decode( )");
75
NBitInputStream in = null;
76         in = new NBitInputStream( compressedData );
77         in.setBitsInChunk( 9 );
78         LZWDictionary dic = new LZWDictionary();
79         byte firstByte = 0;
80         long nextCommand = 0;
81         while( (nextCommand = in.read() ) != EOD )
82         {
83             // log.debug( "decode - nextCommand=" + nextCommand + ", bitsInChunk: " + in.getBitsInChunk());
84

85             if( nextCommand == CLEAR_TABLE )
86             {
87                 in.setBitsInChunk( 9 );
88                 dic = new LZWDictionary();
89             }
90             else
91             {
92                 byte[] data = dic.getData( nextCommand );
93                 if( data == null )
94                 {
95                     dic.visit( firstByte );
96                     data = dic.getData( nextCommand );
97                     dic.clear();
98                 }
99                 if( data == null )
100                 {
101                     throw new StreamCorruptedException JavaDoc( "Error: data is null" );
102                 }
103                 dic.visit(data);
104
105                 //log.debug( "decode - dic.getNextCode(): " + dic.getNextCode());
106

107                 if( dic.getNextCode() >= 2047 )
108                 {
109                     in.setBitsInChunk( 12 );
110                 }
111                 else if( dic.getNextCode() >= 1023 )
112                 {
113                     in.setBitsInChunk( 11 );
114                 }
115                 else if( dic.getNextCode() >= 511 )
116                 {
117                     in.setBitsInChunk( 10 );
118                 }
119                 else
120                 {
121                     in.setBitsInChunk( 9 );
122                 }
123                 /**
124                 if( in.getBitsInChunk() != dic.getCodeSize() )
125                 {
126                     in.unread( nextCommand );
127                     in.setBitsInChunk( dic.getCodeSize() );
128                     System.out.print( "Switching " + nextCommand + " to " );
129                     nextCommand = in.read();
130                     System.out.println( "" + nextCommand );
131                     data = dic.getData( nextCommand );
132                 }**/

133                 firstByte = data[0];
134                 result.write( data );
135             }
136         }
137         result.flush();
138     }
139
140
141     /**
142      * This will encode some data.
143      *
144      * @param rawData The raw data to encode.
145      * @param result The place to write to encoded results to.
146      * @param options The options to use to encode the data.
147      *
148      * @throws IOException If there is an error compressing the stream.
149      */

150     public void encode( InputStream JavaDoc rawData, OutputStream JavaDoc result, COSDictionary options ) throws IOException JavaDoc
151     {
152         //log.debug("encode( )");
153
PushbackInputStream JavaDoc input = new PushbackInputStream JavaDoc( rawData, 4096 );
154         LZWDictionary dic = new LZWDictionary();
155         NBitOutputStream out = new NBitOutputStream( result );
156         out.setBitsInChunk( 9 ); //initially nine
157
out.write( CLEAR_TABLE );
158         ByteArrayOutputStream JavaDoc buffer = new ByteArrayOutputStream JavaDoc();
159         int byteRead = 0;
160         for( int i=0; (byteRead = input.read()) != -1; i++ )
161         {
162             //log.debug( "byteRead = '" + (char)byteRead + "' (0x" + Integer.toHexString(byteRead) + "), i=" + i);
163
buffer.write( byteRead );
164             dic.visit( (byte)byteRead );
165             out.setBitsInChunk( dic.getCodeSize() );
166
167             //log.debug( "Getting node '" + new String( buffer.toByteArray() ) + "', buffer.size = " + buffer.size() );
168
LZWNode node = dic.getNode( buffer.toByteArray() );
169             int nextByte = input.read();
170             if( nextByte != -1 )
171             {
172                 //log.debug( "nextByte = '" + (char)nextByte + "' (0x" + Integer.toHexString(nextByte) + ")");
173
LZWNode next = node.getNode( (byte)nextByte );
174                 if( next == null )
175                 {
176                     //log.debug("encode - No next node, writing node and resetting buffer (" +
177
// " node.getCode: " + node.getCode() + ")" +
178
// " bitsInChunk: " + out.getBitsInChunk() +
179
// ")");
180
out.write( node.getCode() );
181                     buffer.reset();
182                 }
183
184                 input.unread( nextByte );
185             }
186             else
187             {
188                 //log.debug("encode - EOF on lookahead: writing node, resetting buffer, and terminating read loop (" +
189
// " node.getCode: " + node.getCode() + ")" +
190
// " bitsInChunk: " + out.getBitsInChunk() +
191
// ")");
192
out.write( node.getCode() );
193                 buffer.reset();
194                 break;
195             }
196
197             if( dic.getNextCode() == 4096 )
198             {
199                 //log.debug("encode - Clearing dictionary and unreading pending buffer data (" +
200
// " bitsInChunk: " + out.getBitsInChunk() +
201
// ")");
202
out.write( CLEAR_TABLE );
203                 dic = new LZWDictionary();
204                 input.unread( buffer.toByteArray() );
205                 buffer.reset();
206             }
207         }
208
209         // Fix the code size based on the fact that we are writing the EOD
210
//
211
if( dic.getNextCode() >= 2047 )
212         {
213             out.setBitsInChunk( 12 );
214         }
215         else if( dic.getNextCode() >= 1023 )
216         {
217             out.setBitsInChunk( 11 );
218         }
219         else if( dic.getNextCode() >= 511 )
220         {
221             out.setBitsInChunk( 10 );
222         }
223         else
224         {
225             out.setBitsInChunk( 9 );
226         }
227
228         //log.debug("encode - Writing EOD (" +
229
// " bitsInChunk: " + out.getBitsInChunk() +
230
// ")");
231
out.write( EOD );
232         out.close();
233         result.flush();
234     }
235 }
Popular Tags