Added median filter but for some reason it always trigger pointer exceptions
This commit is contained in:
@@ -49,6 +49,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Effect.cs" />
|
||||
<Compile Include="EffectGrayScale.cs" />
|
||||
<Compile Include="EffectMedianFilter.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
|
||||
+5
-1
@@ -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 };
|
||||
|
||||
@@ -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<int> Blues = new List<int>();
|
||||
List<int> Greens = new List<int>();
|
||||
List<int> Reds = new List<int>();
|
||||
|
||||
List<Point> 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<Point> getSurroundingPixels(Point centerPoint, int Radius, int imageWidth, int imageHeight)
|
||||
{
|
||||
List<Point> result = new List<Point>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+40
-39
@@ -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);
|
||||
|
||||
+9
-1
@@ -25,7 +25,7 @@ namespace AgraV2
|
||||
{
|
||||
effects = new List<Effect>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user