示例#1
0
        /// <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);
        }
示例#2
0
        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);
        }
示例#3
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;
            }
        }
示例#4
0
        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++;
            }
        }
示例#5
0
        /// <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));
        }
示例#6
0
        /// <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));
                            }
                        }
                    }
                }
            }
        }
示例#7
0
        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++;
        }