class PRStream extends PdfStream {

    protected PdfReader reader;
    protected int offset;
    protected int length;

    //added by ujihara for decryption
    protected int objNum = 0;
    protected int objGen = 0;

    public PRStream(PRStream stream, PdfDictionary newDic) {
        reader = stream.reader;
        offset = stream.offset;
        length = stream.length;
        compressed = stream.compressed;
        compressionLevel = stream.compressionLevel;
        streamBytes = stream.streamBytes;
        bytes = stream.bytes;
        objNum = stream.objNum;
        objGen = stream.objGen;
        if (newDic != null) {
            putAll(newDic);
        } else {
            hashMap.putAll(stream.hashMap);
        }
    }

    public PRStream(PRStream stream, PdfDictionary newDic, PdfReader reader) {
        this(stream, newDic);
        this.reader = reader;
    }

    public PRStream(PdfReader reader, int offset) {
        this.reader = reader;
        this.offset = offset;
    }

    public PRStream(PdfReader reader, byte[] conts) {
        this(reader, conts, DEFAULT_COMPRESSION);
    }

    /**
     * Creates a new PDF stream object that will replace a stream in a existing PDF file.
     *
     * @param reader           the reader that holds the existing PDF
     * @param conts            the new content
     * @param compressionLevel the compression level for the content
     * @since 2.1.3 (replacing the existing constructor without param compressionLevel)
     */
    public PRStream(PdfReader reader, byte[] conts, int compressionLevel) {
        this.reader = reader;
        this.offset = -1;
        if (Document.compress) {
            try {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                Deflater deflater = new Deflater(compressionLevel);
                DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
                zip.write(conts);
                zip.close();
                deflater.end();
                bytes = stream.toByteArray();
            } catch (IOException ioe) {
                throw new ExceptionConverter(ioe);
            }
            put(PdfName.FILTER, PdfName.FLATEDECODE);
        } else {
            bytes = conts;
        }
        setLength(bytes.length);
    }

    /**
     * Sets the data associated with the stream, either compressed or uncompressed. Note that the data will never be
     * compressed if Document.compress is set to false.
     *
     * @param data     raw data, decrypted and uncompressed.
     * @param compress true if you want the stream to be compressed.
     * @since iText 2.1.1
     */
    public void setData(byte[] data, boolean compress) {
        setData(data, compress, DEFAULT_COMPRESSION);
    }

    /**
     * Sets the data associated with the stream, either compressed or uncompressed. Note that the data will never be
     * compressed if Document.compress is set to false.
     *
     * @param data             raw data, decrypted and uncompressed.
     * @param compress         true if you want the stream to be compressed.
     * @param compressionLevel a value between -1 and 9 (ignored if compress == false)
     * @since iText 2.1.3
     */
    public void setData(byte[] data, boolean compress, int compressionLevel) {<FILL_FUNCTION_BODY>}

    /**
     * Sets the data associated with the stream
     *
     * @param data raw data, decrypted and uncompressed.
     */
    public void setData(byte[] data) {
        setData(data, true);
    }

    public int getOffset() {
        return offset;
    }

    public int getLength() {
        return length;
    }

    public void setLength(int length) {
        this.length = length;
        put(PdfName.LENGTH, new PdfNumber(length));
    }

    public PdfReader getReader() {
        return reader;
    }

    public byte[] getBytes() {
        return bytes;
    }

    public void setObjNum(int objNum, int objGen) {
        this.objNum = objNum;
        this.objGen = objGen;
    }

    int getObjNum() {
        return objNum;
    }

    int getObjGen() {
        return objGen;
    }

    public void toPdf(PdfWriter writer, OutputStream os) throws IOException {
        byte[] b = PdfReader.getStreamBytesRaw(this);
        PdfEncryption crypto = null;
        if (writer != null) {
            crypto = writer.getEncryption();
        }
        PdfObject objLen = get(PdfName.LENGTH);
        int nn = b.length;
        if (crypto != null) {
            nn = crypto.calculateStreamSize(nn);
        }
        put(PdfName.LENGTH, new PdfNumber(nn));
        superToPdf(writer, os);
        put(PdfName.LENGTH, objLen);
        os.write(STARTSTREAM);
        if (length > 0) {
            if (crypto != null && !crypto.isEmbeddedFilesOnly()) {
                b = crypto.encryptByteArray(b);
            }
            os.write(b);
        }
        os.write(ENDSTREAM);
    }
}

        remove(PdfName.FILTER);
        this.offset = -1;
        if (Document.compress && compress) {
            try {
                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                Deflater deflater = new Deflater(compressionLevel);
                DeflaterOutputStream zip = new DeflaterOutputStream(stream, deflater);
                zip.write(data);
                zip.close();
                deflater.end();
                bytes = stream.toByteArray();
                this.compressionLevel = compressionLevel;
            } catch (IOException ioe) {
                throw new ExceptionConverter(ioe);
            }
            put(PdfName.FILTER, PdfName.FLATEDECODE);
        } else {
            bytes = data;
        }
        setLength(bytes.length);
    
<methods>public void <init>(byte[]) ,public void <init>(java.io.InputStream, com.lowagie.text.pdf.PdfWriter) ,public void flateCompress() ,public void flateCompress(int) ,public long getRawLength() ,public void toPdf(com.lowagie.text.pdf.PdfWriter, java.io.OutputStream) throws java.io.IOException,public java.lang.String toString() ,public void writeContent(java.io.OutputStream) throws java.io.IOException,public void writeLength() throws java.io.IOException<variables>public static final int BEST_COMPRESSION,public static final int BEST_SPEED,public static final int DEFAULT_COMPRESSION,static final byte[] ENDSTREAM,public static final int NO_COMPRESSION,static final int SIZESTREAM,static final byte[] STARTSTREAM,protected boolean compressed,protected int compressionLevel,protected java.io.InputStream inputStream,protected long inputStreamLength,protected long rawLength,protected com.lowagie.text.pdf.PdfIndirectReference ref,protected java.io.ByteArrayOutputStream streamBytes,protected com.lowagie.text.pdf.PdfWriter writer