diff --git a/Implementation/Linux.artistic.float.rsp b/Implementation/Linux.artistic.float.rsp index 000cb9f..229e9ff 100644 --- a/Implementation/Linux.artistic.float.rsp +++ b/Implementation/Linux.artistic.float.rsp @@ -7,12 +7,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Artistic.model" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.artistic.rsp b/Implementation/Linux.artistic.rsp index 7dd7ae9..223c841 100644 --- a/Implementation/Linux.artistic.rsp +++ b/Implementation/Linux.artistic.rsp @@ -8,12 +8,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Artistic.hmodel" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.artistic.simd.float.rsp b/Implementation/Linux.artistic.simd.float.rsp index db1b88e..9c48e92 100644 --- a/Implementation/Linux.artistic.simd.float.rsp +++ b/Implementation/Linux.artistic.simd.float.rsp @@ -9,12 +9,11 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Artistic.model" -/resource:"src/Resources/ColorfulSoft.png" + "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.artistic.simd.rsp b/Implementation/Linux.artistic.simd.rsp index 40852bb..d8a1ff2 100644 --- a/Implementation/Linux.artistic.simd.rsp +++ b/Implementation/Linux.artistic.simd.rsp @@ -10,12 +10,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Artistic.hmodel" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.stable.float.rsp b/Implementation/Linux.stable.float.rsp index 162786e..79e6b1c 100644 --- a/Implementation/Linux.stable.float.rsp +++ b/Implementation/Linux.stable.float.rsp @@ -8,12 +8,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Stable.model" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.stable.rsp b/Implementation/Linux.stable.rsp index c224b6d..5ae8b0f 100644 --- a/Implementation/Linux.stable.rsp +++ b/Implementation/Linux.stable.rsp @@ -9,12 +9,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Stable.hmodel" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.stable.simd.float.rsp b/Implementation/Linux.stable.simd.float.rsp index 0f6f99b..c6986ca 100644 --- a/Implementation/Linux.stable.simd.float.rsp +++ b/Implementation/Linux.stable.simd.float.rsp @@ -10,12 +10,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Stable.model" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Linux.stable.simd.rsp b/Implementation/Linux.stable.simd.rsp index ec6c31d..1f326fc 100644 --- a/Implementation/Linux.stable.simd.rsp +++ b/Implementation/Linux.stable.simd.rsp @@ -11,12 +11,10 @@ /r:System.Windows.Forms.dll /resource:"src/Resources/Preview.jpg" -/resource:"src/Resources/Input.jpg" -/resource:"src/Resources/Output.jpg" /resource:"src/Resources/Info.png" /resource:"src/Resources/Icon.png" + /resource:"src/Resources/Stable.hmodel" -/resource:"src/Resources/ColorfulSoft.png" "src/Functional.cs" "src/HalfHelper.cs" diff --git a/Implementation/Windows.artistic.float.rsp b/Implementation/Windows.artistic.float.rsp index d823418..1602744 100644 --- a/Implementation/Windows.artistic.float.rsp +++ b/Implementation/Windows.artistic.float.rsp @@ -10,13 +10,13 @@ /r:System.Drawing.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Artistic.model" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.artistic.rsp b/Implementation/Windows.artistic.rsp index 16fe980..02858ef 100644 --- a/Implementation/Windows.artistic.rsp +++ b/Implementation/Windows.artistic.rsp @@ -11,13 +11,13 @@ /r:System.Drawing.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Artistic.hmodel" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.artistic.simd.float.rsp b/Implementation/Windows.artistic.simd.float.rsp index 418cdbc..e4d37b6 100644 --- a/Implementation/Windows.artistic.simd.float.rsp +++ b/Implementation/Windows.artistic.simd.float.rsp @@ -12,13 +12,13 @@ /r:System.Numerics.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Artistic.model" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.artistic.simd.rsp b/Implementation/Windows.artistic.simd.rsp index 38cecaf..0374f84 100644 --- a/Implementation/Windows.artistic.simd.rsp +++ b/Implementation/Windows.artistic.simd.rsp @@ -13,13 +13,13 @@ /r:System.Numerics.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Artistic.hmodel" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.stable.float.rsp b/Implementation/Windows.stable.float.rsp index 7ffb6b0..601bd9a 100644 --- a/Implementation/Windows.stable.float.rsp +++ b/Implementation/Windows.stable.float.rsp @@ -11,13 +11,13 @@ /r:System.Drawing.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Stable.model" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.stable.rsp b/Implementation/Windows.stable.rsp index dc9b494..e99f605 100644 --- a/Implementation/Windows.stable.rsp +++ b/Implementation/Windows.stable.rsp @@ -12,13 +12,13 @@ /r:System.Drawing.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Stable.hmodel" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.stable.simd.float.rsp b/Implementation/Windows.stable.simd.float.rsp index daf2bca..3bc5dfa 100644 --- a/Implementation/Windows.stable.simd.float.rsp +++ b/Implementation/Windows.stable.simd.float.rsp @@ -13,13 +13,13 @@ /r:System.Numerics.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Stable.model" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/Windows.stable.simd.rsp b/Implementation/Windows.stable.simd.rsp index 694cbd8..55646e1 100644 --- a/Implementation/Windows.stable.simd.rsp +++ b/Implementation/Windows.stable.simd.rsp @@ -14,13 +14,13 @@ /r:System.Numerics.dll /r:System.Windows.Forms.dll +/win32manifest:"src\Resources\app.manifest" + /resource:"src\Resources\Preview.jpg" -/resource:"src\Resources\Input.jpg" -/resource:"src\Resources\Output.jpg" /resource:"src\Resources\Info.png" /resource:"src\Resources\Icon.png" + /resource:"src\Resources\Stable.hmodel" -/resource:"src\Resources\ColorfulSoft.png" "src\Functional.cs" "src\HalfHelper.cs" diff --git a/Implementation/src/Program.cs b/Implementation/src/Program.cs index a31cf19..3e85195 100644 --- a/Implementation/src/Program.cs +++ b/Implementation/src/Program.cs @@ -20,19 +20,16 @@ public static class Program [STAThread] public static void Main(string[] args) { + // Reduce application CPU priority to avoid freezes during image processing + System.Diagnostics.Process.GetCurrentProcess().PriorityClass = + System.Diagnostics.ProcessPriorityClass.BelowNormal; DeOldify.Initialize(); if(args.Length > 0) { return; } Application.EnableVisualStyles(); - try - { - Application.Run(new MainForm()); - } - catch - { - } + Application.Run(new MainForm()); } } diff --git a/Implementation/src/Resources/app.manifest b/Implementation/src/Resources/app.manifest new file mode 100644 index 0000000..e1f585f --- /dev/null +++ b/Implementation/src/Resources/app.manifest @@ -0,0 +1,12 @@ + + + + + true + PerMonitorV2 + + + + + + diff --git a/Implementation/src/UI.cs b/Implementation/src/UI.cs index 14988ab..c147029 100644 --- a/Implementation/src/UI.cs +++ b/Implementation/src/UI.cs @@ -9,6 +9,8 @@ using System.Reflection; using System.Windows.Forms; using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Net; namespace ColorfulSoft.DeOldify { @@ -65,294 +67,131 @@ public HelpForm() : base() } /// - /// Operation execution control button. Supports progress indication like ProgressBar. + /// The main form of the application. /// - public sealed class StartButton : UserControl + public sealed class MainForm : Form { /// - /// The graphical shell of the control. + /// Form with general information about this project. /// - private Graphics __Graphics; + private HelpForm __HelpForm; /// - /// Redraws the control. + /// Button to open HelpForm. /// - private void Redraw() - { - this.__Graphics.Clear(SystemColors.ControlDark); - if(this.Progress == 0) - { - this.__Graphics.DrawString(this.Text, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - this.Text.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - return; - } - this.__Graphics.FillRectangle(Brushes.DarkGreen, 0, 0, this.Width / 100f * this.Progress, this.Height); - var txt = this.Text + (this.__ShowProgress ? string.Format("({0,2:0.##} %)", this.Progress) : ""); - this.__Graphics.DrawString(txt, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - txt.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - } + private Button __HelpButton; /// - /// Indicates whether the progress of the operation should be shown. + // Table layout panel /// - private bool __ShowProgress = false; + private TableLayoutPanel __TableLayoutPanel; /// - /// Indicates whether the progress of the operation should be shown. + /// Header panel /// - public bool ShowProgress - { - - get - { - return this.__ShowProgress; - } - - set - { - this.__ShowProgress = value; - Redraw(); - } - - } + private Panel __HeaderPanel; /// - /// Initializes the control. + /// Source image location ComboBox label /// - public StartButton() : base() - { - this.__Graphics = this.CreateGraphics(); - this.Paint += delegate - { - this.Redraw(); - }; - this.Resize += delegate - { - this.__Graphics = this.CreateGraphics(); - this.Redraw(); - }; - this.TextChanged += delegate - { - this.Redraw(); - }; - this.MouseEnter += delegate - { - if(this.Progress == 0) - { - this.__Graphics.Clear(SystemColors.Control); - this.__Graphics.DrawString(this.Text, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - this.Text.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - } - }; - this.MouseLeave += delegate - { - if(this.Progress == 0) - { - this.__Graphics.Clear(SystemColors.ControlDark); - this.__Graphics.DrawString(this.Text, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - this.Text.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - } - }; - } + private Label __LabelLocation; /// - /// Current progress of execution. + /// Source image location ComboBox. /// - private float __Progress; + private ComboBox __InputLocation; /// - /// Gets or sets the current progress of execution. + // Tab control /// - public float Progress - { - get - { - return this.__Progress; - } - set - { - if((value < 0) || (value > 100)) - { - throw new ArgumentException("Progress should be in [0..100] range."); - } - this.__Progress = value; - this.Redraw(); - } - } - - } - - /// - /// Flat button. - /// - public sealed class FlatButton : UserControl - { + private TabControl __TabControl; /// - /// Graphical shell of the control. + /// Split Container /// - private Graphics __Graphics; + private SplitContainer __SplitContainer; /// - /// Redraws the control. - /// - private void Redraw() - { - this.__Graphics.Clear(SystemColors.ControlDark); - this.__Graphics.DrawString(this.Text, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - this.Text.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - if(this.__Image != null) - { - this.__Graphics.DrawImage(this.__Image, 0, 0, this.ClientSize.Width, this.ClientSize.Height); - } - } - - /// - /// Image on the button. - /// - private Bitmap __Image; - - /// - /// Image on the button. - /// - public Bitmap Image - { - - get - { - return this.__Image; - } - - set - { - this.__Image = value; - this.Redraw(); - } - - } - - /// - /// Initializes the control. - /// - public FlatButton() : base() - { - this.__Graphics = this.CreateGraphics(); - this.Paint += delegate - { - this.Redraw(); - }; - this.Resize += delegate - { - this.__Graphics = this.CreateGraphics(); - this.Redraw(); - }; - this.TextChanged += delegate - { - this.Redraw(); - }; - this.MouseEnter += delegate - { - this.__Graphics.Clear(SystemColors.Control); - this.__Graphics.DrawString(this.Text, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - this.Text.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - if(this.__Image != null) - { - this.__Graphics.DrawImage(this.__Image, 0, 0, this.ClientSize.Width, this.ClientSize.Height); - } - }; - this.MouseLeave += delegate - { - this.__Graphics.Clear(SystemColors.ControlDark); - this.__Graphics.DrawString(this.Text, this.Font, SystemBrushes.ControlText, Math.Max((this.Width - this.Text.Length * this.Font.Size) / 2, 0), Math.Max((this.Height - this.Font.Height) / 2, 0)); - if(this.__Image != null) - { - this.__Graphics.DrawImage(this.__Image, 0, 0, this.ClientSize.Width, this.ClientSize.Height); - } - }; - } - - } - - /// - /// The main form of the application. - /// - public sealed class MainForm : Form - { - - /// - /// Form with general information about this project. - /// - private HelpForm __HelpForm; - - /// - /// Button to open HelpForm. + /// Contains input controls. /// - private FlatButton __HelpButton; + private Panel __InputBox; /// - /// Contains input controls. + /// Drag hint label /// - private GroupBox __InputBox; + private Label __InputLabel; /// /// Input image picture box. /// - private PictureBox __InputImage; + private PictureBox __InputPictureBox; /// /// Input image. /// - private Bitmap __Input; + private Bitmap __InputImage; - /// - /// Normal input image. - /// - private Bitmap __NormalInput; + private ContextMenuStrip __InputBoxContextMenuStrip; + private ToolStripMenuItem __InputBoxMenuItem1; /// - /// Blurrified input image. + /// Button to open file dialog. /// - private Bitmap __BlurryInput; + private Button __ButtonBrowse; /// - /// Button to open input image. + /// Button to load input image file or URL. /// - private FlatButton __OpenInput; + private Button __ButtonLoad; /// /// Contains output controls. /// - private GroupBox __OutputBox; + private Panel __OutputBox; /// /// Output image picture box. /// - private PictureBox __OutputImage; + private PictureBox __OutputPictureBox; /// - /// Output image. + /// Output image picture box context menu. /// - private Bitmap __Output; + private ContextMenuStrip __OutputBoxContextMenuStrip; + private ToolStripMenuItem __OutputBoxMenuItem1; + private ToolStripMenuItem __OutputBoxMenuItem2; + private ToolStripMenuItem __OutputBoxMenuItem3; /// - /// Normal output image. + /// Button to save output image. /// - private Bitmap __NormalOutput; + private Button __ButtonSave; /// - /// Blurrified output image. + /// Footer panel /// - private Bitmap __BlurryOutput; + private Panel __FooterPanel; /// - /// Button to save output image. + /// Using stock ProgressBar /// - private FlatButton __SaveOutput; + private ProgressBar __ProgressBar; /// - /// ColorfulSoft's logo. + /// Label for progress status /// - private Bitmap __ColorfulSoftLogo; + private Label __ProgressLabel; /// /// Button to start, stop and control colorization. /// - private StartButton __StartButton; + private Button __StartButton; + + /// + /// Button to desaturate an image + /// + private Button __DecolorizeButton; /// /// Thread for neural network. @@ -362,14 +201,18 @@ public sealed class MainForm : Form /// /// The name of the open file. /// - private string __IFName; + private string __ImageFileName; + + private string __ProgressLabelText = "{0} %"; + + private TextBox __DebugMemo; /// /// Blurrifies the image. /// /// Input image. /// Blurrified image. - private static Bitmap __Blurify(Bitmap source) + public static Bitmap __Blurify(Bitmap source) { var output = new Bitmap(source.Width, source.Height); for(int y = 0; y < output.Height; ++y) @@ -412,7 +255,7 @@ private static Bitmap __Blurify(Bitmap source) /// /// Input image. /// Greyscale image. - private static Bitmap __Decolorize(Bitmap source) + public static Bitmap __Decolorize(Bitmap source) { var result = new Bitmap(source); for(int y = 0; y < result.Height; ++y) @@ -428,111 +271,413 @@ private static Bitmap __Decolorize(Bitmap source) } /// - /// Sets the input image. + /// Workaround for .NET Framework incomplete high DPI support. Scale from 96 to current form DPI. /// - /// Input image. - private void __SetInputImage(Bitmap source) + /// Size of control. + private Size __ScaleDPI(Size control_size) { - source = __Decolorize(source); - this.__Input = source; - if(source.Height > source.Width) - { - this.__InputImage.Image = new Bitmap(source, (int)(256f / source.Height * source.Width), 256); - } + SizeF scale_ratio = new SizeF(this.AutoScaleDimensions.Width / 96, this.AutoScaleDimensions.Height / 96); + control_size = new Size ( + (int) Math.Ceiling (control_size.Width * scale_ratio.Width), + (int) Math.Ceiling (control_size.Height * scale_ratio.Height) + ); + return control_size; + } + + /// + /// Workaround for .NET Framework incomplete high DPI support. Scale from 96 to current form DPI. + /// + /// Size of control. + private int __ScaleDPI(int number, Boolean round_up = false) + { + float scale_ratio = this.AutoScaleDimensions.Width / 96; + if (round_up) + number = (int) Math.Ceiling (number * scale_ratio); else - { - this.__InputImage.Image = new Bitmap(source, 256, (int)(256f / source.Width * source.Height)); + number = (int) Math.Floor (number * scale_ratio); + + return number; + } + + /// + /// Toggle controls. + /// + /// True to enable images and disable progress. False to disable images and enable progress. + private void ToggleControls(Boolean state) { + // review: enumerated - enabled/disabled instead? + if (state) + __StartButton.Text = "DeOldify!"; + else + __StartButton.Text = "Stop"; + __InputPictureBox.Enabled = state; + __OutputPictureBox.Enabled = state; + __ProgressBar.Visible = !state; + __ProgressLabel.Visible = !state; + } + + /// + /// Stops the colorization process and image loading. Event Handler. + /// + /// Sender. + /// Args. + private void StopColorizationThread(object sender, EventArgs e) + { + + __InputPictureBox.CancelAsync(); + + if (__ColorizationThread != null) { + __ColorizationThread.Interrupt(); + __ColorizationThread.Join(); } - this.__NormalInput = (Bitmap)this.__InputImage.Image; - this.__BlurryInput = __Blurify((Bitmap)this.__InputImage.Image); - if(this.__OutputImage != null) + + } + + /// + /// Starts the colorization process. Event handler. + /// + /// Sender. + /// Args. + private void StartColorizationThread(object sender, EventArgs e) + { + + StopColorizationThread(sender, e); + if (__InputImage == null) + return; + __ProgressBar.Maximum = 1000; + __ProgressBar.Value = 0; + ToggleControls(false); + __StartButton.Click -= StartColorizationThread; + __StartButton.Click += StopColorizationThread; + + __ColorizationThread = new Thread(() => { - this.__Output = null; - this.__BlurryOutput = null; - this.__NormalOutput = null; - this.__OutputImage.Image = this.__ColorfulSoftLogo; - this.__OutputImage.Enabled = false; + try { + Bitmap OutputImage = DeOldify.Colorize(this.__InputImage); + if (this.InvokeRequired) { + this.BeginInvoke((MethodInvoker) delegate() { + if (OutputImage != null) { + this.__OutputPictureBox.Image = OutputImage; + this.__TabControl.SelectedIndex = 1; + } + }); + } + } + catch (System.Threading.ThreadInterruptedException) {} + catch (System.Threading.Tasks.TaskSchedulerException) {} + catch (Exception ex) { + MessageBox.Show(String.Format("{0} ({1})", ex.Message, ex.HResult.ToString()) , + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally { + // GC.Collect(); // bugs. will collect by its own eventually. + if (this.InvokeRequired) { + this.BeginInvoke((MethodInvoker) delegate() { + __StartButton.Click -= StopColorizationThread; + __StartButton.Click += StartColorizationThread; + ToggleControls(true); + }); + } + } + }); + __ColorizationThread.Start(); + + } + + /// + /// Starting image downloading. + /// + /// Image URL. + private Image DownloadImage (String url) + { + + StopColorizationThread(this, null); + + __StartButton.Click -= StartColorizationThread; + __StartButton.Click += StopColorizationThread; + + __ProgressBar.Maximum = 100; + __ProgressBar.Minimum = 0; + UpdateProgress(0); + + ToggleControls(false); + + __InputPictureBox.LoadAsync(url); + return null; + + } + + /// + /// Opening and image from location. + /// + /// File or network location of an image. + private Boolean OpenImage (String sourceLocation) + { + + __ImageFileName = ""; + __InputPictureBox.Image = null; + __InputLabel.Visible = false; + __InputPictureBox.SuspendLayout(); + + if (Uri.IsWellFormedUriString(sourceLocation, UriKind.Absolute)) { + DownloadImage(sourceLocation); } - if(this.__StartButton != null) - { - this.__StartButton.Enabled = true; - this.__StartButton.Text = "DeOldify!"; - this.__StartButton.Progress = 0f; + else { + try + { + __InputImage = new Bitmap(sourceLocation); + __ImageFileName = sourceLocation; + OpenImage(__InputImage, false); + } + catch (Exception ex) { + MessageBox.Show(String.Format("{0} ({1})" , ex.Message, ex.HResult), + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + __InputLabel.Visible = true; + __InputPictureBox.ResumeLayout(); + return false; + } } + + AddLocationHistory(sourceLocation); + + return true; } /// - /// Sets output image. + /// Opening and image from Bitmap. /// - /// Output image. - private void __SetOutputImage(Bitmap source) + /// Source Bitmap. + /// Clear load. I.e. not been called during another opening process. + private Boolean OpenImage (Bitmap sourceImage, Boolean clear = true) { - this.__Output = source; - if(source.Height > source.Width) + + if (clear) + __ImageFileName = ""; + + try { - this.__OutputImage.Image = new Bitmap(source, (int)(256f / source.Height * source.Width), 256); + // __InputImage = __PrepareInputImage(sourceImage); // too slow, unnecessary for most images + __InputImage = sourceImage; + __InputPictureBox.Image = __InputImage; + __InputLabel.Visible = false; + if (__TabControl.SelectedIndex == 1) + __TabControl.SelectedIndex = 0; + __OutputPictureBox.Image = null; } - else + catch(Exception ex) + { + MessageBox.Show(String.Format("{0} ({1})", ex.Message, ex.HResult.ToString()) , + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + return false; + } + finally { - this.__OutputImage.Image = new Bitmap(source, 256, (int)(256f / source.Width * source.Height)); + __InputPictureBox.ResumeLayout(); } - this.__NormalOutput = (Bitmap)this.__OutputImage.Image; - this.__BlurryOutput = __Blurify((Bitmap)this.__OutputImage.Image); + + return true; + } /// - /// Stops the colorization process. Event Handler. + /// Open/Paste an image from clipboard /// - /// Sender. - /// Args. - private void StopHandler(object sender, EventArgs e) + private Boolean OpenImageFromClipboard () { - this.__ColorizationThread.Abort(); - this.__StartButton.Text = "DeOldify!"; - this.__StartButton.Progress = 0f; - this.__StartButton.Click -= this.StopHandler; - this.__StartButton.Click += this.StartHandler; - this.__InputImage.Enabled = true; - this.__OutputImage.Enabled = true; - this.__StartButton.ShowProgress = false; + + try + { + if (Clipboard.ContainsImage()) { + OpenImage ( (Bitmap) Clipboard.GetImage() ); + return true; + } + } + // todo: show error message + catch { } + + return false; + } /// - /// Starts the colorization process. Event handler. + /// Saving an image /// - /// Sender. - /// Args. - private void StartHandler(object sender, EventArgs e) + /// True to show Save As dialog. + private Boolean SaveImage (Boolean saveas = false) { - this.__InputImage.Enabled = false; - this.__OutputImage.Enabled = false; - this.__StartButton.ShowProgress = true; - this.__StartButton.Text = "Stop"; - this.__StartButton.Click -= this.StartHandler; - this.__StartButton.Click += this.StopHandler; - this.__ColorizationThread = new Thread(() => - { - this.__Output = DeOldify.Colorize(this.__Input); - if(this.__Output.Height > this.__Output.Width) + + if (__OutputPictureBox.Image == null) + return false; + + String destPath = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures); + String destFileName = "Deoldified"; + ImageFormat format = ImageFormat.Jpeg; + + if (!String.IsNullOrEmpty(__ImageFileName)) { + destPath = Path.GetFullPath(__ImageFileName); + destFileName = Path.GetFileNameWithoutExtension(__ImageFileName) + "-deoldified"; + } + + if (saveas) { + var SFD = new SaveFileDialog(); + SFD.Title = "Save colorized"; + SFD.Filter = "BMP images (*.bmp)|*.bmp|EMF images (*.emf)|*.emf|EXIF images (*.exif)|*.exif|GIF images (*.gif)|*.gif|ICO images (*.ico)|*.ico|JPG images (*.jpg)|*.jpg|PNG images (*.png)|*.png|TIFF images (*.tiff)|*.tiff|WMF images (*.wmf)|*.wmf"; // For future use "WebP images (*.webp)|*.webp" + SFD.FilterIndex = 7; + SFD.FileName = destFileName; + SFD.InitialDirectory = destPath; + SFD.OverwritePrompt = true; + if(SFD.ShowDialog() == DialogResult.OK) { - this.__NormalOutput = new Bitmap(this.__Output, (int)(256f / this.__Output.Height * this.__Output.Width), 256); + destPath = SFD.FileName; + if (Path.HasExtension(destPath)) { + format = GetImageFormat(destPath); + if (format == null) + format = GetImageFormat(SFD.FilterIndex); + } + else { + format = GetImageFormat(SFD.FilterIndex); + } } else { - this.__NormalOutput = new Bitmap(this.__Output, 256, (int)(256f / this.__Output.Width * this.__Output.Height)); + return false; } - this.__BlurryOutput = __Blurify(this.__NormalOutput); - this.__OutputImage.Image = this.__NormalOutput; - this.__OutputImage.Enabled = true; - this.__InputImage.Enabled = true; - this.__StartButton.Text = "Done!"; - this.__StartButton.Enabled = false; - this.__StartButton.ShowProgress = false; - this.__StartButton.Click -= this.StopHandler; - this.__StartButton.Click += this.StartHandler; - GC.Collect(); - }); - this.__ColorizationThread.Start(); + } + else { + String[] joins = {destFileName, DateTime.Now.ToString("yyyyMMdd-HHmmss")}; + destFileName = String.Join("-", joins); + destFileName += GetImageExtension(format); + destPath = Path.Combine(destPath, destFileName); + if (File.Exists(destPath)) { + DialogResult response = + MessageBox.Show (String.Format ("File {0} already exist. Do you wish to overwrite it?", destFileName), Application.ProductName, + MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2); + if (response == DialogResult.No) + return false; + } + } + + __OutputPictureBox.Image.Save(destPath, format); + + return true; + + } + + /// + /// Copy an output image to clipboard. + /// + private void CopyImageToClipboard() + { + if (__OutputPictureBox.Image != null) + Clipboard.SetDataObject((Bitmap)__OutputPictureBox.Image); + } + + /// + /// Returning ImageFormat based on file extension. + /// + /// Filename. + private ImageFormat GetImageFormat (String fileName) + { + String ext = Path.GetExtension(fileName).ToLower(); + switch(ext) { + case ".bmp": return ImageFormat.Bmp; + case ".emf": return ImageFormat.Emf; + case ".exif": return ImageFormat.Exif; + case ".gif": return ImageFormat.Gif; + case ".ico": return ImageFormat.Icon; + case ".jpg": + case ".jpeg": return ImageFormat.Jpeg; + case ".png": return ImageFormat.Png; + case ".tif": + case ".tiff": return ImageFormat.Tiff; + case ".wmf": return ImageFormat.Wmf; + // case ".webp": return ImageFormat.Webp; //WebP support is still broken as of .NET 7.0 + default: return null; + } + } + + /// + /// Returning ImageFormat based on Save As dialog filter. + /// + /// Save As dialog filter index. + private ImageFormat GetImageFormat (int filterIndex) + { + switch(filterIndex) + { + case 1: return ImageFormat.Bmp; + case 2: return ImageFormat.Emf; + case 3: return ImageFormat.Exif; + case 4: return ImageFormat.Gif; + case 5: return ImageFormat.Icon; + case 6: return ImageFormat.Jpeg; + case 7: return ImageFormat.Png; + case 8: return ImageFormat.Tiff; + case 9: return ImageFormat.Wmf; + // case 10: return ImageFormat.Webp; //WebP support is still broken as of .NET 7.0 + default: return ImageFormat.Jpeg; + } + } + + /// + /// Returning file extension based on ImageFormat. + /// + /// ImageFormat. + private String GetImageExtension (ImageFormat format) + { + if (format == ImageFormat.Bmp) + return ".bmp"; + if (format == ImageFormat.Emf) + return ".emf"; + if (format == ImageFormat.Exif) + return ".exif"; + if (format == ImageFormat.Icon) + return ".ico"; + if (format == ImageFormat.Jpeg) + return ".jpg"; + if (format == ImageFormat.Png) + return ".png"; + if (format == ImageFormat.Tiff) + return ".tif"; + if (format == ImageFormat.Wmf) + return ".wmf"; + // if (format == ImageFormat.Webp) + // return ".webp"; + // if (format == ImageFormat.Heif) + // return ".heif"; + return ".jpeg"; + } + + /// + /// Add a source location to Location ComboBox history + /// + /// Source of an image. + private void AddLocationHistory (String sourceLocation) + { + __InputLocation.Items.Insert(0, sourceLocation); + for (int i = 1; i < __InputLocation.Items.Count-1; i++) { + if (__InputLocation.Items[i].ToString() == sourceLocation) + __InputLocation.Items.RemoveAt(i); + } + __InputLocation.Text = sourceLocation; // in .NET Text property will reset, when inserting new items. + } + + /// + /// Update progressBar and Label + /// + /// Current progress position. + private void UpdateProgress (int progressValue) + { + __ProgressLabel.Text = String.Format(__ProgressLabelText, progressValue.ToString()); + __ProgressBar.Value = progressValue; + } + + /// + /// Update progressBar and Label + /// + /// Current progress position. + private void UpdateProgress (float progressValue) + { + __ProgressBar.Value = (int)progressValue*10; + __ProgressLabel.Text = String.Format(__ProgressLabelText, ((int)progressValue).ToString()); } /// @@ -540,6 +685,10 @@ private void StartHandler(object sender, EventArgs e) /// public MainForm() : base() { + + try + { + this.Text = #if stable "Stable " + @@ -558,55 +707,265 @@ public MainForm() : base() " w32"; #endif this.Icon = Icon.FromHandle((new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("Icon.png"))).GetHicon()); - this.BackColor = SystemColors.ControlDarkDark; - this.FormBorderStyle = FormBorderStyle.FixedSingle; - this.ClientSize = new Size(582, 363); - this.MaximizeBox = false; - this.MinimizeBox = false; + this.FormBorderStyle = FormBorderStyle.Sizable; + this.AutoScaleDimensions = new SizeF(96F, 96F); + this.AutoScaleMode = AutoScaleMode.Dpi; + this.MinimumSize = new Size(800, 800); + this.Height = (int)(Screen.FromControl(this).Bounds.Height * 0.7); + this.Width = (int)(this.Height * 1.2); //proportions closer to 3:2 and 4:3 + this.MaximizeBox = true; + this.MinimizeBox = true; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + this.Font = new Font("Segue UI", this.Font.Size); + this.AllowDrop = true; + this.KeyPreview = true; + + // HelpForm + this.__HelpForm = new HelpForm(); + + //////////////////////////////////////////////////////////////////////////////// + // FORM LAYOUT + this.__TableLayoutPanel = new TableLayoutPanel(); + this.__TableLayoutPanel.Location = new Point(0, 0); + this.__TableLayoutPanel.Dock = DockStyle.Fill; + this.__TableLayoutPanel.ColumnCount = 1; + this.__TableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100)); + this.__TableLayoutPanel.RowCount = 3; + this.__TableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, __ScaleDPI(42))); + this.__TableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50)); + this.__TableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, __ScaleDPI(64))); + this.__TableLayoutPanel.TabIndex = 0; + this.__TableLayoutPanel.CellBorderStyle = TableLayoutPanelCellBorderStyle.None; + this.Controls.Add(this.__TableLayoutPanel); + + //////////////////////////////////////////////////////////////////////////////// + // Header row + + this.__HeaderPanel = new Panel(); + this.__HeaderPanel.Dock = DockStyle.Fill; + this.__TableLayoutPanel.Controls.Add(this.__HeaderPanel, 0, 0); + + this.__LabelLocation = new Label(); + this.__InputLocation = new ComboBox(); + this.__ButtonBrowse = new Button(); + this.__ButtonLoad = new Button(); + + this.__LabelLocation.Text = "Image file or URL:"; + this.__LabelLocation.TextAlign = ContentAlignment.BottomLeft; + this.__LabelLocation.AutoSize = true; + this.__LabelLocation.Left = __ScaleDPI(18); + this.__HeaderPanel.Controls.Add(this.__LabelLocation); + + this.__ButtonLoad.Text = "Load image"; + this.__ButtonLoad.AutoSize = true; + this.__ButtonLoad.Left = this.__HeaderPanel.Width - this.__ButtonLoad.Width - __ScaleDPI(20); + this.__ButtonLoad.Anchor = (AnchorStyles.Top | AnchorStyles.Right); + this.__HeaderPanel.Controls.Add(this.__ButtonLoad); + + this.__ButtonBrowse.Text = "Browse"; + this.__ButtonBrowse.AutoSize = true; + this.__ButtonBrowse.Left = this.__ButtonLoad.Left - this.__ButtonBrowse.Width - __ScaleDPI(20); + this.__ButtonBrowse.Anchor = (AnchorStyles.Top | AnchorStyles.Right); + this.__HeaderPanel.Controls.Add(this.__ButtonBrowse); + + this.__InputLocation.Location = new Point( + this.__LabelLocation.Right + __ScaleDPI(10), + (this.__HeaderPanel.ClientSize.Height - this.__InputLocation.Height) / 2 + ); + this.__InputLocation.Width = this.__ButtonBrowse.Left - this.__InputLocation.Left - __ScaleDPI(10); + this.__InputLocation.Anchor = (AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right); + this.__HeaderPanel.Controls.Add(this.__InputLocation); + + this.__ButtonBrowse.MinimumSize = new Size(0, this.__InputLocation.Height); + this.__LabelLocation.Top = this.__InputLocation.Top; + this.__ButtonBrowse.Top = this.__InputLocation.Top - (this.__ButtonBrowse.Height - this.__InputLocation.Height) + __ScaleDPI(1, true); + this.__ButtonLoad.Top = this.__InputLocation.Top - (this.__ButtonBrowse.Height - this.__InputLocation.Height) + __ScaleDPI(1, true); + + //////////////////////////////////////////////////////////////////////////////// + // Main row + + this.__TabControl = new TabControl(); + this.__TabControl.Dock = DockStyle.Fill; + this.__TabControl.TabPages.Add("Source"); + this.__TabControl.TabPages.Add("DeOldified"); + this.__TabControl.TabPages.Add("Side-by-side"); + this.__TableLayoutPanel.Controls.Add(__TabControl, 0, 1); + + this.__InputBox = new Panel(); + this.__InputBox.Dock = DockStyle.Fill; + this.__InputBox.BackColor = Color.Gray; + this.__TabControl.TabPages[0].Controls.Add(this.__InputBox); + this.__InputPictureBox = new PictureBox(); + this.__InputPictureBox.BorderStyle = BorderStyle.None; + this.__InputPictureBox.Dock = DockStyle.Fill; + this.__InputPictureBox.SizeMode = PictureBoxSizeMode.Zoom; + this.__InputBox.Controls.Add(this.__InputPictureBox); + this.__InputLabel = new Label(); + this.__InputLabel.Dock = DockStyle.Fill; + this.__InputLabel.FlatStyle = FlatStyle.Flat; + this.__InputLabel.TextAlign = ContentAlignment.MiddleCenter; + this.__InputLabel.ForeColor = Color.LightGray; + this.__InputLabel.BackColor = Color.Transparent; + this.__InputLabel.Text = "(Drop or paste an image here)"; + this.__InputPictureBox.Controls.Add(this.__InputLabel); + + this.__InputBoxContextMenuStrip = new ContextMenuStrip(); + this.__InputBoxMenuItem1 = new ToolStripMenuItem(); + this.__InputBoxMenuItem1.Text = "Paste"; + this.__InputBoxContextMenuStrip.Items.Add( this.__InputBoxMenuItem1); + this.__InputPictureBox.ContextMenuStrip = this.__InputBoxContextMenuStrip; + + this.__OutputBox = new Panel(); + this.__OutputBox.Dock = DockStyle.Fill; + this.__OutputBox.BackColor = Color.Gray; + this.__TabControl.TabPages[1].Controls.Add(this.__OutputBox); + this.__OutputPictureBox = new PictureBox(); + this.__OutputPictureBox.BorderStyle = BorderStyle.None; + this.__OutputPictureBox.Dock = DockStyle.Fill; + this.__OutputPictureBox.SizeMode = PictureBoxSizeMode.Zoom; + this.__OutputBox.Controls.Add(this.__OutputPictureBox); + + this.__OutputBoxContextMenuStrip = new ContextMenuStrip(); + this.__OutputBoxMenuItem1 = new ToolStripMenuItem(); + this.__OutputBoxMenuItem2 = new ToolStripMenuItem(); + this.__OutputBoxMenuItem3 = new ToolStripMenuItem(); + this.__OutputBoxMenuItem1.Text = "Copy"; + this.__OutputBoxMenuItem2.Text = "Save"; + this.__OutputBoxMenuItem3.Text = "Save As..."; + this.__OutputBoxContextMenuStrip.Items.Add( this.__OutputBoxMenuItem1); + this.__OutputBoxContextMenuStrip.Items.Add( this.__OutputBoxMenuItem2); + this.__OutputBoxContextMenuStrip.Items.Add( this.__OutputBoxMenuItem3); + this.__OutputPictureBox.ContextMenuStrip = this.__OutputBoxContextMenuStrip; + + this.__SplitContainer = new SplitContainer(); + ((System.ComponentModel.ISupportInitialize)(this.__SplitContainer)).BeginInit(); + this.__SplitContainer.BorderStyle = BorderStyle.None; + this.__SplitContainer.Dock = DockStyle.Fill; + this.__SplitContainer.SplitterDistance = this.__SplitContainer.Width/2; + this.__SplitContainer.BackColor = Color.Gray; + this.__SplitContainer.Panel1.Padding = new Padding(4); + this.__SplitContainer.Panel2.Padding = new Padding(4); + this.__TabControl.TabPages[2].Controls.Add(this.__SplitContainer); + this.__SplitContainer.ResumeLayout(false); + + //////////////////////////////////////////////////////////////////////////////// + // Footer row row + + this.__FooterPanel = new Panel(); + this.__FooterPanel.Dock = DockStyle.Fill; + this.__TableLayoutPanel.Controls.Add(this.__FooterPanel, 0, 2); + + this.__ProgressBar = new ProgressBar(); + this.__ProgressBar.Dock = DockStyle.Top; + this.__ProgressBar.Height = __ScaleDPI(8); + this.__ProgressBar.Step = 1; + this.__FooterPanel.Controls.Add(this.__ProgressBar); + + this.__ProgressLabel = new Label(); + this.__ProgressLabel.Text = "0 %"; + this.__ProgressLabel.AutoSize = true; + this.__ProgressLabel.Left = __ScaleDPI(10); + this.__ProgressLabel.Top = (__FooterPanel.ClientSize.Height + __ProgressBar.Height - __ProgressLabel.Height) / 2; + this.__ProgressLabel.Visible = false; + this.__FooterPanel.Controls.Add(this.__ProgressLabel); + + this.__StartButton = new Button(); + this.__StartButton.Text = "DeOldify!"; + this.__StartButton.NotifyDefault(true); + this.__StartButton.Size = __ScaleDPI(new Size(120, 25)); + this.__StartButton.Top = (__FooterPanel.ClientSize.Height + __ProgressBar.Height - __StartButton.Height) / 2; + this.__StartButton.Left = this.__FooterPanel.ClientSize.Width - this.__StartButton.Width - __ScaleDPI(10); + this.__StartButton.Anchor = (AnchorStyles.Top | AnchorStyles.Right); + this.__StartButton.Click += StartColorizationThread; + this.__FooterPanel.Controls.Add(this.__StartButton); + + this.__DecolorizeButton = new Button(); + this.__DecolorizeButton.Text = "Decolorize"; + this.__DecolorizeButton.Size = __ScaleDPI(new Size(120, 25)); + this.__DecolorizeButton.Location = new Point(this.__StartButton.Left - __ScaleDPI(10) - this.__DecolorizeButton.Width, this.__StartButton.Top); + this.__DecolorizeButton.Anchor = (AnchorStyles.Top | AnchorStyles.Right); + this.__FooterPanel.Controls.Add(this.__DecolorizeButton); + + this.__ButtonSave = new Button(); + this.__ButtonSave.Text = "Save"; + this.__ButtonSave.Size = __ScaleDPI(new Size(120, 25)); + this.__ButtonSave.Location = new Point(this.__DecolorizeButton.Left - __ScaleDPI(10) - this.__ButtonSave.Width, this.__StartButton.Top); + this.__ButtonSave.Anchor = (AnchorStyles.Top | AnchorStyles.Right); + this.__FooterPanel.Controls.Add(this.__ButtonSave); + + this.__HelpButton = new Button(); + this.__HelpButton.Text = "About..."; + this.__HelpButton.Size = __ScaleDPI(new Size(100, 25)); + this.__HelpButton.Location = new Point(this.__ButtonSave.Left - __ScaleDPI(10) - this.__HelpButton.Width, this.__StartButton.Top); + this.__HelpButton.Anchor = (AnchorStyles.Top | AnchorStyles.Right); + this.__FooterPanel.Controls.Add(this.__HelpButton); + + ToggleControls(true); + + // debug: + this.__DebugMemo = new TextBox(); + __DebugMemo.Multiline = true; + __DebugMemo.ScrollBars = ScrollBars.Both; + __DebugMemo.Location = new Point(0, 0); + __DebugMemo.Size = new Size(400, 600); + __InputPictureBox.Controls.Add(__DebugMemo); + + __DebugMemo.BringToFront(); + __DebugMemo.Visible = false; + // __DebugMemo.AppendText ( Environment.NewLine ); + + //////////////////////////////////////////////////////////////////////////////// + // Events + + this.__HelpButton.Click += delegate + { + __HelpForm.ShowDialog(); + }; + this.Closing += delegate { - try - { - this.__ColorizationThread.Abort(); - } - catch - { - } + StopColorizationThread(this, null); }; - this.AllowDrop = true; + + this.KeyDown += (s, e) => + { + if (e.Modifiers == Keys.Control && e.KeyCode == Keys.V) + OpenImageFromClipboard(); + + if (e.Modifiers == Keys.Control && e.KeyCode == Keys.C) + CopyImageToClipboard(); + }; + + this.__InputLocation.KeyDown += (s, e) => + { + if (e.KeyCode == Keys.Enter) + OpenImage(__InputLocation.Text); + }; + this.DragDrop += (object sender, DragEventArgs e) => { + + if (e.Data == null) + return; + if(e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); - try - { - this.__SetInputImage(new Bitmap(files[0])); - this.__IFName = Path.GetFileNameWithoutExtension(files[0]); - } - catch(Exception ex) - { - MessageBox.Show(ex.Message); - return; - } + OpenImage(files[0]); } if(e.Data.GetDataPresent(DataFormats.Bitmap)) { - try - { - this.__SetInputImage((Bitmap)e.Data.GetData(DataFormats.Bitmap)); - this.__IFName = null; - } - catch(Exception ex) - { - MessageBox.Show(ex.Message); - } + OpenImage((Bitmap)e.Data.GetData(DataFormats.Bitmap)); } + + StartColorizationThread(this, null); + }; + this.DragEnter += (object sender, DragEventArgs e) => { if(e.Data.GetDataPresent(DataFormats.Bitmap) || - e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Data.GetDataPresent(DataFormats.FileDrop)) { e.Effect = DragDropEffects.Copy; } @@ -615,196 +974,173 @@ public MainForm() : base() e.Effect = DragDropEffects.None; } }; - // HelpForm - this.__HelpForm = new HelpForm(); - // HelpButton - this.__HelpButton = new FlatButton(); - this.__HelpButton.Image = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("Info.png")); - this.__HelpButton.Width = 22; - this.__HelpButton.Height = 22; - this.__HelpButton.Top = 1; - this.__HelpButton.Left = 559; - this.__HelpButton.Click += delegate + + this.__TabControl.SelectedIndexChanged += delegate { + + if (__TabControl.SelectedIndex == 2) { + __InputBox.Parent = __SplitContainer.Panel1; + __OutputBox.Parent = __SplitContainer.Panel2; + } + else { + __InputBox.Parent = __TabControl.TabPages[0]; + __OutputBox.Parent = __TabControl.TabPages[1]; + } + + }; + + this.__InputPictureBox.MouseEnter += delegate { - this.__HelpForm.ShowDialog(); + // this.__InputImage.Image = this.__BlurryInput; + // this.__InputImage.Controls.Add(this.__ButtonOpen); }; - this.Controls.Add(this.__HelpButton); - // InputBox - this.__InputBox = new GroupBox(); - this.__InputBox.Size = new Size(276, 286); - this.__InputBox.Text = "B&W image"; - this.__InputBox.Top = 22; - this.__InputBox.Left = 10; - this.__InputBox.ForeColor = SystemColors.Control; - //-> InputImage - this.__InputImage = new PictureBox(); - this.__InputImage.Size = new Size(256, 256); - this.__InputImage.Top = 20; - this.__InputImage.Left = 10; - this.__InputImage.BackColor = SystemColors.ControlDarkDark; - this.__InputImage.BorderStyle = BorderStyle.FixedSingle; - this.__InputImage.SizeMode = PictureBoxSizeMode.Zoom; - this.__InputImage.MouseEnter += delegate - { - this.__InputImage.Image = this.__BlurryInput; - this.__InputImage.Controls.Add(this.__OpenInput); - }; - this.__InputImage.MouseLeave += delegate - { - this.__InputImage.Image = this.__NormalInput; - var p = Control.MousePosition; - if(this.__OpenInput.ClientRectangle.Contains(this.__OpenInput.PointToClient(p))) - { - this.__InputImage.Image = this.__BlurryInput; - return; - } - this.__InputImage.Controls.Remove(this.__OpenInput); - }; - this.__SetInputImage(new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("Input.jpg"))); - this.__InputBox.Controls.Add(this.__InputImage); - //-> OpenInput - this.__OpenInput = new FlatButton(); - this.__OpenInput.Enabled = true; - this.__OpenInput.Top = 115; - this.__OpenInput.Left = 40; - this.__OpenInput.Size = new Size(176, 25); - this.__OpenInput.Text = "Open B&W image"; - this.__OpenInput.Click += delegate - { - this.__InputImage.Controls.Remove(this.__OpenInput); - var OFD = new OpenFileDialog(); - OFD.Title = "Open"; - OFD.Filter = "Images (*.bmp; *.emf; *.exif; *.gif; *.ico; *.jpg; *.png; *.tiff; *.wmf)|*.bmp; *.emf; *.exif; *.gif; *.ico; *.jpg; *.png; *.tiff; *.wmf|All files|*.*"; - if(OFD.ShowDialog() == DialogResult.OK) - { - try - { - this.__SetInputImage(new Bitmap(OFD.FileName)); - this.__IFName = Path.GetFileNameWithoutExtension(OFD.FileName); - } - catch(Exception e) - { - MessageBox.Show(e.Message); - } - } - }; - this.Controls.Add(this.__InputBox); - //-> __OutputBox - this.__OutputBox = new GroupBox(); - this.__OutputBox.Size = new Size(276, 286); - this.__OutputBox.Text = "Result"; - this.__OutputBox.Top = 22; - this.__OutputBox.Left = 296; - this.__OutputBox.ForeColor = SystemColors.Control; - //-> OutputImage - this.__OutputImage = new PictureBox(); - this.__OutputImage.Size = new Size(256, 256); - this.__OutputImage.Top = 20; - this.__OutputImage.Left = 10; - this.__OutputImage.BackColor = SystemColors.ControlDarkDark; - this.__OutputImage.BorderStyle = BorderStyle.FixedSingle; - this.__OutputImage.SizeMode = PictureBoxSizeMode.Zoom; - this.__OutputImage.MouseEnter += delegate - { - this.__OutputImage.Image = this.__BlurryOutput; - this.__OutputImage.Controls.Add(this.__SaveOutput); - }; - this.__OutputImage.MouseLeave += delegate - { - this.__OutputImage.Image = this.__NormalOutput; - var p = Control.MousePosition; - if(this.__SaveOutput.ClientRectangle.Contains(this.__SaveOutput.PointToClient(p))) - { - this.__OutputImage.Image = this.__BlurryOutput; - return; - } - this.__OutputImage.Controls.Remove(this.__SaveOutput); - }; - this.__SetOutputImage(new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("Output.jpg"))); - this.__OutputBox.Controls.Add(this.__OutputImage); - //-> SaveOutput - this.__SaveOutput = new FlatButton(); - this.__SaveOutput.Top = 115; - this.__SaveOutput.Left = 40; - this.__SaveOutput.Size = new Size(176, 25); - this.__SaveOutput.Text = "Save"; - this.__SaveOutput.Click += delegate - { - this.__OutputImage.Controls.Remove(this.__SaveOutput); - var SFD = new SaveFileDialog(); - SFD.Title = "Save colorized"; - SFD.Filter = "BMP images (*.bmp)|*.bmp|EMF images (*.emf)|*.emf|EXIF images (*.exif)|*.exif|GIF images (*.gif)|*.gif|ICO images (*.ico)|*.ico|JPG images (*.jpg)|*.jpg|PNG images (*.png)|*.png|TIFF images (*.tiff)|*.tiff|WMF images (*.wmf)|*.wmf"; - SFD.FilterIndex = 7; - SFD.FileName = (this.__IFName == null) ? "deoldified" : (this.__IFName + "-deoldified"); - if(SFD.ShowDialog() == DialogResult.OK) - { - switch(SFD.FilterIndex) - { - case 1: - { - this.__Output.Save(SFD.FileName, ImageFormat.Bmp); - break; - } - case 2: - { - this.__Output.Save(SFD.FileName, ImageFormat.Emf); - break; - } - case 3: - { - this.__Output.Save(SFD.FileName, ImageFormat.Exif); - break; - } - case 4: - { - this.__Output.Save(SFD.FileName, ImageFormat.Gif); - break; - } - case 5: - { - this.__Output.Save(SFD.FileName, ImageFormat.Icon); - break; - } - case 6: - { - this.__Output.Save(SFD.FileName, ImageFormat.Jpeg); - break; - } - case 7: - { - this.__Output.Save(SFD.FileName, ImageFormat.Png); - break; - } - case 8: - { - this.__Output.Save(SFD.FileName, ImageFormat.Tiff); - break; - } - case 9: - { - this.__Output.Save(SFD.FileName, ImageFormat.Wmf); - break; - } - } - } - }; - this.Controls.Add(this.__OutputBox); - // - this.__ColorfulSoftLogo = new Bitmap(Assembly.GetExecutingAssembly().GetManifestResourceStream("ColorfulSoft.png")); - // - this.__StartButton = new StartButton(); - this.__StartButton.Top = 318; - this.__StartButton.Left = 10; - this.__StartButton.Width = 562; - this.__StartButton.Height = 25; - this.__StartButton.Text = "DeOldify!"; - this.__StartButton.Click += StartHandler; - this.Controls.Add(this.__StartButton); - // + this.__InputPictureBox.MouseLeave += delegate + { + // this.__InputImage.Image = this.__NormalInput; + // var p = Control.MousePosition; + // if(this.__ButtonOpen.ClientRectangle.Contains(this.__ButtonOpen.PointToClient(p))) + // { + // this.__InputImage.Image = this.__BlurryInput; + // return; + // } + // this.__InputImage.Controls.Remove(this.__ButtonOpen); + }; + this.__ButtonBrowse.Click += delegate + { + var OFD = new OpenFileDialog(); + OFD.Title = "Open"; + OFD.Filter = "Images (*.bmp; *.emf; *.exif; *.gif; *.ico; *.jpg; *.png; *.tiff; *.wmf)|*.bmp; *.emf; *.exif; *.gif; *.ico; *.jpg; *.png; *.tiff; *.wmf|All files|*.*"; + if(OFD.ShowDialog() == DialogResult.OK) { + __InputLocation.Text = OFD.FileName; + OpenImage(OFD.FileName); + } + }; + this.__ButtonLoad.Click += delegate + { + OpenImage(__InputLocation.Text); + }; + this.__OutputPictureBox.MouseEnter += delegate + { + // this.__OutputImage.Image = this.__BlurryOutput; + // this.__OutputImage.Controls.Add(this.__ButtonSave); + }; + this.__OutputPictureBox.MouseLeave += delegate + { + // this.__OutputImage.Image = this.__NormalOutput; + // var p = Control.MousePosition; + // if(this.__ButtonSave.ClientRectangle.Contains(this.__ButtonSave.PointToClient(p))) + // { + // this.__OutputImage.Image = this.__BlurryOutput; + // return; + // } + // this.__OutputImage.Controls.Remove(this.__ButtonSave); + }; + + this.__InputBoxContextMenuStrip.ItemClicked += (object sender, ToolStripItemClickedEventArgs e) => + { + __InputBoxContextMenuStrip.Hide(); // Workaround menu won't disappear until ItemClick event is finished. + if (e.ClickedItem == __InputBoxMenuItem1) { + OpenImageFromClipboard(); + } + }; + + this.__OutputBoxContextMenuStrip.ItemClicked += (object sender, ToolStripItemClickedEventArgs e) => + { + __OutputBoxContextMenuStrip.Hide(); // Workaround menu won't disappear until ItemClick event is finished. + if (e.ClickedItem == __OutputBoxMenuItem1) + CopyImageToClipboard(); + if (e.ClickedItem == __OutputBoxMenuItem2) + SaveImage(false); + if (e.ClickedItem == __OutputBoxMenuItem3) + SaveImage(true); + }; + + this.__DecolorizeButton.Click += delegate + { + if (__InputPictureBox.Image != null) { + __InputPictureBox.Image = __Decolorize((Bitmap)__InputPictureBox.Image); + } + }; + + this.__ButtonSave.Click += delegate + { + SaveImage(true); + }; + + this.__InputPictureBox.LoadProgressChanged += (s, e) => + { + __ProgressLabelText = "Downloading: {0} %"; + UpdateProgress (e.ProgressPercentage); + }; + + this.__InputPictureBox.LoadCompleted += (s, e) => + { + + try { + + if (e.Error != null) { + if (e.Error is WebException) { + WebException ex = (WebException) e.Error; + if (ex.Response != null) { + HttpStatusCode statusCode = ((HttpWebResponse)(ex.Response)).StatusCode; + MessageBox.Show(String.Format("{0}: {1} ({2})" , statusCode, ex.Message, ex.HResult), + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else { + // debug: SSL error on many sites. Move to WebClient and its security options to resolve? + MessageBox.Show(String.Format("{0} ({1})", ex.Message, ex.HResult), + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + else if (e.Error is System.ArgumentException) { + System.ArgumentException ex = (System.ArgumentException) e.Error; + MessageBox.Show( + String.Format("{0} ({1}).{2}Server is likely using unknown to .NET format, like WebP or AVIF.", + ex.Message, ex.HResult.ToString(), Environment.NewLine + Environment.NewLine) , + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + else { + Exception ex = e.Error; + MessageBox.Show(String.Format("{0} ({1})" , ex.Message, ex.HResult), + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + if (e.Cancelled || e.Error != null) { + __InputPictureBox.Image = null; + __InputLabel.Visible = true; + __InputPictureBox.ResumeLayout(); + return; + }; + + OpenImage ((Bitmap) __InputPictureBox.Image); //reopen to perform all tasks on image // review: load without picturebox? + + } + catch (Exception ex) { + MessageBox.Show(String.Format("{0} ({1})", ex.Message, ex.HResult.ToString()) , + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally { + __StartButton.Click -= StopColorizationThread; + __StartButton.Click += StartColorizationThread; + ToggleControls (true); + } + + }; + DeOldify.Progress += (float Percent) => { - this.__StartButton.Progress = Percent; + __ProgressLabelText = "Colorizing: {0} %"; + UpdateProgress(Percent); }; + + ((System.ComponentModel.ISupportInitialize)(this.__SplitContainer)).EndInit(); + + } + catch (Exception ex){ + MessageBox.Show(String.Format("{0} ({1})", ex.Message, ex.HResult.ToString()) , + Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } } diff --git a/dummy.csproj b/dummy.csproj new file mode 100644 index 0000000..8c36021 --- /dev/null +++ b/dummy.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net48 + ColorfulSoft.DeOldify + enable + true + enable + + + \ No newline at end of file