// TODO: Something in the flow is wrong and causes bleeding pixels when doing a move. private static unsafe void CopyRegion(byte *fromBuffer, byte *toBuffer, int totalWidth, MovedRegion region) { var widthInBytes = totalWidth * 4; for (var yOffset = 0; yOffset < region.Height; yOffset++) { var yOrigin = region.FromY + yOffset; var yOriginIndex = yOrigin * widthInBytes; var yDestination = region.ToY + yOffset; var yDestinationIndex = yDestination * widthInBytes; for (var xOffset = 0; xOffset < region.Width; xOffset++) { var xOrigin = region.FromX + xOffset; var xOriginIndex = yOriginIndex + xOrigin * 4; var xDestination = region.ToX + xOffset; var xDestinationIndex = yDestinationIndex + xDestination * 4; toBuffer[xDestinationIndex + 0] = fromBuffer[xOriginIndex + 0]; toBuffer[xDestinationIndex + 1] = fromBuffer[xOriginIndex + 1]; toBuffer[xDestinationIndex + 2] = fromBuffer[xOriginIndex + 2]; toBuffer[xDestinationIndex + 3] = fromBuffer[xOriginIndex + 3]; } } }
public RemoteDesktopDataInfo CaptureScreen(IStreamCodec streamCodec, ICursorStreamCodec cursorStreamCodec, bool updateCursor) { //Debug.Print("_desktopDupl == null: " + (_deskDupl == null)); if (!RetrieveFrame()) { return(null); } // Get the desktop capture texture var mapSource = _device.ImmediateContext.MapSubresource(_desktopImageTexture, 0, MapMode.Read, MapFlags.None); try { if (updateCursor) { _screenHelper.UpdateCursor(cursorStreamCodec, _currentMonitor); } #if FALSE if (updateCursor) { cursorStreamCodec.UpdateCursorInfo(_frameInfo.PointerPosition.Position.X, _frameInfo.PointerPosition.Position.Y, _frameInfo.PointerPosition.Visible); if (_frameInfo.LastMouseUpdateTime != 0 && _frameInfo.PointerShapeBufferSize > 0) { var buffer = new byte[_frameInfo.PointerShapeBufferSize]; unsafe { fixed(byte *ptrShapeBufferPtr = buffer) { int bufferSize; OutputDuplicatePointerShapeInformation shapeInfo; _deskDupl.GetFramePointerShape(_frameInfo.PointerShapeBufferSize, (IntPtr)ptrShapeBufferPtr, out bufferSize, out shapeInfo); switch (shapeInfo.Type) { case 0x1: //DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME var size = Image.GetPixelFormatSize(PixelFormat.Format1bppIndexed); //var bitmap = new Bitmap(32, 32, 4, PixelFormat.Format1bppIndexed, (IntPtr)ptrShapeBufferPtr); cursorStreamCodec.UpdateCursorImage((IntPtr)ptrShapeBufferPtr, shapeInfo.Pitch, 32, 32, PixelFormat.Format1bppIndexed); Debug.Print("DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MONOCHROME"); break; case 0x2: //DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR cursorStreamCodec.UpdateCursorImage((IntPtr)ptrShapeBufferPtr, shapeInfo.Pitch, shapeInfo.Width, shapeInfo.Height, PixelFormat.Format32bppArgb); Debug.Print("DXGI_OUTDUPL_POINTER_SHAPE_TYPE_COLOR"); break; case 0x4: //DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR Debug.Print("DXGI_OUTDUPL_POINTER_SHAPE_TYPE_MASKED_COLOR"); break; } } } } } #endif if (_frameInfo.TotalMetadataBufferSize > 0) { int movedRegionsLength; OutputDuplicateMoveRectangle[] movedRectangles = new OutputDuplicateMoveRectangle[_frameInfo.TotalMetadataBufferSize]; _deskDupl.GetFrameMoveRects(movedRectangles.Length, movedRectangles, out movedRegionsLength); var movedRegions = new MovedRegion[movedRegionsLength / Marshal.SizeOf(typeof(OutputDuplicateMoveRectangle))]; for (int i = 0; i < movedRegions.Length; i++) { var moveRectangle = movedRectangles[i]; movedRegions[i] = new MovedRegion { Source = new Point(moveRectangle.SourcePoint.X, moveRectangle.SourcePoint.Y), Destination = new Rectangle(moveRectangle.DestinationRect.Left, moveRectangle.DestinationRect.Top, moveRectangle.DestinationRect.GetWidth(), moveRectangle.DestinationRect.GetHeight()) }; } int dirtyRegionsLength; var dirtyRectangles = new RawRectangle[_frameInfo.TotalMetadataBufferSize - movedRegionsLength]; _deskDupl.GetFrameDirtyRects(dirtyRectangles.Length, dirtyRectangles, out dirtyRegionsLength); var updatedAreas = new Rectangle[dirtyRegionsLength / Marshal.SizeOf(typeof(Rectangle))]; for (int i = 0; i < updatedAreas.Length; i++) { var dirtyRectangle = dirtyRectangles[i]; updatedAreas[i] = new Rectangle(dirtyRectangle.Left, dirtyRectangle.Top, dirtyRectangle.GetWidth(), dirtyRectangle.GetHeight()); } return(streamCodec.CodeImage(mapSource.DataPointer, updatedAreas, movedRegions, new Size(_outputDesc.DesktopBounds.GetWidth(), _outputDesc.DesktopBounds.GetHeight()), PixelFormat.Format32bppArgb)); } else { return(streamCodec.CodeImage(mapSource.DataPointer, new Rectangle(0, 0, _outputDesc.DesktopBounds.GetWidth(), _outputDesc.DesktopBounds.GetHeight()), new Size(_outputDesc.DesktopBounds.GetWidth(), _outputDesc.DesktopBounds.GetHeight()), PixelFormat.Format32bppArgb)); } } finally { _device.ImmediateContext.UnmapSubresource(_desktopImageTexture, 0); ReleaseFrame(); } }
private static unsafe void ProcessDelta(Bitmap bitmap, byte[] buffer, int offset, int count) { var imageBoundaries = new Rectangle(0, 0, bitmap.Width, bitmap.Height); var imageData = bitmap.LockBits(imageBoundaries, ImageLockMode.WriteOnly, bitmap.PixelFormat); var reader = new QuickBinaryReader(buffer); var imagePointer = (byte*)imageData.Scan0; // Moved Regions var movedRegions = reader.ReadUnsignedVariableLength(); if (movedRegions != 0) { var tempBuffer = new byte[bitmap.Width * bitmap.Height * 4]; fixed (byte* tempBufferPointer = &tempBuffer[0]) { for (var n = 0; n < movedRegions; n++) { var fromX = reader.ReadUnsignedVariableLength(); var fromY = reader.ReadUnsignedVariableLength(); var toX = reader.ReadUnsignedVariableLength(); var toY = reader.ReadUnsignedVariableLength(); var width = reader.ReadUnsignedVariableLength(); var height = reader.ReadUnsignedVariableLength(); var region = new MovedRegion { FromX = fromX, FromY = fromY, Height = height, ToX = toX, ToY = toY, Width = width }; CopyRegion(imagePointer, tempBufferPointer, bitmap.Width, region); CopyRegion(tempBufferPointer, imagePointer, bitmap.Width, region); } } } // Modified Regions var s = 0; while (reader.Position < count) { var i = reader.ReadSignedVariableLength(); var pointer = imagePointer + s + i; var bg = reader.ReadByte(); var gr = reader.ReadByte(); pointer[0] = (byte)(bg & 248); pointer[1] = (byte)((bg & 7) << 5 | (gr & 7) << 2); pointer[2] = (byte)(gr & 248); s += i; } bitmap.UnlockBits(imageData); }