mirror of https://github.com/SixLabors/ImageSharp
98 changed files with 3169 additions and 672 deletions
@ -0,0 +1,22 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
// Note the value assignment, This will allow us to add 1, 2, and 4 bit encoding when we support it.
|
|||
namespace SixLabors.ImageSharp.Formats.Png |
|||
{ |
|||
/// <summary>
|
|||
/// Provides enumeration for the available PNG bit depths.
|
|||
/// </summary>
|
|||
public enum PngBitDepth |
|||
{ |
|||
/// <summary>
|
|||
/// 8 bits per sample or per palette index (not per pixel).
|
|||
/// </summary>
|
|||
Bit8 = 8, |
|||
|
|||
/// <summary>
|
|||
/// 16 bits per sample or per palette index (not per pixel).
|
|||
/// </summary>
|
|||
Bit16 = 16 |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,256 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// 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 three 16-bit unsigned normalized values ranging from 0 to 635535.
|
|||
/// <para>
|
|||
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
|
|||
/// </para>
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct Rgb48 : IPixel<Rgb48> |
|||
{ |
|||
private const float Max = 65535F; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the red component.
|
|||
/// </summary>
|
|||
public ushort R; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the green component.
|
|||
/// </summary>
|
|||
public ushort G; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the blue component.
|
|||
/// </summary>
|
|||
public ushort B; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb48"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
public Rgb48(ushort r, ushort g, ushort b) |
|||
: this() |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb48"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
public Rgb48(float r, float g, float b) |
|||
: this() |
|||
{ |
|||
this.R = (ushort)MathF.Round(r.Clamp(0, 1) * Max); |
|||
this.G = (ushort)MathF.Round(g.Clamp(0, 1) * Max); |
|||
this.B = (ushort)MathF.Round(b.Clamp(0, 1) * Max); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb48"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the components values.</param>
|
|||
public Rgb48(Vector3 vector) |
|||
: this(vector.X, vector.Y, vector.Z) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgb48"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Rgb48"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Rgb48"/> 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(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(Rgb48 left, Rgb48 right) |
|||
{ |
|||
return left.R == right.R |
|||
&& left.G == right.G |
|||
&& left.B == right.B; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgb48"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Rgb48"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Rgb48"/> 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(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(Rgb48 left, Rgb48 right) |
|||
{ |
|||
return left.R != right.R |
|||
|| left.G != right.G |
|||
|| left.B != right.B; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public PixelOperations<Rgb48> CreatePixelOperations() => new PixelOperations<Rgb48>(); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromScaledVector4(Vector4 vector) |
|||
{ |
|||
this.PackFromVector4(vector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector4 ToScaledVector4() |
|||
{ |
|||
return this.ToVector4(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.R / Max, this.G / Max, this.B / Max, 1); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max; |
|||
this.R = (ushort)MathF.Round(vector.X); |
|||
this.G = (ushort)MathF.Round(vector.Y); |
|||
this.B = (ushort)MathF.Round(vector.Z); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromRgba32(Rgba32 source) |
|||
{ |
|||
this.PackFromVector4(source.ToVector4()); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromArgb32(Argb32 source) |
|||
{ |
|||
this.PackFromVector4(source.ToVector4()); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromBgra32(Bgra32 source) |
|||
{ |
|||
this.PackFromVector4(source.ToVector4()); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromRgba64(Rgba64 source) => this = source.Rgb; |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgb24(ref Rgb24 dest) |
|||
{ |
|||
dest.R = (byte)(((this.R * 255) + 32895) >> 16); |
|||
dest.G = (byte)(((this.G * 255) + 32895) >> 16); |
|||
dest.B = (byte)(((this.B * 255) + 32895) >> 16); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgba32(ref Rgba32 dest) |
|||
{ |
|||
dest.R = (byte)(((this.R * 255) + 32895) >> 16); |
|||
dest.G = (byte)(((this.G * 255) + 32895) >> 16); |
|||
dest.B = (byte)(((this.B * 255) + 32895) >> 16); |
|||
dest.A = 255; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToArgb32(ref Argb32 dest) |
|||
{ |
|||
dest.R = (byte)(((this.R * 255) + 32895) >> 16); |
|||
dest.G = (byte)(((this.G * 255) + 32895) >> 16); |
|||
dest.B = (byte)(((this.B * 255) + 32895) >> 16); |
|||
dest.A = 255; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToBgr24(ref Bgr24 dest) |
|||
{ |
|||
dest.R = (byte)(((this.R * 255) + 32895) >> 16); |
|||
dest.G = (byte)(((this.G * 255) + 32895) >> 16); |
|||
dest.B = (byte)(((this.B * 255) + 32895) >> 16); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToBgra32(ref Bgra32 dest) |
|||
{ |
|||
dest.R = (byte)(((this.R * 255) + 32895) >> 16); |
|||
dest.G = (byte)(((this.G * 255) + 32895) >> 16); |
|||
dest.B = (byte)(((this.B * 255) + 32895) >> 16); |
|||
dest.A = 255; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromRgb48(Rgb48 source) => this = source; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgb48(ref Rgb48 dest) => dest = this; |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgba64(ref Rgba64 dest) |
|||
{ |
|||
dest.Rgb = this; |
|||
dest.A = ushort.MaxValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is Rgb48 rgb48 && this.Equals(rgb48); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Rgb48 other) |
|||
{ |
|||
return this.R == other.R |
|||
&& this.G == other.G |
|||
&& this.B == other.B; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() => this.ToVector4().ToString(); |
|||
|
|||
/// <inheritdoc />
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() |
|||
{ |
|||
return HashHelpers.Combine( |
|||
this.R.GetHashCode(), |
|||
HashHelpers.Combine(this.G.GetHashCode(), this.B.GetHashCode())); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System.Numerics; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.PixelFormats |
|||
{ |
|||
public class Rgb48Tests |
|||
{ |
|||
[Fact] |
|||
public void Rgb48_Values() |
|||
{ |
|||
var rgb = new Rgba64(5243, 9830, 19660, 29491); |
|||
|
|||
Assert.Equal(5243, rgb.R); |
|||
Assert.Equal(9830, rgb.G); |
|||
Assert.Equal(19660, rgb.B); |
|||
Assert.Equal(29491, rgb.A); |
|||
|
|||
rgb = new Rgba64(5243 / 65535F, 9830 / 65535F, 19660 / 65535F, 29491 / 65535F); |
|||
|
|||
Assert.Equal(5243, rgb.R); |
|||
Assert.Equal(9830, rgb.G); |
|||
Assert.Equal(19660, rgb.B); |
|||
Assert.Equal(29491, rgb.A); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_ToVector4() |
|||
{ |
|||
Assert.Equal(new Vector4(0, 0, 0, 1), new Rgb48(Vector3.Zero).ToVector4()); |
|||
Assert.Equal(Vector4.One, new Rgb48(Vector3.One).ToVector4()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_ToScaledVector4() |
|||
{ |
|||
// arrange
|
|||
var short2 = new Rgb48(Vector3.One); |
|||
|
|||
// act
|
|||
Vector4 actual = short2.ToScaledVector4(); |
|||
|
|||
// assert
|
|||
Assert.Equal(1, actual.X); |
|||
Assert.Equal(1, actual.Y); |
|||
Assert.Equal(1, actual.Z); |
|||
Assert.Equal(1, actual.W); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_PackFromScaledVector4() |
|||
{ |
|||
// arrange
|
|||
var pixel = default(Rgb48); |
|||
var short3 = new Rgb48(Vector3.One); |
|||
var expected = new Rgb48(Vector3.One); |
|||
|
|||
// act
|
|||
Vector4 scaled = short3.ToScaledVector4(); |
|||
pixel.PackFromScaledVector4(scaled); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, pixel); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_Clamping() |
|||
{ |
|||
Assert.Equal(new Vector4(0, 0, 0, 1), new Rgb48(Vector3.One * -1234.0f).ToVector4()); |
|||
Assert.Equal(Vector4.One, new Rgb48(Vector3.One * 1234.0f).ToVector4()); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_ToRgb24() |
|||
{ |
|||
// arrange
|
|||
var rgba48 = new Rgb48(0.08f, 0.15f, 0.30f); |
|||
var actual = default(Rgb24); |
|||
var expected = new Rgb24(20, 38, 76); |
|||
|
|||
// act
|
|||
rgba48.ToRgb24(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_ToRgba32() |
|||
{ |
|||
// arrange
|
|||
var rgba48 = new Rgb48(0.08f, 0.15f, 0.30f); |
|||
var actual = default(Rgba32); |
|||
var expected = new Rgba32(20, 38, 76, 255); |
|||
|
|||
// act
|
|||
rgba48.ToRgba32(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_ToArgb32() |
|||
{ |
|||
// arrange
|
|||
var rgba48 = new Rgb48(0.08f, 0.15f, 0.30f); |
|||
var actual = default(Argb32); |
|||
var expected = new Argb32(20, 38, 76, 255); |
|||
|
|||
// act
|
|||
rgba48.ToArgb32(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgba64_ToBgr24() |
|||
{ |
|||
// arrange
|
|||
var rgb48 = new Rgb48(0.08f, 0.15f, 0.30f); |
|||
var actual = default(Bgr24); |
|||
var expected = new Bgr24(20, 38, 76); |
|||
|
|||
// act
|
|||
rgb48.ToBgr24(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_ToBgra32() |
|||
{ |
|||
// arrange
|
|||
var rgba48 = new Rgb48(0.08f, 0.15f, 0.30f); |
|||
var actual = default(Bgra32); |
|||
var expected = new Bgra32(20, 38, 76, 255); |
|||
|
|||
// act
|
|||
rgba48.ToBgra32(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_PackFromRgba32_ToRgba32() |
|||
{ |
|||
// arrange
|
|||
var rgb48 = default(Rgb48); |
|||
var actual = default(Rgba32); |
|||
var expected = new Rgba32(20, 38, 76, 255); |
|||
|
|||
// act
|
|||
rgb48.PackFromRgba32(expected); |
|||
rgb48.ToRgba32(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_PackFromRgb48_ToRgb48() |
|||
{ |
|||
// arrange
|
|||
var input = default(Rgb48); |
|||
var actual = default(Rgb48); |
|||
var expected = new Rgb48(65535, 0, 65535); |
|||
|
|||
// act
|
|||
input.PackFromRgb48(expected); |
|||
input.ToRgb48(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Rgb48_PackFromRgba64_ToRgba64() |
|||
{ |
|||
// arrange
|
|||
var input = default(Rgb48); |
|||
var actual = default(Rgba64); |
|||
var expected = new Rgba64(65535, 0, 65535, 65535); |
|||
|
|||
// act
|
|||
input.PackFromRgba64(expected); |
|||
input.ToRgba64(ref actual); |
|||
|
|||
// assert
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
Subproject commit 0e6407be7081341526f815a4d70e7912db276a98 |
|||
Subproject commit 6fcee2ccd5e8bac98a0290b467ad86bb02d00b6c |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:8367d01b7d0f926f6c89d6e545735a50cd35815ba7c13367ad5b0489069bd735 |
|||
size 1448 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:f150b76c824e4870322d6564a214a8ef00b4b100d5fd6f5ba551f6f242005bcc |
|||
size 684 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:dc3444bd2457c7c3414359bed6f05d1a5b84c08186b3b54a9ab4a4c503775f63 |
|||
size 859 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:c0e327f49e2b0deda69811cdf20d36f2ff54f9335e11647755ad4473a6f1408a |
|||
size 684 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:3ad2152ee0de2aaa8745757a9ff5e90a30b6e84365bd90f450286eb2734bd78a |
|||
size 1377 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:733a3f940d41b320ae884ba74339bc94ec8ad5f5a37479ea23b19c1e7b0d0274 |
|||
size 2624 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:d98223a9a3084f34609bb5dbf55b5ca156559743240bef3406466775a9950e9d |
|||
size 1624 |
|||
Loading…
Reference in new issue