Dashboard/Dashboard.Common/ImageProperties.cs

197 lines
5.5 KiB
C#

using System;
using System.Diagnostics.CodeAnalysis;
namespace Dashboard
{
/// <summary>
/// Pixel format for images.
/// </summary>
public enum PixelFormat
{
R8I,
Rg8I,
Rgb8I,
Rgba8I,
R16F,
Rg816F,
Rgb16F,
Rgba16F,
}
/// <summary>
/// Color channels for images.
/// </summary>
public enum ColorChannel
{
/// <summary>
/// The zero channel. Used for swizzle masks.
/// </summary>
Zero = 0,
/// <summary>
/// The one channel. Used for swizzle masks.
/// </summary>
One = 1,
/// <summary>
/// An invalid swizzle mask.
/// </summary>
Unknown = 2,
/// <summary>
/// The red channel.
/// </summary>
Red = 4,
/// <summary>
/// The green channel.
/// </summary>
Green = 5,
/// <summary>
/// The blue channel.
/// </summary>
Blue = 6,
/// <summary>
/// The alpha channel.
/// </summary>
Alpha = 7,
}
/// <summary>
/// Defines a image swizzle mask.
/// </summary>
public struct ColorSwizzle : IEquatable<ColorSwizzle>
{
public short Mask;
private const int MASK = 7;
private const int RBIT = 0;
private const int GBIT = 3;
private const int BBIT = 6;
private const int ABIT = 9;
/// <summary>
/// Swizzle the red channel.
/// </summary>
public ColorChannel R
{
get => (ColorChannel)((Mask >> RBIT) & MASK);
set => Mask = (short)(((int)value << RBIT) | (Mask & ~(MASK << RBIT)));
}
/// <summary>
/// Swizzle the green channel.
/// </summary>
public ColorChannel G
{
get => (ColorChannel)((Mask >> GBIT) & MASK);
set => Mask = (short)(((int)value << GBIT) | (Mask & ~(MASK << GBIT)));
}
/// <summary>
/// Swizzle the blue channel.
/// </summary>
public ColorChannel B
{
get => (ColorChannel)((Mask >> BBIT) & MASK);
set => Mask = (short)(((int)value << BBIT) | (Mask & ~(MASK << BBIT)));
}
/// <summary>
/// Swizzle the alpha channel.
/// </summary>
public ColorChannel A
{
get => (ColorChannel)((Mask >> ABIT) & MASK);
set => Mask = (short)(((int)value << ABIT) | (Mask & ~(MASK << ABIT)));
}
public ColorSwizzle(short mask)
{
Mask = mask;
}
public ColorSwizzle(ColorChannel r, ColorChannel g, ColorChannel b, ColorChannel a)
{
Mask = (short)(((int)r << RBIT) | ((int)g << GBIT) | ((int)b << BBIT) | ((int)a << ABIT));
}
public override string ToString()
{
return $"{GetChannelChar(R)}{GetChannelChar(G)}{GetChannelChar(B)}{GetChannelChar(A)}";
char GetChannelChar(ColorChannel channel) => channel switch
{
ColorChannel.Zero => '0',
ColorChannel.Red => 'R',
ColorChannel.Green => 'G',
ColorChannel.Blue => 'B',
ColorChannel.Alpha => 'A',
ColorChannel.One => '1',
_ => '?',
};
}
public override int GetHashCode()
{
return Mask.GetHashCode();
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
return obj is ColorSwizzle other && Equals(other);
}
public bool Equals(ColorSwizzle other)
{
return Mask == other.Mask;
}
public static readonly ColorSwizzle Default = Parse("RGBA");
public static readonly ColorSwizzle White = Parse("1111");
public static readonly ColorSwizzle Black = Parse("0001");
public static readonly ColorSwizzle Transparent = Parse("0000");
public static readonly ColorSwizzle RedToGrayscale = Parse("RRR1");
public static readonly ColorSwizzle RedToWhiteAlpha = Parse("111A");
public static bool TryParse(ReadOnlySpan<char> str, out ColorSwizzle value)
{
if (str.Length < 4)
{
value = default;
return false;
}
ColorChannel r = GetChannelFromChar(str[0]);
ColorChannel g = GetChannelFromChar(str[1]);
ColorChannel b = GetChannelFromChar(str[2]);
ColorChannel a = GetChannelFromChar(str[3]);
value = new ColorSwizzle(r, g, b, a);
return true;
ColorChannel GetChannelFromChar(char chr) => chr switch
{
'0' => ColorChannel.Zero,
'R' => ColorChannel.Red,
'G' => ColorChannel.Green,
'B' => ColorChannel.Blue,
'A' => ColorChannel.Alpha,
'1' => ColorChannel.One,
_ => ColorChannel.Unknown,
};
}
public static ColorSwizzle Parse(ReadOnlySpan<char> str) =>
TryParse(str, out ColorSwizzle value) ? value : throw new FormatException(nameof(str));
public static bool operator ==(ColorSwizzle left, ColorSwizzle right) =>
left.Mask == right.Mask;
public static bool operator !=(ColorSwizzle left, ColorSwizzle right) =>
left.Mask != right.Mask;
}
}