mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
71 changed files with 2129 additions and 151 deletions
@ -0,0 +1,396 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <summary>
|
|||
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in alpha, red, green, and blue order (least significant to most significant byte).
|
|||
/// <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>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public partial struct Abgr32 : IPixel<Abgr32>, IPackedVector<uint> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the alpha component.
|
|||
/// </summary>
|
|||
public byte A; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the blue component.
|
|||
/// </summary>
|
|||
public byte B; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the green component.
|
|||
/// </summary>
|
|||
public byte G; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the red component.
|
|||
/// </summary>
|
|||
public byte R; |
|||
|
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new(255); |
|||
|
|||
/// <summary>
|
|||
/// The half vector value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new(0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Abgr32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Abgr32(byte r, byte g, byte b) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
this.A = byte.MaxValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Abgr32"/> struct.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Abgr32(byte r, byte g, byte b, byte a) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
this.A = a; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Abgr32"/> struct.
|
|||
/// </summary>
|
|||
/// <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>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Abgr32(float r, float g, float b, float a = 1) |
|||
: this() => this.Pack(r, g, b, a); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Abgr32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// The vector containing the components for the packed vector.
|
|||
/// </param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Abgr32(Vector3 vector) |
|||
: this() => this.Pack(ref vector); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Abgr32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// The vector containing the components for the packed vector.
|
|||
/// </param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Abgr32(Vector4 vector) |
|||
: this() => this.Pack(ref vector); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Abgr32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="packed">
|
|||
/// The packed value.
|
|||
/// </param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Abgr32(uint packed) |
|||
: this() => this.Abgr = packed; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the packed representation of the Abgrb32 struct.
|
|||
/// </summary>
|
|||
public uint Abgr |
|||
{ |
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
readonly get => Unsafe.As<Abgr32, uint>(ref Unsafe.AsRef(this)); |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
set => Unsafe.As<Abgr32, uint>(ref this) = value; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public uint PackedValue |
|||
{ |
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
readonly get => this.Abgr; |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
set => this.Abgr = value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts an <see cref="Abgr32"/> to <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Abgr32"/>.</param>
|
|||
/// <returns>The <see cref="Color"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static implicit operator Color(Abgr32 source) => new(source); |
|||
|
|||
/// <summary>
|
|||
/// Converts a <see cref="Color"/> to <see cref="Abgr32"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The <see cref="Color"/>.</param>
|
|||
/// <returns>The <see cref="Abgr32"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static implicit operator Abgr32(Color color) => color.ToAbgr32(); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Argb32"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Abgr32"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Abgr32"/> 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 ==(Abgr32 left, Abgr32 right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Abgr32"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Abgr32"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Abgr32"/> 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 !=(Abgr32 left, Abgr32 right) => !left.Equals(right); |
|||
|
|||
/// <inheritdoc />
|
|||
public readonly PixelOperations<Abgr32> CreatePixelOperations() => new PixelOperations(); |
|||
|
|||
/// <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) => this.Pack(ref vector); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public readonly Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromAbgr32(Abgr32 source) => this = source; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromBgra5551(Bgra5551 source) => this.FromScaledVector4(source.ToScaledVector4()); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromBgr24(Bgr24 source) |
|||
{ |
|||
// We can assign the Bgr24 value directly to last three bytes of this instance.
|
|||
ref byte thisRef = ref Unsafe.As<Abgr32, byte>(ref this); |
|||
ref byte thisRefFromB = ref Unsafe.AddByteOffset(ref thisRef, new IntPtr(1)); |
|||
Unsafe.As<byte, Bgr24>(ref thisRefFromB) = source; |
|||
this.A = byte.MaxValue; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromArgb32(Argb32 source) |
|||
{ |
|||
this.R = source.R; |
|||
this.G = source.G; |
|||
this.B = source.B; |
|||
this.A = source.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromBgra32(Bgra32 source) |
|||
{ |
|||
this.R = source.R; |
|||
this.G = source.G; |
|||
this.B = source.B; |
|||
this.A = source.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromL8(L8 source) |
|||
{ |
|||
this.R = source.PackedValue; |
|||
this.G = source.PackedValue; |
|||
this.B = source.PackedValue; |
|||
this.A = byte.MaxValue; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromL16(L16 source) |
|||
{ |
|||
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue); |
|||
this.R = rgb; |
|||
this.G = rgb; |
|||
this.B = rgb; |
|||
this.A = byte.MaxValue; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromLa16(La16 source) |
|||
{ |
|||
this.R = source.L; |
|||
this.G = source.L; |
|||
this.B = source.L; |
|||
this.A = source.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromLa32(La32 source) |
|||
{ |
|||
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L); |
|||
this.R = rgb; |
|||
this.G = rgb; |
|||
this.B = rgb; |
|||
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgb24(Rgb24 source) |
|||
{ |
|||
this.R = source.R; |
|||
this.G = source.G; |
|||
this.B = source.B; |
|||
this.A = byte.MaxValue; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgba32(Rgba32 source) |
|||
{ |
|||
this.R = source.R; |
|||
this.G = source.G; |
|||
this.B = source.B; |
|||
this.A = source.A; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void ToRgba32(ref Rgba32 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
dest.A = this.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgb48(Rgb48 source) |
|||
{ |
|||
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); |
|||
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); |
|||
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); |
|||
this.A = byte.MaxValue; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public void FromRgba64(Rgba64 source) |
|||
{ |
|||
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R); |
|||
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G); |
|||
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B); |
|||
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override readonly bool Equals(object obj) => obj is Abgr32 abgr32 && this.Equals(abgr32); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public readonly bool Equals(Abgr32 other) => this.Abgr == other.Abgr; |
|||
|
|||
/// <summary>
|
|||
/// Gets a string representation of the packed vector.
|
|||
/// </summary>
|
|||
/// <returns>A string representation of the packed vector.</returns>
|
|||
public override readonly string ToString() => $"Abgr({this.A}, {this.B}, {this.G}, {this.R})"; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public override readonly int GetHashCode() => this.Abgr.GetHashCode(); |
|||
|
|||
/// <summary>
|
|||
/// Packs the four floats into a color.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <param name="z">The z-component</param>
|
|||
/// <param name="w">The w-component</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private void Pack(float x, float y, float z, float w) |
|||
{ |
|||
var value = new Vector4(x, y, z, w); |
|||
this.Pack(ref value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a <see cref="Vector3"/> into a uint.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the values to pack.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private void Pack(ref Vector3 vector) |
|||
{ |
|||
var value = new Vector4(vector, 1); |
|||
this.Pack(ref value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a <see cref="Vector4"/> into a color.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the values to pack.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
private void Pack(ref Vector4 vector) |
|||
{ |
|||
vector *= MaxBytes; |
|||
vector += Half; |
|||
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
this.R = (byte)vector.X; |
|||
this.G = (byte)vector.Y; |
|||
this.B = (byte)vector.Z; |
|||
this.A = (byte)vector.W; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Abgr32 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal partial class PixelOperations : PixelOperations<Abgr32> |
|||
{ |
|||
private static readonly Lazy<PixelTypeInfo> LazyInfo = |
|||
new Lazy<PixelTypeInfo>(() => PixelTypeInfo.Create<Abgr32>(PixelAlphaRepresentation.Unassociated), true); |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelTypeInfo GetPixelTypeInfo() => LazyInfo.Value; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,346 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
// <auto-generated />
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.PixelFormats.Utils; |
|||
|
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Abgr32 |
|||
{ |
|||
/// <summary>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </summary>
|
|||
internal partial class PixelOperations : PixelOperations<Abgr32> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override void FromAbgr32(Configuration configuration, ReadOnlySpan<Abgr32> source, Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(source, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
source.CopyTo(destinationPixels.Slice(0, source.Length)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void ToAbgr32(Configuration configuration, ReadOnlySpan<Abgr32> sourcePixels, Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
sourcePixels.CopyTo(destinationPixels.Slice(0, sourcePixels.Length)); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void FromVector4Destructive( |
|||
Configuration configuration, |
|||
Span<Vector4> sourceVectors, |
|||
Span<Abgr32> destinationPixels, |
|||
PixelConversionModifiers modifiers) |
|||
{ |
|||
Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destinationPixels, modifiers.Remove(PixelConversionModifiers.Scale)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void ToVector4( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Vector4> destVectors, |
|||
PixelConversionModifiers modifiers) |
|||
{ |
|||
Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale)); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToRgba32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Rgba32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Abgr32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Rgba32, byte>(destinationPixels); |
|||
PixelConverter.FromAbgr32.ToRgba32(source, dest); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void FromRgba32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Rgba32> sourcePixels, |
|||
Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Rgba32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Abgr32, byte>(destinationPixels); |
|||
PixelConverter.FromRgba32.ToAbgr32(source, dest); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToArgb32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Argb32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Abgr32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Argb32, byte>(destinationPixels); |
|||
PixelConverter.FromAbgr32.ToArgb32(source, dest); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void FromArgb32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Argb32> sourcePixels, |
|||
Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Argb32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Abgr32, byte>(destinationPixels); |
|||
PixelConverter.FromArgb32.ToAbgr32(source, dest); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToBgra32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Bgra32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Abgr32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Bgra32, byte>(destinationPixels); |
|||
PixelConverter.FromAbgr32.ToBgra32(source, dest); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void FromBgra32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Bgra32> sourcePixels, |
|||
Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Bgra32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Abgr32, byte>(destinationPixels); |
|||
PixelConverter.FromBgra32.ToAbgr32(source, dest); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToRgb24( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Rgb24> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Abgr32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Rgb24, byte>(destinationPixels); |
|||
PixelConverter.FromAbgr32.ToRgb24(source, dest); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void FromRgb24( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Rgb24> sourcePixels, |
|||
Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Rgb24, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Abgr32, byte>(destinationPixels); |
|||
PixelConverter.FromRgb24.ToAbgr32(source, dest); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToBgr24( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Bgr24> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Abgr32, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Bgr24, byte>(destinationPixels); |
|||
PixelConverter.FromAbgr32.ToBgr24(source, dest); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void FromBgr24( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Bgr24> sourcePixels, |
|||
Span<Abgr32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ReadOnlySpan<byte> source = MemoryMarshal.Cast<Bgr24, byte>(sourcePixels); |
|||
Span<byte> dest = MemoryMarshal.Cast<Abgr32, byte>(destinationPixels); |
|||
PixelConverter.FromBgr24.ToAbgr32(source, dest); |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToL8( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<L8> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref L8 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref L8 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToL16( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<L16> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref L16 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref L16 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToLa16( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<La16> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref La16 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref La16 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToLa32( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<La32> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref La32 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref La32 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToRgb48( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Rgb48> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToRgba64( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Rgba64> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void ToBgra5551( |
|||
Configuration configuration, |
|||
ReadOnlySpan<Abgr32> sourcePixels, |
|||
Span<Bgra5551> destinationPixels) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels)); |
|||
|
|||
ref Abgr32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels); |
|||
ref Bgra5551 destRef = ref MemoryMarshal.GetReference(destinationPixels); |
|||
|
|||
for (nint i = 0; i < sourcePixels.Length; i++) |
|||
{ |
|||
ref Abgr32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Bgra5551 dp = ref Unsafe.Add(ref destRef, i); |
|||
|
|||
dp.FromAbgr32(sp); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public override void From<TSourcePixel>( |
|||
Configuration configuration, |
|||
ReadOnlySpan<TSourcePixel> sourcePixels, |
|||
Span<Abgr32> destinationPixels) |
|||
{ |
|||
PixelOperations<TSourcePixel>.Instance.ToAbgr32(configuration, sourcePixels, destinationPixels.Slice(0, sourcePixels.Length)); |
|||
} |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<#@include file="_Common.ttinclude" #> |
|||
<#@ output extension=".cs" #> |
|||
namespace SixLabors.ImageSharp.PixelFormats |
|||
{ |
|||
/// <content> |
|||
/// Provides optimized overrides for bulk operations. |
|||
/// </content> |
|||
public partial struct Abgr32 |
|||
{ |
|||
/// <summary> |
|||
/// Provides optimized overrides for bulk operations. |
|||
/// </summary> |
|||
internal partial class PixelOperations : PixelOperations<Abgr32> |
|||
{ |
|||
<# GenerateAllDefaultConversionMethods("Abgr32"); #> |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Numerics; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.PixelFormats |
|||
{ |
|||
[Trait("Category", "PixelFormats")] |
|||
public class Abgr32Tests |
|||
{ |
|||
/// <summary>
|
|||
/// Tests the equality operators for equality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreEqual() |
|||
{ |
|||
var color1 = new Abgr32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue); |
|||
var color2 = new Abgr32(byte.MaxValue, byte.MaxValue, byte.MaxValue); |
|||
|
|||
Assert.Equal(color1, color2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Tests the equality operators for inequality.
|
|||
/// </summary>
|
|||
[Fact] |
|||
public void AreNotEqual() |
|||
{ |
|||
var color1 = new Abgr32(0, 0, byte.MaxValue, byte.MaxValue); |
|||
var color2 = new Abgr32(byte.MaxValue, byte.MaxValue, byte.MaxValue); |
|||
|
|||
Assert.NotEqual(color1, color2); |
|||
} |
|||
|
|||
public static readonly TheoryData<byte, byte, byte, byte> ColorData = |
|||
new() |
|||
{ |
|||
{ 1, 2, 3, 4 }, |
|||
{ 4, 5, 6, 7 }, |
|||
{ 0, 255, 42, 0 }, |
|||
{ 1, 2, 3, 255 } |
|||
}; |
|||
|
|||
[Theory] |
|||
[MemberData(nameof(ColorData))] |
|||
public void Constructor(byte b, byte g, byte r, byte a) |
|||
{ |
|||
var p = new Abgr32(r, g, b, a); |
|||
|
|||
Assert.Equal(r, p.R); |
|||
Assert.Equal(g, p.G); |
|||
Assert.Equal(b, p.B); |
|||
Assert.Equal(a, p.A); |
|||
} |
|||
|
|||
[Fact] |
|||
public unsafe void ByteLayoutIsSequentialBgra() |
|||
{ |
|||
var color = new Abgr32(1, 2, 3, 4); |
|||
byte* ptr = (byte*)&color; |
|||
|
|||
Assert.Equal(4, ptr[0]); |
|||
Assert.Equal(3, ptr[1]); |
|||
Assert.Equal(2, ptr[2]); |
|||
Assert.Equal(1, ptr[3]); |
|||
} |
|||
|
|||
[Theory] |
|||
[MemberData(nameof(ColorData))] |
|||
public void Equality_WhenTrue(byte r, byte g, byte b, byte a) |
|||
{ |
|||
var x = new Abgr32(r, g, b, a); |
|||
var y = new Abgr32(r, g, b, a); |
|||
|
|||
Assert.True(x.Equals(y)); |
|||
Assert.True(x.Equals((object)y)); |
|||
Assert.Equal(x.GetHashCode(), y.GetHashCode()); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(1, 2, 3, 4, 1, 2, 3, 5)] |
|||
[InlineData(0, 0, 255, 0, 0, 0, 244, 0)] |
|||
[InlineData(0, 255, 0, 0, 0, 244, 0, 0)] |
|||
[InlineData(1, 255, 0, 0, 0, 255, 0, 0)] |
|||
public void Equality_WhenFalse(byte b1, byte g1, byte r1, byte a1, byte b2, byte g2, byte r2, byte a2) |
|||
{ |
|||
var x = new Abgr32(r1, g1, b1, a1); |
|||
var y = new Abgr32(r2, g2, b2, a2); |
|||
|
|||
Assert.False(x.Equals(y)); |
|||
Assert.False(x.Equals((object)y)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void FromRgba32() |
|||
{ |
|||
var abgr = default(Abgr32); |
|||
abgr.FromRgba32(new Rgba32(1, 2, 3, 4)); |
|||
|
|||
Assert.Equal(1, abgr.R); |
|||
Assert.Equal(2, abgr.G); |
|||
Assert.Equal(3, abgr.B); |
|||
Assert.Equal(4, abgr.A); |
|||
} |
|||
|
|||
private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4( |
|||
r / 255f, |
|||
g / 255f, |
|||
b / 255f, |
|||
a / 255f); |
|||
|
|||
[Fact] |
|||
public void FromVector4() |
|||
{ |
|||
var c = default(Abgr32); |
|||
c.FromVector4(Vec(1, 2, 3, 4)); |
|||
|
|||
Assert.Equal(1, c.R); |
|||
Assert.Equal(2, c.G); |
|||
Assert.Equal(3, c.B); |
|||
Assert.Equal(4, c.A); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ToVector4() |
|||
{ |
|||
var abgr = new Abgr32(1, 2, 3, 4); |
|||
|
|||
Assert.Equal(Vec(1, 2, 3, 4), abgr.ToVector4()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Abgr32_FromBgra5551() |
|||
{ |
|||
// arrange
|
|||
var abgr = default(Abgr32); |
|||
uint expected = uint.MaxValue; |
|||
|
|||
// act
|
|||
abgr.FromBgra5551(new Bgra5551(1.0f, 1.0f, 1.0f, 1.0f)); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, abgr.PackedValue); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue