⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deflaterhuffman.cs

📁 Fireball.CodeEditor is an source code editor control derived from the best compona SyntaxBox Control
💻 CS
📖 第 1 页 / 共 3 页
字号:
            /* Literal codes */
            staticLCodes = new short[LITERAL_NUM];
            staticLLength = new byte[LITERAL_NUM];
            int i = 0;
            while (i < 144)
            {
                staticLCodes[i] = BitReverse((0x030 + i) << 8);
                staticLLength[i++] = 8;
            }
            while (i < 256)
            {
                staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
                staticLLength[i++] = 9;
            }
            while (i < 280)
            {
                staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
                staticLLength[i++] = 7;
            }
            while (i < LITERAL_NUM)
            {
                staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
                staticLLength[i++] = 8;
            }

            /* Distant codes */
            staticDCodes = new short[DIST_NUM];
            staticDLength = new byte[DIST_NUM];
            for (i = 0; i < DIST_NUM; i++)
            {
                staticDCodes[i] = BitReverse(i << 11);
                staticDLength[i] = 5;
            }
        }

        /// <summary>
        /// Construct instance with pending buffer
        /// </summary>
        /// <param name="pending">Pending buffer to use</param>
        public DeflaterHuffman(DeflaterPending pending)
        {
            this.pending = pending;

            literalTree = new Tree(this, LITERAL_NUM, 257, 15);
            distTree = new Tree(this, DIST_NUM, 1, 15);
            blTree = new Tree(this, BITLEN_NUM, 4, 7);

            d_buf = new short[BUFSIZE];
            l_buf = new byte[BUFSIZE];
        }

        /// <summary>
        /// Reset internal state
        /// </summary>		
        public void Reset()
        {
            last_lit = 0;
            extra_bits = 0;
            literalTree.Reset();
            distTree.Reset();
            blTree.Reset();
        }

        int Lcode(int len)
        {
            if (len == 255)
            {
                return 285;
            }

            int code = 257;
            while (len >= 8)
            {
                code += 4;
                len >>= 1;
            }
            return code + len;
        }

        int Dcode(int distance)
        {
            int code = 0;
            while (distance >= 4)
            {
                code += 2;
                distance >>= 1;
            }
            return code + distance;
        }

        /// <summary>
        /// Write all trees to pending buffer
        /// </summary>		
        public void SendAllTrees(int blTreeCodes)
        {
            blTree.BuildCodes();
            literalTree.BuildCodes();
            distTree.BuildCodes();
            pending.WriteBits(literalTree.numCodes - 257, 5);
            pending.WriteBits(distTree.numCodes - 1, 5);
            pending.WriteBits(blTreeCodes - 4, 4);
            for (int rank = 0; rank < blTreeCodes; rank++)
            {
                pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
            }
            literalTree.WriteTree(blTree);
            distTree.WriteTree(blTree);
            //			if (DeflaterConstants.DEBUGGING) {
            //				blTree.CheckEmpty();
            //			}
        }

        /// <summary>
        /// Compress current buffer writing data to pending buffer
        /// </summary>
        public void CompressBlock()
        {
            for (int i = 0; i < last_lit; i++)
            {
                int litlen = l_buf[i] & 0xff;
                int dist = d_buf[i];
                if (dist-- != 0)
                {
                    //					if (DeflaterConstants.DEBUGGING) {
                    //						Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
                    //					}

                    int lc = Lcode(litlen);
                    literalTree.WriteSymbol(lc);

                    int bits = (lc - 261) / 4;
                    if (bits > 0 && bits <= 5)
                    {
                        pending.WriteBits(litlen & ((1 << bits) - 1), bits);
                    }

                    int dc = Dcode(dist);
                    distTree.WriteSymbol(dc);

                    bits = dc / 2 - 1;
                    if (bits > 0)
                    {
                        pending.WriteBits(dist & ((1 << bits) - 1), bits);
                    }
                }
                else
                {
                    //					if (DeflaterConstants.DEBUGGING) {
                    //						if (litlen > 32 && litlen < 127) {
                    //							Console.Write("("+(char)litlen+"): ");
                    //						} else {
                    //							Console.Write("{"+litlen+"}: ");
                    //						}
                    //					}
                    literalTree.WriteSymbol(litlen);
                }
            }
            //			if (DeflaterConstants.DEBUGGING) {
            //				Console.Write("EOF: ");
            //			}
            literalTree.WriteSymbol(EOF_SYMBOL);
            //			if (DeflaterConstants.DEBUGGING) {
            //				literalTree.CheckEmpty();
            //				distTree.CheckEmpty();
            //			}
        }

        /// <summary>
        /// Flush block to output with no compression
        /// </summary>
        /// <param name="stored">Data to write</param>
        /// <param name="storedOffset">Index of first byte to write</param>
        /// <param name="storedLength">Count of bytes to write</param>
        /// <param name="lastBlock">True if this is the last block</param>
        public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
        {
            //			if (DeflaterConstants.DEBUGGING) {
            //				//Console.WriteLine("Flushing stored block "+ storedLength);
            //			}
            pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
            pending.AlignToByte();
            pending.WriteShort(storedLength);
            pending.WriteShort(~storedLength);
            pending.WriteBlock(stored, storedOffset, storedLength);
            Reset();
        }

        /// <summary>
        /// Flush block to output with compression
        /// </summary>		
        /// <param name="stored">Data to flush</param>
        /// <param name="storedOffset">Index of first byte to flush</param>
        /// <param name="storedLength">Count of bytes to flush</param>
        /// <param name="lastBlock">True if this is the last block</param>
        public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
        {
            literalTree.freqs[EOF_SYMBOL]++;

            /* Build trees */
            literalTree.BuildTree();
            distTree.BuildTree();

            /* Calculate bitlen frequency */
            literalTree.CalcBLFreq(blTree);
            distTree.CalcBLFreq(blTree);

            /* Build bitlen tree */
            blTree.BuildTree();

            int blTreeCodes = 4;
            for (int i = 18; i > blTreeCodes; i--)
            {
                if (blTree.length[BL_ORDER[i]] > 0)
                {
                    blTreeCodes = i + 1;
                }
            }
            int opt_len = 14 + blTreeCodes * 3 + blTree.GetEncodedLength() +
                literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
                extra_bits;

            int static_len = extra_bits;
            for (int i = 0; i < LITERAL_NUM; i++)
            {
                static_len += literalTree.freqs[i] * staticLLength[i];
            }
            for (int i = 0; i < DIST_NUM; i++)
            {
                static_len += distTree.freqs[i] * staticDLength[i];
            }
            if (opt_len >= static_len)
            {
                /* Force static trees */
                opt_len = static_len;
            }

            if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3)
            {
                /* Store Block */
                //				if (DeflaterConstants.DEBUGGING) {
                //					//Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
                //					                  + " <= " + static_len);
                //				}
                FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
            }
            else if (opt_len == static_len)
            {
                /* Encode with static tree */
                pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
                literalTree.SetStaticCodes(staticLCodes, staticLLength);
                distTree.SetStaticCodes(staticDCodes, staticDLength);
                CompressBlock();
                Reset();
            }
            else
            {
                /* Encode with dynamic tree */
                pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
                SendAllTrees(blTreeCodes);
                CompressBlock();
                Reset();
            }
        }

        /// <summary>
        /// Get value indicating if internal buffer is full
        /// </summary>
        /// <returns>true if buffer is full</returns>
        public bool IsFull()
        {
            return last_lit >= BUFSIZE;
        }

        /// <summary>
        /// Add literal to buffer
        /// </summary>
        /// <param name="lit"></param>
        /// <returns>Value indicating internal buffer is full</returns>
        public bool TallyLit(int lit)
        {
            //			if (DeflaterConstants.DEBUGGING) {
            //				if (lit > 32 && lit < 127) {
            //					//Console.WriteLine("("+(char)lit+")");
            //				} else {
            //					//Console.WriteLine("{"+lit+"}");
            //				}
            //			}
            d_buf[last_lit] = 0;
            l_buf[last_lit++] = (byte)lit;
            literalTree.freqs[lit]++;
            return IsFull();
        }

        /// <summary>
        /// Add distance code and length to literal and distance trees
        /// </summary>
        /// <param name="dist">Distance code</param>
        /// <param name="len">Length</param>
        /// <returns>Value indicating if internal buffer is full</returns>
        public bool TallyDist(int dist, int len)
        {
            //			if (DeflaterConstants.DEBUGGING) {
            //				//Console.WriteLine("["+dist+","+len+"]");
            //			}

            d_buf[last_lit] = (short)dist;
            l_buf[last_lit++] = (byte)(len - 3);

            int lc = Lcode(len - 3);
            literalTree.freqs[lc]++;
            if (lc >= 265 && lc < 285)
            {
                extra_bits += (lc - 261) / 4;
            }

            int dc = Dcode(dist - 1);
            distTree.freqs[dc]++;
            if (dc >= 4)
            {
                extra_bits += dc / 2 - 1;
            }
            return IsFull();
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -