New feature : Add and substact of two images of the same type is now possible
This commit is contained in:
@@ -48,6 +48,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Effect.cs" />
|
<Compile Include="Effect.cs" />
|
||||||
|
<Compile Include="EffectArythmeticOperations.cs" />
|
||||||
<Compile Include="EffectGrayScale.cs" />
|
<Compile Include="EffectGrayScale.cs" />
|
||||||
<Compile Include="EffectMedianFilter.cs" />
|
<Compile Include="EffectMedianFilter.cs" />
|
||||||
<Compile Include="EffectScale.cs" />
|
<Compile Include="EffectScale.cs" />
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace AgraV2
|
||||||
|
{
|
||||||
|
internal class EffectArythmeticOperations : Effect
|
||||||
|
{
|
||||||
|
private readonly object balancelock = new object();
|
||||||
|
public static List<string> Operations = new List<string>() { "Substract","Add" };
|
||||||
|
|
||||||
|
private string _operationType;
|
||||||
|
private Bitmap _imageToCompare;
|
||||||
|
public Bitmap ImageToCompare { get => _imageToCompare; set => _imageToCompare = value; }
|
||||||
|
public string OperationType { get => _operationType; set => _operationType = value; }
|
||||||
|
|
||||||
|
public EffectArythmeticOperations(string name, Panel toolBox) : base(name, toolBox)
|
||||||
|
{
|
||||||
|
ImageToCompare = new Bitmap(1,1);
|
||||||
|
OperationType = Operations[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void populatePannel()
|
||||||
|
{
|
||||||
|
base.populatePannel();
|
||||||
|
|
||||||
|
const int UI_MARGIN = 10;
|
||||||
|
|
||||||
|
PictureBox pictureBox = new PictureBox();
|
||||||
|
pictureBox.Width = ToolBox.Width;
|
||||||
|
pictureBox.Height = ToolBox.Width;
|
||||||
|
pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
|
||||||
|
pictureBox.Location = new Point(0,0);
|
||||||
|
|
||||||
|
if (ImageToCompare.Size != new Size(1,1))
|
||||||
|
{
|
||||||
|
pictureBox.Image = ImageToCompare;
|
||||||
|
}
|
||||||
|
|
||||||
|
Button button = new Button();
|
||||||
|
button.Click += LoadImage;
|
||||||
|
button.Location = new Point(0,pictureBox.Location.Y + pictureBox.Height + UI_MARGIN);
|
||||||
|
|
||||||
|
ListBox listBox = new ListBox();
|
||||||
|
listBox.DataSource = Operations;
|
||||||
|
listBox.SelectedIndexChanged += operationChange;
|
||||||
|
listBox.Location = new Point(0,button.Location.Y + button.Height + UI_MARGIN);
|
||||||
|
|
||||||
|
ToolBox.Controls.Add(pictureBox);
|
||||||
|
ToolBox.Controls.Add(button);
|
||||||
|
ToolBox.Controls.Add(listBox);
|
||||||
|
}
|
||||||
|
private void operationChange(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is ListBox)
|
||||||
|
{
|
||||||
|
OperationType = Operations[(sender as ListBox).SelectedIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override Bitmap[] apply(Bitmap inputBmp)
|
||||||
|
{
|
||||||
|
if (inputBmp == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
//This is important for when the user wants to re apply an effet
|
||||||
|
ProcessingDuration = new List<double>();
|
||||||
|
|
||||||
|
Bitmap[] result = new Bitmap[] { Substract(inputBmp,ImageToCompare) };
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
public unsafe Bitmap Substract(Bitmap image,Bitmap imageToSubstract)
|
||||||
|
{
|
||||||
|
Chrono.Restart();
|
||||||
|
|
||||||
|
Size imageSize = image.Size;
|
||||||
|
|
||||||
|
Bitmap result = new Bitmap(imageSize.Width,imageSize.Height);
|
||||||
|
|
||||||
|
BitmapData xData = result.LockBits(new Rectangle(0, 0, imageSize.Width, imageSize.Height), ImageLockMode.ReadWrite, image.PixelFormat);
|
||||||
|
BitmapData firstData = image.LockBits(new Rectangle(0, 0, imageSize.Width, imageSize.Height), ImageLockMode.ReadWrite, image.PixelFormat);
|
||||||
|
BitmapData secondData = imageToSubstract.LockBits(new Rectangle(0, 0, imageSize.Width, imageSize.Height), ImageLockMode.ReadWrite, image.PixelFormat);
|
||||||
|
|
||||||
|
|
||||||
|
int bytesPerPixel = Bitmap.GetPixelFormatSize(image.PixelFormat) / 8;
|
||||||
|
int byteCount = xData.Stride * image.Height;
|
||||||
|
int offset = xData.Stride - bytesPerPixel * image.Width;
|
||||||
|
|
||||||
|
lock (balancelock)
|
||||||
|
{
|
||||||
|
byte* ResultStartPx = (byte*)xData.Scan0.ToPointer();
|
||||||
|
byte* FirstStartPx = (byte*)firstData.Scan0.ToPointer();
|
||||||
|
byte* SecondStartPx = (byte*)secondData.Scan0.ToPointer();
|
||||||
|
|
||||||
|
byte* ResultCursor = ResultStartPx;
|
||||||
|
byte* FirstCursor = FirstStartPx;
|
||||||
|
byte* SecondCursor = SecondStartPx;
|
||||||
|
|
||||||
|
for (int x = 0; x < imageSize.Width; x++)
|
||||||
|
{
|
||||||
|
for (int y = 0; y < imageSize.Height; y++)
|
||||||
|
{
|
||||||
|
int firstBlue = FirstCursor[0];
|
||||||
|
int firstGreen = FirstCursor[1];
|
||||||
|
int firstRed = FirstCursor[2];
|
||||||
|
|
||||||
|
int secondBlue = SecondCursor[0];
|
||||||
|
int secondGreen = SecondCursor[1];
|
||||||
|
int secondRed = SecondCursor[2];
|
||||||
|
|
||||||
|
switch (OperationType)
|
||||||
|
{
|
||||||
|
case "Substract":
|
||||||
|
ResultCursor[0] = (byte)Math.Max(0, firstBlue - secondBlue);
|
||||||
|
ResultCursor[1] = (byte)Math.Max(0, firstGreen - secondGreen);
|
||||||
|
ResultCursor[2] = (byte)Math.Max(0, firstRed - secondRed);
|
||||||
|
break;
|
||||||
|
case "Add":
|
||||||
|
ResultCursor[0] = (byte)Math.Min(255, firstBlue + secondBlue);
|
||||||
|
ResultCursor[1] = (byte)Math.Min(255, firstGreen + secondGreen);
|
||||||
|
ResultCursor[2] = (byte)Math.Min(255, firstRed + secondRed);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ResultCursor[0] = (byte)0;
|
||||||
|
ResultCursor[1] = (byte)0;
|
||||||
|
ResultCursor[2] = (byte)0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResultCursor += bytesPerPixel;
|
||||||
|
FirstCursor += bytesPerPixel;
|
||||||
|
SecondCursor += bytesPerPixel;
|
||||||
|
}
|
||||||
|
//Taking care of the offset
|
||||||
|
ResultCursor += offset;
|
||||||
|
FirstCursor += offset;
|
||||||
|
SecondCursor += offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
result.UnlockBits(xData);
|
||||||
|
image.UnlockBits(firstData);
|
||||||
|
imageToSubstract.UnlockBits(secondData);
|
||||||
|
|
||||||
|
ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadImage(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
OpenFileDialog dialog = new OpenFileDialog();
|
||||||
|
if (dialog.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
FileInfo file = new FileInfo(dialog.FileName);
|
||||||
|
|
||||||
|
ImageToCompare = (Bitmap)Image.FromFile(file.FullName);
|
||||||
|
|
||||||
|
populatePannel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+1
@@ -287,6 +287,7 @@
|
|||||||
//
|
//
|
||||||
// pnlEffectToolbox
|
// pnlEffectToolbox
|
||||||
//
|
//
|
||||||
|
this.pnlEffectToolbox.AutoScroll = true;
|
||||||
this.pnlEffectToolbox.Location = new System.Drawing.Point(6, 24);
|
this.pnlEffectToolbox.Location = new System.Drawing.Point(6, 24);
|
||||||
this.pnlEffectToolbox.Name = "pnlEffectToolbox";
|
this.pnlEffectToolbox.Name = "pnlEffectToolbox";
|
||||||
this.pnlEffectToolbox.Size = new System.Drawing.Size(188, 250);
|
this.pnlEffectToolbox.Size = new System.Drawing.Size(188, 250);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace AgraV2
|
|||||||
effects.Add(new EffectGrayScale("GrayScale", pnlEffectToolbox));
|
effects.Add(new EffectGrayScale("GrayScale", pnlEffectToolbox));
|
||||||
effects.Add(new EffectMedianFilter("Median Filter", pnlEffectToolbox));
|
effects.Add(new EffectMedianFilter("Median Filter", pnlEffectToolbox));
|
||||||
effects.Add(new EffectScale("Scaling", pnlEffectToolbox));
|
effects.Add(new EffectScale("Scaling", pnlEffectToolbox));
|
||||||
|
effects.Add(new EffectArythmeticOperations("Arithmetic Operations", pnlEffectToolbox));
|
||||||
RefreshUi();
|
RefreshUi();
|
||||||
}
|
}
|
||||||
private void RefreshUi()
|
private void RefreshUi()
|
||||||
|
|||||||
Reference in New Issue
Block a user