/// <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> /// 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])); } } } } }
private static void InverseDWT_2D(short[,] data2D, int pass) { //level > 0 //data2D.Length % (1<<(level - 1)) == 0 int inScopelen; switch (pass) { case 1: { // First pass inScopelen = 64; break; } case 2: { // Second pass inScopelen = 33; break; } case 3: { // Third pass inScopelen = 17; break; } default: { throw new InvalidOperationException("DWT_2D: the parameter level should only be 1, 2, or 3."); } } //Horizontal DWT for (int y = 0; y < inScopelen; y++) { short[] row; RemoteFXDecoder.getRowFrom2DArr <short>(data2D, out row, y, inScopelen); row = InverseDWT_1D(row); for (int x = 0; x < inScopelen; x++) { data2D[x, y] = row[x]; } } //Vertical DWT for (int x = 0; x < inScopelen; x++) { short[] col; RemoteFXDecoder.getColFrom2DArr <short>(data2D, out col, x, inScopelen); col = InverseDWT_1D(col); for (int y = 0; y < inScopelen; y++) { data2D[x, y] = col[y]; } } }
/// <summary> /// Decode a tile from DWT /// </summary> /// <param name="codecContext">The codec context which contains the DWT data of a tile.</param> public static void DecodeTileFromDwtQ(RfxProgressiveCodecContext codecContext) { //Sub Band Reconstruction SubBandReconstruction(codecContext); //De-quantization Dequantization(codecContext); //Inverse DWT if (codecContext.UseReduceExtrapolate) { InverseDWT(codecContext); } else { RemoteFXDecoder.InverseDWT(codecContext); } //(Y, U, V) to (R, G, B) RemoteFXDecoder.YCbCrToRGB(codecContext); }
/// <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); } }