aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.RemoteDesktop/Frames
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-03-02 23:30:34 +0200
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-03-02 23:30:34 +0200
commit0dcd742a3c35527386a93e1b1ef761c2aeff8308 (patch)
treed5adb3fee35e73af95fa5d68b5316d25522471de /Software/Visual_Studio/Tango.RemoteDesktop/Frames
parent1a7fb274158f8a0e279aef26206a65fefac8c4c3 (diff)
downloadTango-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')
-rw-r--r--Software/Visual_Studio/Tango.RemoteDesktop/Frames/RasterFrame.cs134
-rw-r--r--Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrame.cs227
-rw-r--r--Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFrameColor.cs93
-rw-r--r--Software/Visual_Studio/Tango.RemoteDesktop/Frames/VectorFramePixel.cs34
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; }
+ }
+}