//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); }
//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); }
//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]; } } }
/// <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); }
//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); }
//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); }
//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; }
//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); }