diff --git a/src/ImageSharp/Colors/PackedPixel/Alpha8.cs b/src/ImageSharp/Colors/PackedPixel/Alpha8.cs new file mode 100644 index 000000000..72011f30d --- /dev/null +++ b/src/ImageSharp/Colors/PackedPixel/Alpha8.cs @@ -0,0 +1,155 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp +{ + using System; + using System.Numerics; + + /// + /// Packed vector type containing a single 8 bit normalized W values that is ranging from 0 to 1. + /// + public struct Alpha8 : IPackedPixel, IEquatable + { + /// + /// Initializes a new instance of the struct. + /// + /// + /// The alpha component + /// + public Alpha8(float alpha) + { + this.PackedValue = Pack(alpha); + } + + /// + public byte PackedValue { get; set; } + + /// + /// Compares two objects for equality. + /// + /// + /// The on the left side of the operand. + /// + /// + /// The on the right side of the operand. + /// + /// + /// True if the parameter is equal to the parameter; otherwise, false. + /// + public static bool operator ==(Alpha8 left, Alpha8 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 parameter is equal to the parameter; otherwise, false. + /// + public static bool operator !=(Alpha8 left, Alpha8 right) + { + return left.PackedValue != right.PackedValue; + } + + /// + public void PackFromVector4(Vector4 vector) + { + this.PackedValue = Pack(vector.W); + } + + /// + public Vector4 ToVector4() + { + return new Vector4(0, 0, 0, this.PackedValue / 255F); + } + + /// + public void PackFromBytes(byte x, byte y, byte z, byte w) + { + this.PackedValue = w; + } + + /// + public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) + { + switch (componentOrder) + { + case ComponentOrder.ZYX: + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + break; + case ComponentOrder.ZYXW: + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = this.PackedValue; + break; + case ComponentOrder.XYZ: + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + break; + case ComponentOrder.XYZW: + bytes[startIndex] = 0; + bytes[startIndex + 1] = 0; + bytes[startIndex + 2] = 0; + bytes[startIndex + 3] = this.PackedValue; + break; + default: + throw new NotSupportedException(); + } + } + + /// + /// Compares an object with the packed vector. + /// + /// The object to compare. + /// True if the object is equal to the packed vector. + public override bool Equals(object obj) + { + return (obj is Alpha8) && this.Equals((Alpha8)obj); + } + + /// + /// Compares another Alpha8 packed vector with the packed vector. + /// + /// The Alpha8 packed vector to compare. + /// True if the packed vectors are equal. + public bool Equals(Alpha8 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.PackedValue / 255F).ToString(); + } + + /// + public override int GetHashCode() + { + return this.PackedValue.GetHashCode(); + } + + /// + /// Packs a into a byte. + /// + /// The float containing the value to pack. + /// The containing the packed values. + private static byte Pack(float alpha) + { + return (byte)Math.Round(alpha.Clamp(0, 1) * 255F); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Colors/PackedVectorTests.cs b/tests/ImageSharp.Tests/Colors/PackedVectorTests.cs new file mode 100644 index 000000000..dd3e5e3b1 --- /dev/null +++ b/tests/ImageSharp.Tests/Colors/PackedVectorTests.cs @@ -0,0 +1,57 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Tests.Colors +{ + using System.Numerics; + + using Xunit; + + /// + /// The packed vector tests. + /// + public class PackedVectorTests + { + [Fact] + public void Alpha8() + { + // Test the limits. + Assert.Equal(0x0, new Alpha8(0F).PackedValue); + Assert.Equal(0xFF, new Alpha8(1F).PackedValue); + + // Test clamping. + Assert.Equal(0x0, new Alpha8(-1234F).PackedValue); + Assert.Equal(0xFF, new Alpha8(1234F).PackedValue); + + // Test ordering + Assert.Equal(124, new Alpha8(124F / 0xFF).PackedValue); + Assert.Equal(26, new Alpha8(0.1F).PackedValue); + + // Test ordering + Vector4 vector = new Alpha8(.5F).ToVector4(); + Assert.Equal(vector.X, 0); + Assert.Equal(vector.Y, 0); + Assert.Equal(vector.Z, 0); + Assert.Equal(vector.W, .5F, 2); + + byte[] rgb = new byte[3]; + byte[] rgba = new byte[4]; + byte[] bgr = new byte[3]; + byte[] bgra = new byte[4]; + + new Alpha8(.5F).ToBytes(rgb, 0, ComponentOrder.XYZ); + Assert.Equal(rgb, new byte[] { 0, 0, 0 }); + + new Alpha8(.5F).ToBytes(rgba, 0, ComponentOrder.XYZW); + Assert.Equal(rgba, new byte[] { 0, 0, 0, 128 }); + + new Alpha8(.5F).ToBytes(rgb, 0, ComponentOrder.ZYX); + Assert.Equal(bgr, new byte[] { 0, 0, 0 }); + + new Alpha8(.5F).ToBytes(rgb, 0, ComponentOrder.ZYXW); + Assert.Equal(bgra, new byte[] { 0, 0, 0, 128 }); + } + } +} \ No newline at end of file