diff --git a/AgraV2/AgraV2.csproj b/AgraV2/AgraV2.csproj index a177909..0285f59 100644 --- a/AgraV2/AgraV2.csproj +++ b/AgraV2/AgraV2.csproj @@ -49,6 +49,7 @@ + Form diff --git a/AgraV2/Effect.cs b/AgraV2/Effect.cs index 0487e6d..2084476 100644 --- a/AgraV2/Effect.cs +++ b/AgraV2/Effect.cs @@ -30,7 +30,11 @@ namespace AgraV2 //I start and stop it so the child can just always use Restart() Chrono.Start();Chrono.Stop(); } - + public virtual void populatePannel() + { + //For the childs to explore + ToolBox.Controls.Clear(); + } public virtual Bitmap[] apply(Bitmap inputBmp) { return new Bitmap[] { inputBmp }; diff --git a/AgraV2/EffectMedianFilter.cs b/AgraV2/EffectMedianFilter.cs new file mode 100644 index 0000000..f8b08c5 --- /dev/null +++ b/AgraV2/EffectMedianFilter.cs @@ -0,0 +1,143 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace AgraV2 +{ + internal class EffectMedianFilter : Effect + { + private readonly object balancelock = new object(); + private int _Radius; + + public int Radius { get => _Radius; set => _Radius = value; } + + public EffectMedianFilter(string name, Panel toolBox) : base(name, toolBox) + { + //This is just the default value + Radius = 1; + } + public override void populatePannel() + { + Label label = new Label(); + label.Text = "Radius : "; + + NumericUpDown nup = new NumericUpDown(); + nup.Minimum = 1; + nup.Maximum = 100; + nup.Increment = 1; + nup.ValueChanged += nup_ValueChanged; + nup.Location = new Point(label.Location.X + label.Width,label.Location.Y); + + ToolBox.Controls.Add(label); + ToolBox.Controls.Add(nup); + } + private void nup_ValueChanged(object sender, EventArgs e) + { + if (sender is NumericUpDown) + { + NumericUpDown nup = (NumericUpDown)sender; + Radius = (int)nup.Value; + } + } + public override Bitmap[] apply(Bitmap inputBmp) + { + Bitmap[] result = new Bitmap[] { medianFilter(inputBmp) }; + return result; + } + public unsafe Bitmap medianFilter(Bitmap inputBmp) + { + Chrono.Restart(); + + Size imgSize = new Size(inputBmp.Width,inputBmp.Height); + Bitmap result = new Bitmap(imgSize.Width, imgSize.Height); + BitmapData resultData = result.LockBits(new Rectangle(0, 0, imgSize.Width, imgSize.Height), ImageLockMode.ReadWrite, inputBmp.PixelFormat); + BitmapData inputData = inputBmp.LockBits(new Rectangle(0, 0, imgSize.Width, imgSize.Height), ImageLockMode.ReadWrite, inputBmp.PixelFormat); + + int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBmp.PixelFormat) / 8; + int byteCount = resultData.Stride * inputBmp.Height; + int offset = resultData.Stride - bytesPerPixel * imgSize.Width; + + lock (balancelock) + { + byte* resultStartPx = (byte*)resultData.Scan0.ToPointer(); + byte* resultCursor = resultStartPx; + byte* originalStartPx = (byte*)inputData.Scan0.ToPointer(); + byte* originalCursor = originalStartPx; + + for (int y = 0; y < inputBmp.Height; y++) + { + for (int x = 0; x < imgSize.Width; x++) + { + //We wont process border pixels + if (x > Radius && y > Radius && x < imgSize.Width - Radius && y < inputBmp.Height - Radius) + { + List Blues = new List(); + List Greens = new List(); + List Reds = new List(); + + List surroundingPixels = getSurroundingPixels(new Point(x, y), 2, imgSize.Width, inputBmp.Height); + + foreach (Point pixel in surroundingPixels) + { + int relativePosition = (pixel.X) * bytesPerPixel + (pixel.Y * (imgSize.Width * bytesPerPixel + offset)); + byte* address = (byte*)(relativePosition + originalStartPx); + Blues.Add(address[0]); + Greens.Add(address[1]); + Reds.Add(address[2]); + } + + Blues.Sort(); + Greens.Sort(); + Reds.Sort(); + resultCursor[0] = (byte)Blues[Blues.Count / 2]; + resultCursor[1] = (byte)Greens[Greens.Count / 2]; + resultCursor[2] = (byte)Reds[Reds.Count / 2]; + + } + originalCursor += bytesPerPixel; + resultCursor += bytesPerPixel; + } + //Taking care of the offset + originalCursor += offset; + resultCursor += offset; + } + + } + result.UnlockBits(resultData); + inputBmp.UnlockBits(inputData); + + Chrono.Stop(); + ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0); + + return result; + } + public List getSurroundingPixels(Point centerPoint, int Radius, int imageWidth, int imageHeight) + { + List result = new List(); + int width = (Radius * 2 + 1); + + Point cursor = centerPoint; + + //we place the cursor on the top left of the matrix + cursor = new Point(cursor.X - Radius, cursor.Y - Radius); + + for (int y = 0; y < width; y++) + { + //This scans top to bottom + for (int x = 0; x < width; x++) + { + //This scans left to right + result.Add(cursor); + cursor = new Point(cursor.X + 1, cursor.Y); + } + cursor = new Point(cursor.X - (Radius * 2 + 1), cursor.Y + 1); + } + return result; + } + } +} diff --git a/AgraV2/Form1.Designer.cs b/AgraV2/Form1.Designer.cs index 436135d..9ff6fb7 100644 --- a/AgraV2/Form1.Designer.cs +++ b/AgraV2/Form1.Designer.cs @@ -31,12 +31,15 @@ this.pbxOriginal = new System.Windows.Forms.PictureBox(); this.gpbx1 = new System.Windows.Forms.GroupBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.lblTimer1 = new System.Windows.Forms.Label(); this.btnDowload1 = new System.Windows.Forms.Button(); this.pbxResult1 = new System.Windows.Forms.PictureBox(); this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.lblTimer2 = new System.Windows.Forms.Label(); this.btnDownload2 = new System.Windows.Forms.Button(); this.pbxResult2 = new System.Windows.Forms.PictureBox(); this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.lblTimer3 = new System.Windows.Forms.Label(); this.btnDownload3 = new System.Windows.Forms.Button(); this.pbxResult3 = new System.Windows.Forms.PictureBox(); this.gpbxFiles = new System.Windows.Forms.GroupBox(); @@ -47,9 +50,6 @@ this.lsbEffects = new System.Windows.Forms.ListBox(); this.groupBox6 = new System.Windows.Forms.GroupBox(); this.pnlEffectToolbox = new System.Windows.Forms.Panel(); - this.lblTimer1 = new System.Windows.Forms.Label(); - this.lblTimer2 = new System.Windows.Forms.Label(); - this.lblTimer3 = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.pbxOriginal)).BeginInit(); this.gpbx1.SuspendLayout(); this.groupBox2.SuspendLayout(); @@ -95,6 +95,18 @@ this.groupBox2.TabStop = false; this.groupBox2.Text = "Result 1"; // + // lblTimer1 + // + this.lblTimer1.AutoSize = true; + this.lblTimer1.BackColor = System.Drawing.Color.Black; + this.lblTimer1.ForeColor = System.Drawing.Color.Green; + this.lblTimer1.Location = new System.Drawing.Point(6, 25); + this.lblTimer1.Name = "lblTimer1"; + this.lblTimer1.Size = new System.Drawing.Size(54, 20); + this.lblTimer1.TabIndex = 2; + this.lblTimer1.Text = "0.00s"; + this.lblTimer1.Visible = false; + // // btnDowload1 // this.btnDowload1.Location = new System.Drawing.Point(44, 247); @@ -127,6 +139,18 @@ this.groupBox3.TabStop = false; this.groupBox3.Text = "Result 2"; // + // lblTimer2 + // + this.lblTimer2.AutoSize = true; + this.lblTimer2.BackColor = System.Drawing.Color.Black; + this.lblTimer2.ForeColor = System.Drawing.Color.Green; + this.lblTimer2.Location = new System.Drawing.Point(6, 25); + this.lblTimer2.Name = "lblTimer2"; + this.lblTimer2.Size = new System.Drawing.Size(54, 20); + this.lblTimer2.TabIndex = 3; + this.lblTimer2.Text = "0.00s"; + this.lblTimer2.Visible = false; + // // btnDownload2 // this.btnDownload2.Location = new System.Drawing.Point(44, 247); @@ -159,6 +183,18 @@ this.groupBox4.TabStop = false; this.groupBox4.Text = "Result3"; // + // lblTimer3 + // + this.lblTimer3.AutoSize = true; + this.lblTimer3.BackColor = System.Drawing.Color.Black; + this.lblTimer3.ForeColor = System.Drawing.Color.Green; + this.lblTimer3.Location = new System.Drawing.Point(6, 25); + this.lblTimer3.Name = "lblTimer3"; + this.lblTimer3.Size = new System.Drawing.Size(54, 20); + this.lblTimer3.TabIndex = 4; + this.lblTimer3.Text = "0.00s"; + this.lblTimer3.Visible = false; + // // btnDownload3 // this.btnDownload3.Location = new System.Drawing.Point(44, 247); @@ -237,6 +273,7 @@ this.lsbEffects.Name = "lsbEffects"; this.lsbEffects.Size = new System.Drawing.Size(188, 204); this.lsbEffects.TabIndex = 4; + this.lsbEffects.SelectedIndexChanged += new System.EventHandler(this.lsbEffects_SelectedIndexChanged); // // groupBox6 // @@ -255,42 +292,6 @@ this.pnlEffectToolbox.Size = new System.Drawing.Size(188, 250); this.pnlEffectToolbox.TabIndex = 2; // - // lblTimer1 - // - this.lblTimer1.AutoSize = true; - this.lblTimer1.BackColor = System.Drawing.Color.Black; - this.lblTimer1.ForeColor = System.Drawing.Color.Green; - this.lblTimer1.Location = new System.Drawing.Point(6, 25); - this.lblTimer1.Name = "lblTimer1"; - this.lblTimer1.Size = new System.Drawing.Size(54, 20); - this.lblTimer1.TabIndex = 2; - this.lblTimer1.Text = "0.00s"; - this.lblTimer1.Visible = false; - // - // lblTimer2 - // - this.lblTimer2.AutoSize = true; - this.lblTimer2.BackColor = System.Drawing.Color.Black; - this.lblTimer2.ForeColor = System.Drawing.Color.Green; - this.lblTimer2.Location = new System.Drawing.Point(6, 25); - this.lblTimer2.Name = "lblTimer2"; - this.lblTimer2.Size = new System.Drawing.Size(54, 20); - this.lblTimer2.TabIndex = 3; - this.lblTimer2.Text = "0.00s"; - this.lblTimer2.Visible = false; - // - // lblTimer3 - // - this.lblTimer3.AutoSize = true; - this.lblTimer3.BackColor = System.Drawing.Color.Black; - this.lblTimer3.ForeColor = System.Drawing.Color.Green; - this.lblTimer3.Location = new System.Drawing.Point(6, 25); - this.lblTimer3.Name = "lblTimer3"; - this.lblTimer3.Size = new System.Drawing.Size(54, 20); - this.lblTimer3.TabIndex = 4; - this.lblTimer3.Text = "0.00s"; - this.lblTimer3.Visible = false; - // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); diff --git a/AgraV2/Form1.cs b/AgraV2/Form1.cs index 7532238..beab2a9 100644 --- a/AgraV2/Form1.cs +++ b/AgraV2/Form1.cs @@ -25,7 +25,7 @@ namespace AgraV2 { effects = new List(); effects.Add(new EffectGrayScale("GrayScale", pnlEffectToolbox)); - + effects.Add(new EffectMedianFilter("Median Filter", pnlEffectToolbox)); RefreshUi(); } private void RefreshUi() @@ -143,5 +143,13 @@ namespace AgraV2 { DownloadImage(pbxResult3.Image); } + + private void lsbEffects_SelectedIndexChanged(object sender, EventArgs e) + { + if (lsbEffects.SelectedIndex >= 0) + { + effects[lsbEffects.SelectedIndex].populatePannel(); + } + } } }