using System; using System.Diagnostics.CodeAnalysis; namespace Dashboard { /// /// Pixel format for images. /// public enum PixelFormat { R8I, Rg8I, Rgb8I, Rgba8I, R16F, Rg816F, Rgb16F, Rgba16F, } /// /// Color channels for images. /// public enum ColorChannel { /// /// The zero channel. Used for swizzle masks. /// Zero = 0, /// /// The one channel. Used for swizzle masks. /// One = 1, /// /// An invalid swizzle mask. /// Unknown = 2, /// /// The red channel. /// Red = 4, /// /// The green channel. /// Green = 5, /// /// The blue channel. /// Blue = 6, /// /// The alpha channel. /// Alpha = 7, } /// /// Defines a image swizzle mask. /// public struct ColorSwizzle : IEquatable { 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; /// /// Swizzle the red channel. /// public ColorChannel R { get => (ColorChannel)((Mask >> RBIT) & MASK); set => Mask = (short)(((int)value << RBIT) | (Mask & ~(MASK << RBIT))); } /// /// Swizzle the green channel. /// public ColorChannel G { get => (ColorChannel)((Mask >> GBIT) & MASK); set => Mask = (short)(((int)value << GBIT) | (Mask & ~(MASK << GBIT))); } /// /// Swizzle the blue channel. /// public ColorChannel B { get => (ColorChannel)((Mask >> BBIT) & MASK); set => Mask = (short)(((int)value << BBIT) | (Mask & ~(MASK << BBIT))); } /// /// Swizzle the alpha channel. /// 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 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 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; } }