Stores pixel data for a VNC session.
Наследование: IVncFramebufferSource
Пример #1
0
        /// <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());
            }
        }
Пример #2
0
        /// <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="target">The bitmap to copy into.</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 unsafe static void CopyFromFramebuffer(VncFramebuffer source, VncRectangle sourceRectangle,
                                                      Bitmap target, int targetX, int targetY)
        {
            Throw.If.Null(source, "source").Null(target, "target");
            if (sourceRectangle.IsEmpty) { return; }

            var winformsRect = new Rectangle(targetX, targetY, sourceRectangle.Width, sourceRectangle.Height);
            var data = target.LockBits(winformsRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
            try
            {
                fixed (byte* framebufferData = source.GetBuffer())
                {
                    VncPixelFormat.Copy((IntPtr)framebufferData, source.Stride, source.PixelFormat, sourceRectangle,
                                        data.Scan0, data.Stride, new VncPixelFormat());
                }
            }
            finally
            {
                target.UnlockBits(data);
            }
        }
Пример #3
0
        void NegotiateDesktop()
        {
            _c.SendByte((byte)(_options.ShareDesktop ? 1 : 0));

            var width  = _c.ReceiveUInt16BE(); VncStream.SanityCheck(width > 0 && width < 0x8000);
            var height = _c.ReceiveUInt16BE(); VncStream.SanityCheck(height > 0 && height < 0x8000);

            VncPixelFormat pixelFormat;

            try
            {
                pixelFormat = VncPixelFormat.Decode(_c.Receive(VncPixelFormat.Size), 0);
            }
            catch (ArgumentException e)
            {
                throw new VncException("Unsupported pixel format.",
                                       VncFailureReason.UnsupportedPixelFormat, e);
            }

            var name = _c.ReceiveString();

            Framebuffer = new VncFramebuffer(name, width, height, pixelFormat);
        }
Пример #4
0
        void HandleFramebufferUpdate()
        {
            _c.ReceiveByte(); // padding

            var numRects = _c.ReceiveUInt16BE();
            var rects    = new List <VncRectangle>();

            for (int i = 0; i < numRects; i++)
            {
                var r = _c.ReceiveRectangle();
                int x = r.X, y = r.Y, w = r.Width, h = r.Height;
                VncStream.SanityCheck(w > 0 && w < 0x8000);
                VncStream.SanityCheck(h > 0 && h < 0x8000);

                int fbW = Framebuffer.Width, fbH = Framebuffer.Height, bpp = Framebuffer.PixelFormat.BytesPerPixel;
                var inRange = w <= fbW && h <= fbH && x <= fbW - w && y <= fbH - h; byte[] pixels;

                var encoding = (VncEncoding)_c.ReceiveUInt32BE();
                switch (encoding)
                {
                case VncEncoding.Hextile:     // KVM seems to avoid this now that I support Zlib.
                    var background = new byte[bpp];
                    var foreground = new byte[bpp];

                    for (int ty = 0; ty < h; ty += 16)
                    {
                        int th = Math.Min(16, h - ty);
                        for (int tx = 0; tx < w; tx += 16)
                        {
                            int tw = Math.Min(16, w - tx);

                            var subencoding = _c.ReceiveByte();
                            pixels = AllocateFramebufferScratch(tw * th * bpp);

                            if (0 != (subencoding & 1))     // raw
                            {
                                _c.Receive(pixels, 0, tw * th * bpp);

                                if (inRange)
                                {
                                    lock (Framebuffer.SyncRoot) { CopyToFramebuffer(x + tx, y + ty, tw, th, pixels); }
                                }
                            }
                            else
                            {
                                pixels = AllocateFramebufferScratch(tw * th * bpp);
                                if (0 != (subencoding & 2))
                                {
                                    background = _c.Receive(bpp);
                                }
                                if (0 != (subencoding & 4))
                                {
                                    foreground = _c.Receive(bpp);
                                }

                                int ptr = 0;
                                for (int pp = 0; pp < tw * th; pp++)
                                {
                                    for (int pe = 0; pe < bpp; pe++)
                                    {
                                        pixels[ptr++] = background[pe];
                                    }
                                }

                                int nsubrects = 0 != (subencoding & 8) ? _c.ReceiveByte() : 0;
                                if (nsubrects > 0)
                                {
                                    var subrectsColored = 0 != (subencoding & 16);
                                    for (int subrect = 0; subrect < nsubrects; subrect++)
                                    {
                                        var color = subrectsColored ? _c.Receive(bpp) : foreground;
                                        var srxy = _c.ReceiveByte(); var srwh = _c.ReceiveByte();
                                        int srx = (srxy >> 4) & 0xf, srw = ((srwh >> 4) & 0xf) + 1;
                                        int sry = (srxy >> 0) & 0xf, srh = ((srwh >> 0) & 0xf) + 1;
                                        if (srx + srw > tw || sry + srh > th)
                                        {
                                            continue;
                                        }

                                        for (int py = 0; py < srh; py++)
                                        {
                                            for (int px = 0; px < srw; px++)
                                            {
                                                int off = bpp * ((py + sry) * tw + (px + srx));
                                                for (int pe = 0; pe < bpp; pe++)
                                                {
                                                    pixels[off + pe] = color[pe];
                                                }
                                            }
                                        }
                                    }
                                }

                                lock (Framebuffer.SyncRoot) { CopyToFramebuffer(x + tx, y + ty, tw, th, pixels); }
                            }
                        }
                    }
                    break;

                case VncEncoding.CopyRect:
                    var srcx = (int)_c.ReceiveUInt16BE();
                    var srcy = (int)_c.ReceiveUInt16BE();
                    if (srcx + w > fbW)
                    {
                        w = fbW - srcx;
                    }
                    if (srcy + h > fbH)
                    {
                        h = fbH - srcy;
                    }
                    if (w < 1 || h < 1)
                    {
                        continue;
                    }

                    pixels = AllocateFramebufferScratch(w * h * bpp);
                    lock (Framebuffer.SyncRoot)
                    {
                        CopyToGeneral(0, 0, w, h, pixels, srcx, srcy, fbW, fbH, Framebuffer.GetBuffer(), w, h);
                        CopyToFramebuffer(x, y, w, h, pixels);
                    }
                    break;

                case VncEncoding.Raw:
                    pixels = AllocateFramebufferScratch(w * h * bpp);
                    _c.Receive(pixels, 0, w * h * bpp);

                    if (inRange)
                    {
                        lock (Framebuffer.SyncRoot) { CopyToFramebuffer(x, y, w, h, pixels); }
                    }
                    break;

                case VncEncoding.Zlib:
                    int bytesDesired = w * h * bpp;

                    int size = (int)_c.ReceiveUInt32BE(); VncStream.SanityCheck(size >= 0 && size < 0x10000000);
                    VncUtility.AllocateScratch(size, ref _zlibScratch);
                    _c.Receive(_zlibScratch, 0, size);

                    _zlibMemoryStream.Position = 0;
                    _zlibMemoryStream.Write(_zlibScratch, 0, size);
                    _zlibMemoryStream.SetLength(size);
                    _zlibMemoryStream.Position = 0;

                    if (_zlibInflater == null)     // Zlib has a two-byte header.
                    {
                        VncStream.SanityCheck(size >= 2); _zlibMemoryStream.Position = 2;
                        _zlibInflater = new DeflateStream(_zlibMemoryStream, CompressionMode.Decompress, false);
                    }

                    pixels = AllocateFramebufferScratch(bytesDesired);
                    for (int j = 0; j < bytesDesired;)
                    {
                        int count = 0;

                        try
                        {
                            count = _zlibInflater.Read(pixels, j, bytesDesired - j);
                        }
                        catch (InvalidDataException)
                        {
                            VncStream.Require(false,
                                              "Bad data compressed.",
                                              VncFailureReason.UnrecognizedProtocolElement);
                        }

                        VncStream.Require(count > 0,
                                          "No data compressed.",
                                          VncFailureReason.UnrecognizedProtocolElement);
                        j += count;
                    }

                    if (inRange)
                    {
                        lock (Framebuffer.SyncRoot) { CopyToFramebuffer(x, y, w, h, pixels); }
                    }
                    break;

                case VncEncoding.PseudoDesktopSize:
                    Framebuffer = new VncFramebuffer(Framebuffer.Name, w, h, Framebuffer.PixelFormat);
                    continue;     // Don't call OnFramebufferChanged for this one.

                default:
                    VncStream.Require(false,
                                      "Unsupported encoding.",
                                      VncFailureReason.UnrecognizedProtocolElement);
                    break;
                }

                rects.Add(new VncRectangle(x, y, w, h));
            }

            if (rects.Count > 0)
            {
                OnFramebufferChanged(new FramebufferChangedEventArgs(rects));
            }
        }
        /// <summary>
        /// Captures the screen.
        /// </summary>
        /// <returns>A framebuffer corresponding to the screen.</returns>
        public VncFramebuffer Capture()
        {
            var bounds = _getScreenBounds();
            int w = bounds.Width, h = bounds.Height;

            if (_bitmap == null || _bitmap.Width != w || _bitmap.Height != h)
            {
                _bitmap = new Bitmap(w, h);
                _framebuffer = new VncFramebuffer(_name, w, h, new VncPixelFormat());
            }

            using (var g = Graphics.FromImage(_bitmap))
            {
                g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size);

                lock (_framebuffer.SyncRoot)
                {
                    VncBitmap.CopyToFramebuffer(_bitmap, new VncRectangle(0, 0, w, h),
                                                _framebuffer, 0, 0);
                }
            }

            return _framebuffer;
        }
Пример #6
0
        void UpdateFramebuffer(bool force, VncFramebuffer framebuffer)
        {
            if (framebuffer == null) { return; }
            int w = framebuffer.Width, h = framebuffer.Height;

            if (_bitmap == null || _bitmap.Width != w || _bitmap.Height != h || force)
            {
                _bitmap = new Bitmap(w, h, PixelFormat.Format32bppRgb);
                VncBitmap.CopyFromFramebuffer(framebuffer, new VncRectangle(0, 0, w, h), _bitmap, 0, 0);
                ClientSize = new Size(w, h); Invalidate();
            }
        }