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; } }
/// <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); }