/// <summary>
 /// Constructor
 /// </summary>
 /// <param name="tsRfxCodecQuant"></param>
 /// <param name="mode"></param>
 public RemoteFXCodecContext(TS_RFX_CODEC_QUANT tsRfxCodecQuant, EntropyAlgorithm mode)
 {
     this.CodecQuantVals = new TS_RFX_CODEC_QUANT[] { tsRfxCodecQuant };
     this.QuantIdxY      = 0;
     this.QuantIdxCb     = 0;
     this.QuantIdxCr     = 0;
     this.Mode           = mode;
 }
 /// <summary>
 /// Set the default Codec Quant
 /// </summary>
 private void initCodecQuant()
 {
     codecQuant         = new TS_RFX_CODEC_QUANT();
     codecQuant.LL3_LH3 = 0x66;
     codecQuant.HL3_HH3 = 0x66;
     codecQuant.LH2_HL2 = 0x77;
     codecQuant.HH2_LH1 = 0x88;
     codecQuant.HL1_HH1 = 0x98;
 }
        /// <summary>
        /// Quantization
        /// </summary>
        /// <param name="component">Y_Set, Cb_Set, Cr_Set</param>
        /// <param name="tsRfxCodecQuant">TS_RFX_CODEC_QUANT struct stored quantization factor</param>
        protected static void doQuantization_Component(short[,] component, TS_RFX_CODEC_QUANT tsRfxCodecQuant)
        {
            // Quantization factor: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3
            Hashtable scaleValueTable = new Hashtable();
            int       HL1_Factor      = tsRfxCodecQuant.HL1_HH1 & 0x0f;
            int       LH1_Factor      = (tsRfxCodecQuant.HH2_LH1 & 0xf0) >> 4;
            int       HH1_Factor      = (tsRfxCodecQuant.HL1_HH1 & 0xf0) >> 4;
            int       HL2_Factor      = (tsRfxCodecQuant.LH2_HL2 & 0xf0) >> 4;
            int       LH2_Factor      = tsRfxCodecQuant.LH2_HL2 & 0x0f;
            int       HH2_Factor      = tsRfxCodecQuant.HH2_LH1 & 0x0f;
            int       HL3_Factor      = tsRfxCodecQuant.HL3_HH3 & 0x0f;
            int       LH3_Factor      = (tsRfxCodecQuant.LL3_LH3 & 0xf0) >> 4;
            int       HH3_Factor      = (tsRfxCodecQuant.HL3_HH3 & 0xf0) >> 4;
            int       LL3_Factor      = tsRfxCodecQuant.LL3_LH3 & 0x0f;

            int[] HL_Factor = { HL1_Factor, HL2_Factor, HL3_Factor };
            int[] LH_Factor = { LH1_Factor, LH2_Factor, LH3_Factor };
            int[] HH_Factor = { HH1_Factor, HH2_Factor, HH3_Factor };

            int top, left, right, bottom;

            //Level 1, 2, 3
            for (int i = 0; i <= 2; i++)
            {
                int levelSize = TileSize >> i;

                //HL1,2,3
                top    = 0;
                left   = levelSize / 2;
                right  = levelSize - 1;
                bottom = levelSize / 2 - 1;
                doQuantization_Subband(component, left, top, right, bottom, HL_Factor[i]);

                //LH1,2,3
                top    = levelSize / 2;
                left   = 0;
                right  = levelSize / 2 - 1;
                bottom = levelSize - 1;
                doQuantization_Subband(component, left, top, right, bottom, LH_Factor[i]);

                //HH1,2,3
                top    = levelSize / 2;
                left   = levelSize / 2;
                right  = levelSize - 1;
                bottom = levelSize - 1;
                doQuantization_Subband(component, left, top, right, bottom, HH_Factor[i]);
            }
            //LL3
            top    = 0;
            left   = 0;
            right  = TileSize / 8 - 1;
            bottom = TileSize / 8 - 1;
            doQuantization_Subband(component, left, top, right, bottom, LL3_Factor);
        }
 /// <summary>
 /// Consturctor
 /// </summary>
 /// <param name="tsRfxCodecQuantVals">Codec quantity values array</param>
 /// <param name="quantIdxY">Index of Y component in quantity array</param>
 /// <param name="quantIdxCb">Index of Cb component in quantity array</param>
 /// <param name="quantIdxCr">Index of Cr component in quantity array</param>
 /// <param name="bProgressive">indicates if use progressive codec</param>
 /// <param name="bTileDiff">indicates if sub-diffing</param>
 /// <param name="bReduceExtrapolate">Indicates if use Reduce-Extrapolate method in DWT</param>
 public RfxProgressiveCodecContext(
     TS_RFX_CODEC_QUANT[] tsRfxCodecQuantVals,
     byte quantIdxY,
     byte quantIdxCb,
     byte quantIdxCr,
     bool bProgressive = false,
     bool bTileDiff = true,
     bool bReduceExtrapolate = true)
     : base(tsRfxCodecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, EntropyAlgorithm.CLW_ENTROPY_RLGR1)
 {
     UseProgressive = bProgressive;
     UseDifferenceTile = bTileDiff;
     UseReduceExtrapolate = bReduceExtrapolate;
     prevProgQuant = RdpegfxTileUtils.GetProgCodecQuant(ProgressiveChunk_Values.kChunk_None);
 }
        protected static void doQuantization_Component(short[,] component, TS_RFX_CODEC_QUANT tsRfxCodecQuant, bool useReduceExtrapolate)
        {
            // Quantization factor: HL1, LH1, HH1, HL2, LH2, HH2, HL3, LH3, HH3, LL3
            Hashtable scaleValueTable = new Hashtable();
            int HL1_Factor = tsRfxCodecQuant.HL1_HH1 & 0x0f;
            int LH1_Factor = (tsRfxCodecQuant.HH2_LH1 & 0xf0) >> 4;
            int HH1_Factor = (tsRfxCodecQuant.HL1_HH1 & 0xf0) >> 4;
            int HL2_Factor = (tsRfxCodecQuant.LH2_HL2 & 0xf0) >> 4;
            int LH2_Factor = tsRfxCodecQuant.LH2_HL2 & 0x0f;
            int HH2_Factor = tsRfxCodecQuant.HH2_LH1 & 0x0f;
            int HL3_Factor = tsRfxCodecQuant.HL3_HH3 & 0x0f;
            int LH3_Factor = (tsRfxCodecQuant.LL3_LH3 & 0xf0) >> 4;
            int HH3_Factor = (tsRfxCodecQuant.HL3_HH3 & 0xf0) >> 4;
            int LL3_Factor = tsRfxCodecQuant.LL3_LH3 & 0x0f;

            BandType_Values[] bandArr = new BandType_Values[] { BandType_Values.HL1, BandType_Values.LH1, BandType_Values.HH1, BandType_Values.HL2, BandType_Values.LH2, BandType_Values.HH2, BandType_Values.HL3, BandType_Values.LH3, BandType_Values.HH3, BandType_Values.LL3 };
            int[] bandFactor = new int[] { HL1_Factor, LH1_Factor, HH1_Factor, HL2_Factor, LH2_Factor, HH2_Factor, HL3_Factor, LH3_Factor, HH3_Factor, LL3_Factor };

            for (int i = 0; i < bandArr.Length; i++)
            {
                BandRect br = RdpegfxTileUtils.GetBandRect(bandArr[i], useReduceExtrapolate);
                doQuantization_Subband(component, br.left, br.top, br.right, br.bottom, bandFactor[i]);
            }
        }
 /// <summary>
 /// Get codec quant with the specified quality
 /// </summary>
 /// <param name="quality">the encoding quality</param>
 /// <returns>The codec quant</returns>
 public static TS_RFX_CODEC_QUANT GetCodecQuant(ImageQuality_Values quality)
 {
     TS_RFX_CODEC_QUANT quant = new TS_RFX_CODEC_QUANT();
     quant.LL3_LH3 = (byte)(GetQuantValue(quality, BandType_Values.LL3) | (GetQuantValue(quality, BandType_Values.LH3) << 4));
     quant.HL3_HH3  = (byte)(GetQuantValue(quality, BandType_Values.HL3) | (GetQuantValue(quality, BandType_Values.HH3) << 4));
     quant.LH2_HL2  = (byte)(GetQuantValue(quality, BandType_Values.LH2) | (GetQuantValue(quality, BandType_Values.HL2) << 4));
     quant.HH2_LH1 = (byte)(GetQuantValue(quality, BandType_Values.HH2) | (GetQuantValue(quality, BandType_Values.LH1) << 4));
     quant.HL1_HH1 = (byte)(GetQuantValue(quality, BandType_Values.HL1) | (GetQuantValue(quality, BandType_Values.HH1) << 4));
     return quant;
 }
        private TS_RFX_CODEC_QUANT[] GenerateCodecQuantVals()
        {
            TS_RFX_CODEC_QUANT[] quantVals = new TS_RFX_CODEC_QUANT[3];
            quantVals[0].LL3_LH3 = 0x66;
            quantVals[0].HL3_HH3 = 0x66;
            quantVals[0].LH2_HL2 = 0x77;
            quantVals[0].HH2_LH1 = 0x88;
            quantVals[0].HL1_HH1 = 0x98;

            quantVals[1].LL3_LH3 = 0x66;
            quantVals[1].HL3_HH3 = 0x66;
            quantVals[1].LH2_HL2 = 0x99;
            quantVals[1].HH2_LH1 = 0x99;
            quantVals[1].HL1_HH1 = 0x99;

            quantVals[2].LL3_LH3 = 0x66;
            quantVals[2].HL3_HH3 = 0x88;
            quantVals[2].LH2_HL2 = 0x77;
            quantVals[2].HH2_LH1 = 0x88;
            quantVals[2].HL1_HH1 = 0x98;

            return quantVals;
        }
 /// <summary>
 /// Consturctor
 /// </summary>
 /// <param name="tsRfxCodecQuantVals">Codec quantity values array</param>
 /// <param name="quantIdxY">Index of Y component in quantity array</param>
 /// <param name="quantIdxCb">Index of Cb component in quantity array</param>
 /// <param name="quantIdxCr">Index of Cr component in quantity array</param>
 /// <param name="useReduceExtrapolate">Indicates if used Reduce-Extrapolate method in DWT</param>
 public RfxProgressiveCodecContext(
     TS_RFX_CODEC_QUANT[] tsRfxCodecQuantVals,
     byte quantIdxY,
     byte quantIdxCb,
     byte quantIdxCr,
     bool useReduceExtrapolate = true)
     : base(tsRfxCodecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, EntropyAlgorithm.CLW_ENTROPY_RLGR1)
 {
     UseReduceExtrapolate = useReduceExtrapolate;
 }
        /// <summary>
        /// Method to send TS_RFX_TILESET to client.
        /// </summary>
        /// <param name="opMode">Indicates the operational mode.</param>
        /// <param name="entropy">Indicates the entropy algorithm.</param>
        /// <param name="tileImages">The image array for tiles to be sent. The width and height must be less than or equals with 64.</param>
        /// <param name="positions">A TILE_POSITION array indicating the positions of each tile images</param>
        /// <param name="codecQuantVals">Quant values array</param>
        /// <param name="quantIdxYs">Index array of Y component in Quant value array</param>
        /// <param name="quantIdxCbs">Index array of Cb component in Quant value array</param>
        /// <param name="quantIdxCrs">Index array of Cr component in Quant value array</param>
        public void SendTsRfxTileSet(OperationalMode opMode, EntropyAlgorithm entropy, Image[] tileImages, TILE_POSITION[] positions,
            TS_RFX_CODEC_QUANT[] codecQuantVals = null, byte[] quantIdxYs = null, byte[] quantIdxCbs = null, byte[] quantIdxCrs = null)
        {
            this.admEntropyAlgorithm = entropy;
            this.admOperationMode = opMode;
            TS_RFX_TILESET rfxTileSet = rdprfxServer.CreateTsRfxTileSet(opMode, entropy, tileImages, positions, codecQuantVals, quantIdxYs, quantIdxCbs, quantIdxCrs);
            if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidIdx)
            {
                rfxTileSet.idx = 0x0001; //set to an invalid value other than 0x0000.
            }
            else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidLt)
            {
                rfxTileSet.properties &= 0xFFFE; //set "lt" to an invalid value: 0x0.
            }
            else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidCct)
            {
                rfxTileSet.properties &= 0xFFCF; //set "cct" to an invalid value: 0x0.
            }
            else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidXft)
            {
                rfxTileSet.properties &= 0xFC3F; //set "xft" to an invalid value: 0x0.
            }
            else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidQt)
            {
                rfxTileSet.properties &= 0x3FFF; //set "xft" to an invalid value: 0x0.
            }
            else if (this.currentTestType == RdprfxNegativeType.TsRfxTileSet_InvalidTileSize)
            {
                rfxTileSet.tileSize = 0x80; //set to an invalid value other than 0x40.
            }

            if (this.rdpbcgrAdapter.SimulatedScreen != null)
            {
                this.rdpbcgrAdapter.SimulatedScreen.SetRemoteFXTileSet(rfxTileSet, entropy);
            }

            AddToPendingList(rfxTileSet);
            if (!CheckIfClientSupports(opMode, entropy))
            {
                Site.Log.Add(LogEntryKind.Debug, "The client Cap is not supported: OperationalMode = {0}, EntropyAlgorithm = {1}",
                    opMode.ToString(),
                    entropy.ToString());
            }
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="tsRfxCodecQuantVals"></param>
 /// <param name="quantIdxY"></param>
 /// <param name="quantIdxCb"></param>
 /// <param name="quantIdxCr"></param>
 /// <param name="mode"></param>
 public RemoteFXCodecContext(TS_RFX_CODEC_QUANT[] tsRfxCodecQuantVals, byte quantIdxY, byte quantIdxCb, byte quantIdxCr, EntropyAlgorithm mode)
 {
     if(tsRfxCodecQuantVals == null || tsRfxCodecQuantVals.Length == 0)
     {
         throw new ArgumentException("Parameter tsRfxCodecQuantVals cannot be null and its length must larger than 0.");
     }
     int maxIndex = tsRfxCodecQuantVals.Length -1;
     if (quantIdxY > maxIndex || quantIdxCb > maxIndex || quantIdxCr > maxIndex)
     {
         throw new ArgumentException("Quant index for Y , Cb or Cr is/are larger than the size of tsRfxCodecQuantVals.");
     }
     this.CodecQuantVals = tsRfxCodecQuantVals;
     this.QuantIdxY = quantIdxY;
     this.QuantIdxCb = quantIdxCb;
     this.QuantIdxCr = quantIdxCr;
     this.Mode = mode;
 }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="tsRfxCodecQuant"></param>
 /// <param name="mode"></param>
 public RemoteFXCodecContext(TS_RFX_CODEC_QUANT tsRfxCodecQuant, EntropyAlgorithm mode)
 {
     this.CodecQuantVals = new TS_RFX_CODEC_QUANT[] { tsRfxCodecQuant };
     this.QuantIdxY = 0;
     this.QuantIdxCb = 0;
     this.QuantIdxCr = 0;
     this.Mode = mode;
 }
        /// <summary>
        /// Method to create TS_RFX_TILESET.
        /// </summary>
        /// <param name="opMode">Indicates the operational mode.</param>
        /// <param name="entropy">Indicates the entropy algorithm.</param>
        /// <param name="tileImages">An array of bitmaps in Image type for a tile. The width and heigth must be less than or equals with 64.</param>
        /// <param name="positions">A TILE_POSITION array indicating the positions of each tile images</param>
        /// <param name="codecQuantVals">Quant values array</param>
        /// <param name="quantIdxYs">Index array of Y component in Quant value array</param>
        /// <param name="quantIdxCbs">Index array of Cb component in Quant value array</param>
        /// <param name="quantIdxCrs">Index array of Cr component in Quant value array</param>
        /// <returns></returns>
        public TS_RFX_TILESET CreateTsRfxTileSet(
            OperationalMode opMode,
            EntropyAlgorithm entropy,
            Image[] tileImages,
            TILE_POSITION[] positions,
            TS_RFX_CODEC_QUANT[] codecQuantVals = null,
            byte[] quantIdxYs  = null,
            byte[] quantIdxCbs = null,
            byte[] quantIdxCrs = null
            )
        {
            if (codecQuantVals == null)
            {
                codecQuantVals    = new TS_RFX_CODEC_QUANT[1];
                codecQuantVals[0] = codecQuant;
            }

            TS_RFX_TILESET rfxTileSet = new TS_RFX_TILESET();

            rfxTileSet.CodecChannelT           = new TS_RFX_CODEC_CHANNELT();
            rfxTileSet.CodecChannelT.blockType = blockType_Value.WBT_EXTENSION;
            rfxTileSet.CodecChannelT.blockLen  = 22 + 5;
            rfxTileSet.CodecChannelT.codecId   = 0x01;
            rfxTileSet.CodecChannelT.channelId = 0x00;
            rfxTileSet.subtype = 0xCAC2;
            rfxTileSet.idx     = 0x0000;

            ushort lt    = 0x0001;
            ushort flags = 0x0002;

            if (opMode == OperationalMode.VideoMode)
            {
                flags = 0x0000;
            }
            ushort cct = 0x0001;
            ushort xft = 0x0001;
            ushort et  = 0x0001;

            if (entropy == EntropyAlgorithm.CLW_ENTROPY_RLGR3)
            {
                et = 0x0004;
            }
            ushort qt = 0x0001;

            rfxTileSet.properties  = lt;
            rfxTileSet.properties |= (ushort)(flags << 1);
            rfxTileSet.properties |= (ushort)(cct << 4);
            rfxTileSet.properties |= (ushort)(xft << 6);
            rfxTileSet.properties |= (ushort)(et << 10);
            rfxTileSet.properties |= (ushort)(qt << 14);

            rfxTileSet.numQuant = (byte)codecQuantVals.Length;
            rfxTileSet.tileSize = RdprfxServer.TileSize;
            rfxTileSet.numTiles = 1;

            rfxTileSet.quantVals = codecQuantVals;

            byte[] yData, cbData, crData;

            rfxTileSet.tiles    = new TS_RFX_TILE[tileImages.Length];
            rfxTileSet.numTiles = (ushort)rfxTileSet.tiles.Length;

            for (int i = 0; i < tileImages.Length; i++)
            {
                byte quantIdxY  = quantIdxYs == null ? (byte)0 : (quantIdxYs.Length > i ? quantIdxYs[i] : (byte)0);
                byte quantIdxCb = quantIdxCbs == null ? (byte)0 : (quantIdxCbs.Length > i ? quantIdxCbs[i] : (byte)0);
                byte quantIdxCr = quantIdxCrs == null ? (byte)0 : (quantIdxCrs.Length > i ? quantIdxCrs[i] : (byte)0);

                RemoteFXCodecContext encodingContext = new RemoteFXCodecContext(codecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, entropy);
                RemoteFXEncoder.EncodeTile(tileImages[i], 0, 0, encodingContext);
                yData  = encodingContext.YData;
                cbData = encodingContext.CbData;
                crData = encodingContext.CrData;

                rfxTileSet.tiles[i].BlockT.blockType = blockType_Value.CBT_TILE;
                rfxTileSet.tiles[i].BlockT.blockLen  = (uint)(19 + yData.Length + cbData.Length + crData.Length);
                rfxTileSet.tiles[i].quantIdxY        = quantIdxY;
                rfxTileSet.tiles[i].quantIdxCb       = quantIdxCb;
                rfxTileSet.tiles[i].quantIdxCr       = quantIdxCr;
                rfxTileSet.tiles[i].xIdx             = positions[i].xIdx;
                rfxTileSet.tiles[i].yIdx             = positions[i].yIdx;
                rfxTileSet.tiles[i].YLen             = (ushort)yData.Length;
                rfxTileSet.tiles[i].CbLen            = (ushort)cbData.Length;
                rfxTileSet.tiles[i].CrLen            = (ushort)crData.Length;
                rfxTileSet.tiles[i].YData            = yData;
                rfxTileSet.tiles[i].CbData           = cbData;
                rfxTileSet.tiles[i].CrData           = crData;

                rfxTileSet.tilesDataSize         += rfxTileSet.tiles[i].BlockT.blockLen;
                rfxTileSet.CodecChannelT.blockLen = (uint)(22 + 5 * rfxTileSet.numQuant + rfxTileSet.tilesDataSize);
            }

            return(rfxTileSet);
        }
 /// <summary>
 /// Set the default Codec Quant
 /// </summary>
 private void initCodecQuant()
 {
     codecQuant = new TS_RFX_CODEC_QUANT();
     codecQuant.LL3_LH3 = 0x66;
     codecQuant.HL3_HH3 = 0x66;
     codecQuant.LH2_HL2 = 0x77;
     codecQuant.HH2_LH1 = 0x88;
     codecQuant.HL1_HH1 = 0x98;
 }
        /// <summary>
        /// Method to create TS_RFX_TILESET.
        /// </summary>
        /// <param name="opMode">Indicates the operational mode.</param>
        /// <param name="entropy">Indicates the entropy algorithm.</param>
        /// <param name="tileImages">An array of bitmaps in Image type for a tile. The width and heigth must be less than or equals with 64.</param>
        /// <param name="positions">A TILE_POSITION array indicating the positions of each tile images</param>
        /// <param name="codecQuantVals">Quant values array</param>
        /// <param name="quantIdxYs">Index array of Y component in Quant value array</param>
        /// <param name="quantIdxCbs">Index array of Cb component in Quant value array</param>
        /// <param name="quantIdxCrs">Index array of Cr component in Quant value array</param>
        /// <returns></returns>
        public TS_RFX_TILESET CreateTsRfxTileSet(
            OperationalMode opMode,
            EntropyAlgorithm entropy,
            Image[] tileImages,
            TILE_POSITION[] positions,
            TS_RFX_CODEC_QUANT[] codecQuantVals = null,
            byte[] quantIdxYs = null,
            byte[] quantIdxCbs = null,
            byte[] quantIdxCrs = null
            )
        {
            if (codecQuantVals == null)
            {
                codecQuantVals = new TS_RFX_CODEC_QUANT[1];
                codecQuantVals[0] = codecQuant;
            }

            TS_RFX_TILESET rfxTileSet = new TS_RFX_TILESET();
            rfxTileSet.CodecChannelT = new TS_RFX_CODEC_CHANNELT();
            rfxTileSet.CodecChannelT.blockType = blockType_Value.WBT_EXTENSION;
            rfxTileSet.CodecChannelT.blockLen = 22 + 5;
            rfxTileSet.CodecChannelT.codecId = 0x01;
            rfxTileSet.CodecChannelT.channelId = 0x00;
            rfxTileSet.subtype = 0xCAC2;
            rfxTileSet.idx = 0x0000;

            ushort lt = 0x0001;
            ushort flags = 0x0002;
            if (opMode == OperationalMode.VideoMode) flags = 0x0000;
            ushort cct = 0x0001;
            ushort xft = 0x0001;
            ushort et = 0x0001;
            if (entropy == EntropyAlgorithm.CLW_ENTROPY_RLGR3) et = 0x0004;
            ushort qt = 0x0001;
            rfxTileSet.properties = lt;
            rfxTileSet.properties |= (ushort)(flags << 1);
            rfxTileSet.properties |= (ushort)(cct << 4);
            rfxTileSet.properties |= (ushort)(xft << 6);
            rfxTileSet.properties |= (ushort)(et << 10);
            rfxTileSet.properties |= (ushort)(qt << 14);

            rfxTileSet.numQuant = (byte)codecQuantVals.Length;
            rfxTileSet.tileSize = RdprfxServer.TileSize;
            rfxTileSet.numTiles = 1;

            rfxTileSet.quantVals = codecQuantVals;

            byte[] yData, cbData, crData;

            rfxTileSet.tiles = new TS_RFX_TILE[tileImages.Length];
            rfxTileSet.numTiles = (ushort) rfxTileSet.tiles.Length;

            for (int i = 0; i < tileImages.Length; i++)
            {
                byte quantIdxY = quantIdxYs == null ? (byte)0 : (quantIdxYs.Length > i ? quantIdxYs[i] : (byte)0);
                byte quantIdxCb = quantIdxCbs == null ? (byte)0 : (quantIdxCbs.Length > i ? quantIdxCbs[i] : (byte)0);
                byte quantIdxCr = quantIdxCrs == null ? (byte)0 : (quantIdxCrs.Length > i ? quantIdxCrs[i] : (byte)0);

                RemoteFXCodecContext encodingContext = new RemoteFXCodecContext(codecQuantVals, quantIdxY, quantIdxCb, quantIdxCr, entropy);
                RemoteFXEncoder.EncodeTile(tileImages[i], 0, 0, encodingContext);
                yData = encodingContext.YData;
                cbData = encodingContext.CbData;
                crData = encodingContext.CrData;

                rfxTileSet.tiles[i].BlockT.blockType = blockType_Value.CBT_TILE;
                rfxTileSet.tiles[i].BlockT.blockLen = (uint)(19 + yData.Length + cbData.Length + crData.Length);
                rfxTileSet.tiles[i].quantIdxY = quantIdxY;
                rfxTileSet.tiles[i].quantIdxCb = quantIdxCb;
                rfxTileSet.tiles[i].quantIdxCr = quantIdxCr;
                rfxTileSet.tiles[i].xIdx = positions[i].xIdx;
                rfxTileSet.tiles[i].yIdx = positions[i].yIdx;
                rfxTileSet.tiles[i].YLen = (ushort)yData.Length;
                rfxTileSet.tiles[i].CbLen = (ushort)cbData.Length;
                rfxTileSet.tiles[i].CrLen = (ushort)crData.Length;
                rfxTileSet.tiles[i].YData = yData;
                rfxTileSet.tiles[i].CbData = cbData;
                rfxTileSet.tiles[i].CrData = crData;

                rfxTileSet.tilesDataSize += rfxTileSet.tiles[i].BlockT.blockLen;
                rfxTileSet.CodecChannelT.blockLen = (uint)(22 + 5 * rfxTileSet.numQuant + rfxTileSet.tilesDataSize);
            }

            return rfxTileSet;
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="y">Y component data</param>
 /// <param name="cb">Cb component data</param>
 /// <param name="cr">Cr component data</param>
 /// <param name="quant">Codec quantity</param>
 /// <param name="bReduceExtrapolate">Indicates if used Reduce-Extrapolate method in DWT</param>
 /// <param name="progQuant">The progressive codec quantity</param>
 public DwtTile(short[] y, short[] cb, short[] cr, TS_RFX_CODEC_QUANT[] quantVals, byte quantIdxY, byte quantIdxCb, byte quantIdxCr, bool bReduceExtrapolate, RFX_PROGRESSIVE_CODEC_QUANT progQuant = null)
 {
     // Clone the array, make sure different DwtTitle cannot hold the same array reference
     Y_DwtQ = (short[])y.Clone();
     Cb_DwtQ = (short[])cb.Clone();
     Cr_DwtQ = (short[])cr.Clone();
     CodecQuantVals = quantVals;
     this.QuantIdxY = quantIdxY;
     this.QuantIdxCb = quantIdxCb;
     this.QuantIdxCr = quantIdxCr;
     UseReduceExtrapolate = bReduceExtrapolate;
     ProgCodecQuant = progQuant;
 }