using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace AgraV2 { internal class EffectGrayScale:Effect { private readonly object balancelock = new object(); public EffectGrayScale(string name, Panel toolBox) : base(name, toolBox) { //Empty } 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[] { useGetSetPixel(inputBmp), useByteArray(inputBmp), usePointers(inputBmp)}; return result; } public Bitmap useGetSetPixel(Bitmap inputBmp) { Chrono.Restart(); Bitmap outputBmp = new Bitmap(inputBmp.Width, inputBmp.Height); for (int x = 0; x < inputBmp.Width; x++) { for (int y = 0; y < inputBmp.Height; y++) { Color pixelColor = inputBmp.GetPixel(x, y); int grayScale = (Math.Min(pixelColor.R, Math.Min(pixelColor.G, pixelColor.B)) + Math.Max(pixelColor.R, Math.Max(pixelColor.G, pixelColor.B))) / 2; Color newPixelColor = Color.FromArgb(grayScale, grayScale, grayScale); outputBmp.SetPixel(x, y, newPixelColor); } } Chrono.Stop(); ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0); return outputBmp; } public Bitmap useByteArray(Bitmap inputBmp) { Chrono.Restart(); Bitmap result = (Bitmap)inputBmp.Clone(); BitmapData xData = result.LockBits(new Rectangle(0, 0, inputBmp.Width, inputBmp.Height), ImageLockMode.ReadWrite, inputBmp.PixelFormat); int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBmp.PixelFormat) / 8; int byteCount = xData.Stride * inputBmp.Height; int offset = xData.Stride - bytesPerPixel * inputBmp.Width; byte[] data = new byte[byteCount]; Marshal.Copy(xData.Scan0, data, 0, byteCount); for (int x = 0; x < inputBmp.Width; x++) { for (int y = 0; y < inputBmp.Height; y++) { int position = y * (bytesPerPixel * inputBmp.Width + offset) + x * bytesPerPixel; int Blue = data[position]; int Green = data[position + 1]; int Red = data[position + 2]; int grayScale = (Math.Min(Red, Math.Min(Green, Blue)) + Math.Max(Red, Math.Max(Green, Blue))) / 2; data[position] = (byte)grayScale; data[position + 1] = (byte)grayScale; data[position + 2] = (byte)grayScale; } } Marshal.Copy(data, 0, xData.Scan0, data.Length); result.UnlockBits(xData); Chrono.Stop(); ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0); return result; } public unsafe Bitmap usePointers(Bitmap inputBmp) { Chrono.Restart(); Bitmap result = (Bitmap)inputBmp.Clone(); BitmapData xData = result.LockBits(new Rectangle(0, 0, inputBmp.Width, inputBmp.Height), ImageLockMode.ReadWrite, inputBmp.PixelFormat); int bytesPerPixel = Bitmap.GetPixelFormatSize(inputBmp.PixelFormat) / 8; int byteCount = xData.Stride * inputBmp.Height; int offset = xData.Stride - bytesPerPixel * inputBmp.Width; lock (balancelock) { byte* startPx = (byte*)xData.Scan0.ToPointer(); byte* cursor = startPx; for (int x = 0; x < inputBmp.Width; x++) { for (int y = 0; y < inputBmp.Height; y++) { int Blue = cursor[0]; int Green = cursor[1]; int Red = cursor[2]; int grayScale = (Math.Min(Red, Math.Min(Green, Blue)) + Math.Max(Red, Math.Max(Green, Blue))) / 2; cursor[0] = (byte)grayScale; cursor[1] = (byte)grayScale; cursor[2] = (byte)grayScale; cursor += bytesPerPixel; } //Taking care of the offset cursor += offset; } } result.UnlockBits(xData); Chrono.Stop(); ProcessingDuration.Add(Chrono.ElapsedMilliseconds / 1000.0); return result; } } }