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