/// <summary> /// Finishes slice encoding and advances to next slice. /// </summary> /// <param name="zp"></param> /// <returns></returns> public int FinishCodeSlice(IDataCoder zp) { // Reduce quantization threshold _QuantHigh[_CurrentBand] = _QuantHigh[_CurrentBand] >> 1; if (_CurrentBand == 0) { for (int i = 0; i < 16; i++) { _QuantLow[i] = _QuantLow[i] >> 1; } } // Proceed to the next slice if (++_CurrentBand >= _BandBuckets.Length) { _CurrentBand = 0; _CurrentBitPlane += 1; if (_QuantHigh[_BandBuckets.Length - 1] == 0) { _CurrentBitPlane = -1; return(0); } } return(1); }
public int CodeSlice(IDataCoder coder) { if (_CurrentBitPlane >= 0) { if (!IsNullSlice(_CurrentBitPlane, _CurrentBand)) { for (int blockno = 0; blockno < _Map.BlockNumber; blockno++) { int fbucket = _BandBuckets[_CurrentBand].Start; int nbucket = _BandBuckets[_CurrentBand].Size; DecodeBuckets(coder, _CurrentBitPlane, _CurrentBand, _Map.Blocks[blockno], fbucket, nbucket); } } if (++_CurrentBand >= _BandBuckets.Length) { _CurrentBand = 0; _CurrentBitPlane++; if (NextQuant() == 0) { _CurrentBitPlane = -1; return(0); } } return(1); } return(0); }
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 Map slices. /// </summary> /// <param name="zp"></param> /// <returns></returns> public int CodeSlice(IDataCoder zp) { // Check that code_slice can still run if (_CurrentBitPlane < 0) { return(0); } // Perform coding if (!IsNullSlice(_CurrentBitPlane, _CurrentBand)) { for (int blockno = 0; blockno < _Map.BlockNumber; blockno++) { int fbucket = _BandBuckets[_CurrentBand].Start; int nbucket = _BandBuckets[_CurrentBand].Size; EncodeBuckets(zp, _CurrentBitPlane, _CurrentBand, _Map.Blocks[blockno], _EMap.Blocks[blockno], fbucket, nbucket); } } return(FinishCodeSlice(zp)); }
/// <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)); } } } } } }
public void DecodeBuckets(IDataCoder coder, int bit, int band, InterWaveBlock blk, int fbucket, int nbucket) { int thres = _QuantHigh[band]; int bbstate = 0; sbyte[] cstate = _CoefficientState; int cidx = 0; for (int buckno = 0; buckno < nbucket; buckno++, cidx += 16) { int bstatetmp = 0; short[] pcoeff = blk.GetBlock(fbucket + buckno); if (pcoeff == null) { bstatetmp = 8; } else { for (int i = 0; i < 16; i++) { int cstatetmp = cstate[cidx + i] & 1; if (cstatetmp == 0) { if (pcoeff[i] != 0) { cstatetmp |= 2; } else { cstatetmp |= 8; } } cstate[cidx + i] = (sbyte)cstatetmp; bstatetmp |= cstatetmp; } } _BucketState[buckno] = (sbyte)bstatetmp; bbstate |= bstatetmp; } if (nbucket < 16 || (bbstate & 2) != 0) { bbstate |= 4; } else if ((bbstate & 8) != 0) { if (coder.Decoder(ref _CtxRoot) != 0) { bbstate |= 4; } } if ((bbstate & 4) != 0) { for (int buckno = 0; buckno < nbucket; buckno++) { if ((_BucketState[buckno] & 8) != 0) { int ctx = 0; //if (!DjVuOptions.NOCTX_BUCKET_UPPER && (band > 0)) if ((band > 0)) { int k = (fbucket + buckno) << 2; short[] b = blk.GetBlock(k >> 4); if (b != null) { k &= 0xf; if (b[k] != 0) { ctx++; } if (b[k + 1] != 0) { ctx++; } if (b[k + 2] != 0) { ctx++; } if ((ctx < 3) && (b[k + 3] != 0)) { ctx++; } } } //if (!DjVuOptions.NOCTX_BUCKET_ACTIVE && ((bbstate & 2) != 0)) if ((bbstate & 2) != 0) { ctx |= 4; } if (coder.Decoder(ref _CtxBucket[band][ctx]) != 0) { _BucketState[buckno] |= 4; } } } } if ((bbstate & 4) != 0) { cstate = _CoefficientState; cidx = 0; for (int buckno = 0; buckno < nbucket; buckno++, cidx += 16) { if ((_BucketState[buckno] & 4) != 0) { short[] pcoeff = blk.GetBlock(fbucket + buckno); if (pcoeff == null) { pcoeff = blk.GetInitializedBlock(fbucket + buckno); for (int i = 0; i < 16; i++) { if ((cstate[cidx + i] & 1) == 0) { cstate[cidx + i] = 8; } } } int gotcha = 0; int maxgotcha = 7; //if (!DjVuOptions.NOCTX_EXPECT) { for (int i = 0; i < 16; i++) { if ((cstate[cidx + i] & 8) != 0) { gotcha++; } } } for (int i = 0; i < 16; i++) { if ((cstate[cidx + i] & 8) != 0) { if (band == 0) { thres = _QuantLow[i]; } int ctx = 0; //if (!DjVuOptions.NOCTX_EXPECT) { if (gotcha >= maxgotcha) { ctx = maxgotcha; } else { ctx = gotcha; } } //if (!DjVuOptions.NOCTX_ACTIVE && ((bucketstate[buckno] & 2) != 0)) if (((_BucketState[buckno] & 2) != 0)) { ctx |= 8; } if (coder.Decoder(ref _CtxStart[ctx]) != 0) { cstate[cidx + i] |= 4; int halfthres = thres >> 1; int coeff = (thres + halfthres) - (halfthres >> 2); if (coder.IWDecoder() != 0) { pcoeff[i] = (short)(-coeff); } else { pcoeff[i] = (short)coeff; } } //if (!DjVuOptions.NOCTX_EXPECT) { if ((cstate[cidx + i] & 4) != 0) { gotcha = 0; } else if (gotcha > 0) { gotcha--; } } } } } } } if ((bbstate & 2) != 0) { cstate = _CoefficientState; cidx = 0; for (int buckno = 0; buckno < nbucket; buckno++, cidx += 16) { if ((_BucketState[buckno] & 2) != 0) { short[] pcoeff = blk.GetBlock(fbucket + buckno); for (int i = 0; i < 16; i++) { if ((cstate[cidx + i] & 2) != 0) { int coeff = pcoeff[i]; if (coeff < 0) { coeff = -coeff; } if (band == 0) { thres = _QuantLow[i]; } if (coeff <= (3 * thres)) { coeff += (thres >> 2); if (coder.Decoder(ref _CtxMant) != 0) { coeff += (thres >> 1); } else { coeff = (coeff - thres) + (thres >> 1); } } else { if (coder.IWDecoder() != 0) { coeff += (thres >> 1); } else { coeff = (coeff - thres) + (thres >> 1); } } if (pcoeff[i] > 0) { pcoeff[i] = (short)coeff; } else { pcoeff[i] = (short)(-coeff); } } } // end for (int i = 0 ... } } // end for (int buckno = 0 .... } }
public void Decode(IBinaryReader reader) { if (_YDecoder == null) { _CSlices = _CSerial = 0; _YMap = null; } byte serial = reader.ReadByte(); byte slices = reader.ReadByte(); if (serial != _CSerial) { throw new DjvuFormatException( $"{nameof(IInterWavePixelMap)} received out of order data. Expected serial number {_CSerial}, actual {serial}"); } int nslices = _CSlices + slices; if (_CSerial == 0) { int major = reader.ReadByte(); int minor = reader.ReadByte(); if ((major & 0x7f) != InterWaveCodec.MajorVersion) { throw new DjvuFormatException("File has been compressed with an incompatible codec"); } if (minor > InterWaveCodec.MinorVersion) { throw new DjvuFormatException("File has been compressed with a more recent codec"); } int w = (reader.ReadByte() << 8); w |= reader.ReadByte(); int h = (reader.ReadByte() << 8); h |= reader.ReadByte(); int crcbDelay = 0; if ((major & 0x7f) == 1 && minor >= 2) { crcbDelay = reader.ReadByte(); if (minor >= 2) { _CrCbDelay = (crcbDelay & 0x7f); } } if (minor >= 2) { _CrCbHalf = ((crcbDelay & 0x80) != 0 ? false : true); } if ((major & 0x80) != 0) { _CrCbDelay = -1; } _YMap = new InterWaveMap(w, h); _YDecoder = new InterWaveDecoder(_YMap); if (_CrCbDelay >= 0) { _CbMap = new InterWaveMap(w, h); _CrMap = new InterWaveMap(w, h); _CbDecoder = new InterWaveDecoder(_CbMap); _CrDecoder = new InterWaveDecoder(_CrMap); } } IDataCoder coder = DjvuSettings.Current.CoderFactory.CreateCoder(reader.BaseStream, false); for (int flag = 1; flag != 0 && _CSlices < nslices; _CSlices++) { flag = _YDecoder.CodeSlice(coder); if (_CrDecoder != null && _CbDecoder != null && _CrCbDelay <= _CSlices) { flag |= _CbDecoder.CodeSlice(coder); flag |= _CrDecoder.CodeSlice(coder); } } _CSerial++; }