code: /* 
   * $Id: PDFStream.java,v 1.2 2007/08/26 18:56:35 gil1 Exp $
   *
   * $Date: 2007/08/26 18:56:35 $
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public 
   * License as published by the Free Software Foundation; either 
   * version 2.1 of the License, or (at your option) any later version. 
   * 
   * This library is distributed in the hope that it will be useful, 
   * but WITHOUT ANY WARRANTY; without even the implied warranty of 
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
   * Lesser General Public License for more details. 
   * 
   * You should have received a copy of the GNU Lesser General Public 
   * License along with this library; if not, write to the Free Software 
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
   */
  package pdf;
  
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.PrintWriter;
  import java.io.Serializable;
  import java.util.zip.DeflaterOutputStream;
  
  /**
   * This class implements a PDF stream object. In PDF, streams contain data
   * like the graphic operators that render a page, or the pixels of an image.
   *
   * <p>In PDF, a stream can be compressed using several different methods, or
   * left uncompressed. Here we support both uncompressed, and FlateDecode as
   * it's supported by the java core.
   *
   * @author Peter T Mount http://www.retep.org.uk/pdf/
   * @author Eric Z. Beard, ericzbeard@hotmail.com
   * @version $Revision: 1.2 $, $Date: 2007/08/26 18:56:35 $
   *
   */
  public class PDFStream extends PDFObject implements Serializable
  {
  
  
    /*
     * NOTE: The original class is the work of Peter T. Mount, who released it 
     * in the uk.org.retep.pdf package.  It was modified by Eric Z. Beard as 
     * follows: 
     * The package name was changed to gnu.jpdf.  
     * The formatting was changed a little bit.
     * It is still licensed under the LGPL.
     */
  
      /**
       * This holds the stream's content.
       */
      transient ByteArrayOutputStream buf;
      
      /**
       * True if we will compress the stream in the pdf file
       */
      boolean deflate;
      
      /**
       * Constructs a plain stream.
       * <p>By default, the stream will be compressed.
       */
      public PDFStream() {
          this(null);
      }
      
      /**
       * Constructs a stream. The supplied type is stored in the stream's header
       * and is used by other objects that extend the PDFStream class (like
       * PDFImage).
       * <p>By default, the stream will be compressed.
       * @param type type for the stream
       * @see PDFImage
       */
      public PDFStream(String type) {
          super(type);
          buf = new ByteArrayOutputStream();
          
          // default deflate mode
          deflate = false;
      }
      
      /**
       * @param mode true will FlatDecode the stream
       */
      public void setDeflate(boolean mode) {
      	// TODO: Restore the next line of code to allow deflate to occur.
          deflate = mode;
      }
      
      /**
       * Returs true if the stream will be compressed.
       * @return true if compression is enabled
       */
      public boolean getDeflate() {
          return deflate;
      }
      
      /**
       * Returns the OutputStream that will append to this stream.
       * @return The stream for this object
       */
      public OutputStream getOutputStream() {
          return (OutputStream)buf;
      }
      
      /**
       * Creates a PrintWriter that will append to this stream.
       * @return a PrintWriter to write to the stream
       */
      public PrintWriter getWriter() {
          return new PrintWriter(buf,true);
      }
      
      /**
       * This is for extenders, and provides access to the stream.
       * @return ByteArrayOutputStream containing the contents.
       */
      public ByteArrayOutputStream getStream() {
          return buf;
      }
      
      /**
       * @param os OutputStream to send the object to
       * @exception IOException on error
       */
      public void write(OutputStream os) throws IOException {
          writeStart(os);
          writeStream(os);
          // Unlike most PDF objects, we dont call writeEnd(os) because we
          // contain a stream
      }
      
      /**
       * This inserts the Streams length, then the actual stream, finally
       * the end of stream/object markers.
       *
       * <p>This is intended for anyone extending PDFStream, as objects
       * containing streams do no use writeEnd(), and they must be able
       * to write the actual stream.
       *
       * @param os OutputStream to send the object to
       * @exception IOException on error
       */
      public void writeStream(OutputStream os) throws IOException {
          if(deflate) {
              ByteArrayOutputStream b = new ByteArrayOutputStream();
              DeflaterOutputStream dos = new DeflaterOutputStream(b);
              //,new Deflater(Deflater.BEST_COMPRESSION,true));
              buf.writeTo(dos);
              dos.finish();
              dos.close();
              
              // FlatDecode is compatible with the java.util.zip.Deflater class
              os.write("/Filter /FlateDecode\n".getBytes());
              os.write("/Length ".getBytes());
              os.write(Integer.toString(b.size()+1).getBytes());
              os.write("\n>>\nstream\n".getBytes());
              b.writeTo(os);
              os.write("\n".getBytes());
          } else {
              // This is a non-deflated stream
              os.write("/Length ".getBytes());
              os.write(Integer.toString(buf.size()).getBytes());
              os.write("\n>>\nstream\n".getBytes());
              buf.writeTo(os);
          }
          
          os.write("endstream\nendobj\n".getBytes());
          
          // Unlike most PDF objects, we dont call writeEnd(os) because we
          // contain a stream
      }
  
  
  
    // Why is this here?  Did it have a specific purpose?
  
      
      /**
       * This implements our own special Serialization for this object.
       *
       * <p>Here we write the length of the stream's contents, then a byte
       * array of the contents. We have to do this, as ByteArrayOutputStream
       * is not serializable (hence the transient tag).
       *
       */
      private void writeObject(java.io.ObjectOutputStream out) throws IOException
      {
          out.writeInt(buf.size());
          out.write(buf.toByteArray());
      }
      
      /**
       * This implements our own special Serialization for this object
       *
       * <p>Here we read the length of the stream's contents, then a byte
       * array of the contents. Then we recreate a new ByteArrayOutputStream.
       * We have to do this, as ByteArrayOutputStream is not serializable
       * (hence the transient tag).
       *
       */
      private void readObject(java.io.ObjectInputStream in) throws IOException
      {
          int l = in.readInt();
          byte b[] = new byte[l];
          in.read(b,0,l);
          buf=new ByteArrayOutputStream(l);
          buf.write(b);
      }
      
  }
  