mirror of https://github.com/SixLabors/ImageSharp
107 changed files with 1021 additions and 991 deletions
@ -1,240 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp; |
|||
|
|||
/// <content>
|
|||
/// Contains constructors and implicit conversion methods.
|
|||
/// </content>
|
|||
public readonly partial struct Color |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgba64"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgba64 pixel) |
|||
{ |
|||
this.data = pixel; |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgb48"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgb48 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel.R, pixel.G, pixel.B, ushort.MaxValue); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="La32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(La32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel.L, pixel.L, pixel.L, pixel.A); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="L16"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(L16 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel.PackedValue, pixel.PackedValue, pixel.PackedValue, ushort.MaxValue); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgba32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgba32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Argb32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Argb32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Bgra32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Bgra32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Abgr32"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Abgr32 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Rgb24"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Rgb24 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="pixel">The <see cref="Bgr24"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Bgr24 pixel) |
|||
{ |
|||
this.data = new Rgba64(pixel); |
|||
this.boxedHighPrecisionPixel = null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The <see cref="Vector4"/> containing the color information.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Color(Vector4 vector) |
|||
{ |
|||
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); |
|||
this.boxedHighPrecisionPixel = new RgbaVector(vector.X, vector.Y, vector.Z, vector.W); |
|||
this.data = default; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Color"/> to <see cref="Vector4"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The <see cref="Color"/>.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static explicit operator Vector4(Color color) => color.ToScaledVector4(); |
|||
|
|||
/// <summary>
|
|||
/// Converts an <see cref="Vector4"/> to <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/>.</param>
|
|||
/// <returns>The <see cref="Color"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static explicit operator Color(Vector4 source) => new(source); |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Rgba32 ToRgba32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToRgba32(); |
|||
} |
|||
|
|||
Rgba32 value = default; |
|||
this.boxedHighPrecisionPixel.ToRgba32(ref value); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Bgra32 ToBgra32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToBgra32(); |
|||
} |
|||
|
|||
Bgra32 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Argb32 ToArgb32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToArgb32(); |
|||
} |
|||
|
|||
Argb32 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Abgr32 ToAbgr32() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToAbgr32(); |
|||
} |
|||
|
|||
Abgr32 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Rgb24 ToRgb24() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToRgb24(); |
|||
} |
|||
|
|||
Rgb24 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Bgr24 ToBgr24() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToBgr24(); |
|||
} |
|||
|
|||
Bgr24 value = default; |
|||
value.FromScaledVector4(this.boxedHighPrecisionPixel.ToScaledVector4()); |
|||
return value; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
internal Vector4 ToScaledVector4() |
|||
{ |
|||
if (this.boxedHighPrecisionPixel is null) |
|||
{ |
|||
return this.data.ToScaledVector4(); |
|||
} |
|||
|
|||
return this.boxedHighPrecisionPixel.ToScaledVector4(); |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Represents pixel component information within a pixel format.
|
|||
/// </summary>
|
|||
public readonly struct PixelComponentInfo |
|||
{ |
|||
private readonly long precisionData1; |
|||
private readonly long precisionData2; |
|||
|
|||
private PixelComponentInfo(int count, int padding, long precisionData1, long precisionData2) |
|||
{ |
|||
this.ComponentCount = count; |
|||
this.Padding = padding; |
|||
this.precisionData1 = precisionData1; |
|||
this.precisionData2 = precisionData2; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of components within the pixel.
|
|||
/// </summary>
|
|||
public int ComponentCount { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of bytes of padding within the pixel.
|
|||
/// </summary>
|
|||
public int Padding { get; } |
|||
|
|||
/// <summary>
|
|||
/// Creates a new <see cref="PixelComponentInfo"/> instance.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of pixel format.</typeparam>
|
|||
/// <param name="count">The number of components within the pixel format.</param>
|
|||
/// <param name="precision">The precision in bits of each component.</param>
|
|||
/// <returns>The <see cref="PixelComponentInfo"/>.</returns>
|
|||
/// <exception cref="ArgumentOutOfRangeException">The component precision and index cannot exceed the component range.</exception>
|
|||
public static PixelComponentInfo Create<TPixel>(int count, params int[] precision) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
if (precision.Length != count || precision.Length > 16) |
|||
{ |
|||
throw new ArgumentException($"Count must match the length of precision array and cannot exceed 16."); |
|||
} |
|||
|
|||
long precisionData1 = 0; |
|||
long precisionData2 = 0; |
|||
int sum = 0; |
|||
for (int i = 0; i < precision.Length; i++) |
|||
{ |
|||
int p = precision[i]; |
|||
if (p is < 0 or > 255) |
|||
{ |
|||
throw new ArgumentException("Precision must be between 0 and 255."); |
|||
} |
|||
|
|||
if (i < 8) |
|||
{ |
|||
precisionData1 |= ((long)p) << (8 * i); |
|||
} |
|||
else |
|||
{ |
|||
precisionData2 |= ((long)p) << (8 * (i - 8)); |
|||
} |
|||
|
|||
sum += p; |
|||
} |
|||
|
|||
return new PixelComponentInfo(count, (Unsafe.SizeOf<TPixel>() * 8) - sum, precisionData1, precisionData2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the precision of the component in bits at the given index.
|
|||
/// </summary>
|
|||
/// <param name="componentIndex">The component index.</param>
|
|||
/// <returns>The <see cref="int"/>.</returns>
|
|||
/// <exception cref="ArgumentOutOfRangeException">The component index cannot exceed the component range.</exception>
|
|||
public int GetComponentPrecision(int componentIndex) |
|||
{ |
|||
if (componentIndex < 0 || componentIndex >= this.ComponentCount) |
|||
{ |
|||
throw new ArgumentOutOfRangeException($"Component index must be between 0 and {this.ComponentCount - 1} inclusive."); |
|||
} |
|||
|
|||
long selectedPrecisionData = componentIndex < 8 ? this.precisionData1 : this.precisionData2; |
|||
return (int)((selectedPrecisionData >> (8 * (componentIndex & 7))) & 0xFF); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the maximum precision in bits of all components.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="int"/>.</returns>
|
|||
public int GetMaximumComponentPrecision() |
|||
{ |
|||
int maxPrecision = 0; |
|||
for (int i = 0; i < this.ComponentCount; i++) |
|||
{ |
|||
int componentPrecision = this.GetComponentPrecision(i); |
|||
if (componentPrecision > maxPrecision) |
|||
{ |
|||
maxPrecision = componentPrecision; |
|||
} |
|||
} |
|||
|
|||
return maxPrecision; |
|||
} |
|||
} |
|||
@ -0,0 +1,180 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests; |
|||
|
|||
/// <summary>
|
|||
/// Unpacked pixel type containing four 64-bit floating-point values typically ranging from 0 to 1.
|
|||
/// The color components are stored in red, green, blue, and alpha order.
|
|||
/// <para>
|
|||
/// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
|
|||
/// </para>
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
/// <remarks>
|
|||
/// Initializes a new instance of the <see cref="RgbaDouble"/> struct.
|
|||
/// </remarks>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <param name="a">The alpha component.</param>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
[method: MethodImpl(InliningOptions.ShortMethod)] |
|||
public partial struct RgbaDouble(double r, double g, double b, double a = 1) : IPixel<RgbaDouble> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the red component.
|
|||
/// </summary>
|
|||
public double R = r; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the green component.
|
|||
/// </summary>
|
|||
public double G = g; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the blue component.
|
|||
/// </summary>
|
|||
public double B = b; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the alpha component.
|
|||
/// </summary>
|
|||
public double A = a; |
|||
|
|||
private const float MaxBytes = byte.MaxValue; |
|||
private static readonly Vector4 Max = new(MaxBytes); |
|||
private static readonly Vector4 Half = new(0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="RgbaDouble"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="RgbaDouble"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="RgbaDouble"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator ==(RgbaDouble left, RgbaDouble right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="RgbaDouble"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="RgbaDouble"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="RgbaDouble"/> on the right side of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static bool operator !=(RgbaDouble left, RgbaDouble right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc />
|
|||
public static PixelTypeInfo GetPixelTypeInfo() => PixelTypeInfo.Create<RgbaDouble>(PixelComponentInfo.Create<RgbaDouble>(4, 64, 64, 64, 64), PixelAlphaRepresentation.Unassociated); |
|||
|
|||
/// <inheritdoc />
|
|||
public readonly PixelOperations<RgbaDouble> CreatePixelOperations() => new(); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromScaledVector4(Vector4 vector) => this.FromVector4(vector); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public readonly Vector4 ToScaledVector4() => this.ToVector4(); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromVector4(Vector4 vector) |
|||
{ |
|||
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One); |
|||
this.R = vector.X; |
|||
this.G = vector.Y; |
|||
this.B = vector.Z; |
|||
this.A = vector.W; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public readonly Vector4 ToVector4() => new((float)this.R, (float)this.G, (float)this.B, (float)this.A); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromArgb32(Argb32 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromBgr24(Bgr24 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromBgra32(Bgra32 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromAbgr32(Abgr32 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromL8(L8 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromL16(L16 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromLa16(La16 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromLa32(La32 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgb24(Rgb24 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgba32(Rgba32 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void ToRgba32(ref Rgba32 dest) => dest.FromScaledVector4(this.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgb48(Rgb48 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgba64(Rgba64 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override readonly bool Equals(object obj) => obj is RgbaDouble other && this.Equals(other); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public readonly bool Equals(RgbaDouble other) => |
|||
this.R.Equals(other.R) |
|||
&& this.G.Equals(other.G) |
|||
&& this.B.Equals(other.B) |
|||
&& this.A.Equals(other.A); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override readonly string ToString() => FormattableString.Invariant($"RgbaDouble({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##}, {this.A:#0.##})"); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override readonly int GetHashCode() => HashCode.Combine(this.R, this.G, this.B, this.A); |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue