// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageProcessorCore { using System; using System.Numerics; using System.Runtime.InteropServices; /// /// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 1. /// [StructLayout(LayoutKind.Explicit)] public struct Bgra32 : IPackedVector, IEquatable { /// /// Gets or sets the blue component. /// [FieldOffset(0)] public byte B; /// /// Gets or sets the green component. /// [FieldOffset(1)] public byte G; /// /// Gets or sets the red component. /// [FieldOffset(2)] public byte R; /// /// Gets or sets the alpha component. /// [FieldOffset(3)] public byte A; /// /// The packed value. /// [FieldOffset(0)] private readonly uint packedValue; /// /// Initializes a new instance of the struct. /// /// The blue component. /// The green component. /// The red component. /// The alpha component. public Bgra32(float b, float g, float r, float a) : this() { Vector4 clamped = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, Vector4.One) * 255f; this.B = (byte)Math.Round(clamped.X); this.G = (byte)Math.Round(clamped.Y); this.R = (byte)Math.Round(clamped.Z); this.A = (byte)Math.Round(clamped.W); } /// /// Initializes a new instance of the struct. /// /// The blue component. /// The green component. /// The red component. /// The alpha component. public Bgra32(byte b, byte g, byte r, byte a) : this() { this.B = b; this.G = g; this.R = r; this.A = a; } /// /// Initializes a new instance of the struct. /// /// /// The vector containing the components for the packed vector. /// public Bgra32(Vector4 vector) : this() { Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f; this.B = (byte)Math.Round(clamped.X); this.G = (byte)Math.Round(clamped.Y); this.R = (byte)Math.Round(clamped.Z); this.A = (byte)Math.Round(clamped.W); } /// /// Compares two objects for equality. /// /// /// The on the left side of the operand. /// /// /// The on the right side of the operand. /// /// /// True if the current left is equal to the parameter; otherwise, false. /// public static bool operator ==(Bgra32 left, Bgra32 right) { return left.packedValue == right.packedValue; } /// /// Compares two objects for equality. /// /// The on the left side of the operand. /// The on the right side of the operand. /// /// True if the current left is equal to the parameter; otherwise, false. /// public static bool operator !=(Bgra32 left, Bgra32 right) { return left.packedValue != right.packedValue; } /// public void Add(Bgra32 value) { this.B = (byte)(this.B + value.B); this.G = (byte)(this.G + value.G); this.R = (byte)(this.R + value.R); this.A = (byte)(this.A + value.A); } /// public void Subtract(Bgra32 value) { this.B = (byte)(this.B - value.B); this.G = (byte)(this.G - value.G); this.R = (byte)(this.R - value.R); this.A = (byte)(this.A - value.A); } /// public void Multiply(Bgra32 value) { this.B = (byte)(this.B * value.B); this.G = (byte)(this.G * value.G); this.R = (byte)(this.R * value.R); this.A = (byte)(this.A * value.A); } /// public void Multiply(float value) { this.B = (byte)(this.B * value); this.G = (byte)(this.G * value); this.R = (byte)(this.R * value); this.A = (byte)(this.A * value); } /// public void Divide(Bgra32 value) { this.B = (byte)(this.B / value.B); this.G = (byte)(this.G / value.G); this.R = (byte)(this.R / value.R); this.A = (byte)(this.A / value.A); } /// public void Divide(float value) { this.B = (byte)(this.B / value); this.G = (byte)(this.G / value); this.R = (byte)(this.R / value); this.A = (byte)(this.A / value); } /// public uint PackedValue() { return this.packedValue; } /// public void PackVector(Vector4 vector) { Vector4 clamped = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * 255f; this.B = (byte)Math.Round(clamped.X); this.G = (byte)Math.Round(clamped.Y); this.R = (byte)Math.Round(clamped.Z); this.A = (byte)Math.Round(clamped.W); } /// public void PackBytes(byte x, byte y, byte z, byte w) { this.B = x; this.G = y; this.R = z; this.A = w; } /// public Vector4 ToVector4() { return new Vector4(this.B, this.G, this.R, this.A) / 255f; } /// public byte[] ToBytes() { return new[] { this.B, this.G, this.R, this.A }; } /// public override bool Equals(object obj) { return (obj is Bgra32) && this.Equals((Bgra32)obj); } /// public bool Equals(Bgra32 other) { return this.packedValue == other.packedValue; } /// /// Gets a string representation of the packed vector. /// /// A string representation of the packed vector. public override string ToString() { return this.ToVector4().ToString(); } /// public override int GetHashCode() { return this.GetHashCode(this); } /// /// Returns the hash code for this instance. /// /// /// The instance of to return the hash code for. /// /// /// A 32-bit signed integer that is the hash code for this instance. /// private int GetHashCode(Bgra32 packed) { return packed.packedValue.GetHashCode(); } } }