diff --git a/espScreenCast-cs/App.config b/espScreenCast-cs/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/espScreenCast-cs/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/espScreenCast-cs/Form1.Designer.cs b/espScreenCast-cs/Form1.Designer.cs
new file mode 100644
index 0000000..594be99
--- /dev/null
+++ b/espScreenCast-cs/Form1.Designer.cs
@@ -0,0 +1,218 @@
+namespace espScreenCast
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ this.timer1 = new System.Windows.Forms.Timer(this.components);
+ this.panel1 = new System.Windows.Forms.Panel();
+ this.checkBox1 = new System.Windows.Forms.CheckBox();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.label2 = new System.Windows.Forms.Label();
+ this.hScrollBar1 = new System.Windows.Forms.HScrollBar();
+ this.label3 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.label5 = new System.Windows.Forms.Label();
+ this.label6 = new System.Windows.Forms.Label();
+ this.hScrollBar2 = new System.Windows.Forms.HScrollBar();
+ this.button1 = new System.Windows.Forms.Button();
+ this.richTextBox1 = new System.Windows.Forms.RichTextBox();
+ this.SuspendLayout();
+ //
+ // timer1
+ //
+ this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+ //
+ // panel1
+ //
+ this.panel1.Location = new System.Drawing.Point(12, 12);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(255, 255);
+ this.panel1.TabIndex = 1;
+ //
+ // checkBox1
+ //
+ this.checkBox1.AutoSize = true;
+ this.checkBox1.Location = new System.Drawing.Point(475, 86);
+ this.checkBox1.Name = "checkBox1";
+ this.checkBox1.Size = new System.Drawing.Size(65, 17);
+ this.checkBox1.TabIndex = 2;
+ this.checkBox1.Text = "Sending";
+ this.checkBox1.UseVisualStyleBackColor = true;
+ this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
+ //
+ // textBox1
+ //
+ this.textBox1.Location = new System.Drawing.Point(369, 84);
+ this.textBox1.Name = "textBox1";
+ this.textBox1.Size = new System.Drawing.Size(100, 20);
+ this.textBox1.TabIndex = 3;
+ this.textBox1.Text = "192.168.1.42";
+ this.textBox1.TextChanged += new System.EventHandler(this.textBox1_TextChanged);
+ this.textBox1.Leave += new System.EventHandler(this.textBox1_Leave);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(273, 87);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(96, 13);
+ this.label1.TabIndex = 4;
+ this.label1.Text = "esp IP / Hostname";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Font = new System.Drawing.Font("Segoe UI Semibold", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label2.Location = new System.Drawing.Point(348, 9);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(194, 37);
+ this.label2.TabIndex = 5;
+ this.label2.Text = "espScreenCast";
+ //
+ // hScrollBar1
+ //
+ this.hScrollBar1.Location = new System.Drawing.Point(355, 125);
+ this.hScrollBar1.Maximum = 255;
+ this.hScrollBar1.Name = "hScrollBar1";
+ this.hScrollBar1.Size = new System.Drawing.Size(143, 19);
+ this.hScrollBar1.TabIndex = 6;
+ this.hScrollBar1.Value = 128;
+ this.hScrollBar1.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hScrollBar1_Scroll);
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(504, 128);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(13, 13);
+ this.label3.TabIndex = 7;
+ this.label3.Text = "0";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(293, 128);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(56, 13);
+ this.label4.TabIndex = 8;
+ this.label4.Text = "Brightness";
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(307, 163);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(42, 13);
+ this.label5.TabIndex = 11;
+ this.label5.Text = "Interval";
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(504, 163);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(13, 13);
+ this.label6.TabIndex = 10;
+ this.label6.Text = "0";
+ //
+ // hScrollBar2
+ //
+ this.hScrollBar2.Location = new System.Drawing.Point(355, 160);
+ this.hScrollBar2.Maximum = 200;
+ this.hScrollBar2.Minimum = 1;
+ this.hScrollBar2.Name = "hScrollBar2";
+ this.hScrollBar2.Size = new System.Drawing.Size(143, 19);
+ this.hScrollBar2.TabIndex = 9;
+ this.hScrollBar2.Value = 20;
+ this.hScrollBar2.Scroll += new System.Windows.Forms.ScrollEventHandler(this.hScrollBar2_Scroll);
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(465, 201);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(75, 23);
+ this.button1.TabIndex = 13;
+ this.button1.Text = "Scroll text";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // richTextBox1
+ //
+ this.richTextBox1.Location = new System.Drawing.Point(296, 203);
+ this.richTextBox1.Name = "richTextBox1";
+ this.richTextBox1.Size = new System.Drawing.Size(159, 22);
+ this.richTextBox1.TabIndex = 14;
+ this.richTextBox1.Text = "";
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(548, 274);
+ this.Controls.Add(this.richTextBox1);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.label5);
+ this.Controls.Add(this.label6);
+ this.Controls.Add(this.hScrollBar2);
+ this.Controls.Add(this.label4);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.hScrollBar1);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.textBox1);
+ this.Controls.Add(this.checkBox1);
+ this.Controls.Add(this.panel1);
+ this.Name = "Form1";
+ this.Text = "Form1";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.Shown += new System.EventHandler(this.Form1_Shown);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.Timer timer1;
+ private System.Windows.Forms.Panel panel1;
+ private System.Windows.Forms.CheckBox checkBox1;
+ private System.Windows.Forms.TextBox textBox1;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.HScrollBar hScrollBar1;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.HScrollBar hScrollBar2;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.RichTextBox richTextBox1;
+ }
+}
+
diff --git a/espScreenCast-cs/Form1.cs b/espScreenCast-cs/Form1.cs
new file mode 100644
index 0000000..6625e80
--- /dev/null
+++ b/espScreenCast-cs/Form1.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace espScreenCast
+{
+
+
+ public partial class Form1 : Form
+ {
+ Bitmap bmpScreenshot = new Bitmap(8,
+ 8,
+ PixelFormat.Format24bppRgb);
+ private static Timer aTimer;
+ WSBitmap wsBitmap = new WSBitmap();
+ List pictureboxes;
+ Graphics gfxScreenshot;
+ bool sending = false;
+ bool scrolling = false;
+ private int brightness;
+
+ public Form1()
+ {
+ InitializeComponent();
+ gfxScreenshot = Graphics.FromImage(bmpScreenshot);
+
+ pictureboxes = Enumerable.Range(1, 64).ToList().Select(h => new PictureBox() { Name = "runebox" + h.ToString() }).ToList();
+ var i = 0;
+ pictureboxes.ForEach(pic =>
+ {
+ int y = (i / 8) * 30 + panel1.Location.X;
+ int x = (i % 8) * 30 + panel1.Location.Y;
+ pic.BackColor = Color.FromArgb(new Random(i).Next(Int32.MaxValue));
+ pic.Size = new Size(25, 25);
+ pic.Location = new Point(x, y);
+ Console.WriteLine("adding one\n");
+
+ this.panel1.Controls.Add(pic);
+ i++;
+ });
+
+ }
+ private void getSnip()
+ {
+ var pos = System.Windows.Forms.Cursor.Position;
+ // Take the screenshot from the upper left corner to the right bottom corner.
+ gfxScreenshot.CopyFromScreen(pos.X,
+ pos.Y,
+ 0,
+ 0,
+ new Size(8, 8));
+
+
+ wsBitmap.emulate(pictureboxes, bmpScreenshot);
+ if (sending)
+ wsBitmap.send(bmpScreenshot, brightness);
+
+
+ }
+
+ private Bitmap textToBmp(String str)
+ {
+ Font font = new Font("Tahoma", 8);
+
+ Bitmap bmp = new Bitmap(800,8,PixelFormat.Format24bppRgb);
+ RectangleF rectf = new RectangleF(0, 0, bmp.Width, bmp.Height);
+ Graphics g = Graphics.FromImage(bmp);
+ StringFormat format = new StringFormat()
+ {
+ Alignment = StringAlignment.Near,
+ LineAlignment = StringAlignment.Center
+ };
+
+ g.DrawString(str, font, Brushes.Red, rectf, format);
+ // Flush all graphics changes to the bitmap
+ g.Flush();
+ return bmp;
+ }
+
+ int pos = 0;
+ private void scrollTick(Bitmap txtBmp,int strLen)
+ {
+
+ using (Graphics grD = Graphics.FromImage(bmpScreenshot))
+ {
+ grD.DrawImage(txtBmp, new Rectangle(0,0,8,8), new Rectangle(pos++,0,8,8), GraphicsUnit.Pixel);
+ }
+ wsBitmap.emulate(pictureboxes, bmpScreenshot);
+ wsBitmap.send(bmpScreenshot, brightness);
+ if (pos > strLen) {
+ aTimer.Dispose();
+ pos = 0;
+ scrolling = false;
+ }
+ }
+
+ private void scrollText(String text)
+ {
+ scrolling = true;
+ Bitmap bmp = textToBmp(text);
+ var size = richTextBox1.GetPreferredSize(Size.Empty);
+ if (!(aTimer is null)) {
+ aTimer.Dispose();
+ pos = 0;
+ }
+ aTimer = new Timer();
+ aTimer.Interval = hScrollBar2.Value * 2;
+
+ aTimer.Tick += (sender, e) => scrollTick(bmp,size.Width);
+ aTimer.Enabled = true;
+
+ }
+
+
+
+
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ timer1.Start();
+ }
+
+ private void timer1_Tick(object sender, EventArgs e)
+ {
+ if (!scrolling)
+ getSnip();
+ }
+
+ private void checkBox1_CheckedChanged(object sender, EventArgs e)
+ {
+ sending = checkBox1.Checked;
+ }
+
+ private void textBox1_TextChanged(object sender, EventArgs e)
+ {
+ checkBox1.Enabled = (textBox1.Text.Length > 1);
+ }
+
+ private void textBox1_Leave(object sender, EventArgs e)
+ {
+ wsBitmap.setHost(textBox1.Text);
+ }
+
+ private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
+ {
+ label3.Text = hScrollBar1.Value.ToString();
+ brightness = hScrollBar1.Value;
+ }
+
+ private void Form1_Shown(object sender, EventArgs e)
+ {
+ hScrollBar1_Scroll(null, null);
+ hScrollBar2_Scroll(null, null);
+
+ textBox1_TextChanged(null, null);
+
+ textBox1_Leave(null, null);
+
+ }
+
+ private void hScrollBar2_Scroll(object sender, ScrollEventArgs e)
+ {
+ label6.Text = hScrollBar2.Value.ToString();
+ timer1.Interval = hScrollBar2.Value;
+ }
+
+ private void button1_Click(object sender, EventArgs e)
+ {
+ scrollText(richTextBox1.Text);
+ }
+
+ }
+}
diff --git a/espScreenCast-cs/Form1.resx b/espScreenCast-cs/Form1.resx
new file mode 100644
index 0000000..1f666f2
--- /dev/null
+++ b/espScreenCast-cs/Form1.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/espScreenCast-cs/Program.cs b/espScreenCast-cs/Program.cs
new file mode 100644
index 0000000..8361378
--- /dev/null
+++ b/espScreenCast-cs/Program.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace espScreenCast
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+
+ }
+}
diff --git a/espScreenCast-cs/Properties/AssemblyInfo.cs b/espScreenCast-cs/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c29c5d4
--- /dev/null
+++ b/espScreenCast-cs/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("espScreenCast")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("espScreenCast")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("146ae745-a08a-4619-8ca1-f5dddbc5d821")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/espScreenCast-cs/Properties/Resources.Designer.cs b/espScreenCast-cs/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..d0c1641
--- /dev/null
+++ b/espScreenCast-cs/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace espScreenCast.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("espScreenCast.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/espScreenCast-cs/Properties/Resources.resx b/espScreenCast-cs/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/espScreenCast-cs/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/espScreenCast-cs/Properties/Settings.Designer.cs b/espScreenCast-cs/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..12d8c0c
--- /dev/null
+++ b/espScreenCast-cs/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace espScreenCast.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/espScreenCast-cs/Properties/Settings.settings b/espScreenCast-cs/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/espScreenCast-cs/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/espScreenCast-cs/WSBitmap.cs b/espScreenCast-cs/WSBitmap.cs
new file mode 100644
index 0000000..b54e892
--- /dev/null
+++ b/espScreenCast-cs/WSBitmap.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using System.Net.Sockets;
+using System.Security.AccessControl;
+using System.Security.Cryptography;
+using System.Security.Permissions;
+using System.Security.Policy;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace espScreenCast
+{
+ class WSBitmap
+ {
+ public Bitmap bitmap;
+ private UdpClient udpClient;
+ private int port = 2812;
+
+ public void setHost(string host)
+ {
+ this.udpClient = new UdpClient(host, port);
+ }
+
+ public void update()
+ {
+ bitmap.GetHbitmap();
+ }
+
+ public static byte[] ImageToByte(Bitmap bitmap)
+ {
+ var bitdata = bitmap.LockBits(new Rectangle(0, 0, 8, 8), System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
+ // Get the address of the first line.
+ IntPtr ptr = bitdata.Scan0;
+ // Declare an array to hold the bytes of the bitmap.
+ int bytes = Math.Abs(bitdata.Stride) * bitmap.Height;
+ byte[] rgbValues = new byte[bytes];
+
+ // Copy the RGB values into the array.
+ System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
+ bitmap.UnlockBits(bitdata);
+ return rgbValues;
+ }
+
+ public void emulate(List pictureboxes, Bitmap bitmap)
+ {
+ var i = 0;
+ byte[] bytes = ImageToByte(bitmap);
+
+ pictureboxes.ForEach(pic => {
+ pic.BackColor = Color.FromArgb(bytes[i * 3+2], bytes[i * 3 +1 ], bytes[i * 3]);
+ i++;
+ });
+ }
+
+ public void send(Bitmap bitmap, int brightness = 128)
+ {
+ byte[] bytes = ImageToByte(bitmap);
+ List ts = new List();
+ ts.AddRange(bytes);
+ ts.Add((byte)brightness);
+
+ udpClient.Send(ts.ToArray(), ts.Count);
+ }
+ }
+}
diff --git a/espScreenCast-cs/espScreenCast.csproj b/espScreenCast-cs/espScreenCast.csproj
new file mode 100644
index 0000000..7afcf58
--- /dev/null
+++ b/espScreenCast-cs/espScreenCast.csproj
@@ -0,0 +1,85 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {146AE745-A08A-4619-8CA1-F5DDDBC5D821}
+ WinExe
+ espScreenCast
+ espScreenCast
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+
+ Form1.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/espScreenCast-pioProject/.gitignore b/espScreenCast-pioProject/.gitignore
new file mode 100644
index 0000000..89cc49c
--- /dev/null
+++ b/espScreenCast-pioProject/.gitignore
@@ -0,0 +1,5 @@
+.pio
+.vscode/.browse.c_cpp.db*
+.vscode/c_cpp_properties.json
+.vscode/launch.json
+.vscode/ipch
diff --git a/espScreenCast-pioProject/.travis.yml b/espScreenCast-pioProject/.travis.yml
new file mode 100644
index 0000000..7c486f1
--- /dev/null
+++ b/espScreenCast-pioProject/.travis.yml
@@ -0,0 +1,67 @@
+# Continuous Integration (CI) is the practice, in software
+# engineering, of merging all developer working copies with a shared mainline
+# several times a day < https://docs.platformio.org/page/ci/index.html >
+#
+# Documentation:
+#
+# * Travis CI Embedded Builds with PlatformIO
+# < https://docs.travis-ci.com/user/integration/platformio/ >
+#
+# * PlatformIO integration with Travis CI
+# < https://docs.platformio.org/page/ci/travis.html >
+#
+# * User Guide for `platformio ci` command
+# < https://docs.platformio.org/page/userguide/cmd_ci.html >
+#
+#
+# Please choose one of the following templates (proposed below) and uncomment
+# it (remove "# " before each line) or use own configuration according to the
+# Travis CI documentation (see above).
+#
+
+
+#
+# Template #1: General project. Test it using existing `platformio.ini`.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio run
+
+
+#
+# Template #2: The project is intended to be used as a library with examples.
+#
+
+# language: python
+# python:
+# - "2.7"
+#
+# sudo: false
+# cache:
+# directories:
+# - "~/.platformio"
+#
+# env:
+# - PLATFORMIO_CI_SRC=path/to/test/file.c
+# - PLATFORMIO_CI_SRC=examples/file.ino
+# - PLATFORMIO_CI_SRC=path/to/test/directory
+#
+# install:
+# - pip install -U platformio
+# - platformio update
+#
+# script:
+# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
diff --git a/espScreenCast-pioProject/include/README b/espScreenCast-pioProject/include/README
new file mode 100644
index 0000000..194dcd4
--- /dev/null
+++ b/espScreenCast-pioProject/include/README
@@ -0,0 +1,39 @@
+
+This directory is intended for project header files.
+
+A header file is a file containing C declarations and macro definitions
+to be shared between several project source files. You request the use of a
+header file in your project source file (C, C++, etc) located in `src` folder
+by including it, with the C preprocessing directive `#include'.
+
+```src/main.c
+
+#include "header.h"
+
+int main (void)
+{
+ ...
+}
+```
+
+Including a header file produces the same results as copying the header file
+into each source file that needs it. Such copying would be time-consuming
+and error-prone. With a header file, the related declarations appear
+in only one place. If they need to be changed, they can be changed in one
+place, and programs that include the header file will automatically use the
+new version when next recompiled. The header file eliminates the labor of
+finding and changing all the copies as well as the risk that a failure to
+find one copy will result in inconsistencies within a program.
+
+In C, the usual convention is to give header files names that end with `.h'.
+It is most portable to use only letters, digits, dashes, and underscores in
+header file names, and at most one dot.
+
+Read more about using header files in official GCC documentation:
+
+* Include Syntax
+* Include Operation
+* Once-Only Headers
+* Computed Includes
+
+https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
diff --git a/espScreenCast-pioProject/lib/README b/espScreenCast-pioProject/lib/README
new file mode 100644
index 0000000..6debab1
--- /dev/null
+++ b/espScreenCast-pioProject/lib/README
@@ -0,0 +1,46 @@
+
+This directory is intended for project specific (private) libraries.
+PlatformIO will compile them to static libraries and link into executable file.
+
+The source code of each library should be placed in a an own separate directory
+("lib/your_library_name/[here are source files]").
+
+For example, see a structure of the following two libraries `Foo` and `Bar`:
+
+|--lib
+| |
+| |--Bar
+| | |--docs
+| | |--examples
+| | |--src
+| | |- Bar.c
+| | |- Bar.h
+| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
+| |
+| |--Foo
+| | |- Foo.c
+| | |- Foo.h
+| |
+| |- README --> THIS FILE
+|
+|- platformio.ini
+|--src
+ |- main.c
+
+and a contents of `src/main.c`:
+```
+#include
+#include
+
+int main (void)
+{
+ ...
+}
+
+```
+
+PlatformIO Library Dependency Finder will find automatically dependent
+libraries scanning project source files.
+
+More information about PlatformIO Library Dependency Finder
+- https://docs.platformio.org/page/librarymanager/ldf.html
diff --git a/espScreenCast-pioProject/platformio.ini b/espScreenCast-pioProject/platformio.ini
new file mode 100644
index 0000000..d19e8e0
--- /dev/null
+++ b/espScreenCast-pioProject/platformio.ini
@@ -0,0 +1,20 @@
+; PlatformIO Project Configuration File
+;
+; Build options: build flags, source filter
+; Upload options: custom upload port, speed and extra flags
+; Library options: dependencies, extra library storages
+; Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:esp32dev]
+platform = espressif32
+board = esp32dev
+framework = arduino
+monitor_speed = 115200
+upload_speed = 921600
+lib_deps =
+ # RECOMMENDED
+ # Accept new functionality in a backwards compatible manner and patches
+ fastled/FastLED @ ^3.4.0
\ No newline at end of file
diff --git a/espScreenCast-pioProject/src/main.cpp b/espScreenCast-pioProject/src/main.cpp
new file mode 100644
index 0000000..c644de3
--- /dev/null
+++ b/espScreenCast-pioProject/src/main.cpp
@@ -0,0 +1,51 @@
+#include "WiFi.h"
+#include "AsyncUDP.h"
+
+const char * ssid = "**ssid**";
+const char * password = "**pass**";
+
+AsyncUDP udp;
+
+#include
+#define NUM_LEDS 64
+
+CRGBArray leds;
+
+void display(AsyncUDPPacket packet){
+ byte bmp[packet.length()] = {0};
+ memcpy(bmp,packet.data(),packet.length());
+ FastLED.setBrightness(bmp[packet.length()-1]);
+ // Serial.printf("got packet with brightness %d",bmp[packet.length()-1]);
+
+ for(int i = 0; i < NUM_LEDS; i++) {
+ leds[i]=CRGB(bmp[i*3+2],bmp[i*3+1],bmp[i*3]);
+ }
+ FastLED.show();
+
+}
+
+void setup() {
+ Serial.begin(115200);
+ WiFi.mode(WIFI_STA);
+ WiFi.begin(ssid, password);
+ if (WiFi.waitForConnectResult() != WL_CONNECTED) {
+ Serial.println("WiFi Failed");
+ while(1) {
+ delay(1000);
+ }
+ }
+ if(udp.listen(2812)) {
+ Serial.print("UDP Listening on IP: ");
+ Serial.println(WiFi.localIP());
+ udp.onPacket(display);
+ }
+
+
+ FastLED.addLeds(leds, NUM_LEDS);
+ FastLED.setBrightness(4);
+
+}
+
+void loop(){
+
+}
diff --git a/espScreenCast-pioProject/test/README b/espScreenCast-pioProject/test/README
new file mode 100644
index 0000000..df5066e
--- /dev/null
+++ b/espScreenCast-pioProject/test/README
@@ -0,0 +1,11 @@
+
+This directory is intended for PIO Unit Testing and project tests.
+
+Unit Testing is a software testing method by which individual units of
+source code, sets of one or more MCU program modules together with associated
+control data, usage procedures, and operating procedures, are tested to
+determine whether they are fit for use. Unit testing finds problems early
+in the development cycle.
+
+More information about PIO Unit Testing:
+- https://docs.platformio.org/page/plus/unit-testing.html
diff --git a/espScreenCast.sln b/espScreenCast.sln
new file mode 100644
index 0000000..8d2da63
--- /dev/null
+++ b/espScreenCast.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30128.74
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "espScreenCast", "espScreenCast-cs\espScreenCast.csproj", "{146AE745-A08A-4619-8CA1-F5DDDBC5D821}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {146AE745-A08A-4619-8CA1-F5DDDBC5D821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {146AE745-A08A-4619-8CA1-F5DDDBC5D821}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {146AE745-A08A-4619-8CA1-F5DDDBC5D821}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {146AE745-A08A-4619-8CA1-F5DDDBC5D821}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {4CEAA2B8-620B-4480-A38B-FF6104BBD63E}
+ EndGlobalSection
+EndGlobal