2024-05-12 22:51:23 +02:00
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
using System.Drawing;
|
2024-05-12 22:35:52 +02:00
|
|
|
|
|
|
|
|
|
namespace MSDF_Test;
|
|
|
|
|
|
2024-05-12 22:51:23 +02:00
|
|
|
|
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
|
|
|
|
|
internal class Glyph
|
2024-05-12 22:35:52 +02:00
|
|
|
|
{
|
2024-05-12 22:51:23 +02:00
|
|
|
|
private readonly Bitmap _originalBitmap;
|
2024-05-12 22:35:52 +02:00
|
|
|
|
private const float MaxColor = 255; //255 for Bitmaps
|
|
|
|
|
private const float DistanceRange = 255; //255 for Bitmaps
|
|
|
|
|
|
|
|
|
|
public Glyph(Bitmap texture)
|
|
|
|
|
{
|
2024-05-12 22:51:23 +02:00
|
|
|
|
this._originalBitmap = texture;
|
2024-05-12 22:35:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal Bitmap GetBitmap(int size, Color foreground, Color background)
|
|
|
|
|
{
|
2024-05-12 22:51:23 +02:00
|
|
|
|
Bitmap ret = new(size, size, _originalBitmap.PixelFormat);
|
2024-05-12 22:35:52 +02:00
|
|
|
|
for (int x = 0; x < ret.Width; x++)
|
|
|
|
|
{
|
|
|
|
|
for (int y = 0; y < ret.Height; y++)
|
|
|
|
|
{
|
|
|
|
|
PointF scaledPoint = new (x, y);
|
2024-05-12 22:51:23 +02:00
|
|
|
|
ret.SetPixel(x, y, GeneratePixel(scaledPoint.Scale((float)_originalBitmap.Width / size)) ? foreground : background);
|
2024-05-12 22:35:52 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool GeneratePixel(PointF point)
|
|
|
|
|
{
|
|
|
|
|
Color s = SampleBilinear(point);
|
|
|
|
|
float sample = Median(s);
|
|
|
|
|
float d = ColorDistance(sample);
|
|
|
|
|
return d >= 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Color SampleBilinear(PointF point)
|
|
|
|
|
{
|
|
|
|
|
int x1 = (int)Math.Floor(point.X - .5);
|
|
|
|
|
int y1 = (int)Math.Floor(point.Y - .5);
|
|
|
|
|
int x2 = x1 + 1;
|
|
|
|
|
int y2 = y1 + 1;
|
|
|
|
|
double wx = point.X - x1 - .5;
|
|
|
|
|
double wy = point.Y - y1 - .5;
|
|
|
|
|
|
2024-05-12 22:51:23 +02:00
|
|
|
|
if (x1 >= 0 && y1 >= 0 && x2 <= (_originalBitmap.Width - 1) && y2 <= (_originalBitmap.Height - 1))
|
2024-05-12 22:35:52 +02:00
|
|
|
|
{
|
2024-05-12 22:51:23 +02:00
|
|
|
|
Color x1y1 = _originalBitmap.GetPixel(x1, y1).MultiplyWith((1 - wx) * (1 - wy));
|
|
|
|
|
Color x1y2 = _originalBitmap.GetPixel(x1, y2).MultiplyWith((1 - wx) * wy);
|
|
|
|
|
Color x2y1 = _originalBitmap.GetPixel(x2, y1).MultiplyWith(wx * (1 - wy));
|
|
|
|
|
Color x2y2 = _originalBitmap.GetPixel(x2, y2).MultiplyWith(wx * wy);
|
2024-05-12 22:35:52 +02:00
|
|
|
|
|
|
|
|
|
return x1y1.Add(x1y2).Add(x2y1).Add(x2y2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Color.Black; //Edges can not be interpolated. Just return 0
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 22:51:23 +02:00
|
|
|
|
private static float Median(float r, float g, float b)
|
2024-05-12 22:35:52 +02:00
|
|
|
|
{
|
|
|
|
|
return Math.Max(Math.Min(r, g), Math.Min(Math.Max(r, g), b));
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-12 22:51:23 +02:00
|
|
|
|
private static float Median(Color c) => Median(c.R, c.G, c.B);
|
2024-05-12 22:35:52 +02:00
|
|
|
|
|
2024-05-12 22:51:23 +02:00
|
|
|
|
private static float ColorDistance(float sample)
|
2024-05-12 22:35:52 +02:00
|
|
|
|
{
|
|
|
|
|
return ((sample / MaxColor) - .5f) * DistanceRange;
|
|
|
|
|
}
|
|
|
|
|
}
|