//Load a tile from image
        public static void GetTileData(Image image, int leftOffset, int topOffset, RemoteFXCodecContext encodingContext)
        {
            Bitmap bitmap = new Bitmap(image);

            encodingContext.RSet = new byte[TileSize, TileSize];
            encodingContext.GSet = new byte[TileSize, TileSize];
            encodingContext.BSet = new byte[TileSize, TileSize];

            int right  = Math.Min(image.Width - 1, leftOffset + TileSize - 1);
            int bottom = Math.Min(image.Height - 1, topOffset + TileSize - 1);

            BitmapData bmpData = bitmap.LockBits(new Rectangle(leftOffset, topOffset, right - leftOffset + 1, bottom - topOffset + 1), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            unsafe
            {
                byte *cusor = (byte *)bmpData.Scan0.ToPointer();
                for (int y = topOffset; y <= bottom; y++)
                {
                    for (int x = leftOffset; x <= right; x++)
                    {
                        int tileX = x - leftOffset;
                        int tileY = y - topOffset;
                        encodingContext.BSet[tileX, tileY] = cusor[0];
                        encodingContext.GSet[tileX, tileY] = cusor[1];
                        encodingContext.RSet[tileX, tileY] = cusor[2];
                        cusor += 3;
                    }
                    cusor += (bmpData.Stride - 3 * (bmpData.Width));
                }
            }
            bitmap.UnlockBits(bmpData);
        }
        //RLGREncode
        public static void RLGREncode(RemoteFXCodecContext encodingContext)
        {
            RLGREncoder encoder = new RLGREncoder();

            encodingContext.YData  = encoder.Encode(encodingContext.YComponent, encodingContext.Mode);
            encodingContext.CbData = encoder.Encode(encodingContext.CbComponent, encodingContext.Mode);
            encodingContext.CrData = encoder.Encode(encodingContext.CrComponent, encodingContext.Mode);
        }
Beispiel #3
0
        //RLGR decode
        public static void RLGRDecode(RemoteFXCodecContext codecContext)
        {
            RLGRDecoder decoder = new RLGRDecoder();
            int         comLen  = TileSize * TileSize;

            codecContext.YComponent  = decoder.Decode(codecContext.YData, codecContext.Mode, comLen);
            codecContext.CbComponent = decoder.Decode(codecContext.CbData, codecContext.Mode, comLen);
            codecContext.CrComponent = decoder.Decode(codecContext.CrData, codecContext.Mode, comLen);
        }
Beispiel #4
0
 //Load encoded data into decoding context
 public static void FileEncodedData(RemoteFXCodecContext codecContext, byte[] yData, byte[] cbData, byte[] crData)
 {
     codecContext.YData  = new byte[yData.Length];
     codecContext.CbData = new byte[cbData.Length];
     codecContext.CrData = new byte[crData.Length];
     Array.Copy(yData, codecContext.YData, yData.Length);
     Array.Copy(cbData, codecContext.CbData, cbData.Length);
     Array.Copy(crData, codecContext.CrData, crData.Length);
 }
 //Color coversion
 public static void RGBToYCbCr(RemoteFXCodecContext encodingContext)
 {
     encodingContext.YSet  = new short[TileSize, TileSize];
     encodingContext.CbSet = new short[TileSize, TileSize];
     encodingContext.CrSet = new short[TileSize, TileSize];
     for (int x = 0; x < TileSize; x++)
     {
         for (int y = 0; y < TileSize; y++)
         {
             short[] yuv = RGBToYCbCr(encodingContext.RSet[x, y], encodingContext.GSet[x, y], encodingContext.BSet[x, y]);
             encodingContext.YSet[x, y]  = yuv[0];
             encodingContext.CbSet[x, y] = yuv[1];
             encodingContext.CrSet[x, y] = yuv[2];
         }
     }
 }
Beispiel #6
0
        /// <summary>
        /// Decode the tile data
        /// </summary>
        /// <param name="codecContext">The decoding context</param>
        /// <param name="yData">The Y data to be decoded.</param>
        /// <param name="cbData">The Cb data to be decoded.</param>
        /// <param name="crData">The Cr data to be decoded.</param>
        public static void DecodeTile(RemoteFXCodecContext codecContext, byte[] yData, byte[] cbData, byte[] crData)
        {
            //Load the encoded tile data
            FileEncodedData(codecContext, yData, cbData, crData);

            //Do ALGR decode
            RLGRDecode(codecContext);

            //Do reconstruction
            SubBandReconstruction(codecContext);

            //Dequantization
            Dequantization(codecContext);

            //Inverse DWT
            InverseDWT(codecContext);

            //Color coversion
            YCbCrToRGB(codecContext);
        }
        /// <summary>
        /// Encode a tile from an image.
        /// </summary>
        /// <param name="image">The input image.</param>
        /// <param name="leftOffset">The left offset of the tile.</param>
        /// <param name="topOffset">The top offset of the tile.</param>
        /// <param name="encodingContext">The encoding context.</param>
        public static void EncodeTile(Image image, int leftOffset, int topOffset, RemoteFXCodecContext encodingContext)
        {
            //Initialize the encoding context
            GetTileData(image, leftOffset, topOffset, encodingContext);

            //Do color conversion
            RGBToYCbCr(encodingContext);

            //Do three level DWT
            DWT(encodingContext);

            //Do quantiztion
            Quantization(encodingContext);

            //Do linearization
            Linearization(encodingContext);

            //ALRG encode
            RLGREncode(encodingContext);
        }
        /// <summary>
        /// Encode a tile from an image.
        /// </summary>
        /// <param name="image">The input RgbTile.</param>
        /// <param name="leftOffset">The left offset of the tile.</param>
        /// <param name="topOffset">The top offset of the tile.</param>
        /// <param name="encodingContext">The encoding context.</param>
        public static void EncodeTile(RgbTile tile, int leftOffset, int topOffset, RemoteFXCodecContext encodingContext)
        {
            //Initialize the encoding context
            encodingContext.RSet = tile.RSet;
            encodingContext.GSet = tile.GSet;
            encodingContext.BSet = tile.BSet;

            //Do color conversion
            RGBToYCbCr(encodingContext);

            //Do three level DWT
            DWT(encodingContext);

            //Do quantiztion
            Quantization(encodingContext);

            //Do linearization
            Linearization(encodingContext);

            //ALRG encode
            RLGREncode(encodingContext);
        }
        /// <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);
        }
Beispiel #10
0
 //Sub-Band Reconstruction
 public static void SubBandReconstruction(RemoteFXCodecContext codecContext)
 {
     reconstruction_Component(codecContext.YComponent, out codecContext.YSet);
     reconstruction_Component(codecContext.CbComponent, out codecContext.CbSet);
     reconstruction_Component(codecContext.CrComponent, out codecContext.CrSet);
 }
 //Quantization
 public static void Quantization(RemoteFXCodecContext encodingContext)
 {
     doQuantization_Component(encodingContext.YSet, encodingContext.CodecQuantVals[encodingContext.QuantIdxY]);
     doQuantization_Component(encodingContext.CbSet, encodingContext.CodecQuantVals[encodingContext.QuantIdxCb]);
     doQuantization_Component(encodingContext.CrSet, encodingContext.CodecQuantVals[encodingContext.QuantIdxCr]);
 }
 //Linearization
 public static void Linearization(RemoteFXCodecContext encodingContext)
 {
     linearization_Compontent(encodingContext.YSet, out encodingContext.YComponent);
     linearization_Compontent(encodingContext.CbSet, out encodingContext.CbComponent);
     linearization_Compontent(encodingContext.CrSet, out encodingContext.CrComponent);
 }
Beispiel #13
0
 //Dequantization
 public static void Dequantization(RemoteFXCodecContext codecContext)
 {
     dequantization_Component(codecContext.YSet, codecContext.CodecQuantVals[codecContext.QuantIdxY]);
     dequantization_Component(codecContext.CbSet, codecContext.CodecQuantVals[codecContext.QuantIdxCb]);
     dequantization_Component(codecContext.CrSet, codecContext.CodecQuantVals[codecContext.QuantIdxCr]);
 }
 //DWT
 public static void DWT(RemoteFXCodecContext encodingContext)
 {
     DWT_RomoteFX(encodingContext.YSet);
     DWT_RomoteFX(encodingContext.CbSet);
     DWT_RomoteFX(encodingContext.CrSet);
 }
Beispiel #15
0
 //InverseDWT
 public static void InverseDWT(RemoteFXCodecContext codecContext)
 {
     InverseDWT_Component(codecContext.YSet);
     InverseDWT_Component(codecContext.CbSet);
     InverseDWT_Component(codecContext.CrSet);
 }
 /// <summary>
 /// Draw the picture on output screen
 /// SetRemoteFXRegion and SetRemoteFXTileSet must be called before calling this method
 /// </summary>
 /// <param name="left"></param>
 /// <param name="top"></param>
 /// <param name="surfaceId"></param>
 public void RenderRemoteFXTile(ushort left, ushort top)
 {
     Bitmap image = baseImage;
     byte quantIdxY = remoteFXContext.TileSet.tiles[0].quantIdxY;
     byte quantIdxCb = remoteFXContext.TileSet.tiles[0].quantIdxCb;
     byte quantIdxCr = remoteFXContext.TileSet.tiles[0].quantIdxCr;
     RemoteFXCodecContext context = new RemoteFXCodecContext(remoteFXContext.TileSet.quantVals, quantIdxY, quantIdxCb, quantIdxCr, remoteFXContext.Entropy);
     foreach (TS_RFX_TILE tile in remoteFXContext.TileSet.tiles)
     {
         RemoteFXDecoder.DecodeTile(context, tile.YData, tile.CbData, tile.CrData);
         for (int i = 0; i < RgbTile.TileSize; i++)
         {
             for (int j = 0; j < RgbTile.TileSize; j++)
             {
                 int x = tile.xIdx * 64 + i;
                 int y =  tile.yIdx * 64 + j;
                 if (IsInRects(x, y, remoteFXContext.Region.rects))
                 {
                     image.SetPixel(left + x, top + y, Color.FromArgb(context.RSet[i, j], context.GSet[i, j], context.BSet[i, j]));
                 }
             }
         }
     }
 }
        /// <summary>
        /// Method to create TS_RFX_TILESET.
        /// </summary>
        /// <param name="isImageMode">Indicates the operational mode.</param>
        /// <param name="entropy">Indicates the entropy algorithm.</param>
        /// <param name="tileImage">A RgbTile. The width and heigth must be less than or equals with 64.</param>
        public TS_RFX_TILESET CreateTsRfxTileSet(OperationalMode opMode, EntropyAlgorithm entropy, RgbTile tileImage)
        {
            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 = 1;
            rfxTileSet.tileSize = RdprfxServer.TileSize;
            rfxTileSet.numTiles = 1;

            rfxTileSet.quantVals = new TS_RFX_CODEC_QUANT[1];
            rfxTileSet.quantVals[0] = codecQuant;

            byte[] yData, cbData, crData;

            RemoteFXCodecContext encodingContext = new RemoteFXCodecContext(codecQuant, entropy);
            RemoteFXEncoder.EncodeTile(tileImage, 0, 0, encodingContext);
            yData = encodingContext.YData;
            cbData = encodingContext.CbData;
            crData = encodingContext.CrData;

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

            rfxTileSet.tilesDataSize = rfxTileSet.tiles[0].BlockT.blockLen;
            rfxTileSet.CodecChannelT.blockLen = 22 + 5 + rfxTileSet.tilesDataSize;

            return rfxTileSet;
        }
        /// <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;
        }
Beispiel #19
0
 //YCbCrToRGB
 public static void YCbCrToRGB(RemoteFXCodecContext codecContext)
 {
     YCbCrToRGB(codecContext.YSet, codecContext.CbSet, codecContext.CrSet, out codecContext.RSet, out codecContext.GSet, out codecContext.BSet);
 }
        /// <summary>
        /// Draw the picture on Surface
        /// </summary>
        /// <param name="surfaceId"></param>
        /// <param name="destRect"></param>
        public void RenderRemoteFXTile(ushort surfaceId, RDPGFX_RECT16 destRect)
        {
            if (surfaceDic.ContainsKey(surfaceId))
            {
                Surface sur = surfaceDic[surfaceId];

                byte quantIdxY = remoteFXContext.TileSet.tiles[0].quantIdxY;
                byte quantIdxCb = remoteFXContext.TileSet.tiles[0].quantIdxCb;
                byte quantIdxCr = remoteFXContext.TileSet.tiles[0].quantIdxCr;
                RemoteFXCodecContext context = new RemoteFXCodecContext(remoteFXContext.TileSet.quantVals, quantIdxY, quantIdxCb, quantIdxCr, remoteFXContext.Entropy);
                foreach (TS_RFX_TILE tile in remoteFXContext.TileSet.tiles)
                {
                    RemoteFXDecoder.DecodeTile(context, tile.YData, tile.CbData, tile.CrData);
                    for (int i = 0; i < RgbTile.TileSize; i++)
                    {
                        for (int j = 0; j < RgbTile.TileSize; j++)
                        {
                            int x = tile.xIdx + i;
                            int y = tile.yIdx + j;
                            if (IsInRects(x, y, remoteFXContext.Region.rects))
                            {
                                if (destRect.left + x < destRect.right && destRect.top + y < destRect.bottom)
                                {
                                    sur.SetPixel(destRect.left + x, destRect.top + y, Color.FromArgb(context.RSet[i, j], context.GSet[i, j], context.BSet[i, j]));
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Method to create TS_RFX_TILESET.
        /// </summary>
        /// <param name="isImageMode">Indicates the operational mode.</param>
        /// <param name="entropy">Indicates the entropy algorithm.</param>
        /// <param name="tileImage">A RgbTile. The width and heigth must be less than or equals with 64.</param>
        public TS_RFX_TILESET CreateTsRfxTileSet(OperationalMode opMode, EntropyAlgorithm entropy, RgbTile tileImage)
        {
            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 = 1;
            rfxTileSet.tileSize = RdprfxServer.TileSize;
            rfxTileSet.numTiles = 1;

            rfxTileSet.quantVals    = new TS_RFX_CODEC_QUANT[1];
            rfxTileSet.quantVals[0] = codecQuant;

            byte[] yData, cbData, crData;

            RemoteFXCodecContext encodingContext = new RemoteFXCodecContext(codecQuant, entropy);

            RemoteFXEncoder.EncodeTile(tileImage, 0, 0, encodingContext);
            yData  = encodingContext.YData;
            cbData = encodingContext.CbData;
            crData = encodingContext.CrData;

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

            rfxTileSet.tilesDataSize          = rfxTileSet.tiles[0].BlockT.blockLen;
            rfxTileSet.CodecChannelT.blockLen = 22 + 5 + rfxTileSet.tilesDataSize;

            return(rfxTileSet);
        }