Files
AgraSandbox/AgraV2/EffectGrayScale.cs
T

141 lines
4.9 KiB
C#

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<double>();
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;
}
}
}