예제 #1
0
        public void Encode()
        {
            int markerpos = _Size - 1;

            BlockSort.BlockSortData(_Data, _Size, ref markerpos);

            // Encode Output Stream

            // Header
            EncodeRaw(Coder, 24, _Size);

            // Determine and Encode Estimation Speed
            int fshift = 0;

            if (_Size < FreqS0)
            {
                fshift = 0;
                Coder.Encoder(0);
            }
            else if (_Size < FreqS1)
            {
                fshift = 1;
                Coder.Encoder(1);
                Coder.Encoder(0);
            }
            else
            {
                fshift = 2;
                Coder.Encoder(1);
                Coder.Encoder(1);
            }
            // MTF
            byte[] mtf  = new byte[256];
            byte[] rmtf = new byte[256];
            uint[] freq = new uint[FreqMax];

            uint m = 0;

            for (m = 0; m < 256; m++)
            {
                mtf[m] = (byte)m;
            }

            for (m = 0; m < 256; m++)
            {
                rmtf[mtf[m]] = (byte)m;
            }

            int fadd = 4;

            // Encode
            int i;
            int mtfno = 3;

            for (i = 0; i < _Size; i++)
            {
                // Get MTF data
                int c     = _Data[i];
                int ctxid = CTXIDS - 1;

                if (ctxid > mtfno)
                {
                    ctxid = mtfno;
                }

                mtfno = rmtf[c];

                if (i == markerpos)
                {
                    mtfno = 256;
                }

                // Encode using ZPCoder
                int b;
                b = (mtfno == 0) ? 1 : 0;

                int cx = 0;

                Coder.Encoder(b, ref _Cxt[ctxid]);

                if (b != 0)
                {
                    goto rotate;
                }

                cx += CTXIDS;

                b = (mtfno == 1) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[ctxid + cx]);

                if (b != 0)
                {
                    goto rotate;
                }

                cx += CTXIDS;
                b   = (mtfno < 4) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 1, mtfno - 2, cx + 1);
                    goto rotate;
                }

                cx += 1 + 1;

                b = (mtfno < 8) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 2, mtfno - 4, cx + 1);
                    goto rotate;
                }

                cx += 1 + 3;
                b   = (mtfno < 16) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 3, mtfno - 8, cx + 1);
                    goto rotate;
                }

                cx += 1 + 7;
                b   = (mtfno < 32) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 4, mtfno - 16, cx + 1);
                    goto rotate;
                }

                cx += 1 + 15;
                b   = (mtfno < 64) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 5, mtfno - 32, cx + 1);
                    goto rotate;
                }

                cx += 1 + 31;
                b   = (mtfno < 128) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 6, mtfno - 64, cx + 1);
                    goto rotate;
                }

                cx += 1 + 63;
                b   = (mtfno < 256) ? 1 : 0;

                Coder.Encoder(b, ref _Cxt[cx]);

                if (b != 0)
                {
                    EncodeBinary(Coder, _Cxt, 7, mtfno - 128, cx + 1);
                    goto rotate;
                }

                continue;

                // Rotate MTF according to empirical frequencies (new!)
rotate:
                // Adjust frequencies for overflow
                fadd = fadd + (fadd >> fshift);
                if (fadd > 0x10000000)
                {
                    fadd      = fadd >> 24;
                    freq[0] >>= 24;
                    freq[1] >>= 24;
                    freq[2] >>= 24;
                    freq[3] >>= 24;
                    for (int kk = 4; kk < FreqMax; kk++)
                    {
                        freq[kk] >>= 24;
                    }
                }
                // Relocate new char according to new freq
                uint fc = (uint)fadd;

                if (mtfno < FreqMax)
                {
                    fc += freq[mtfno];
                }

                int k;
                for (k = mtfno; k >= FreqMax; k--)
                {
                    mtf[k]       = mtf[k - 1];
                    rmtf[mtf[k]] = (byte)k;
                }

                for (; k > 0 && fc >= freq[k - 1]; k--)
                {
                    mtf[k]       = mtf[k - 1];
                    freq[k]      = freq[k - 1];
                    rmtf[mtf[k]] = (byte)k;
                }

                mtf[k]       = (byte)c;
                freq[k]      = fc;
                rmtf[mtf[k]] = (byte)k;
            }
        }
예제 #2
0
파일: BlockSort.cs 프로젝트: sahwar/DjvuNet
        /// <summary>
        /// Main entry point for Block Sort sorting used in bzz compression
        /// </summary>
        /// <param name="data"></param>
        /// <param name="size"></param>
        /// <param name="markerpos"></param>
        public static void BlockSortData(byte[] data, int size, ref int markerpos)
        {
            BlockSort bsort = new BlockSort(data, size);

            bsort.Sort(ref markerpos);
        }