This commit is contained in:
AUnicornWithNoLife 2023-02-03 09:03:47 +00:00
parent 50c9c32b50
commit 299eecfbe8
3 changed files with 91 additions and 252 deletions

View File

@ -8,6 +8,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="ComputeSharp" Version="2.0.3" />
<PackageReference Include="ComputeSharp.Dynamic" Version="2.0.3" />
<PackageReference Include="System.Drawing.Common" Version="7.0.0" /> <PackageReference Include="System.Drawing.Common" Version="7.0.0" />
</ItemGroup> </ItemGroup>

View File

@ -8,3 +8,6 @@ using System.Diagnostics.CodeAnalysis;
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", 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 = "<Pending>", 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 = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.FloatImage.#ctor(System.Drawing.Bitmap)")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.FloatImage.#ctor(System.Drawing.Bitmap)")]
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.Main(System.String[])~System.Threading.Tasks.Task")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.Main(System.String[])~System.Threading.Tasks.Task")]
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.Main(System.String[])")]
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.Average.Execute")]
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:Cupola.Program.Brightest.Execute")]

View File

@ -1,305 +1,139 @@
using System.Drawing; using ComputeSharp;
using static Cupola.Program;
namespace Cupola namespace Cupola
{ {
internal class Program internal partial class Program
{ {
static async Task Main(string[] args) static void Main(string[] args)
{ {
List<Bitmap> images = new List<Bitmap>();
Console.WriteLine("Image Dir?"); Console.WriteLine("Image Dir?");
string fileLoc = Console.ReadLine(); string? fileLoc = Console.ReadLine();
if (fileLoc == null) if (fileLoc == null)
throw new ArgumentException("input should not be NULL"); throw new ArgumentException("input should not be NULL");
string[] files = Directory.GetFiles(fileLoc); string[] files = Directory.GetFiles(fileLoc);
ReadWriteTexture2D<Bgra32, float4>[] images = new ReadWriteTexture2D<Bgra32, Float4>[files.Length];
for (int i = 0; i < files.Length; i++) for (int i = 0; i < files.Length; i++)
{ {
Console.WriteLine(files[i]); Console.WriteLine(files[i]);
images.Add(new Bitmap(files[i])); images[i] = GraphicsDevice.GetDefault().LoadReadWriteTexture2D<Bgra32, float4>(files[i]);
} }
Console.WriteLine("Output: "); Console.WriteLine("Output: ");
string name = Console.ReadLine(); string? name = Console.ReadLine();
if (name == null)
throw new Exception("UwU");
Console.WriteLine("mode?"); Console.WriteLine("mode?");
Console.WriteLine(); Console.WriteLine();
ConsoleKey key = Console.ReadKey().Key;
ConsoleKey keyGG = Console.ReadKey().Key; if (key == ConsoleKey.P)
if (keyGG == ConsoleKey.F)
{ {
FloatImage[] fImages = new FloatImage[images.Count]; ReadWriteTexture2D<Bgra32, Float4> brightest = images[0];
ReadWriteTexture2D<Bgra32, Float4> output = images[0];
for (int i = 0; i < images.Count; i++) for (int i = 1; i < images.Length; i++)
{ {
fImages[i] = new FloatImage(images[i]); Console.WriteLine(i.ToString());
ReadWriteTexture2D<Bgra32, Float4> temp = images[i];
GraphicsDevice.GetDefault().For
(
temp.Width,
temp.Height,
new Brightest(brightest, temp)
);
GraphicsDevice.GetDefault().For
(
temp.Width,
temp.Height,
new Average(temp, output)
);
GraphicsDevice.GetDefault().For
(
temp.Width,
temp.Height,
new Average(temp, brightest)
);
output = temp;
} }
Console.WriteLine("BLEND"); output.Save(name + ".jpg");
FloatImage blend = await FloatImage.Blend(fImages, true);
Console.WriteLine("HEIHGT");
FloatImage height = await FloatImage.Highest(fImages);
Console.WriteLine("FINAL");
Bitmap final = (await FloatImage.Blend(new FloatImage[] { blend, height }, true)).ToBitmap();
Console.WriteLine("SAVE");
final.Save(name + ".png");
} }
else if (keyGG == ConsoleKey.V) else
{ {
FloatImage previous = new FloatImage(images[0]); ReadWriteTexture2D<Bgra32, Float4> i1 = images[0];
FloatImage brightest = new FloatImage(images[0]); ReadWriteTexture2D<Bgra32, Float4> i2 = images[1];
for (int i = 1; i < images.Count; i++) GraphicsDevice.GetDefault().For
{ (
Console.Write(i.ToString()); i1.Width,
i1.Height,
new Average(i1, i2)
);
previous.ToBitmap().Save(name + i.ToString() + ".png"); i1.Save(name + ".jpg");
Task<FloatImage> blend = FloatImage.Blend(new FloatImage[] { previous, new FloatImage(images[i]) }, true);
Task<FloatImage> height = FloatImage.Highest(new FloatImage[] { brightest, new FloatImage(images[i]) });
FloatImage blendImage = await blend;
FloatImage heightImage = await height;
brightest = heightImage;
Console.Write("a");
previous = await FloatImage.Blend(new FloatImage[] { blendImage, heightImage }, true);
Console.WriteLine();
}
previous.ToBitmap().Save(name + images.Count.ToString() + ".png");
} }
} }
public class FloatImage [AutoConstructor]
public readonly partial struct Brightest : IComputeShader
{ {
public class FloatColor public readonly IReadWriteNormalizedTexture2D<float4> input1;
public readonly IReadWriteNormalizedTexture2D<float4> input2;
// Other captured resources or values here...
public void Execute()
{ {
public float red; float3 i1 = input1[ThreadIds.XY].RGB;
public float green; float3 i2 = input2[ThreadIds.XY].RGB;
public float blue;
public FloatColor(Color color) float i1Intensity = i1.X * i1.Y * i1.Z;
float i2Intensity = i2.X * i2.Y * i2.Z;
if (i1Intensity > i2Intensity)
{ {
this.red = (float)color.R; input1[ThreadIds.XY].RGB = i1;
this.green = (float)color.G;
this.blue = (float)color.B;
} }
else
public Color Export()
{ {
this.red = MathF.Round(this.red); input1[ThreadIds.XY].RGB = i2;
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(red, green, blue);
}
public float Brightness()
{
return this.red + this.green + this.blue;
}
public static void Spread(FloatColor[] colors, ref float minus, ref float multiply)
{
List<float> allColors = new List<float>();
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; } [AutoConstructor]
public uint height { get; private set; } public readonly partial struct Average : IComputeShader
{
public readonly IReadWriteNormalizedTexture2D<float4> input1;
public readonly IReadWriteNormalizedTexture2D<float4> input2;
public FloatColor[,] pixels { get; private set; } // Other captured resources or values here...
public FloatImage(uint width, uint height) public void Execute()
{ {
this.width = width; float3 i1 = input1[ThreadIds.XY].RGB;
this.height = height; float3 i2 = input2[ThreadIds.XY].RGB;
this.pixels = new FloatColor[width, height]; float3 o1 = 0;
for (int x = 0; x < this.width; x++) o1.X = (i1.X + i2.X) / 2;
{ o1.Y = (i1.Y + i2.Y) / 2;
for (int y = 0; y < this.height; y++) o1.Z = (i1.Z + i2.Z) / 2;
{
this.pixels[x, y] = new FloatColor(Color.Black);
}
}
}
public FloatImage(Bitmap bitmap) input1[ThreadIds.XY].RGB = o1;
{
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 Bitmap ToBitmap()
{
Bitmap output = new Bitmap((int)this.width, (int)this.height);
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
output.SetPixel(x, y, pixels[x, y].Export());
}
}
return output;
}
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 async Task<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;
}
if (!spread)
{
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);
}//hi
}
}
Console.Write("b");
return output;
}
public static async Task<FloatImage> Highest(FloatImage[] images)
{
FloatImage output = new FloatImage(images[0].width, images[0].height);
for (int x = 0; x < images[0].width; x++)
{
for (int y = 0; y < images[0].height; y++)
{
FloatColor brightest = new FloatColor(Color.Black);
for (int i = 0; i < images.Length; i++)
{
if (images[i].pixels[x, y].Brightness() > brightest.Brightness())
{
brightest = images[i].pixels[x, y];
}
}
output.SetPixel(x, y, brightest);
}
}
Console.Write("h");
return output;
} }
} }
} }