001: /*
002: * $Id: PDFStream.java,v 1.1.1.1 2001/10/29 19:51:08 ezb Exp $
003: *
004: * $Date: 2001/10/29 19:51:08 $
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package gnu.jpdf;
021:
022: import java.io.*;
023: import java.util.*;
024: import java.util.zip.*;
025:
026: /**
027: * This class implements a PDF stream object. In PDF, streams contain data
028: * like the graphic operators that render a page, or the pixels of an image.
029: *
030: * <p>In PDF, a stream can be compressed using several different methods, or
031: * left uncompressed. Here we support both uncompressed, and FlateDecode as
032: * it's supported by the java core.
033: *
034: * @author Peter T Mount http://www.retep.org.uk/pdf/
035: * @author Eric Z. Beard, ericzbeard@hotmail.com
036: * @author $Author: ezb $
037: * @version $Revision: 1.1.1.1 $, $Date: 2001/10/29 19:51:08 $
038: *
039: */
040: public class PDFStream extends PDFObject implements Serializable {
041:
042: /*
043: * NOTE: The original class is the work of Peter T. Mount, who released it
044: * in the uk.org.retep.pdf package. It was modified by Eric Z. Beard as
045: * follows:
046: * The package name was changed to gnu.jpdf.
047: * The formatting was changed a little bit.
048: * It is still licensed under the LGPL.
049: */
050:
051: /**
052: * This holds the stream's content.
053: */
054: transient ByteArrayOutputStream buf;
055:
056: /**
057: * True if we will compress the stream in the pdf file
058: */
059: boolean deflate;
060:
061: /**
062: * Constructs a plain stream.
063: * <p>By default, the stream will be compressed.
064: */
065: public PDFStream() {
066: this (null);
067: }
068:
069: /**
070: * Constructs a stream. The supplied type is stored in the stream's header
071: * and is used by other objects that extend the PDFStream class (like
072: * PDFImage).
073: * <p>By default, the stream will be compressed.
074: * @param type type for the stream
075: * @see PDFImage
076: */
077: public PDFStream(String type) {
078: super (type);
079: buf = new ByteArrayOutputStream();
080:
081: // default deflate mode
082: deflate = false;
083: }
084:
085: /**
086: * @param mode true will FlatDecode the stream
087: */
088: public void setDeflate(boolean mode) {
089: deflate = mode;
090: }
091:
092: /**
093: * Returs true if the stream will be compressed.
094: * @return true if compression is enabled
095: */
096: public boolean getDeflate() {
097: return deflate;
098: }
099:
100: /**
101: * Returns the OutputStream that will append to this stream.
102: * @return The stream for this object
103: */
104: public OutputStream getOutputStream() {
105: return (OutputStream) buf;
106: }
107:
108: /**
109: * Creates a PrintWriter that will append to this stream.
110: * @return a PrintWriter to write to the stream
111: */
112: public PrintWriter getWriter() {
113: return new PrintWriter(buf, true);
114: }
115:
116: /**
117: * This is for extenders, and provides access to the stream.
118: * @return ByteArrayOutputStream containing the contents.
119: */
120: public ByteArrayOutputStream getStream() {
121: return buf;
122: }
123:
124: /**
125: * @param os OutputStream to send the object to
126: * @exception IOException on error
127: */
128: public void write(OutputStream os) throws IOException {
129: writeStart(os);
130: writeStream(os);
131: // Unlike most PDF objects, we dont call writeEnd(os) because we
132: // contain a stream
133: }
134:
135: /**
136: * This inserts the Streams length, then the actual stream, finally
137: * the end of stream/object markers.
138: *
139: * <p>This is intended for anyone extending PDFStream, as objects
140: * containing streams do no use writeEnd(), and they must be able
141: * to write the actual stream.
142: *
143: * @param os OutputStream to send the object to
144: * @exception IOException on error
145: */
146: public void writeStream(OutputStream os) throws IOException {
147: if (deflate) {
148: ByteArrayOutputStream b = new ByteArrayOutputStream();
149: DeflaterOutputStream dos = new DeflaterOutputStream(b);
150: //,new Deflater(Deflater.BEST_COMPRESSION,true));
151: buf.writeTo(dos);
152: dos.finish();
153: dos.close();
154:
155: // FlatDecode is compatible with the java.util.zip.Deflater class
156: os.write("/Filter /FlateDecode\n".getBytes());
157: os.write("/Length ".getBytes());
158: os.write(Integer.toString(b.size() + 1).getBytes());
159: os.write("\n>>\nstream\n".getBytes());
160: b.writeTo(os);
161: os.write("\n".getBytes());
162: } else {
163: // This is a non-deflated stream
164: os.write("/Length ".getBytes());
165: os.write(Integer.toString(buf.size()).getBytes());
166: os.write("\n>>\nstream\n".getBytes());
167: buf.writeTo(os);
168: }
169:
170: os.write("endstream\nendobj\n".getBytes());
171:
172: // Unlike most PDF objects, we dont call writeEnd(os) because we
173: // contain a stream
174: }
175:
176: // Why is this here? Did it have a specific purpose?
177:
178: /**
179: * This implements our own special Serialization for this object.
180: *
181: * <p>Here we write the length of the stream's contents, then a byte
182: * array of the contents. We have to do this, as ByteArrayOutputStream
183: * is not serializable (hence the transient tag).
184: *
185: */
186: private void writeObject(java.io.ObjectOutputStream out)
187: throws IOException {
188: out.writeInt(buf.size());
189: out.write(buf.toByteArray());
190: }
191:
192: /**
193: * This implements our own special Serialization for this object
194: *
195: * <p>Here we read the length of the stream's contents, then a byte
196: * array of the contents. Then we recreate a new ByteArrayOutputStream.
197: * We have to do this, as ByteArrayOutputStream is not serializable
198: * (hence the transient tag).
199: *
200: */
201: private void readObject(java.io.ObjectInputStream in)
202: throws IOException {
203: int l = in.readInt();
204: byte b[] = new byte[l];
205: in.read(b, 0, l);
206: buf = new ByteArrayOutputStream(l);
207: buf.write(b);
208: }
209:
210: }
|