/// <summary>
        /// Decode an encoded tile
        /// </summary>
        /// <param name="enTile">Represents an encoded tile.</param>
        /// <param name="tState">The context state of the tile that going to be decoded.</param>
        public static void DecodeTile(EncodedTile enTile, TileState tState)
        {
            RfxProgressiveCodecContext codecContext = new RfxProgressiveCodecContext(
                enTile.CodecQuantVals,
                enTile.QuantIdxY,
                enTile.QuantIdxCb,
                enTile.QuantIdxCr,
                enTile.DataType == EncodedTileType.Simple ? false : true,
                enTile.IsDifferenceTile,
                enTile.UseReduceExtrapolate);

            //RLGR/SRL Decode
            if (enTile.DataType == EncodedTileType.FirstPass || enTile.DataType == EncodedTileType.Simple)
            {   //first pass or simple
                codecContext.YData  = enTile.YEncodedData;
                codecContext.CbData = enTile.CbEncodedData;
                codecContext.CrData = enTile.CrEncodedData;
                RemoteFXDecoder.RLGRDecode(codecContext);
                ComputeOriginalLL3FromDeltas(codecContext);
            }
            else
            {
                SRLDecode(codecContext, enTile, tState);
            }

            //Progressive Dequantization
            if (enTile.DataType != EncodedTileType.Simple)
            {
                ProgressiveDeQuantization(codecContext, enTile.ProgCodecQuant);
            }

            // Create a DwtTile instance for tri-state
            DwtTile triStateDwt = new DwtTile(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent,
                                              enTile.CodecQuantVals, enTile.QuantIdxY, enTile.QuantIdxCb, enTile.QuantIdxCr, enTile.UseReduceExtrapolate, enTile.ProgCodecQuant);

            //Set Tri-State for progressive codec
            if (enTile.DataType == EncodedTileType.FirstPass)
            {
                //DwtTile tileTriStat = SetTriState(diffDwt, enTile.UseReduceExtrapolate);
                tState.UpdateTriState(triStateDwt);
            }
            else if (enTile.DataType == EncodedTileType.UpgradePass)
            {
                DwtTile prvStat = tState.GetTriState();
                prvStat.Add(triStateDwt);
                // update ProCodecQuant
                prvStat.ProgCodecQuant = triStateDwt.ProgCodecQuant;
                tState.UpdateTriState(prvStat);
            }

            // Create another DwtTile instance for DWT Data.
            // The data in diffDwt is the same as triStateDwt, this will makesure the DWT data and tri-state not share the same DWT tile instance
            DwtTile diffDwt = new DwtTile(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent,
                                          enTile.CodecQuantVals, enTile.QuantIdxY, enTile.QuantIdxCb, enTile.QuantIdxCr, enTile.UseReduceExtrapolate, enTile.ProgCodecQuant);

            //Sum difference
            if (enTile.IsDifferenceTile || enTile.DataType == EncodedTileType.UpgradePass)
            {
                tState.AddDwt(diffDwt);
            }
            else
            {
                tState.UpdateDwt(diffDwt);
            }
        }
        /// <summary>
        /// Decode an encoded tile
        /// </summary>
        /// <param name="enTile">Represents an encoded tile.</param>
        /// <param name="tState">The context state of the tile that going to be decoded.</param>
        public static void DecodeTile(EncodedTile enTile, TileState tState)
        {
            RfxProgressiveCodecContext codecContext = new RfxProgressiveCodecContext(
                enTile.CodecQuantVals,
                enTile.QuantIdxY,
                enTile.QuantIdxCb,
                enTile.QuantIdxCr,
                enTile.DataType == EncodedTileType.Simple ? false : true,
                enTile.IsDifferenceTile,
                enTile.UseReduceExtrapolate);

            //RLGR/SRL Decode
            if (enTile.DataType == EncodedTileType.FirstPass || enTile.DataType == EncodedTileType.Simple)
            {   //first pass or simple
                codecContext.YData = enTile.YEncodedData;
                codecContext.CbData = enTile.CbEncodedData;
                codecContext.CrData = enTile.CrEncodedData;
                RemoteFXDecoder.RLGRDecode(codecContext);
                ComputeOriginalLL3FromDeltas(codecContext);
            }
            else
            {
                SRLDecode(codecContext, enTile, tState);
            }

            //Progressive Dequantization
            if (enTile.DataType != EncodedTileType.Simple)
            {
                ProgressiveDeQuantization(codecContext, enTile.ProgCodecQuant);
            }

            // Create a DwtTile instance for tri-state
            DwtTile triStateDwt = new DwtTile(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent,
                enTile.CodecQuantVals, enTile.QuantIdxY, enTile.QuantIdxCb, enTile.QuantIdxCr, enTile.UseReduceExtrapolate, enTile.ProgCodecQuant);

            //Set Tri-State for progressive codec
            if (enTile.DataType == EncodedTileType.FirstPass)
            {
                //DwtTile tileTriStat = SetTriState(diffDwt, enTile.UseReduceExtrapolate);
                tState.UpdateTriState(triStateDwt);
            }
            else if (enTile.DataType == EncodedTileType.UpgradePass)
            {
                DwtTile prvStat = tState.GetTriState();
                prvStat.Add(triStateDwt);
                // update ProCodecQuant
                prvStat.ProgCodecQuant = triStateDwt.ProgCodecQuant;
                tState.UpdateTriState(prvStat);
            }

            // Create another DwtTile instance for DWT Data.
            // The data in diffDwt is the same as triStateDwt, this will makesure the DWT data and tri-state not share the same DWT tile instance
            DwtTile diffDwt = new DwtTile(codecContext.YComponent, codecContext.CbComponent, codecContext.CrComponent,
                enTile.CodecQuantVals, enTile.QuantIdxY, enTile.QuantIdxCb, enTile.QuantIdxCr, enTile.UseReduceExtrapolate, enTile.ProgCodecQuant);

            //Sum difference
            if ( enTile.IsDifferenceTile || enTile.DataType == EncodedTileType.UpgradePass)
            {
                tState.AddDwt(diffDwt);
            }
            else
            {
                tState.UpdateDwt(diffDwt);
            }
        }
        public static void SRLDecode(RfxProgressiveCodecContext codecContext, EncodedTile enTile, TileState tState)
        {
            SRLDecoder yDecoder  = null;
            SRLDecoder cbDecoder = null;
            SRLDecoder crDecoder = null;

            List <short> yData    = new List <short>();
            List <short> cbData   = new List <short>();
            List <short> crData   = new List <short>();
            DwtTile      triState = tState.GetTriState();
            RFX_PROGRESSIVE_CODEC_QUANT prvProgQuant = tState.GetDwt().ProgCodecQuant;
            int nonLL3Len = RdpegfxTileUtils.ComponentElementCount - RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, enTile.UseReduceExtrapolate);

            if (enTile.YEncodedData != null)
            {
                yDecoder = new SRLDecoder(enTile.YEncodedData);
            }

            if (enTile.CbEncodedData != null)
            {
                cbDecoder = new SRLDecoder(enTile.CbEncodedData);
            }

            if (enTile.CrEncodedData != null)
            {
                crDecoder = new SRLDecoder(enTile.CrEncodedData);
            }

            BitStream yRaw  = BitStream.GetFromBytes(enTile.YRawData);
            BitStream cbRaw = BitStream.GetFromBytes(enTile.CbRawData);
            BitStream crRaw = BitStream.GetFromBytes(enTile.CrRawData);

            for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
            {
                BandType_Values band = RdpegfxTileUtils.GetBandByIndex(i, enTile.UseReduceExtrapolate);

                //Y
                int curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.yQuantValues, band);
                int prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.yQuantValues, band);
                int bitCount  = prvBitPos - curBitPos;
                int sign      = triState.Y_DwtQ[i];
                if (bitCount > 0)
                {
                    if (sign == 0 && i < nonLL3Len)
                    {
                        if (yDecoder != null)
                        {
                            short?decodedValue = yDecoder.DecodeOne(bitCount);
                            if (decodedValue.HasValue)
                            {
                                yData.Add(decodedValue.Value);
                            }
                            else
                            {
                                yData.Add(0);
                            }
                        }
                        else
                        {
                            yData.Add(0);
                        }
                    }
                    else
                    {
                        int output;
                        if (yRaw.ReadInt32(bitCount, out output))
                        {
                            if (sign < 0 && i < nonLL3Len)
                            {
                                output = -output;
                            }
                            yData.Add((short)output);
                        }
                        else
                        {
                            yData.Add(0);
                        }
                    }
                }
                else
                {
                    yData.Add(0);
                }

                //Cb
                curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.cbQuantValues, band);
                prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.cbQuantValues, band);
                bitCount  = prvBitPos - curBitPos;
                sign      = triState.Cb_DwtQ[i];
                if (bitCount > 0)
                {
                    if (sign == 0 && i < nonLL3Len)
                    {
                        if (cbDecoder != null)
                        {
                            short?decodedValue = cbDecoder.DecodeOne(bitCount);
                            if (decodedValue.HasValue)
                            {
                                cbData.Add(decodedValue.Value);
                            }
                            else
                            {
                                cbData.Add(0);
                            }
                        }
                        else
                        {
                            cbData.Add(0);
                        }
                    }
                    else
                    {
                        int output;
                        if (cbRaw.ReadInt32(bitCount, out output))
                        {
                            if (sign < 0 && i < nonLL3Len)
                            {
                                output = -output;
                            }
                            cbData.Add((short)output);
                        }
                        else
                        {
                            cbData.Add(0);
                        }
                    }
                }
                else
                {
                    cbData.Add(0);
                }

                //cr
                curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.crQuantValues, band);
                prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.crQuantValues, band);
                bitCount  = prvBitPos - curBitPos;
                sign      = triState.Cr_DwtQ[i];
                if (bitCount > 0)
                {
                    if (sign == 0 && i < nonLL3Len)
                    {
                        if (crDecoder != null)
                        {
                            short?decodedValue = crDecoder.DecodeOne(bitCount);
                            if (decodedValue.HasValue)
                            {
                                crData.Add(decodedValue.Value);
                            }
                            else
                            {
                                crData.Add(0);
                            }
                        }
                        else
                        {
                            crData.Add(0);
                        }
                    }
                    else
                    {
                        int output;
                        if (crRaw.ReadInt32(bitCount, out output))
                        {
                            if (sign < 0 && i < nonLL3Len)
                            {
                                output = -output;
                            }
                            crData.Add((short)output);
                        }
                        else
                        {
                            crData.Add(0);
                        }
                    }
                }
                else
                {
                    crData.Add(0);
                }
            }

            codecContext.YComponent  = yData.ToArray();
            codecContext.CbComponent = cbData.ToArray();
            codecContext.CrComponent = crData.ToArray();
        }
        public static void SRLDecode(RfxProgressiveCodecContext codecContext, EncodedTile enTile, TileState tState)
        {
            SRLDecoder yDecoder = null;
            SRLDecoder cbDecoder = null;
            SRLDecoder crDecoder = null;

            List<short> yData = new List<short>();
            List<short> cbData = new List<short>();
            List<short> crData = new List<short>();
            DwtTile triState = tState.GetTriState();
            RFX_PROGRESSIVE_CODEC_QUANT prvProgQuant = tState.GetDwt().ProgCodecQuant;
            int nonLL3Len = RdpegfxTileUtils.ComponentElementCount - RdpegfxTileUtils.GetBandSize(BandType_Values.LL3, enTile.UseReduceExtrapolate);

            if (enTile.YEncodedData != null)
            {
                yDecoder = new SRLDecoder(enTile.YEncodedData);
            }

            if (enTile.CbEncodedData != null)
            {
                cbDecoder = new SRLDecoder(enTile.CbEncodedData);
            }

            if (enTile.CrEncodedData != null)
            {
                crDecoder = new SRLDecoder(enTile.CrEncodedData);
            }

            BitStream yRaw = BitStream.GetFromBytes(enTile.YRawData);
            BitStream cbRaw = BitStream.GetFromBytes(enTile.CbRawData);
            BitStream crRaw = BitStream.GetFromBytes(enTile.CrRawData);

            for (int i = 0; i < RdpegfxTileUtils.ComponentElementCount; i++)
            {
                BandType_Values band = RdpegfxTileUtils.GetBandByIndex(i, enTile.UseReduceExtrapolate);

                //Y
                int curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.yQuantValues, band);
                int prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.yQuantValues, band);
                int bitCount = prvBitPos - curBitPos;
                int sign = triState.Y_DwtQ[i];
                if (bitCount > 0)
                {
                    if (sign == 0 && i < nonLL3Len)
                    {
                        if (yDecoder != null)
                        {
                            short? decodedValue = yDecoder.DecodeOne(bitCount);
                            if (decodedValue.HasValue)
                            {
                                yData.Add(decodedValue.Value);
                            }
                            else
                            {
                                yData.Add(0);
                            }
                        }
                        else
                        {
                            yData.Add(0);
                        }
                    }
                    else
                    {
                        int output;
                        if (yRaw.ReadInt32(bitCount, out output))
                        {
                            if (sign < 0 && i < nonLL3Len) output = -output;
                            yData.Add((short)output);
                        }
                        else
                        {
                            yData.Add(0);
                        }
                    }
                }
                else
                {
                    yData.Add(0);
                }

                //Cb
                curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.cbQuantValues, band);
                prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.cbQuantValues, band);
                bitCount = prvBitPos - curBitPos;
                sign = triState.Cb_DwtQ[i];
                if (bitCount > 0)
                {
                    if (sign == 0 && i < nonLL3Len)
                    {
                        if (cbDecoder != null)
                        {
                            short? decodedValue = cbDecoder.DecodeOne(bitCount);
                            if (decodedValue.HasValue)
                            {
                                cbData.Add(decodedValue.Value);
                            }
                            else
                            {
                                cbData.Add(0);
                            }
                        }
                        else
                        {
                            cbData.Add(0);
                        }
                    }
                    else
                    {
                        int output;
                        if (cbRaw.ReadInt32(bitCount, out output))
                        {
                            if (sign < 0 && i < nonLL3Len) output = -output;
                            cbData.Add((short)output);
                        }
                        else
                        {
                            cbData.Add(0);
                        }
                    }
                }
                else
                {
                    cbData.Add(0);
                }

                //cr
                curBitPos = RdpegfxTileUtils.GetBitPosFromQuant(enTile.ProgCodecQuant.crQuantValues, band);
                prvBitPos = RdpegfxTileUtils.GetBitPosFromQuant(prvProgQuant.crQuantValues, band);
                bitCount = prvBitPos - curBitPos;
                sign = triState.Cr_DwtQ[i];
                if (bitCount > 0)
                {
                    if (sign == 0 && i < nonLL3Len)
                    {
                        if (crDecoder != null)
                        {
                            short? decodedValue = crDecoder.DecodeOne(bitCount);
                            if (decodedValue.HasValue)
                            {
                                crData.Add(decodedValue.Value);
                            }
                            else
                            {
                                crData.Add(0);
                            }
                        }
                        else
                        {
                            crData.Add(0);
                        }
                    }
                    else
                    {
                        int output;
                        if (crRaw.ReadInt32(bitCount, out output))
                        {
                            if (sign < 0 && i < nonLL3Len) output = -output;
                            crData.Add((short)output);
                        }
                        else
                        {
                            crData.Add(0);
                        }
                    }
                }
                else
                {
                    crData.Add(0);
                }
            }

            codecContext.YComponent = yData.ToArray();
            codecContext.CbComponent = cbData.ToArray();
            codecContext.CrComponent = crData.ToArray();
        }