diff --git a/GlobalSuppressions.cs b/GlobalSuppressions.cs new file mode 100644 index 0000000..8cee562 --- /dev/null +++ b/GlobalSuppressions.cs @@ -0,0 +1,10 @@ +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:Cupola.Program.Combine(System.Drawing.Bitmap[],System.Single)~System.Threading.Tasks.Task{System.Drawing.Bitmap}")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:Cupola.Program.FloatImage.#ctor(System.Drawing.Bitmap)")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:Cupola.Program.Main(System.String[])~System.Threading.Tasks.Task")] diff --git a/Program.cs b/Program.cs index 5f7ec32..6aa72a1 100644 --- a/Program.cs +++ b/Program.cs @@ -38,23 +38,22 @@ namespace Cupola } else { - Bitmap previousBit = images[0]; - - List oldBitmaps = new List(); - - oldBitmaps.Add(previousBit); + Dictionary> log = new Dictionary>(); for (int i = 1; i < images.Count; i++) { - previousBit.Save(name + "-" + (i - 1).ToString() + ".png"); - Console.WriteLine(i.ToString()); - previousBit = await Combine(new Bitmap[] { previousBit, images[i] }, 1f); + log.Add(name + "-" + (i - 1).ToString() + ".png", Combine(images.Take(i).ToArray(), 0.6f)); + } - oldBitmaps.Add(previousBit); + foreach (KeyValuePair> logItem in log) + { + Console.WriteLine(logItem.Key); - previousBit = await Combine(oldBitmaps.ToArray(), 0.6f); // PERFORMANCE + Bitmap img = await logItem.Value; + + img.Save(logItem.Key); } } } @@ -171,5 +170,176 @@ namespace Cupola { return Color.FromArgb((int)(((weight) * color1.R) + ((1 - weight) * color2.R)), (int)(((weight) * color1.G) + ((1 - weight) * color2.G)), (int)(((weight) * color1.B) + ((1 - weight) * color2.B))); } + + public class FloatImage + { + public class FloatColor + { + public float red; + public float green; + public float blue; + + public FloatColor(Color color) + { + this.red = (float)color.R; + this.green = (float)color.G; + this.blue = (float)color.B; + } + + public Color Export() + { + this.red = MathF.Round(this.red); + this.green = MathF.Round(this.green); + this.blue = MathF.Round(this.blue); + + byte red, green, blue; + + red = (byte)Math.Clamp((int)this.red, 0, 256); + green = (byte)Math.Clamp((int)this.green, 0, 256); + blue = (byte)Math.Clamp((int)this.blue, 0, 256); + + return Color.FromArgb(0, red, green, blue); + } + + public static void Spread(FloatColor[] colors, ref float minus, ref float multiply) + { + List allColors = new List(); + + foreach (FloatColor color in colors) + { + allColors.Add(color.red); + allColors.Add(color.blue); + allColors.Add(color.green); + } + + float min = 0; + float max = 0; + + foreach (float aColor in allColors) + { + if (aColor < min) + min = aColor; + else if (aColor > max) + max = aColor; + } + + minus = min; + + multiply = 255f / (max - minus); + } + } + + public uint width { get; private set; } + public uint height { get; private set; } + + public FloatColor[,] pixels { get; private set; } + + public FloatImage(uint width, uint height) + { + this.width = width; + this.height = height; + + this.pixels = new FloatColor[width, height]; + + for (int x = 0; x < this.width; x++) + { + for (int y = 0; y < this.height; y++) + { + this.pixels[x, y] = new FloatColor(Color.Black); + } + } + } + + public FloatImage(Bitmap bitmap) + { + this.width = (uint)bitmap.Width; + this.height = (uint)bitmap.Height; + + this.pixels = new FloatColor[this.width, this.height]; + + for (int x = 0; x < this.width; x++) + { + for (int y = 0; y < this.height; y++) + { + this.pixels[x, y] = new FloatColor(bitmap.GetPixel(x, y)); + } + } + } + + public void SetPixel(int x, int y, FloatColor color) + { + this.pixels[x, y] = color; + } + + public static void Spread(FloatImage[] images, ref float minus, ref float multiply) + { + FloatColor[] colors = new FloatColor[images[0].width * images[0].height * images.Length]; + + for (int i = 0; i < images.Length; i++) + { + for (int x = 0; x < images[0].width; x++) + { + for (int y = 0; y < images[0].height; y++) + { + colors[(i * images[0].width * images[0].height) + (x * images[0].height) + y] = images[i].pixels[x, y]; + } + } + } + + FloatColor.Spread(colors, ref minus, ref multiply); + } + + public static FloatImage Blend(FloatImage[] images, bool spread = false) + { + FloatImage output = new FloatImage(images[0].width, images[0].height); + + for (int x = 0; x < output.width; x++) + { + for (int y = 0; y < output.height; y++) + { + FloatColor pixel = new FloatColor(Color.Black); + + for (int i = 0; i < images.Length; i++) + { + FloatColor pixTemp = images[i].pixels[x, y]; + + pixel.red += pixTemp.red; + pixel.green += pixTemp.green; + pixel.blue += pixTemp.blue; + } + + pixel.red = pixel.red / images.Length; + pixel.green = pixel.green / images.Length; + pixel.blue = pixel.blue / images.Length; + + output.SetPixel(x, y, pixel); + } + } + + if (spread) + { + float minus = 0; + float multiply = 0; + + FloatImage.Spread(new FloatImage[] { output }, ref minus, ref multiply); + + for (int x = 0; x < output.width; x++) + { + for (int y = 0; y < output.height; y++) + { + FloatColor pixel = output.pixels[x, y]; + + pixel.red = (pixel.red - minus) * multiply; + pixel.green = (pixel.green - minus) * multiply; + pixel.blue = (pixel.blue - minus) * multiply; + + output.SetPixel(x, y, pixel); + } + } + } + + return output; + } + } } } \ No newline at end of file