diff options
| author | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-03-02 23:30:34 +0200 |
|---|---|---|
| committer | Roy Ben Shabat <Roy.mail.net@gmail.com> | 2020-03-02 23:30:34 +0200 |
| commit | 0dcd742a3c35527386a93e1b1ef761c2aeff8308 (patch) | |
| tree | d5adb3fee35e73af95fa5d68b5316d25522471de /Software/Visual_Studio/Tango.RemoteDesktop/Frames | |
| parent | 1a7fb274158f8a0e279aef26206a65fefac8c4c3 (diff) | |
| download | Tango-0dcd742a3c35527386a93e1b1ef761c2aeff8308.tar.gz Tango-0dcd742a3c35527386a93e1b1ef761c2aeff8308.zip | |
Implemented Tango.RemoteDesktop.
Implemented png 8 bit quantization.
Implemented RasterFrame bounds clipping.
Refactored VectorFrame to use indexed colors.
Diffstat (limited to 'Software/Visual_Studio/Tango.RemoteDesktop/Frames')
4 files changed, 488 insertions, 0 deletions
diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Frames/RasterFrame.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/RasterFrame.cs new file mode 100644 index 000000000..bcb372bd3 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/RasterFrame.cs @@ -0,0 +1,134 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media.Imaging; +using Tango.RemoteDesktop.Clipping; + +namespace Tango.RemoteDesktop.Frames +{ + /// <summary> + /// Represents a raster frame encapsulating a standard GDI bitmap. + /// </summary> + /// <seealso cref="Tango.RemoteDesktop.Frame" /> + public class RasterFrame : Frame + { + private Bitmap _bitmap; + + /// <summary> + /// Gets the left position of this frame. + /// Will always be 0 unless <see cref="OptimizeBounds"/> was called. + /// </summary> + public int Left { get; private set; } + + /// <summary> + /// Gets the top position of this frame. + /// Will always be 0 unless <see cref="OptimizeBounds"/> was called. + /// </summary> + public int Top { get; private set; } + + /// <summary> + /// Gets the frame width. + /// </summary> + public override int Width + { + get { return _bitmap.Width; } + } + + /// <summary> + /// Gets the frame height. + /// </summary> + public override int Height + { + get { return _bitmap.Height; } + } + + /// <summary> + /// Initializes a new instance of the <see cref="RasterFrame"/> class. + /// </summary> + /// <param name="bitmap">The bitmap.</param> + public RasterFrame(Bitmap bitmap) + { + _bitmap = bitmap; + } + + /// <summary> + /// Initializes a new instance of the <see cref="RasterFrame"/> class. + /// </summary> + /// <param name="bitmap">The bitmap.</param> + /// <param name="left">The left position of the frame.</param> + /// <param name="top">The top position of the frame.</param> + public RasterFrame(Bitmap bitmap, int left, int top) : this(bitmap) + { + Left = left; + Top = top; + } + + /// <summary> + /// Returns a GDI bitmap representing the frame. + /// </summary> + /// <returns></returns> + public override Bitmap ToBitmap() + { + return _bitmap; + } + + /// <summary> + /// Scales the frame by the specified coefficient. + /// </summary> + /// <param name="coefficient">The coefficient.</param> + /// <returns></returns> + public RasterFrame Scale(float coefficient) + { + var scaled = new Bitmap(_bitmap, new Size((int)(Width * coefficient), (int)(Height * coefficient))); + _bitmap.Dispose(); + _bitmap = scaled; + return this; + } + + /// <summary> + /// Applies this frame onto an existing bitmap. + /// </summary> + /// <param name="bitmap">The bitmap.</param> + public override void Apply(Bitmap bitmap) + { + if (Top == 0 && Left == 0) + { + base.Apply(bitmap); + } + else + { + using (Graphics g = Graphics.FromImage(bitmap)) + { + g.DrawImage(_bitmap, new Rectangle(Left, Top, Width, Height)); + } + } + } + + /// <summary> + /// Optimizes the bounds of this frame by removing unnecessary margins. + /// </summary> + /// <returns></returns> + public RasterFrame OptimizeBounds() + { + var result = BitmapCliper.ClipBitmap(_bitmap); + _bitmap.Dispose(); + Left = result.Bounds.Left; + Top = result.Bounds.Top; + _bitmap = result.Bitmap; + return this; + } + + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + public override void Dispose() + { + _bitmap.Dispose(); + } + } +} diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrame.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrame.cs new file mode 100644 index 000000000..89287ad42 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrame.cs @@ -0,0 +1,227 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.RemoteDesktop.Utils; + +namespace Tango.RemoteDesktop.Frames +{ + /// <summary> + /// Represents a vector frame encapsulating a set of <see cref="VectorFramePixel"/>. + /// </summary> + /// <seealso cref="Tango.RemoteDesktop.Frame" /> + public class VectorFrame : Frame + { + private int _width; + /// <summary> + /// Gets the frame width. + /// </summary> + public override int Width + { + get { return _width; } + } + + private int _height; + /// <summary> + /// Gets the frame height. + /// </summary> + public override int Height + { + get { return _height; } + } + + /// <summary> + /// Gets or sets the colors dictionary. + /// </summary> + public Dictionary<int, VectorFrameColor> Colors { get; set; } + + /// <summary> + /// Gets the pixels. + /// </summary> + /// <value> + /// The pixels. + /// </value> + public List<VectorFramePixel> Pixels { get; private set; } + + /// <summary> + /// Initializes a new instance of the <see cref="VectorFrame"/> class. + /// </summary> + /// <param name="width">The frame width.</param> + /// <param name="height">The frame height.</param> + public VectorFrame(int width, int height) + { + _width = width; + _height = height; + Pixels = new List<VectorFramePixel>(); + Colors = new Dictionary<int, VectorFrameColor>(); + } + + /// <summary> + /// Returns a GDI bitmap representing the frame. + /// </summary> + /// <returns></returns> + public override Bitmap ToBitmap() + { + DirectBitmap directBitmap = new DirectBitmap(Width, Height); + foreach (var pixel in Pixels) + { + directBitmap.SetPixel((int)pixel.X, (int)pixel.Y, pixel.Color.ToColor()); + } + + directBitmap.Dispose(); + return directBitmap.Bitmap; + } + + /// <summary> + /// Applies this frame onto an existing bitmap. + /// </summary> + /// <param name="bitmap">The bitmap.</param> + public override void Apply(Bitmap bitmap) + { + using (FastBitmap fast = bitmap.FastLock()) + { + foreach (var pixel in Pixels) + { + fast.SetPixel((int)pixel.X, (int)pixel.Y, pixel.Color.ToColor()); + } + } + } + + /// <summary> + /// Returns a byte array containing the binary serialized version of this frame. + /// </summary> + /// <returns></returns> + public byte[] Serialize() + { + using (MemoryStream ms = new MemoryStream()) + { + using (BinaryWriter writer = new BinaryWriter(ms)) + { + writer.Write((UInt16)Width); + writer.Write((UInt16)Height); + writer.Write((UInt16)Colors.Count); + + if (Colors.Count > UInt16.MaxValue) + { + throw new InvalidOperationException("Number of color exceeded the maximum colors allowed."); + } + + foreach (var color in Colors) + { + writer.Write(color.Value.R); + writer.Write(color.Value.G); + writer.Write(color.Value.B); + } + + foreach (var pixel in Pixels) + { + writer.Write((UInt16)pixel.X); + writer.Write((UInt16)pixel.ColorIndex); + } + + ms.Position = 0; + return ms.ToArray(); + } + } + } + + /// <summary> + /// Calculates the size of <see cref="Serialize"/> byte output. + /// </summary> + /// <returns></returns> + public int CalculateSize() + { + int size = 0; + + size += sizeof(int) * 3; //Width, Height, Count + size += sizeof(ushort) * 2 * Pixels.Count; //X, Y + size += sizeof(byte) * 3 * Pixels.Count; //RGB + + return size; + } + + /// <summary> + /// Creates a new instance of <see cref="VectorFrame"/> from the specified serialized byte array. + /// </summary> + /// <param name="data">The byte array.</param> + /// <returns></returns> + public static VectorFrame Deserialize(byte[] data) + { + using (MemoryStream ms = new MemoryStream(data)) + { + using (BinaryReader reader = new BinaryReader(ms)) + { + ms.Position = 0; + var vector = new VectorFrame(reader.ReadUInt16(), reader.ReadUInt16()); + + int colorCount = reader.ReadUInt16(); //Number of colors in color table. + + for (int i = 0; i < colorCount; i++) + { + VectorFrameColor color = new VectorFrameColor() + { + R = reader.ReadByte(), + G = reader.ReadByte(), + B = reader.ReadByte(), + Index = i, + }; + + vector.Colors.Add(color.ToInt32(), color); + } + + for (int i = 0; i < vector.Height; i++) + { + VectorFramePixel pixel = new VectorFramePixel(); + pixel.X = reader.ReadUInt16(); + pixel.Y = i; + pixel.ColorIndex = reader.ReadUInt16(); + pixel.Color = vector.Colors.ElementAt(pixel.ColorIndex).Value; + vector.Pixels.Add(pixel); + } + + return vector; + } + } + } + + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + public override void Dispose() + { + Pixels.Clear(); + Pixels = null; + } + + #region Color Helpers + + /// <summary> + /// Converts the specified color to integer. + /// </summary> + /// <param name="color">The color.</param> + /// <returns></returns> + public static int ColorToInteger(byte r, byte g, byte b) + { + return (int)((255 << 24) | (r << 16) | (g << 8) | (b << 0)); + } + + /// <summary> + /// Converts the specified integer to color. + /// </summary> + /// <param name="integer">The integer.</param> + /// <returns></returns> + public static Color IntegerToColor(int integer) + { + byte a = (byte)(integer >> 24); + byte r = (byte)(integer >> 16); + byte g = (byte)(integer >> 8); + byte b = (byte)(integer >> 0); + return Color.FromArgb(a, r, g, b); + } + + #endregion + } +} diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrameColor.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrameColor.cs new file mode 100644 index 000000000..4bdb9ab68 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrameColor.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.RemoteDesktop.Frames +{ + public struct VectorFrameColor + { + /// <summary> + /// Gets or sets the pixel color red component. + /// </summary> + public byte R { get; set; } + + /// <summary> + /// Gets or sets the pixel color green component. + /// </summary> + public byte G { get; set; } + + /// <summary> + /// Gets or sets the pixel color blue component. + /// </summary> + public byte B { get; set; } + + /// <summary> + /// Gets or sets the color index within the dictionary. + /// </summary> + public int Index { get; set; } + + /// <summary> + /// Determines whether the specified <see cref="System.Object" />, is equal to this instance. + /// </summary> + /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param> + /// <returns> + /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>. + /// </returns> + public override bool Equals(object obj) + { + var other = (VectorFrameColor)obj; + return R == other.R && G == other.G && B == other.B; + } + + /// <summary> + /// Returns a hash code for this instance. + /// </summary> + /// <returns> + /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + /// </returns> + public override int GetHashCode() + { + var hashCode = -1520100960; + hashCode = hashCode * -1521134295 + R.GetHashCode(); + hashCode = hashCode * -1521134295 + G.GetHashCode(); + hashCode = hashCode * -1521134295 + B.GetHashCode(); + return hashCode; + } + + /// <summary> + /// Returns a 32 bit integer representing this color. + /// </summary> + /// <returns></returns> + public int ToInt32() + { + return (int)((255 << 24) | (R << 16) | (G << 8) | (B << 0)); + } + + /// <summary> + /// Creates a color from the specified 32 bit integer. + /// </summary> + /// <param name="integer">The integer.</param> + /// <returns></returns> + public static VectorFrameColor FromInt32(int integer) + { + byte a = (byte)(integer >> 24); + byte r = (byte)(integer >> 16); + byte g = (byte)(integer >> 8); + byte b = (byte)(integer >> 0); + return new VectorFrameColor() + { + R = r, + G = g, + B = g, + }; + } + + public Color ToColor() + { + return Color.FromArgb(R, G, B); + } + } +} diff --git a/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFramePixel.cs b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFramePixel.cs new file mode 100644 index 000000000..df1a71232 --- /dev/null +++ b/Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFramePixel.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.RemoteDesktop.Frames +{ + /// <summary> + /// Represents a <see cref="VectorFrame"/> pixel. + /// </summary> + public struct VectorFramePixel + { + /// <summary> + /// Gets or sets the x position. + /// </summary> + public int X { get; set; } + /// <summary> + /// Gets or sets the y position. + /// </summary> + public int Y { get; set; } + + /// <summary> + /// Gets or sets the index of the color. + /// </summary> + public int ColorIndex { get; set; } + + /// <summary> + /// Gets or sets the pixel color (not for serialization!). + /// </summary> + public VectorFrameColor Color { get; set; } + } +} |
