001/*
002 * Copyright 2003-2008 by Paulo Soares.
003 *
004 * This code was originally released in 2001 by SUN (see class
005 * com.sun.media.imageio.plugins.tiff.TIFFDirectory.java)
006 * using the BSD license in a specific wording. In a mail dating from
007 * January 23, 2008, Brian Burkhalter (@sun.com) gave us permission
008 * to use the code under the following version of the BSD license:
009 *
010 * Copyright (c) 2005 Sun Microsystems, Inc. All  Rights Reserved.
011 * 
012 * Redistribution and use in source and binary forms, with or without
013 * modification, are permitted provided that the following conditions
014 * are met: 
015 * 
016 * - Redistribution of source code must retain the above copyright 
017 *   notice, this  list of conditions and the following disclaimer.
018 * 
019 * - Redistribution in binary form must reproduce the above copyright
020 *   notice, this list of conditions and the following disclaimer in 
021 *   the documentation and/or other materials provided with the
022 *   distribution.
023 * 
024 * Neither the name of Sun Microsystems, Inc. or the names of 
025 * contributors may be used to endorse or promote products derived 
026 * from this software without specific prior written permission.
027 * 
028 * This software is provided "AS IS," without a warranty of any 
029 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 
030 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 
031 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
032 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 
033 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 
034 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
035 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 
036 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
037 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
038 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
039 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
040 * POSSIBILITY OF SUCH DAMAGES. 
041 * 
042 * You acknowledge that this software is not designed or intended for 
043 * use in the design, construction, operation or maintenance of any 
044 * nuclear facility. 
045 *
046 * $Revision: 4540 $
047 * $Date: 2010-07-13 05:57:54 -0700 (Tue, 13 Jul 2010) $
048 * $State: Exp $
049 */
050package com.itextpdf.text.pdf.codec;
051
052import java.io.IOException;
053import java.io.OutputStream;
054
055/**
056 * Came from GIFEncoder initially.
057 * Modified - to allow for output compressed data without the block counts
058 * which breakup the compressed data stream for GIF.
059 * @since 5.0.2
060 */
061public class BitFile
062{
063    OutputStream output_;
064    byte buffer_[];
065    int index_;
066    int bitsLeft_;      // bits left at current index that are avail.
067
068    /** note this also indicates gif format BITFile. **/
069    boolean blocks_ = false;
070
071    /**
072         * @param output destination for output data
073         * @param blocks GIF LZW requires block counts for output data
074         **/
075    public BitFile(OutputStream output, boolean blocks)
076    {
077        output_ = output;
078        blocks_ = blocks;
079        buffer_ = new byte[256];
080        index_ = 0;
081        bitsLeft_ =     8;
082    }
083
084    public void flush() throws IOException
085    {
086        int     numBytes = index_ +     (bitsLeft_ == 8 ? 0     : 1);
087        if (numBytes > 0)
088            {
089                if (blocks_)
090                    output_.write(numBytes);
091                output_.write(buffer_, 0, numBytes);
092                buffer_[0] = 0;
093                index_ = 0;
094                bitsLeft_ =     8;
095            }
096    }
097
098    public void writeBits(int bits,     int     numbits) throws IOException
099    {
100        int     bitsWritten     = 0;
101        int     numBytes = 255;         // gif block count
102        do
103            {
104                // This handles the GIF block count stuff
105                if ((index_     == 254 && bitsLeft_     == 0) || index_ > 254)
106                    {
107                        if (blocks_)
108                            output_.write(numBytes);
109
110                        output_.write(buffer_, 0, numBytes);
111
112                        buffer_[0] = 0;
113                        index_ = 0;
114                        bitsLeft_ =     8;
115                    }
116
117                if (numbits     <= bitsLeft_) // bits contents fit in current index byte
118                    {
119                        if (blocks_) // GIF
120                            {
121                                buffer_[index_] |= (bits & ((1 << numbits) - 1)) <<     (8 - bitsLeft_);
122                                bitsWritten     += numbits;
123                                bitsLeft_ -= numbits;
124                                numbits = 0;
125                            }
126                        else
127                            {
128                                buffer_[index_] |= (bits & ((1 << numbits) - 1)) <<     (bitsLeft_ - numbits);
129                                bitsWritten     += numbits;
130                                bitsLeft_ -= numbits;
131                                numbits = 0;
132
133                            }
134                    }
135                else    // bits overflow from current byte to next.
136                    {
137                        if (blocks_)    // GIF
138                            {
139                                // if bits  > space left in current byte then the lowest order bits
140                                // of code are taken and put in current byte and rest put in next.
141                                buffer_[index_] |= (bits & ((1 << bitsLeft_) - 1)) << (8 - bitsLeft_);
142                                bitsWritten     += bitsLeft_;
143                                bits >>= bitsLeft_;
144                                numbits -= bitsLeft_;
145                                buffer_[++index_] =     0;
146                                bitsLeft_ =     8;
147                            }
148                        else
149                            {
150                                // if bits  > space left in current byte then the highest order bits
151                                // of code are taken and put in current byte and rest put in next.
152                                // at highest order bit location !! 
153                                int topbits = (bits >>> (numbits - bitsLeft_)) & ((1 << bitsLeft_) - 1);
154                                buffer_[index_] |= topbits;
155                                numbits -= bitsLeft_;   // ok this many bits gone off the top
156                                bitsWritten     += bitsLeft_;
157                                buffer_[++index_] =     0;      // next index
158                                bitsLeft_ =     8;
159                            }
160                    }
161
162            } while     (numbits !=     0);
163    }
164}