protected unsafe WriteableBitmap DecodeData(byte *codecBuffer, uint length, Dispatcher dispatcher, IEnumerable <IWriteableBitmapModifierTask> modifierTasks) { if (length < 20) { return(_decodedBitmap); } var modifyingTasks = modifierTasks?.ToArray(); if (modifyingTasks?.Length == 0) { modifyingTasks = null; } ImageMetadata metadata; PixelFormat pixelFormat; int width; int height; var position = RemoteDesktopDataInfo.ReadHeader(codecBuffer, out metadata, out pixelFormat, out width, out height); var pixelSize = GetPixelSize(pixelFormat); IntPtr backBuffer = IntPtr.Zero; int backBufferStride = 0; if (_decodedBitmap == null) { dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => { _decodedBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr32, null); _decodedBitmap.Lock(); backBuffer = _decodedBitmap.BackBuffer; backBufferStride = _decodedBitmap.BackBufferStride; })).Wait(); } else dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => { _decodedBitmap.Lock(); backBuffer = _decodedBitmap.BackBuffer; backBufferStride = _decodedBitmap.BackBufferStride; })).Wait(); }
protected virtual unsafe RemoteDesktopDataInfo WriteChanges(Rectangle[] changedAreas, MovedRegion[] movedRegions, int pixelSize, byte *imageBuffer, PixelFormat pixelFormat, Size imageSize, int imageStride) { MemoryStream memoryStream = null; byte[][] dataArrays = null; var changedAreasLength = changedAreas?.Length ?? 0; var movedRegionsLength = movedRegions?.Length ?? 0; FrameInfo[] frames = null; if ((ImageCompression.CompressionMode & CompressionMode.Stream) == CompressionMode.Stream) { memoryStream = new MemoryStream(_encodeBuffer.Length / 200); RemoteDesktopDataInfo.WriteHeader(pixelFormat, ImageMetadata.Frames, imageSize.Width, imageSize.Height, memoryStream); } else if ((ImageCompression.CompressionMode & CompressionMode.ByteArray) == CompressionMode.ByteArray) { dataArrays = new byte[changedAreasLength + movedRegionsLength][]; frames = new FrameInfo[changedAreasLength + movedRegionsLength]; } else { throw new NotSupportedException(ImageCompression.CompressionMode.ToString()); } if (movedRegions != null) { for (int i = 0; i < movedRegions.Length; i++) { var movedRegion = movedRegions[i]; if (memoryStream != null) { RemoteDesktopDataInfo.WriteFrameInfo(movedRegion.Destination, 8, FrameFlags.MovedRegion, memoryStream); memoryStream.Write(BitConverter.GetBytes(movedRegion.Source.X), 0, 4); memoryStream.Write(BitConverter.GetBytes(movedRegion.Source.Y), 0, 4); } else { var data = new byte[8]; Buffer.BlockCopy(BitConverter.GetBytes(movedRegion.Source.X), 0, data, 0, 4); Buffer.BlockCopy(BitConverter.GetBytes(movedRegion.Source.Y), 0, data, 4, 4); dataArrays[i] = data; frames[i] = new FrameInfo(movedRegion.Destination, FrameFlags.MovedRegion); } } } if (changedAreas != null) { for (int i = 0; i < changedAreas.Length; i++) { var blockArea = changedAreas[i]; var blockStride = blockArea.Width * pixelSize; var blockPointer = Marshal.AllocHGlobal(blockStride * blockArea.Height); try { //build bitmap in memory for (int j = 0, offset = 0; j < blockArea.Height; j++) { int blockOffset = imageStride * (blockArea.Y + j) + pixelSize * blockArea.X; CoreMemoryApi.memcpy(blockPointer.Add(offset), (IntPtr)(imageBuffer + blockOffset), (UIntPtr)blockStride); offset += blockStride; } if (memoryStream != null) { RemoteDesktopDataInfo.WriteFrameInfo(blockArea, 0, FrameFlags.UpdatedRegion, memoryStream); var framePos = memoryStream.Position; ImageCompression.Compress(blockPointer, blockStride, blockArea.Size, pixelFormat, memoryStream); var currentPos = memoryStream.Position; memoryStream.Position = framePos - 4; memoryStream.Write(BitConverter.GetBytes(currentPos - framePos), 0, 4); memoryStream.Position = currentPos; } else { dataArrays[i + movedRegionsLength] = ImageCompression.Compress(blockPointer, blockStride, blockArea.Size, pixelFormat); frames[i + movedRegionsLength] = new FrameInfo(blockArea, FrameFlags.UpdatedRegion); } } finally { Marshal.FreeHGlobal(blockPointer); } } } if (memoryStream != null) { using (memoryStream) return(new RemoteDesktopDataInfo(memoryStream.ToArray())); } return(new RemoteDesktopDataInfo(dataArrays, frames, new HeaderInfo(ImageMetadata.Frames, pixelFormat, imageSize.Width, imageSize.Height))); }