/// <summary> /// Copies a region of the framebuffer into a bitmap. /// </summary> /// <param name="source">The framebuffer to read.</param> /// <param name="sourceRectangle">The framebuffer region to copy.</param> /// <param name="scan0">The bitmap buffer start address</param> /// <param name="stride">The bitmap width stride</param> /// <param name="targetX">The leftmost X coordinate of the bitmap to draw to.</param> /// <param name="targetY">The topmost Y coordinate of the bitmap to draw to.</param> public static unsafe void CopyFromFramebuffer( VncFramebuffer source, VncRectangle sourceRectangle, IntPtr scan0, int stride, int targetX, int targetY) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (sourceRectangle.IsEmpty) { return; } fixed(byte *framebufferData = source.GetBuffer()) { VncPixelFormat.Copy( (IntPtr)framebufferData, source.Stride, source.PixelFormat, sourceRectangle, scan0, stride, new VncPixelFormat()); } }
private void NegotiateDesktop() { this.c.SendByte((byte)(this.options.ShareDesktop ? 1 : 0)); var width = this.c.ReceiveUInt16BE(); VncStream.SanityCheck(width > 0 && width < 0x8000); var height = this.c.ReceiveUInt16BE(); VncStream.SanityCheck(height > 0 && height < 0x8000); VncPixelFormat pixelFormat; try { pixelFormat = VncPixelFormat.Decode(this.c.Receive(VncPixelFormat.Size), 0); } catch (ArgumentException e) { throw new VncException( "Unsupported pixel format.", VncFailureReason.UnsupportedPixelFormat, e); } var name = this.c.ReceiveString(); this.Framebuffer = new VncFramebuffer(name, width, height, pixelFormat); }
/// <summary> /// <para> /// Copies pixels. A format conversion is performed if necessary. /// </para> /// <para> /// Be sure to lock <see cref="VncFramebuffer.SyncRoot"/> first to avoid tearing, /// if the connection is active. /// </para> /// </summary> /// <param name="source">A pointer to the upper-left corner of the source.</param> /// <param name="sourceStride">The offset in the source between one Y coordinate and the next.</param> /// <param name="sourceFormat">The source pixel format.</param> /// <param name="sourceRectangle">The rectangle in the source to decode.</param> /// <param name="target">A pointer to the upper-left corner of the target.</param> /// <param name="targetStride">The offset in the target between one Y coordinate and the next.</param> /// <param name="targetFormat">The target pixel format.</param> /// <param name="targetX">The X coordinate in the target that the leftmost pixel should be placed into.</param> /// <param name="targetY">The Y coordinate in the target that the topmost pixel should be placed into.</param> public static unsafe void Copy( IntPtr source, int sourceStride, VncPixelFormat sourceFormat, VncRectangle sourceRectangle, IntPtr target, int targetStride, VncPixelFormat targetFormat, int targetX = 0, int targetY = 0) { Throw.If.True(source == IntPtr.Zero, "source").True(target == IntPtr.Zero, "target"); Throw.If.Null(sourceFormat, "sourceFormat").Null(targetFormat, "targetFormat"); if (sourceRectangle.IsEmpty) { return; } int x = sourceRectangle.X, w = sourceRectangle.Width; int y = sourceRectangle.Y, h = sourceRectangle.Height; var sourceData = (byte *)(void *)source + (y * sourceStride) + (x * sourceFormat.BytesPerPixel); var targetData = (byte *)(void *)target + (targetY * targetStride) + (targetX * targetFormat.BytesPerPixel); if (sourceFormat.Equals(targetFormat)) { for (int iy = 0; iy < h; iy++) { if (sourceFormat.BytesPerPixel == 4) { uint *sourceDataX0 = (uint *)sourceData, targetDataX0 = (uint *)targetData; for (int ix = 0; ix < w; ix++) { *targetDataX0++ = *sourceDataX0++; } } else { int bytes = w * sourceFormat.BytesPerPixel; byte *sourceDataX0 = (byte *)sourceData, targetDataX0 = (byte *)targetData; for (int ib = 0; ib < bytes; ib++) { *targetDataX0++ = *sourceDataX0++; } } sourceData += sourceStride; targetData += targetStride; } } }
/// <summary> /// Initializes a new instance of the <see cref="VncFramebuffer"/> class. /// </summary> /// <param name="name">The framebuffer name. Many VNC clients set their titlebar to this name.</param> /// <param name="width">The framebuffer width.</param> /// <param name="height">The framebuffer height.</param> /// <param name="pixelFormat">The framebuffer pixel format.</param> public VncFramebuffer(string name, int width, int height, VncPixelFormat pixelFormat) { Throw.If.Null(name, "name"); Throw.If.Negative(width, "width").Negative(height, "height"); Throw.If.Null(pixelFormat, "pixelFormat"); this.Name = name; this.Width = width; this.Height = height; this.PixelFormat = pixelFormat; this.Stride = this.PixelFormat.BytesPerPixel * this.Width; this.SyncRoot = new object(); this.buffer = new byte[this.Width * this.Height * this.PixelFormat.BytesPerPixel]; }
/// <summary> /// Copies pixels between two byte arrays. A format conversion is performed if necessary. /// /// Be sure to lock <see cref="VncFramebuffer.SyncRoot"/> first to avoid tearing, /// if the connection is active. /// </summary> /// <param name="source">A pointer to the upper-left corner of the source.</param> /// <param name="sourceWidth">The width of the source image.</param> /// <param name="sourceStride">The offset in the source between one Y coordinate and the next.</param> /// <param name="sourceFormat">The source pixel format.</param> /// <param name="sourceRectangle">The rectangle in the source to decode.</param> /// <param name="target">A pointer to the upper-left corner of the target.</param> /// <param name="targetWidth">The width of the target image.</param> /// <param name="targetStride">The offset in the target between one Y coordinate and the next.</param> /// <param name="targetFormat">The target pixel format.</param> /// <param name="targetX">The X coordinate in the target that the leftmost pixel should be placed into.</param> /// <param name="targetY">The Y coordinate in the target that the topmost pixel should be placed into.</param> public static unsafe void Copy( byte[] source, int sourceWidth, int sourceStride, VncPixelFormat sourceFormat, VncRectangle sourceRectangle, byte[] target, int targetWidth, int targetStride, VncPixelFormat targetFormat, int targetX = 0, int targetY = 0) { Throw.If.Null(source, "source").Null(target, "target"); if (sourceRectangle.IsEmpty) { return; } int x = sourceRectangle.X, w = sourceRectangle.Width; int y = sourceRectangle.Y, h = sourceRectangle.Height; if (sourceFormat.Equals(targetFormat)) { if (sourceRectangle.Width == sourceWidth && sourceWidth == targetWidth && sourceStride == targetStride) { int sourceStart = sourceStride * y; int length = targetStride * h; Buffer.BlockCopy(source, sourceStart, target, 0, length); } else { for (int iy = 0; iy < h; iy++) { int sourceStart = (sourceStride * (iy + y)) + (x * sourceFormat.BitsPerPixel / 8); int targetStart = targetStride * iy; int length = w * sourceFormat.BitsPerPixel / 8; Buffer.BlockCopy(source, sourceStart, target, targetStart, length); } } } }
/// <summary> /// Loads the framebuffer from the specified location and returns a function that can be used to copy the data to a bitmap. /// </summary> /// <param name="x">The x offset. (0 if null)</param> /// <param name="y">The y offset. (0 if null)</param> /// <param name="width">The width. (Framebuffer.Width if null)</param> /// <param name="height">The height (Framebuffer.Height if null)</param> /// <returns>An action with 2 parameters (BitmapData.Scan0 and BitmapData.Stride) that copies the framebuffer data to the specfied address</returns> public Action <IntPtr, int> GetFramebuffer(int?x = null, int?y = null, int?width = null, int?height = null) { var xValue = x ?? 0; var yValue = y ?? 0; var widthValue = width ?? this.Framebuffer.Width; var heightValue = height ?? this.Framebuffer.Height; this.SendFramebufferUpdateRequest(false, xValue, yValue, widthValue, heightValue); ResponseType handledResponse; do { handledResponse = this.HandleResponse(); if (handledResponse == ResponseType.DesktopSize) { this.SendFramebufferUpdateRequest(false, xValue, yValue, widthValue, heightValue); } }while (handledResponse != ResponseType.FramebufferUpdate); return((scan0, stride) => VncPixelFormat.CopyFromFramebuffer( this.Framebuffer, new VncRectangle(xValue, yValue, widthValue, heightValue), scan0, stride, 0, 0)); }