internal static void EncodeBinary(IDataCoder coder, byte[] ctx, int bits, int x, int offset = 0) { // Require 2^bits-1 contexts int n = 1; int m = (1 << bits); while (n < m) { x = (x & (m - 1)) << 1; int b = (x >> bits); coder.Encoder(b, ref ctx[n - 1 + offset]); n = (n << 1) | b; } }
internal static void EncodeRaw(IDataCoder coder, int bits, int x) { int n = 1; int count = 0; int m = (1 << bits); while (n < m) { x = (x & (m - 1)) << 1; int b = (x >> bits); coder.Encoder(b); n = (n << 1) | b; count++; } }
/// <summary> /// Encodes a sequence of buckets in a given block. /// </summary> /// <param name="zp"></param> /// <param name="bit"></param> /// <param name="band"></param> /// <param name="blk"></param> /// <param name="eblk"></param> /// <param name="fbucket"></param> /// <param name="nbucket"></param> public void EncodeBuckets(IDataCoder zp, int bit, int band, InterWaveBlock blk, InterWaveBlock eblk, int fbucket, int nbucket) { // compute state of all coefficients in all buckets int bbstate = EncodePrepare(band, fbucket, nbucket, blk, eblk); // code root bit if ((nbucket < 16) || (bbstate & Active) != 0) { bbstate |= New; } else if ((bbstate & Unk) != 0) { zp.Encoder((bbstate & New) != 0 ? 1 : 0, ref _CtxRoot); } // code bucket bits if ((bbstate & New) != 0) { for (int buckno = 0; buckno < nbucket; buckno++) { // Code bucket bit if ((_BucketState[buckno] & Unk) != 0) { // Context int ctx = 0; if (band > 0) { int k = (fbucket + buckno) << 2; short[] b = eblk.GetBlock(k >> 4); if (b != null) { k = k & 0xf; if (b[k] != 0) { ctx += 1; } if (b[k + 1] != 0) { ctx += 1; } if (b[k + 2] != 0) { ctx += 1; } if (ctx < 3 && b[k + 3] != 0) { ctx += 1; } } } if ((bbstate & Active) != 0) { ctx |= 4; } // Code zp.Encoder((_BucketState[buckno] & New) != 0 ? 1 : 0, ref _CtxBucket[band][ctx]); } } } // code new active coefficient (with their sign) if ((bbstate & New) != 0) { int thres = _QuantHigh[band]; sbyte[] cstate = _CoefficientState; for (int buckno = 0, cidx = 0; buckno < nbucket; buckno++, cidx += 16) { if ((_BucketState[buckno] & New) != 0) { int i; int gotcha = 0; const int maxgotcha = 7; for (i = 0; i < 16; i++) { if ((cstate[i + cidx] & Unk) != 0) { gotcha += 1; } } short[] pcoeff = blk.GetBlock(fbucket + buckno); short[] epcoeff = eblk.GetInitializedBlock(fbucket + buckno); // iterate within bucket for (i = 0; i < 16; i++) { if ((cstate[i] & Unk) != 0) { // Prepare context int ctx = 0; if (gotcha >= maxgotcha) { ctx = maxgotcha; } else { ctx = gotcha; } if ((_BucketState[buckno] & Active) != 0) { ctx |= 8; } // Code zp.Encoder((cstate[i] & New) != 0 ? 1 : 0, ref _CtxStart[ctx]); if ((cstate[i] & New) != 0) { // Code sign zp.IWEncoder((pcoeff[i] < 0) ? true : false); // Set encoder state if (band == 0) { thres = _QuantLow[i]; } epcoeff[i] = (short)(thres + (thres >> 1)); } if ((cstate[i] & New) != 0) { gotcha = 0; } else if (gotcha > 0) { gotcha -= 1; } } } } } } // code mantissa bits if ((bbstate & Active) != 0) { int thres = _QuantHigh[band]; sbyte[] cstate = _CoefficientState; for (int buckno = 0, cidx = 0; buckno < nbucket; buckno++, cidx += 16) { if ((_BucketState[buckno] & Active) != 0) { short[] pcoeff = blk.GetBlock(fbucket + buckno); short[] epcoeff = eblk.GetInitializedBlock(fbucket + buckno); for (int i = 0; i < 16; i++) { if ((cstate[i] & Active) != 0) { // get coefficient int coeff = pcoeff[i]; int ecoeff = epcoeff[i]; if (coeff < 0) { coeff = -coeff; } // get band zero thresholds if (band == 0) { thres = _QuantLow[i]; } // compute mantissa bit int pix = 0; if (coeff >= ecoeff) { pix = 1; } // encode second or lesser mantissa bit if (ecoeff <= 3 * thres) { zp.Encoder(pix, ref _CtxMant); } else { zp.IWEncoder(!!(pix != 0)); } // adjust epcoeff epcoeff[i] = (short)(ecoeff - (pix != 0 ? 0 : thres) + (thres >> 1)); } } } } } }