Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
18 kB
2
Indexable
Never
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class LiveImageProcessing
{
    private PictureBox canvas;
    private List<Layer> layers;
    private int currentLayerIndex;
    private Bitmap outputImage;
    private Graphics graphics;
    private List<HistoryEntry> history;
    private int maxHistory;

    // Magic Wand Tool fields
    private int magicWandThreshold;
    private bool[,] magicWandVisitedPixels;
    private Queue<Point> magicWandPixelQueue;

    // Polygon Lasso Tool fields
    private Point[] polygonPoints;

    public LiveImageProcessing(PictureBox canvas)
    {
        this.canvas = canvas;
        layers = new List<Layer>();
        currentLayerIndex = -1;
        outputImage = new Bitmap(canvas.Width, canvas.Height);
        graphics = Graphics.FromImage(outputImage);
        history = new List<HistoryEntry>();
        maxHistory = 10;

        magicWandThreshold = 30;
        magicWandVisitedPixels = new bool[outputImage.Width, outputImage.Height];
        magicWandPixelQueue = new Queue<Point>();

        polygonPoints = new Point[0];
    }

    public void NewLayer()
    {
        Bitmap bitmap = new Bitmap(canvas.Width, canvas.Height);
        Layer layer = new Layer(bitmap.Width, bitmap.Height);
        layer.Bitmap = bitmap;
        graphics = Graphics.FromImage(layer.Bitmap);
        graphics.Clear(Color.Transparent);
        layers.Add(layer);
        currentLayerIndex = layers.Count - 1;
        UpdateOutputImage();
    }

    public void SelectLayer(int index)
    {
        if (index >= 0 && index < layers.Count)
        {
            currentLayerIndex = index;
            UpdateOutputImage();
        }
    }

    public void DeleteLayer()
    {
        if (layers.Count > 1 && currentLayerIndex >= 0)
        {
            layers.RemoveAt(currentLayerIndex);
            currentLayerIndex = 0;
            UpdateOutputImage();
        }
    }

    public void MoveLayerUp()
    {
        if (currentLayerIndex > 0)
        {
            Layer layer = layers[currentLayerIndex];
            layers.RemoveAt(currentLayerIndex);
            layers.Insert(currentLayerIndex - 1, layer);
            currentLayerIndex--;
            UpdateOutputImage();
        }
    }

    public void MoveLayerDown()
    {
        if (currentLayerIndex < layers.Count - 1)
        {
            Layer layer = layers[currentLayerIndex];
            layers.RemoveAt(currentLayerIndex);
            layers.Insert(currentLayerIndex + 1, layer);
            currentLayerIndex++;
            UpdateOutputImage();
        }
    }

    public void DrawLine(Point startPoint, Point endPoint, Color color, int size)
    {
        AddHistoryEntry();
        graphics.DrawLine(new Pen(color, size), startPoint, endPoint);
        UpdateOutputImage();
    }

    public void DrawRectangle(Rectangle rectangle, Color color, int size)
    {
        AddHistoryEntry();
        graphics.DrawRectangle(new Pen(color, size), rectangle);
        UpdateOutputImage();
    }

    public void FillRectangle(Rectangle rectangle, Color color)
    {
        AddHistoryEntry();
        graphics.FillRectangle(new SolidBrush(color), rectangle);
        UpdateOutputImage();
    }

    public void DrawEllipse(Rectangle rectangle, Color color, int size)
    {
        AddHistoryEntry();
        graphics.DrawEllipse(new Pen(color, size), rectangle);
        UpdateOutputImage();
    }

    public void FillEllipse(Rectangle rectangle, Color color)
    {
        AddHistoryEntry();
        graphics.FillEllipse(new SolidBrush(color), rectangle);
        UpdateOutputImage();
    }

    public void DrawPolygon(Point[] points, Color color, int size)
    {
        AddHistoryEntry();
        graphics.DrawPolygon(new Pen(color, size), points);
        UpdateOutputImage();
    }

    public void FillPolygon(Point[] points, Color color)
    {
        AddHistoryEntry();
        graphics.FillPolygon(new SolidBrush(color), points);
        UpdateOutputImage();
    }

    public void DrawCurve(Point[] points, Color color, int size)
    {
        AddHistoryEntry();
        graphics.DrawCurve(new Pen(color, size), points);
        UpdateOutputImage();
    }

    public void DrawBezier(Point startPoint, Point controlPoint1, Point controlPoint2, Point endPoint, Color color, int size)
    {
        AddHistoryEntry();
        graphics.DrawBezier(new Pen(color, size), startPoint, controlPoint1, controlPoint2, endPoint);
        UpdateOutputImage();
    }

    public void FillRegion(Region region, Color color)
    {
        AddHistoryEntry();
        graphics.FillRegion(new SolidBrush(color), region);
        UpdateOutputImage();
    }

    public void DrawImage(Bitmap image, Rectangle rectangle)
    {
        AddHistoryEntry();
        graphics.DrawImage(image, rectangle);
        UpdateOutputImage();
    }

    public void ResizeImage(int width, int height)
    {
        AddHistoryEntry();
        Bitmap newImage = new Bitmap(outputImage, width, height);
        outputImage = newImage;
        canvas.Image = outputImage;
    }

    public void RotateImage(float angle)
    {
        AddHistoryEntry();
        Bitmap rotatedImage = new Bitmap(outputImage.Width, outputImage.Height);
        Graphics g = Graphics.FromImage(rotatedImage);
        g.TranslateTransform((float)outputImage.Width / 2, (float)outputImage.Height / 2);
        g.RotateTransform(angle);
        g.TranslateTransform(-(float)outputImage.Width / 2, -(float)outputImage.Height / 2);
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(outputImage, 0, 0);
        g.Dispose();
        outputImage = rotatedImage;
        canvas.Image = outputImage;
    }

    public void FlipImage(bool horizontal)
    {
        AddHistoryEntry();
        Bitmap flippedImage = new Bitmap(outputImage.Width, outputImage.Height);
        Graphics g = Graphics.FromImage(flippedImage);
        if (horizontal)
        {
            g.ScaleTransform(-1, 1);
            g.TranslateTransform(-outputImage.Width, 0);
        }
        else
        {
            g.ScaleTransform(1, -1);
            g.TranslateTransform(0, -outputImage.Height);
        }
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.DrawImage(outputImage, 0, 0);
        g.Dispose();
        outputImage = flippedImage;
        canvas.Image = outputImage;
    }

    public void BrightnessCorrection(int amount)
    {
        AddHistoryEntry();
        Bitmap adjustedImage = new Bitmap(outputImage.Width, outputImage.Height);
        for (int x = 0; x < outputImage.Width; x++)
        {
            for (int y = 0; y < outputImage.Height; y++)
            {
                Color originalColor = outputImage.GetPixel(x, y);
                int r = originalColor.R + amount;
                int g = originalColor.G + amount;
                int b = originalColor.B + amount;
                if (r > 255) r = 255;
                if (g > 255) g = 255;
                if (b > 255) b = 255;
                if (r < 0) r = 0;
                if (g < 0) g = 0;
                if (b < 0) b = 0;
                Color adjustedColor = Color.FromArgb(originalColor.A, r, g, b);
                adjustedImage.SetPixel(x, y, adjustedColor);
            }
        }
        outputImage = adjustedImage;
        canvas.Image = outputImage;
    }
    public void ContrastCorrection(double amount)
    {
        AddHistoryEntry();
        Bitmap adjustedImage = new Bitmap(outputImage.Width, outputImage.Height);
        for (int x = 0; x < outputImage.Width; x++)
        {
            for (int y = 0; y < outputImage.Height; y++)
            {
                Color originalColor = outputImage.GetPixel(x, y);
                int r = (int)(amount * (originalColor.R - 128) + 128);
                int g = (int)(amount * (originalColor.G - 128) + 128);
                int b = (int)(amount * (originalColor.B - 128) + 128);
                if (r > 255) r = 255;
                if (g > 255) g = 255;
                if (b > 255) b = 255;
                if (r < 0) r = 0;
                if (g < 0) g = 0;
                if (b < 0) b = 0;
                Color adjustedColor = Color.FromArgb(originalColor.A, r, g, b);
                adjustedImage.SetPixel(x, y, adjustedColor);
            }
        }
        outputImage = adjustedImage;
        canvas.Image = outputImage;
    }

    public void SaturationCorrection(double amount)
    {
        AddHistoryEntry();
        Bitmap adjustedImage = new Bitmap(outputImage.Width, outputImage.Height);
        for (int x = 0; x < outputImage.Width; x++)
        {
            for (int y = 0; y < outputImage.Height; y++)
            {
                Color originalColor = outputImage.GetPixel(x, y);
                double r = originalColor.R / 255.0;
                double g = originalColor.G / 255.0;
                double b = originalColor.B / 255.0;
                double max = Math.Max(r, Math.Max(g, b));
                double min = Math.Min(r, Math.Min(g, b));
                double l = (max + min) / 2;
                double s;
                if (max == min)
                {
                    s = 0;
                }
                else
                {
                    s = l < 0.5 ? (max - min) / (max + min) : (max - min) / (2 - max - min);
                }
                double newS = s * amount;
                if (newS > 1) newS = 1;
                if (newS < 0) newS = 0;
                double newL = l;
                if (newS != 0)
                {
                    if (newL < 0.5) newL *= (1 + newS);
                    else newL = newL * (1 - newS) + newS;
                }
                int newR = (int)(newL * 2.55 * (r / (max * 255)) + 0.5);
                int newG = (int)(newL * 2.55 * (g / (max * 255)) + 0.5);
                int newB = (int)(newL * 2.55 * (b / (max * 255)) + 0.5);
                if (newR > 255) newR = 255;
                if (newG > 255) newG = 255;
                if (newB > 255) newB = 255;
                if (newR < 0) newR = 0;
                if (newG < 0) newG = 0;
                if (newB < 0) newB = 0;
                Color adjustedColor = Color.FromArgb(originalColor.A, newR, newG, newB);
                adjustedImage.SetPixel(x, y, adjustedColor);
            }
        }
        outputImage = adjustedImage;
        canvas.Image = outputImage;
    }

    public void ContentAwareFill(Rectangle source, Point destination)
    {
        AddHistoryEntry();
        int x = destination.X;
        int y = destination.Y;
        int w = source.Width;
        int h = source.Height;
        Bitmap sourceImage = outputImage.Clone(source, outputImage.PixelFormat);
        Bitmap destinationImage = new Bitmap(outputImage.Width, outputImage.Height);
        Graphics g = Graphics.FromImage(destinationImage);
        g.DrawImage(outputImage, 0, 0);
        g.Dispose();
        BitmapData sourceData = sourceImage.LockBits(new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        BitmapData destinationData = destinationImage.LockBits(new Rectangle(0, 0, destinationImage.Width, destinationImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
        int sourceStride = sourceData.Stride;
        int destinationStride = destinationData.Stride;
        byte[] sourcePixels = new byte[sourceStride * h];
        byte[] destinationPixels = new byte[destinationStride * destinationImage.Height];
        Marshal.Copy(sourceData.Scan0, sourcePixels, 0, sourcePixels.Length);
        Marshal.Copy(destinationData.Scan0, destinationPixels, 0, destinationPixels.Length);
        for (int i = 0; i < h; i++)
        {
            for (int j = 0; j < w; j++)
            {
                int sourceIndex = i * sourceStride + j * 4;
                int destinationIndex = (y + i) * destinationStride + (x + j) * 4;
                destinationPixels[destinationIndex] = sourcePixels[sourceIndex];
                destinationPixels[destinationIndex + 1] = sourcePixels[sourceIndex + 1];
                destinationPixels[destinationIndex + 2] = sourcePixels[sourceIndex + 2];
                destinationPixels[destinationIndex + 3] = sourcePixels[sourceIndex + 3];
            }
        }
        Marshal.Copy(destinationPixels, 0, destinationData.Scan0, destinationPixels.Length);
        sourceImage.UnlockBits(sourceData);
        destinationImage.UnlockBits(destinationData);
        outputImage = destinationImage;
        canvas.Image = outputImage;
    }

    public void AddLayer()
    {
        AddHistoryEntry();
        layers.Add(new Layer(outputImage));
    }

    public void SetActiveLayer(int layerIndex)
    {
        if (layerIndex >= 0 && layerIndex < layers.Count)
        {
            activeLayerIndex = layerIndex;
            outputImage = layers[layerIndex].GetImage();
            canvas.Image = outputImage;
        }
    }

    public void MergeLayers()
    {
        AddHistoryEntry();
        Bitmap mergedImage = new Bitmap(outputImage.Width, outputImage.Height);
        Graphics g = Graphics.FromImage(mergedImage);
        for (int i = 0; i < layers.Count; i++)
        {
            Bitmap layerImage = layers[i].GetImage();
            g.DrawImage(layerImage, 0, 0);
        }
        g.Dispose();
        layers.Clear();
        layers.Add(new Layer(mergedImage));
        activeLayerIndex = 0;
        outputImage = mergedImage;
        canvas.Image = outputImage;
    }
    public void AddLayerMask(Rectangle selection)
    {
        if (activeLayerIndex >= 0 && activeLayerIndex < layers.Count)
        {
            AddHistoryEntry();
            LayerMask layerMask = new LayerMask(selection, outputImage.Width, outputImage.Height);
            layers[activeLayerIndex].SetMask(layerMask);
            layerMaskedImage = layerMask.ApplyMask(outputImage);
            canvas.Image = layerMaskedImage;
        }
    }

    public void SetLayerMask(Rectangle selection)
    {
        if (activeLayerIndex >= 0 && activeLayerIndex < layers.Count)
        {
            AddHistoryEntry();
            layers[activeLayerIndex].GetMask().SetMask(selection, outputImage.Width, outputImage.Height);
            layerMaskedImage = layers[activeLayerIndex].GetMask().ApplyMask(outputImage);
            canvas.Image = layerMaskedImage;
        }
    }

    public void RemoveLayerMask()
    {
        if (activeLayerIndex >= 0 && activeLayerIndex < layers.Count)
        {
            AddHistoryEntry();
            layers[activeLayerIndex].SetMask(null);
            layerMaskedImage = null;
            canvas.Image = outputImage;
        }
    }

    public void ApplyLayerMask()
    {
        if (activeLayerIndex >= 0 && activeLayerIndex < layers.Count && layerMaskedImage != null)
        {
            AddHistoryEntry();
            layers[activeLayerIndex].SetImage(layerMaskedImage);
            outputImage = layerMaskedImage;
            layerMaskedImage = null;
            canvas.Image = outputImage;
        }
    }

    public void Undo()
    {
        if (historyIndex > 0)
        {
            historyIndex--;
            outputImage = new Bitmap(history[historyIndex]);
            canvas.Image = outputImage;
        }
    }

    public void Redo()
    {
        if (historyIndex < history.Count - 1)
        {
            historyIndex++;
            outputImage = new Bitmap(history[historyIndex]);
            canvas.Image = outputImage;
        }
        else
        {
            throw new NotImplementedException();
        }
    }

}
public class Layer
{
    private Bitmap image;
    private LayerMask mask;
    public Layer(Bitmap image)
    {
        this.image = image;
    }

    public Bitmap GetImage()
    {
        return image;
    }

    public void SetImage(Bitmap image)
    {
        this.image = image;
    }

    public LayerMask GetMask()
    {
        return mask;
    }

    public void SetMask(LayerMask mask)
    {
        this.mask = mask;
    }
}

public class LayerMask
{
    private Rectangle selection;
    private byte[] mask;
    private int width;
    private int height;
    public LayerMask(Rectangle selection, int width, int height)
    {
        this.selection = selection;
        mask = new byte[width * height];
        this.width = width;
        this.height = height;
    }

    public Rectangle GetSelection()
    {
        return selection;
    }

    public void SetSelection(Rectangle selection)
    {
        this.selection = selection;
    }

    public byte[] GetMask()
    {
        return mask;
    }

    public void SetMask(byte[] mask)
    {
        this.mask = mask;
    }

    public void SetMask(Rectangle selection, int width, int height)
    {
        this.selection = selection;
        mask = new byte[width * height];
    }

    public void SetMaskPixel(int x, int y, byte value)
    {
        mask[y * width + x] = value;
    }

    public byte GetMaskPixel(int x, int y)
    {
        return mask[y * width + x];
    }

    public Bitmap ApplyMask(Bitmap image)
    {
        Bitmap maskedImage = new Bitmap(image.Width, image.Height);
        for (int x = 0; x < image.Width; x++)
        {
            for (int y = 0; y < image.Height; y++)
            {
                Color originalColor = image.GetPixel(x, y);
                byte maskValue = mask[y * width + x];
                Color newColor = Color.FromArgb(originalColor.A, originalColor.R, originalColor.G, originalColor.B);
                if (maskValue == 0)
                {
                    newColor = Color.FromArgb(0, 0, 0, 0);
                }
                maskedImage.SetPixel(x, y, newColor);
            }
        }
        return maskedImage;
    }
}