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; } } }