From d6f194ee8ea17cf2df1fd416b1442f098d2be8a7 Mon Sep 17 00:00:00 2001 From: Hofer Sascha Date: Fri, 18 Aug 2023 16:44:49 +0200 Subject: [PATCH 1/4] RemoteViewing now works with 16bpp instad of 32bpp --- RemoteViewing.Example/MainForm.resx | 120 ++++++++++++++++++++++ RemoteViewing.Windows.Forms/VncBitmap.cs | 4 +- RemoteViewing.Windows.Forms/VncControl.cs | 2 +- RemoteViewing/Vnc/VncPixelFormat.cs | 8 +- 4 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 RemoteViewing.Example/MainForm.resx diff --git a/RemoteViewing.Example/MainForm.resx b/RemoteViewing.Example/MainForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/RemoteViewing.Example/MainForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/RemoteViewing.Windows.Forms/VncBitmap.cs b/RemoteViewing.Windows.Forms/VncBitmap.cs index bb2f77a..8cd58dd 100644 --- a/RemoteViewing.Windows.Forms/VncBitmap.cs +++ b/RemoteViewing.Windows.Forms/VncBitmap.cs @@ -69,7 +69,7 @@ public static unsafe void CopyToFramebuffer( } var winformsRect = new Rectangle(sourceRectangle.X, sourceRectangle.Y, sourceRectangle.Width, sourceRectangle.Height); - var data = source.LockBits(winformsRect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb); + var data = source.LockBits(winformsRect, ImageLockMode.ReadOnly, PixelFormat.Format16bppRgb565); try { fixed (byte* framebufferData = target.GetBuffer()) @@ -113,7 +113,7 @@ public static unsafe void CopyFromFramebuffer( } var winformsRect = new Rectangle(targetX, targetY, sourceRectangle.Width, sourceRectangle.Height); - var data = target.LockBits(winformsRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb); + var data = target.LockBits(winformsRect, ImageLockMode.WriteOnly, PixelFormat.Format16bppRgb565); try { VncPixelFormat.CopyFromFramebuffer(source, sourceRectangle, data.Scan0, data.Stride, targetX, targetY); diff --git a/RemoteViewing.Windows.Forms/VncControl.cs b/RemoteViewing.Windows.Forms/VncControl.cs index 1a492ee..1c66f16 100644 --- a/RemoteViewing.Windows.Forms/VncControl.cs +++ b/RemoteViewing.Windows.Forms/VncControl.cs @@ -327,7 +327,7 @@ private void UpdateFramebuffer(bool force, VncFramebuffer framebuffer) if (this.bitmap == null || this.bitmap.Width != w || this.bitmap.Height != h || force) { - this.bitmap = new Bitmap(w, h, PixelFormat.Format32bppRgb); + this.bitmap = new Bitmap(w, h, PixelFormat.Format16bppRgb565); VncBitmap.CopyFromFramebuffer(framebuffer, new VncRectangle(0, 0, w, h), this.bitmap, 0, 0); this.ScaleFactor = this.GetScaleFactor(framebuffer); diff --git a/RemoteViewing/Vnc/VncPixelFormat.cs b/RemoteViewing/Vnc/VncPixelFormat.cs index d6b75d2..3d41e8d 100644 --- a/RemoteViewing/Vnc/VncPixelFormat.cs +++ b/RemoteViewing/Vnc/VncPixelFormat.cs @@ -40,7 +40,7 @@ public sealed class VncPixelFormat /// with 8 bits each of red, green, and blue channels. /// public VncPixelFormat() - : this(32, 24, 8, 16, 8, 8, 8, 0) + : this(16, 16, 5, 11, 6, 5, 5, 0) { } @@ -74,7 +74,7 @@ public VncPixelFormat( throw new ArgumentOutOfRangeException(nameof(bitsPerPixel)); } - if (bitDepth != 6 && bitDepth != 24) + if (bitDepth != 6 && bitDepth != 16) { throw new ArgumentOutOfRangeException(nameof(bitDepth)); } @@ -248,7 +248,7 @@ public static unsafe void Copy( { throw new ArgumentNullException(nameof(source)); } - + if (target == null) { throw new ArgumentNullException(nameof(target)); @@ -412,7 +412,7 @@ public static unsafe void CopyFromFramebuffer( sourceRectangle, scan0, stride, - new VncPixelFormat()); + source.PixelFormat); } } From 51672bfccf04e3a5a214d975eb6fe51e50d0b211 Mon Sep 17 00:00:00 2001 From: Sascha Hofer Date: Wed, 23 Aug 2023 11:14:42 +0200 Subject: [PATCH 2/4] Replaced default VncPixelFormat constructor which implicitely created an RGB32 Pixelformat and defined a static default VncPixelFormat which explicitely states what it does. --- .../DummyFramebufferSource.cs | 2 +- .../Vnc/Server/RawEncoderTests.cs | 2 +- .../Vnc/Server/TightEncoderTests.cs | 2 +- .../Vnc/Server/ZlibEncoderTests.cs | 4 ++-- .../Vnc/VncPixelFormatTests.cs | 8 ++++---- RemoteViewing.Windows.Forms/VncBitmap.cs | 2 +- RemoteViewing/Vnc/VncPixelFormat.cs | 19 +++++++------------ 7 files changed, 17 insertions(+), 22 deletions(-) diff --git a/RemoteViewing.NoVncExample/DummyFramebufferSource.cs b/RemoteViewing.NoVncExample/DummyFramebufferSource.cs index f6f15d7..205a5c7 100644 --- a/RemoteViewing.NoVncExample/DummyFramebufferSource.cs +++ b/RemoteViewing.NoVncExample/DummyFramebufferSource.cs @@ -106,7 +106,7 @@ public VncFramebuffer Capture() || this.framebuffer.Width != image.Width || this.framebuffer.Height != image.Height) { - this.framebuffer = new VncFramebuffer("Quamotion", image.Width, image.Height, new VncPixelFormat()); + this.framebuffer = new VncFramebuffer("Quamotion", image.Width, image.Height, VncPixelFormat.RGB32); } lock (this.framebuffer.SyncRoot) diff --git a/RemoteViewing.Tests/Vnc/Server/RawEncoderTests.cs b/RemoteViewing.Tests/Vnc/Server/RawEncoderTests.cs index 98a9085..c5debe8 100644 --- a/RemoteViewing.Tests/Vnc/Server/RawEncoderTests.cs +++ b/RemoteViewing.Tests/Vnc/Server/RawEncoderTests.cs @@ -61,7 +61,7 @@ public void SendTest() using (MemoryStream stream = new MemoryStream()) { // The encoder should write the content 'as is' to the stream. - encoder.Send(stream, new VncPixelFormat(), default(VncRectangle), content); + encoder.Send(stream, VncPixelFormat.RGB32, default(VncRectangle), content); Assert.Equal(content, stream.ToArray()); } diff --git a/RemoteViewing.Tests/Vnc/Server/TightEncoderTests.cs b/RemoteViewing.Tests/Vnc/Server/TightEncoderTests.cs index cdf2d50..b3816ed 100644 --- a/RemoteViewing.Tests/Vnc/Server/TightEncoderTests.cs +++ b/RemoteViewing.Tests/Vnc/Server/TightEncoderTests.cs @@ -183,7 +183,7 @@ public void SendSmallRectangleFormat() using (MemoryStream output = new MemoryStream()) { var contents = new byte[] { 0x01, 0x02, 0x03, 0x04 }; - encoder.Send(output, new VncPixelFormat(), default, contents); + encoder.Send(output, VncPixelFormat.RGB32, default, contents); raw = output.ToArray(); } diff --git a/RemoteViewing.Tests/Vnc/Server/ZlibEncoderTests.cs b/RemoteViewing.Tests/Vnc/Server/ZlibEncoderTests.cs index 1cbe96d..8a78b6b 100644 --- a/RemoteViewing.Tests/Vnc/Server/ZlibEncoderTests.cs +++ b/RemoteViewing.Tests/Vnc/Server/ZlibEncoderTests.cs @@ -66,11 +66,11 @@ public void SendTest() // Individual rectangles are compressed using the _same_ zlib stream. Let's send two // rectangles to make sure this is the case. - encoder.Send(output, new VncPixelFormat(), default(VncRectangle), contents); + encoder.Send(output, VncPixelFormat.RGB32, default(VncRectangle), contents); raw1 = output.ToArray(); output.SetLength(0); - encoder.Send(output, new VncPixelFormat(), default(VncRectangle), contents); + encoder.Send(output, VncPixelFormat.RGB32, default(VncRectangle), contents); raw2 = output.ToArray(); } diff --git a/RemoteViewing.Tests/Vnc/VncPixelFormatTests.cs b/RemoteViewing.Tests/Vnc/VncPixelFormatTests.cs index 3bef0d9..aeb3079 100644 --- a/RemoteViewing.Tests/Vnc/VncPixelFormatTests.cs +++ b/RemoteViewing.Tests/Vnc/VncPixelFormatTests.cs @@ -45,7 +45,7 @@ public class VncPixelFormatTests public void ConstructorTest() { // Default pixel format should be RGB32. - var pixelFormat = new VncPixelFormat(); + var pixelFormat = VncPixelFormat.RGB32; Assert.Equal(24, pixelFormat.BitDepth); Assert.Equal(32, pixelFormat.BitsPerPixel); Assert.Equal(4, pixelFormat.BytesPerPixel); @@ -76,9 +76,9 @@ public void ConstuctorInvalidValuesTest() Assert.Throws(() => new VncPixelFormat(4, 1, 1, 0, 1, 0, 1, 0)); Assert.Throws(() => new VncPixelFormat(24, 1, 1, 0, 1, 0, 1, 0)); - // Only bit depth of 8 or 24 + // Only bit depth of 8 or 16 or 24 Assert.Throws(() => new VncPixelFormat(8, 2, 1, 0, 1, 0, 1, 0)); - Assert.Throws(() => new VncPixelFormat(16, 16, 1, 0, 1, 0, 1, 0)); + Assert.Throws(() => new VncPixelFormat(16, 14, 1, 0, 1, 0, 1, 0)); // Red: negative bits or shift, or bits or shift > bit depth Assert.Throws(() => new VncPixelFormat(8, 24, -1, 0, 8, 0, 8, 0)); @@ -105,7 +105,7 @@ public void ConstuctorInvalidValuesTest() [Fact] public void EncodeTest() { - var pixelFormat = new VncPixelFormat(); + var pixelFormat = VncPixelFormat.RGB32; var buffer = new byte[VncPixelFormat.Size]; pixelFormat.Encode(buffer, 0); diff --git a/RemoteViewing.Windows.Forms/VncBitmap.cs b/RemoteViewing.Windows.Forms/VncBitmap.cs index 8cd58dd..117fb54 100644 --- a/RemoteViewing.Windows.Forms/VncBitmap.cs +++ b/RemoteViewing.Windows.Forms/VncBitmap.cs @@ -77,7 +77,7 @@ public static unsafe void CopyToFramebuffer( VncPixelFormat.Copy( data.Scan0, data.Stride, - new VncPixelFormat(), + VncPixelFormat.RGB32, sourceRectangle, (IntPtr)framebufferData, target.Stride, diff --git a/RemoteViewing/Vnc/VncPixelFormat.cs b/RemoteViewing/Vnc/VncPixelFormat.cs index 3d41e8d..eaa2f7f 100644 --- a/RemoteViewing/Vnc/VncPixelFormat.cs +++ b/RemoteViewing/Vnc/VncPixelFormat.cs @@ -35,15 +35,6 @@ namespace RemoteViewing.Vnc /// public sealed class VncPixelFormat { - /// - /// Initializes a new instance of the class, - /// with 8 bits each of red, green, and blue channels. - /// - public VncPixelFormat() - : this(16, 16, 5, 11, 6, 5, 5, 0) - { - } - /// /// Initializes a new instance of the class. /// @@ -74,7 +65,7 @@ public VncPixelFormat( throw new ArgumentOutOfRangeException(nameof(bitsPerPixel)); } - if (bitDepth != 6 && bitDepth != 16) + if (bitDepth != 6 && bitDepth != 16 && bitDepth != 24) { throw new ArgumentOutOfRangeException(nameof(bitDepth)); } @@ -108,10 +99,14 @@ public VncPixelFormat( } /// - /// Gets a with 8 bits of red, green and blue channels. + /// Gets a with 32bits per pixel, 8 bits of red, green and blue channels. /// - public static VncPixelFormat RGB32 { get; } = new VncPixelFormat(); + public static VncPixelFormat RGB32 { get; } = new VncPixelFormat(32, 24, 8, 16, 8, 8, 8, 0); + /// + /// Gets a with 16 bits per pixel with 5 bits of red, 6 bits of green and 5 bits of blue channels. + /// + public static VncPixelFormat RGB16 { get; } = new VncPixelFormat(16, 16, 5, 11, 6, 5, 5, 0); /// /// Gets the number of bits used to store a pixel. /// From e2bd8af515ce6e8b83cba0570f81e6895dc9fb9e Mon Sep 17 00:00:00 2001 From: Sascha Hofer Date: Wed, 23 Aug 2023 15:15:29 +0200 Subject: [PATCH 3/4] Added a VncPixelFormatExtension to convert to System.Drawing.PixelFormat --- RemoteViewing.Example/MainForm.resx | 120 ------------------ RemoteViewing.Windows.Forms/VncControl.cs | 4 +- .../VncPixelFormatExtensions.cs | 21 +++ 3 files changed, 24 insertions(+), 121 deletions(-) delete mode 100644 RemoteViewing.Example/MainForm.resx create mode 100644 RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs diff --git a/RemoteViewing.Example/MainForm.resx b/RemoteViewing.Example/MainForm.resx deleted file mode 100644 index 1af7de1..0000000 --- a/RemoteViewing.Example/MainForm.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/RemoteViewing.Windows.Forms/VncControl.cs b/RemoteViewing.Windows.Forms/VncControl.cs index 1c66f16..12095ab 100644 --- a/RemoteViewing.Windows.Forms/VncControl.cs +++ b/RemoteViewing.Windows.Forms/VncControl.cs @@ -316,6 +316,8 @@ private void ClearInputState() this.keysyms.Clear(); } + + private void UpdateFramebuffer(bool force, VncFramebuffer framebuffer) { if (framebuffer == null) @@ -327,7 +329,7 @@ private void UpdateFramebuffer(bool force, VncFramebuffer framebuffer) if (this.bitmap == null || this.bitmap.Width != w || this.bitmap.Height != h || force) { - this.bitmap = new Bitmap(w, h, PixelFormat.Format16bppRgb565); + this.bitmap = new Bitmap(w, h, framebuffer.PixelFormat.ToSystemDrawingPixelFormat()); VncBitmap.CopyFromFramebuffer(framebuffer, new VncRectangle(0, 0, w, h), this.bitmap, 0, 0); this.ScaleFactor = this.GetScaleFactor(framebuffer); diff --git a/RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs b/RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs new file mode 100644 index 0000000..66d7427 --- /dev/null +++ b/RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs @@ -0,0 +1,21 @@ +using System; +using System.Drawing.Imaging; +using RemoteViewing.Vnc; + +namespace RemoteViewing.Windows.Forms +{ + internal static class VncPixelFormatExtensions + { + + internal static PixelFormat ToSystemDrawingPixelFormat(this VncPixelFormat vncPixelFormat) + { + if (vncPixelFormat.Equals(VncPixelFormat.RGB16)) + return PixelFormat.Format16bppRgb565; + + if (vncPixelFormat.Equals(VncPixelFormat.RGB32)) + return PixelFormat.Format32bppRgb; + + throw new NotSupportedException($"PixelFormat not supported: {vncPixelFormat}"); + } + } +} From 1693121dbd2cb0c3fadd5889c610d4b97ac4d88e Mon Sep 17 00:00:00 2001 From: Sascha Hofer Date: Wed, 23 Aug 2023 15:40:24 +0200 Subject: [PATCH 4/4] Added support for 16bpp RGB565 --- RemoteViewing.Windows.Forms/VncBitmap.cs | 6 ++-- .../VncPixelFormatExtensions.cs | 21 ------------ ...ormatSystemDrawingPixelFormatExtensions.cs | 34 +++++++++++++++++++ 3 files changed, 37 insertions(+), 24 deletions(-) delete mode 100644 RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs create mode 100644 RemoteViewing.Windows.Forms/VncPixelFormatSystemDrawingPixelFormatExtensions.cs diff --git a/RemoteViewing.Windows.Forms/VncBitmap.cs b/RemoteViewing.Windows.Forms/VncBitmap.cs index 117fb54..4ce137e 100644 --- a/RemoteViewing.Windows.Forms/VncBitmap.cs +++ b/RemoteViewing.Windows.Forms/VncBitmap.cs @@ -69,7 +69,7 @@ public static unsafe void CopyToFramebuffer( } var winformsRect = new Rectangle(sourceRectangle.X, sourceRectangle.Y, sourceRectangle.Width, sourceRectangle.Height); - var data = source.LockBits(winformsRect, ImageLockMode.ReadOnly, PixelFormat.Format16bppRgb565); + var data = source.LockBits(winformsRect, ImageLockMode.ReadOnly, source.PixelFormat); try { fixed (byte* framebufferData = target.GetBuffer()) @@ -77,7 +77,7 @@ public static unsafe void CopyToFramebuffer( VncPixelFormat.Copy( data.Scan0, data.Stride, - VncPixelFormat.RGB32, + data.PixelFormat.ToVncPixelFormat(), sourceRectangle, (IntPtr)framebufferData, target.Stride, @@ -113,7 +113,7 @@ public static unsafe void CopyFromFramebuffer( } var winformsRect = new Rectangle(targetX, targetY, sourceRectangle.Width, sourceRectangle.Height); - var data = target.LockBits(winformsRect, ImageLockMode.WriteOnly, PixelFormat.Format16bppRgb565); + var data = target.LockBits(winformsRect, ImageLockMode.WriteOnly, target.PixelFormat); try { VncPixelFormat.CopyFromFramebuffer(source, sourceRectangle, data.Scan0, data.Stride, targetX, targetY); diff --git a/RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs b/RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs deleted file mode 100644 index 66d7427..0000000 --- a/RemoteViewing.Windows.Forms/VncPixelFormatExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Drawing.Imaging; -using RemoteViewing.Vnc; - -namespace RemoteViewing.Windows.Forms -{ - internal static class VncPixelFormatExtensions - { - - internal static PixelFormat ToSystemDrawingPixelFormat(this VncPixelFormat vncPixelFormat) - { - if (vncPixelFormat.Equals(VncPixelFormat.RGB16)) - return PixelFormat.Format16bppRgb565; - - if (vncPixelFormat.Equals(VncPixelFormat.RGB32)) - return PixelFormat.Format32bppRgb; - - throw new NotSupportedException($"PixelFormat not supported: {vncPixelFormat}"); - } - } -} diff --git a/RemoteViewing.Windows.Forms/VncPixelFormatSystemDrawingPixelFormatExtensions.cs b/RemoteViewing.Windows.Forms/VncPixelFormatSystemDrawingPixelFormatExtensions.cs new file mode 100644 index 0000000..b57cbf6 --- /dev/null +++ b/RemoteViewing.Windows.Forms/VncPixelFormatSystemDrawingPixelFormatExtensions.cs @@ -0,0 +1,34 @@ +using System; +using System.Drawing.Imaging; +using RemoteViewing.Vnc; + +namespace RemoteViewing.Windows.Forms +{ + internal static class VncPixelFormatSystemDrawingPixelFormatExtensions + { + + internal static PixelFormat ToSystemDrawingPixelFormat(this VncPixelFormat vncPixelFormat) + { + if (vncPixelFormat.Equals(VncPixelFormat.RGB16)) + return PixelFormat.Format16bppRgb565; + + if (vncPixelFormat.Equals(VncPixelFormat.RGB32)) + return PixelFormat.Format32bppRgb; + + throw new NotSupportedException($"PixelFormat not supported: {vncPixelFormat}"); + } + + internal static VncPixelFormat ToVncPixelFormat(this PixelFormat pixelFormat) + { + switch (pixelFormat) + { + case PixelFormat.Format16bppRgb565: + return VncPixelFormat.RGB16; + case PixelFormat.Format32bppRgb: + return VncPixelFormat.RGB32; + default: + throw new NotSupportedException($"The pixelformat '{pixelFormat}' is not supported."); + } + } + } +}