/// <summary>
        /// Create a RGB tile from a given bitmap
        /// </summary>
        /// <param name="orgImg">The given bitmap</param>
        /// <param name="leftOffset">The left offset of the tile to the bitmap</param>
        /// <param name="topOffset">The top offset of the tile to the bitmap</param>
        /// <returns></returns>
        public static RgbTile GetFromImage(Bitmap orgImg, int leftOffset, int topOffset)
        {
            RgbTile tile = new RgbTile();
            tile.RSet = new byte[TileSize, TileSize];
            tile.GSet = new byte[TileSize, TileSize];
            tile.BSet = new byte[TileSize, TileSize];

            int right = Math.Min(orgImg.Width - 1, leftOffset + TileSize - 1);
            int bottom = Math.Min(orgImg.Height - 1, topOffset + TileSize - 1);
            Rectangle bmpRect = new Rectangle(leftOffset, topOffset, right - leftOffset + 1, bottom - topOffset + 1);
            BitmapData bmpData = orgImg.LockBits(bmpRect, 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;
                        tile.BSet[tileX, tileY] = cusor[0];
                        tile.GSet[tileX, tileY] = cusor[1];
                        tile.RSet[tileX, tileY] = cusor[2];
                        cusor += 3;
                    }
                    cusor += (bmpData.Stride - 3 * (bmpData.Width));
                }
            }
            orgImg.UnlockBits(bmpData);

            return tile;
        }
        /// <summary>
        /// Create a RGB tile from a given bitmap
        /// </summary>
        /// <param name="orgImg">The given bitmap</param>
        /// <param name="leftOffset">The left offset of the tile to the bitmap</param>
        /// <param name="topOffset">The top offset of the tile to the bitmap</param>
        /// <returns></returns>
        public static RgbTile GetFromImage(Bitmap orgImg, int leftOffset, int topOffset)
        {
            RgbTile tile = new RgbTile();

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

            int        right   = Math.Min(orgImg.Width - 1, leftOffset + TileSize - 1);
            int        bottom  = Math.Min(orgImg.Height - 1, topOffset + TileSize - 1);
            Rectangle  bmpRect = new Rectangle(leftOffset, topOffset, right - leftOffset + 1, bottom - topOffset + 1);
            BitmapData bmpData = orgImg.LockBits(bmpRect, 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;
                        tile.BSet[tileX, tileY] = cusor[0];
                        tile.GSet[tileX, tileY] = cusor[1];
                        tile.RSet[tileX, tileY] = cusor[2];
                        cusor += 3;
                    }
                    cusor += (bmpData.Stride - 3 * (bmpData.Width));
                }
            }
            orgImg.UnlockBits(bmpData);

            return(tile);
        }
 /// <summary>
 /// Compare if equals with the given RGB tile
 /// </summary>
 /// <param name="cpTile">The given RGB tile</param>
 /// <returns>True if equals, otherwise false</returns>
 public bool EqualsWith(RgbTile cpTile)
 {
     byte[] lastHash = this.HashValue;
     byte[] newHash  = cpTile.HashValue;
     for (int i = 0; i < lastHash.Length; i++)
     {
         if (lastHash[i] != newHash[i])
         {
             return(false);
         }
     }
     return(true);
 }
        /// <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);
        }
 static void FillRgbData(RfxProgressiveCodecContext encodingContext, RgbTile rgbTile)
 {
     encodingContext.RSet = rgbTile.RSet;
     encodingContext.GSet = rgbTile.GSet;
     encodingContext.BSet = rgbTile.BSet;
 }
 /// <summary>
 /// Update the RGB data of the specified tile.
 /// </summary>
 /// <param name="index">The index of the tile.</param>
 /// <param name="dwtQ">The RGB data.</param>
 public void UpdateTileRgb(TileIndex index, RgbTile rgbT)
 {
     if (index.X * RdpegfxTileUtils.TileSize >= this.Width || index.Y * RdpegfxTileUtils.TileSize >= this.Height) return;
     lock (rgbTileDic)
     {
         if (rgbTileDic.ContainsKey(index))
         {
             rgbTileDic[index] = rgbT;
         }
         else
         {
             rgbTileDic.Add(index, rgbT);
         }
     }
 }
        /// <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="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>
 /// Compare if equals with the given RGB tile
 /// </summary>
 /// <param name="cpTile">The given RGB tile</param>
 /// <returns>True if equals, otherwise false</returns>
 public bool EqualsWith(RgbTile cpTile)
 {
     byte[] lastHash = this.HashValue;
     byte[] newHash = cpTile.HashValue;
     for (int i = 0; i < lastHash.Length; i++)
     {
         if (lastHash[i] != newHash[i]) return false;
     }
     return true;
 }