diff --git a/AgraV2/AgraV2.csproj b/AgraV2/AgraV2.csproj
index 0285f59..1cff558 100644
--- a/AgraV2/AgraV2.csproj
+++ b/AgraV2/AgraV2.csproj
@@ -50,6 +50,7 @@
+
Form
diff --git a/AgraV2/EffectMedianFilter.cs b/AgraV2/EffectMedianFilter.cs
index 9f301f3..d666abb 100644
--- a/AgraV2/EffectMedianFilter.cs
+++ b/AgraV2/EffectMedianFilter.cs
@@ -23,8 +23,11 @@ namespace AgraV2
}
public override void populatePannel()
{
+ base.populatePannel();
+
Label label = new Label();
label.Text = "Radius : ";
+ label.BackColor = Color.Transparent;
NumericUpDown nup = new NumericUpDown();
nup.Minimum = 1;
diff --git a/AgraV2/EffectScale.cs b/AgraV2/EffectScale.cs
new file mode 100644
index 0000000..895e5f0
--- /dev/null
+++ b/AgraV2/EffectScale.cs
@@ -0,0 +1,244 @@
+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 EffectScale : Effect
+ {
+ private readonly object balancelock = new object();
+ private int _radius;
+ private float _scale;
+
+ public int Radius { get => _radius; set => _radius = value; }
+ public float Scale { get => _scale; set => _scale = value; }
+
+ public EffectScale(string name, Panel toolBox) : base(name, toolBox)
+ {
+ //Default values
+ Radius = 1;
+ Scale = 1;
+ }
+ public override void populatePannel()
+ {
+ base.populatePannel();
+
+ Label label = new Label();
+ label.Text = "Range : ";
+ label.BackColor = Color.Transparent;
+ label.Location = new Point(0, 0);
+
+ Label label2 = new Label();
+ label2.Text = "Scale ratio : ";
+ label2.BackColor = Color.Transparent;
+ label2.Location = new Point(0, label.Height);
+
+ NumericUpDown nupRange = new NumericUpDown();
+ nupRange.Minimum = 1;
+ nupRange.Maximum = 100;
+ nupRange.Increment = 1;
+ nupRange.ValueChanged += nupRange_ValueChanged;
+ nupRange.Location = new Point(label.Location.X + label.Width, label.Location.Y);
+
+ NumericUpDown nupScale = new NumericUpDown();
+ nupScale.Minimum = 1;
+ nupScale.Maximum = 100;
+ nupScale.Increment = 0.1M;
+ nupScale.ValueChanged += nupScale_ValueChanged;
+ nupScale.Location = new Point(label2.Location.X + label2.Width, label2.Location.Y);
+
+ ToolBox.Controls.Add(label);
+ ToolBox.Controls.Add(nupRange);
+ ToolBox.Controls.Add(label2);
+ ToolBox.Controls.Add(nupScale);
+ }
+ private void nupRange_ValueChanged(object sender, EventArgs e)
+ {
+ if (sender is NumericUpDown)
+ {
+ NumericUpDown nup = (NumericUpDown)sender;
+ Radius = (int)nup.Value;
+ }
+ }
+ private void nupScale_ValueChanged(object sender, EventArgs e)
+ {
+ if (sender is NumericUpDown)
+ {
+ NumericUpDown nup = (NumericUpDown)sender;
+ Scale = (float)nup.Value;
+ }
+ }
+ 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();
+
+ Bitmap[] result = new Bitmap[] { NearestNeighbor(inputBmp)};
+ return result;
+ }
+ public unsafe Bitmap NearestNeighbor(Bitmap inputBmp)
+ {
+ Chrono.Restart();
+
+ Size imgSize = new Size(inputBmp.Width, inputBmp.Height);
+ Size newSize = new Size((int)(imgSize.Width * Scale), (int)(imgSize.Height * Scale));
+
+ Bitmap result = new Bitmap(newSize.Width, newSize.Height);
+ BitmapData resultData = result.LockBits(new Rectangle(0, 0, newSize.Width, newSize.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 = inputData.Stride * inputBmp.Height;
+ int offset = inputData.Stride - bytesPerPixel * imgSize.Width;
+ int newOffset = resultData.Stride - bytesPerPixel * newSize.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 < newSize.Height; y++)
+ {
+ for (int x = 0; x < newSize.Width; x++)
+ {
+ //We want to know what the pixel on the old x and y was
+
+ int oldX = (int)Math.Floor((float)x / Scale);
+ int oldY = (int)Math.Floor((float)y / Scale);
+
+ if (bytesPerPixel == 3 && oldX == 2 && oldY == 2)
+ Console.WriteLine("coucou");
+
+ //Now we would like to know what the color on this pixel was
+ //transfer x,y to linear : y*(width + offset) + x
+
+ int oldPosition = oldY * imgSize.Width + oldX;
+ oldPosition = oldPosition * bytesPerPixel + oldY * offset;
+ int oldBlue = (originalStartPx + oldPosition)[0];
+ int oldGreen = (originalStartPx + oldPosition)[1];
+ int oldRed = (originalStartPx + oldPosition)[2];
+
+ resultCursor[0] = (byte)oldBlue;
+ resultCursor[1] = (byte)oldGreen;
+ resultCursor[2] = (byte)oldRed;
+
+ //originalCursor += bytesPerPixel;
+ resultCursor += bytesPerPixel;
+ }
+ //Taking care of the offset
+ //originalCursor += offset;
+ resultCursor += newOffset;
+ }
+
+ }
+ result.UnlockBits(resultData);
+ inputBmp.UnlockBits(inputData);
+
+ Chrono.Stop();
+ ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0);
+
+ return result;
+ }
+ public unsafe Bitmap BiLinear(Bitmap inputBmp)
+ {
+ Chrono.Restart();
+
+ Size imgSize = new Size(inputBmp.Width, inputBmp.Height);
+ Size newSize = new Size((int)(imgSize.Width * Scale), (int)(imgSize.Height * Scale));
+
+ Bitmap result = new Bitmap(newSize.Width, newSize.Height);
+ BitmapData resultData = result.LockBits(new Rectangle(0, 0, newSize.Width, newSize.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 = inputData.Stride * inputBmp.Height;
+ int offset = inputData.Stride - bytesPerPixel * imgSize.Width;
+ int newOffset = resultData.Stride - bytesPerPixel * newSize.Width;
+
+
+ lock (balancelock)
+ {
+ byte* resultStartPx = (byte*)resultData.Scan0.ToPointer();
+ byte* resultCursor = resultStartPx;
+ byte* originalStartPx = (byte*)inputData.Scan0.ToPointer();
+ byte* originalCursor = originalStartPx;
+
+ float tx = imgSize.Width / newSize.Width;
+ float ty = imgSize.Height / newSize.Height;
+
+ for (int y = 0; y < newSize.Height; y++)
+ {
+ for (int x = 0; x < newSize.Width; x++)
+ {
+
+ int newX = (int)(tx * x);
+ int newY = (int)(ty * y);
+
+ float x_diff = ((tx *x)-newX);
+ float y_diff = ((ty *y)-newY);
+
+ //int value =
+
+ //THIS METHOD IS NOT FINISHED
+
+ //originalCursor += bytesPerPixel;
+ resultCursor += bytesPerPixel;
+
+ }
+ //Taking care of the offset
+ //originalCursor += offset;
+ resultCursor += newOffset;
+ }
+
+ }
+ result.UnlockBits(resultData);
+ inputBmp.UnlockBits(inputData);
+
+ Chrono.Stop();
+ ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0);
+
+ return result;
+ }
+ public int ConvertPointToLinear(Point position,Size imageSize,int bytesPerPixel, int offset)
+ {
+ int linearPosition = position.Y * imageSize.Width + position.X;
+ linearPosition = linearPosition * bytesPerPixel + position.Y * offset;
+
+ return linearPosition;
+ }
+ 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.cs b/AgraV2/Form1.cs
index beab2a9..1412239 100644
--- a/AgraV2/Form1.cs
+++ b/AgraV2/Form1.cs
@@ -26,6 +26,7 @@ namespace AgraV2
effects = new List();
effects.Add(new EffectGrayScale("GrayScale", pnlEffectToolbox));
effects.Add(new EffectMedianFilter("Median Filter", pnlEffectToolbox));
+ effects.Add(new EffectScale("Scaling", pnlEffectToolbox));
RefreshUi();
}
private void RefreshUi()
@@ -43,6 +44,7 @@ namespace AgraV2
FolderBrowserDialog dialog = new FolderBrowserDialog();
if (dialog.ShowDialog() == DialogResult.OK)
{
+ pnlFiles.Controls.Clear();
selectedDirectory = new DirectoryInfo(dialog.SelectedPath);
List images = new List();