mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Conflicts: src/ImageSharp/Formats/Jpg/Components/Block.cs src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.cs src/ImageSharp/Formats/Jpg/Components/Block8x8F.Generated.tt src/ImageSharp/Formats/Jpg/Components/Block8x8F.cs src/ImageSharp/Formats/Jpg/Components/MutableSpan.cs src/ImageSharp/Formats/Jpg/JpegDecoderCore.cs src/ImageSharp46/Formats/Jpg/Components/Bits.cs src/ImageSharp46/Formats/Jpg/Components/Block.cs src/ImageSharp46/Formats/Jpg/Components/Bytes.cs src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs src/ImageSharp46/ImageSharp46.csproj tests/ConsoleBenchmark/ConsoleBenchmark.csproj tests/ConsoleBenchmark/Program.cs tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementations.cs tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj tests/ImageSharp.Tests46/packages.configaf/merge-core
462 changed files with 7652 additions and 42066 deletions
@ -1,34 +0,0 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio 14 |
|||
VisualStudioVersion = 14.0.25420.1 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp46", "src\ImageSharp46\ImageSharp46.csproj", "{FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageSharp.Tests46", "tests\ImageSharp.Tests46\ImageSharp.Tests46.csproj", "{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleBenchmark", "tests\ConsoleBenchmark\ConsoleBenchmark.csproj", "{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{FBA0B5F6-09C2-4317-8EF6-6ADB9B20E6B1}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{635E0A15-3893-4763-A7F6-FCCFF85BCCA4}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{8783E3A1-79F1-4E37-AA79-F06C48BED5E7}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,153 @@ |
|||
// <copyright file="Alpha8.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing a single 8 bit normalized W values that is ranging from 0 to 1.
|
|||
/// </summary>
|
|||
public struct Alpha8 : IPackedPixel<byte>, IEquatable<Alpha8> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Alpha8"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="alpha">The alpha component</param>
|
|||
public Alpha8(float alpha) |
|||
{ |
|||
this.PackedValue = Pack(alpha); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public byte PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Alpha8"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Alpha8"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Alpha8"/> 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>
|
|||
public static bool operator ==(Alpha8 left, Alpha8 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Alpha8"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Alpha8"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Alpha8"/> 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>
|
|||
public static bool operator !=(Alpha8 left, Alpha8 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(0, 0, 0, this.PackedValue / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackedValue = w; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
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(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares an object with the packed vector.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to compare.</param>
|
|||
/// <returns>True if the object is equal to the packed vector.</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Alpha8) && this.Equals((Alpha8)obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares another Alpha8 packed vector with the packed vector.
|
|||
/// </summary>
|
|||
/// <param name="other">The Alpha8 packed vector to compare.</param>
|
|||
/// <returns>True if the packed vectors are equal.</returns>
|
|||
public bool Equals(Alpha8 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a string representation of the packed vector.
|
|||
/// </summary>
|
|||
/// <returns>A string representation of the packed vector.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return (this.PackedValue / 255F).ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a <see cref="float"/> into a byte.
|
|||
/// </summary>
|
|||
/// <param name="alpha">The float containing the value to pack.</param>
|
|||
/// <returns>The <see cref="byte"/> containing the packed values.</returns>
|
|||
private static byte Pack(float alpha) |
|||
{ |
|||
return (byte)Math.Round(alpha.Clamp(0, 1) * 255F); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,170 @@ |
|||
// <copyright file="Bgr565.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x and z components use 5 bits, and the y component uses 6 bits.
|
|||
/// </summary>
|
|||
public struct Bgr565 : IPackedPixel<ushort>, IEquatable<Bgr565> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgr565"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <param name="z">The z-component</param>
|
|||
public Bgr565(float x, float y, float z) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgr565"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// The vector containing the components for the packed value.
|
|||
/// </param>
|
|||
public Bgr565(Vector3 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ushort PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgr565"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Bgr565"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Bgr565"/> 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>
|
|||
public static bool operator ==(Bgr565 left, Bgr565 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgr565"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Bgr565"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Bgr565"/> 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>
|
|||
public static bool operator !=(Bgr565 left, Bgr565 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector3"/>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector3"/>.</returns>
|
|||
public Vector3 ToVector3() |
|||
{ |
|||
return new Vector3( |
|||
((this.PackedValue >> 11) & 0x1F) * (1F / 31F), |
|||
((this.PackedValue >> 5) & 0x3F) * (1F / 63F), |
|||
(this.PackedValue & 0x1F) * (1F / 31F)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.ToVector3(), 1F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4() * 255F; |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Bgr565) && this.Equals((Bgr565)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Bgr565 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector3().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="ushort"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <param name="z">The z-component</param>
|
|||
/// <returns>The <see cref="ushort"/> containing the packed values.</returns>
|
|||
private static ushort Pack(float x, float y, float z) |
|||
{ |
|||
return (ushort)((((int)Math.Round(x.Clamp(0, 1) * 31F) & 0x1F) << 11) | |
|||
(((int)Math.Round(y.Clamp(0, 1) * 63F) & 0x3F) << 5) | |
|||
((int)Math.Round(z.Clamp(0, 1) * 31F) & 0x1F)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,164 @@ |
|||
// <copyright file="Bgra4444.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing unsigned normalized values, ranging from 0 to 1, using 4 bits each for x, y, z, and w.
|
|||
/// </summary>
|
|||
public struct Bgra4444 : IPackedPixel<ushort>, IEquatable<Bgra4444> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra4444"/> struct.
|
|||
/// </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>
|
|||
public Bgra4444(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra4444"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the components for the packed vector.</param>
|
|||
public Bgra4444(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ushort PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra4444"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Bgra4444"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Bgra4444"/> 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>
|
|||
public static bool operator ==(Bgra4444 left, Bgra4444 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra4444"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Bgra4444"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Bgra4444"/> 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>
|
|||
public static bool operator !=(Bgra4444 left, Bgra4444 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
const float Max = 1 / 15F; |
|||
|
|||
return new Vector4( |
|||
((this.PackedValue >> 8) & 0x0F) * Max, |
|||
((this.PackedValue >> 4) & 0x0F) * Max, |
|||
(this.PackedValue & 0x0F) * Max, |
|||
((this.PackedValue >> 12) & 0x0F) * Max); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4() * 255F; |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Bgra4444) && this.Equals((Bgra4444)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Bgra4444 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector4().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="ushort"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="ushort"/> containing the packed values.</returns>
|
|||
private static ushort Pack(float x, float y, float z, float w) |
|||
{ |
|||
return (ushort)((((int)Math.Round(w.Clamp(0, 1) * 15F) & 0x0F) << 12) | |
|||
(((int)Math.Round(x.Clamp(0, 1) * 15F) & 0x0F) << 8) | |
|||
(((int)Math.Round(y.Clamp(0, 1) * 15F) & 0x0F) << 4) | |
|||
((int)Math.Round(z.Clamp(0, 1) * 15F) & 0x0F)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,171 @@ |
|||
// <copyright file="Bgra5551.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x , y and z components use 5 bits, and the w component uses 1 bit.
|
|||
/// </summary>
|
|||
public struct Bgra5551 : IPackedPixel<ushort>, IEquatable<Bgra5551> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra5551"/> struct.
|
|||
/// </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>
|
|||
public Bgra5551(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra5551"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// The vector containing the components for the packed vector.
|
|||
/// </param>
|
|||
public Bgra5551(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ushort PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra5551"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Bgra5551"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Bgra5551"/> 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>
|
|||
public static bool operator ==(Bgra5551 left, Bgra5551 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra5551"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Bgra5551"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Bgra5551"/> 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>
|
|||
public static bool operator !=(Bgra5551 left, Bgra5551 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
((this.PackedValue >> 10) & 0x1F) / 31F, |
|||
((this.PackedValue >> 5) & 0x1F) / 31F, |
|||
((this.PackedValue >> 0) & 0x1F) / 31F, |
|||
(this.PackedValue >> 15) & 0x01); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4() * 255F; |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Bgra5551) && this.Equals((Bgra5551)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Bgra5551 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a string representation of the packed vector.
|
|||
/// </summary>
|
|||
/// <returns>A string representation of the packed vector.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector4().ToString(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a hash code of the packed vector.
|
|||
/// </summary>
|
|||
/// <returns>The hash code for the packed vector.</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="ushort"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="ushort"/> containing the packed values.</returns>
|
|||
private static ushort Pack(float x, float y, float z, float w) |
|||
{ |
|||
return (ushort)( |
|||
(((int)Math.Round(x.Clamp(0, 1) * 31F) & 0x1F) << 10) | |
|||
(((int)Math.Round(y.Clamp(0, 1) * 31F) & 0x1F) << 5) | |
|||
(((int)Math.Round(z.Clamp(0, 1) * 31F) & 0x1F) << 0) | |
|||
(((int)Math.Round(w.Clamp(0, 1)) & 0x1) << 15)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,177 @@ |
|||
// <copyright file="Byte4.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 8-bit unsigned integer values, ranging from 0 to 255.
|
|||
/// </summary>
|
|||
public struct Byte4 : IPackedPixel<uint>, IEquatable<Byte4> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Byte4"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// A vector containing the initial values for the components of the Byte4 structure.
|
|||
/// </param>
|
|||
public Byte4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Byte4"/> struct.
|
|||
/// </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>
|
|||
public Byte4(float x, float y, float z, float w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w); |
|||
this.PackedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Byte4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Byte4"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Byte4"/> 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>
|
|||
public static bool operator ==(Byte4 left, Byte4 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Byte4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Byte4"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Byte4"/> 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>
|
|||
public static bool operator !=(Byte4 left, Byte4 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Sets the packed representation from a Vector4.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector to create the packed representation from.</param>
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a Vector4.
|
|||
/// </summary>
|
|||
/// <returns>The expanded vector.</returns>
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
this.PackedValue & 0xFF, |
|||
(this.PackedValue >> 0x8) & 0xFF, |
|||
(this.PackedValue >> 0x10) & 0xFF, |
|||
(this.PackedValue >> 0x18) & 0xFF); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Byte4) && this.Equals((Byte4)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Byte4 other) |
|||
{ |
|||
return this == other; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a string representation of the current instance.
|
|||
/// </summary>
|
|||
/// <returns>String that represents the object.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("x8"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a vector into a uint.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the values to pack.</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(ref Vector4 vector) |
|||
{ |
|||
const float Max = 255F; |
|||
const float Min = 0F; |
|||
|
|||
// Clamp the value between min and max values
|
|||
uint byte4 = (uint)Math.Round(vector.X.Clamp(Min, Max)) & 0xFF; |
|||
uint byte3 = ((uint)Math.Round(vector.Y.Clamp(Min, Max)) & 0xFF) << 0x8; |
|||
uint byte2 = ((uint)Math.Round(vector.Z.Clamp(Min, Max)) & 0xFF) << 0x10; |
|||
uint byte1 = ((uint)Math.Round(vector.W.Clamp(Min, Max)) & 0xFF) << 0x18; |
|||
|
|||
return byte4 | byte3 | byte2 | byte1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,160 @@ |
|||
// <copyright file="HalfSingle.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing a single 16 bit floating point value.
|
|||
/// </summary>
|
|||
public struct HalfSingle : IPackedPixel<ushort>, IEquatable<HalfSingle> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half vector value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HalfSingle"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="single">The single component.</param>
|
|||
public HalfSingle(float single) |
|||
{ |
|||
this.PackedValue = HalfTypeHelper.Pack(single); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ushort PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HalfSingle"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="HalfSingle"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="HalfSingle"/> 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>
|
|||
public static bool operator ==(HalfSingle left, HalfSingle right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HalfSingle"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="HalfSingle"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="HalfSingle"/> 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>
|
|||
public static bool operator !=(HalfSingle left, HalfSingle right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="float"/>.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="float"/>.</returns>
|
|||
public float ToSingle() |
|||
{ |
|||
return HalfTypeHelper.Unpack(this.PackedValue); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = HalfTypeHelper.Pack(vector.X); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.ToSingle(), 0, 0, 1); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= MaxBytes; |
|||
vector += Half; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is HalfSingle) && this.Equals((HalfSingle)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(HalfSingle other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToSingle().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,145 @@ |
|||
// <copyright file="HalfTypeHelper.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Runtime.InteropServices; |
|||
|
|||
/// <summary>
|
|||
/// Helper methods for packing and unpacking floating point values
|
|||
/// </summary>
|
|||
internal class HalfTypeHelper |
|||
{ |
|||
/// <summary>
|
|||
/// Packs a <see cref="float"/> into an <see cref="ushort"/>
|
|||
/// </summary>
|
|||
/// <param name="value">The float to pack</param>
|
|||
/// <returns>The <see cref="ushort"/></returns>
|
|||
internal static ushort Pack(float value) |
|||
{ |
|||
Uif uif = new Uif { F = value }; |
|||
return Pack(uif.I); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs an <see cref="int"/> into a <see cref="ushort"/>
|
|||
/// </summary>
|
|||
/// <param name="value">The integer to pack.</param>
|
|||
/// <returns>The <see cref="ushort"/></returns>
|
|||
internal static ushort Pack(int value) |
|||
{ |
|||
int s = (value >> 16) & 0x00008000; |
|||
int e = ((value >> 23) & 0x000000ff) - (127 - 15); |
|||
int m = value & 0x007fffff; |
|||
|
|||
if (e <= 0) |
|||
{ |
|||
if (e < -10) |
|||
{ |
|||
return (ushort)s; |
|||
} |
|||
|
|||
m = m | 0x00800000; |
|||
|
|||
int t = 14 - e; |
|||
int a = (1 << (t - 1)) - 1; |
|||
int b = (m >> t) & 1; |
|||
|
|||
m = (m + a + b) >> t; |
|||
|
|||
return (ushort)(s | m); |
|||
} |
|||
|
|||
if (e == 0xff - (127 - 15)) |
|||
{ |
|||
if (m == 0) |
|||
{ |
|||
return (ushort)(s | 0x7c00); |
|||
} |
|||
|
|||
m >>= 13; |
|||
return (ushort)(s | 0x7c00 | m | ((m == 0) ? 1 : 0)); |
|||
} |
|||
|
|||
m = m + 0x00000fff + ((m >> 13) & 1); |
|||
|
|||
if ((m & 0x00800000) != 0) |
|||
{ |
|||
m = 0; |
|||
e += 1; |
|||
} |
|||
|
|||
if (e > 30) |
|||
{ |
|||
return (ushort)(s | 0x7c00); |
|||
} |
|||
|
|||
return (ushort)(s | (e << 10) | (m >> 13)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Unpacks a <see cref="ushort"/> into a <see cref="float"/>.
|
|||
/// </summary>
|
|||
/// <param name="value">The value.</param>
|
|||
/// <returns>The <see cref="float"/>.</returns>
|
|||
internal static float Unpack(ushort value) |
|||
{ |
|||
uint result; |
|||
uint mantissa = (uint)(value & 1023); |
|||
uint exponent = 0xfffffff2; |
|||
|
|||
if ((value & -33792) == 0) |
|||
{ |
|||
if (mantissa != 0) |
|||
{ |
|||
while ((mantissa & 1024) == 0) |
|||
{ |
|||
exponent--; |
|||
mantissa = mantissa << 1; |
|||
} |
|||
|
|||
mantissa &= 0xfffffbff; |
|||
result = ((uint)((((uint)value & 0x8000) << 16) | ((exponent + 127) << 23))) | (mantissa << 13); |
|||
} |
|||
else |
|||
{ |
|||
result = (uint)((value & 0x8000) << 16); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
result = ((((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0x1f) - 15) + 127) << 23)) | (mantissa << 13); |
|||
} |
|||
|
|||
Uif uif = new Uif { U = result }; |
|||
return uif.F; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Maps the position of number types in memory
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Explicit)] |
|||
private struct Uif |
|||
{ |
|||
/// <summary>
|
|||
/// The float.
|
|||
/// </summary>
|
|||
[FieldOffset(0)] |
|||
public float F; |
|||
|
|||
/// <summary>
|
|||
/// The integer.
|
|||
/// </summary>
|
|||
[FieldOffset(0)] |
|||
public int I; |
|||
|
|||
/// <summary>
|
|||
/// The unsigned integer.
|
|||
/// </summary>
|
|||
[FieldOffset(0)] |
|||
public uint U; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,187 @@ |
|||
// <copyright file="HalfVector2.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing two 16-bit floating-point values.
|
|||
/// </summary>
|
|||
public struct HalfVector2 : IPackedPixel<uint>, IEquatable<HalfVector2> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half vector value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HalfVector2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component.</param>
|
|||
/// <param name="y">The y-component.</param>
|
|||
public HalfVector2(float x, float y) |
|||
{ |
|||
this.PackedValue = Pack(x, y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HalfVector2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">A vector containing the initial values for the components.</param>
|
|||
public HalfVector2(Vector2 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HalfVector2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="HalfVector2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="HalfVector2"/> 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>
|
|||
public static bool operator ==(HalfVector2 left, HalfVector2 right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HalfVector2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="HalfVector2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="HalfVector2"/> 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>
|
|||
public static bool operator !=(HalfVector2 left, HalfVector2 right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector2"/>.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector2"/>.</returns>
|
|||
public Vector2 ToVector2() |
|||
{ |
|||
Vector2 vector; |
|||
vector.X = HalfTypeHelper.Unpack((ushort)this.PackedValue); |
|||
vector.Y = HalfTypeHelper.Unpack((ushort)(this.PackedValue >> 0x10)); |
|||
return vector; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
Vector2 vector = this.ToVector2(); |
|||
return new Vector4(vector.X, vector.Y, 0F, 1F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= MaxBytes; |
|||
vector += Half; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector2().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is HalfVector2) && this.Equals((HalfVector2)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(HalfVector2 other) |
|||
{ |
|||
return this.PackedValue.Equals(other.PackedValue); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="uint"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(float x, float y) |
|||
{ |
|||
uint num2 = HalfTypeHelper.Pack(x); |
|||
uint num = (uint)(HalfTypeHelper.Pack(y) << 0x10); |
|||
return num2 | num; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,182 @@ |
|||
// <copyright file="HalfVector4.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 16-bit floating-point values.
|
|||
/// </summary>
|
|||
public struct HalfVector4 : IPackedPixel<ulong>, IEquatable<HalfVector4> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half vector value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(0.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HalfVector4"/> struct.
|
|||
/// </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>
|
|||
public HalfVector4(float x, float y, float z, float w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w); |
|||
this.PackedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HalfVector4"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">A vector containing the initial values for the components</param>
|
|||
public HalfVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ulong PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HalfVector2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="HalfVector2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="HalfVector2"/> 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>
|
|||
public static bool operator ==(HalfVector4 left, HalfVector4 right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="HalfVector2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="HalfVector2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="HalfVector2"/> 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>
|
|||
public static bool operator !=(HalfVector4 left, HalfVector4 right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
HalfTypeHelper.Unpack((ushort)this.PackedValue), |
|||
HalfTypeHelper.Unpack((ushort)(this.PackedValue >> 0x10)), |
|||
HalfTypeHelper.Unpack((ushort)(this.PackedValue >> 0x20)), |
|||
HalfTypeHelper.Unpack((ushort)(this.PackedValue >> 0x30))); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= MaxBytes; |
|||
vector += Half; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector4().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is HalfVector4) && this.Equals((HalfVector4)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(HalfVector4 other) |
|||
{ |
|||
return this.PackedValue.Equals(other.PackedValue); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a <see cref="Vector4"/> into a <see cref="ulong"/>.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the values to pack.</param>
|
|||
/// <returns>The <see cref="ulong"/> containing the packed values.</returns>
|
|||
private static ulong Pack(ref Vector4 vector) |
|||
{ |
|||
ulong num4 = HalfTypeHelper.Pack(vector.X); |
|||
ulong num3 = (ulong)HalfTypeHelper.Pack(vector.Y) << 0x10; |
|||
ulong num2 = (ulong)HalfTypeHelper.Pack(vector.Z) << 0x20; |
|||
ulong num1 = (ulong)HalfTypeHelper.Pack(vector.W) << 0x30; |
|||
return num4 | num3 | num2 | num1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,199 @@ |
|||
// <copyright file="NormalizedByte2.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed packed pixel type containing two 8-bit signed normalized values, ranging from −1 to 1.
|
|||
/// </summary>
|
|||
public struct NormalizedByte2 : IPackedPixel<ushort>, IEquatable<NormalizedByte2> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half the maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(127); |
|||
|
|||
/// <summary>
|
|||
/// The vector value used for rounding.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Round = new Vector4(.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedByte2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public NormalizedByte2(Vector2 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedByte2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component.</param>
|
|||
/// <param name="y">The y-component.</param>
|
|||
public NormalizedByte2(float x, float y) |
|||
{ |
|||
this.PackedValue = Pack(x, y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ushort PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedByte2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedByte2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedByte2"/> 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>
|
|||
public static bool operator ==(NormalizedByte2 left, NormalizedByte2 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedByte2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedByte2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedByte2"/> 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>
|
|||
public static bool operator !=(NormalizedByte2 left, NormalizedByte2 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector2"/>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector2"/>.</returns>
|
|||
public Vector2 ToVector2() |
|||
{ |
|||
return new Vector2( |
|||
(sbyte)((this.PackedValue >> 0) & 0xFF) / 127F, |
|||
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.ToVector2(), 0F, 1F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w); |
|||
vector -= Round; |
|||
vector -= Half; |
|||
vector -= Round; |
|||
vector /= Half; |
|||
this.PackFromVector4(vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= Half; |
|||
vector += Round; |
|||
vector += Half; |
|||
vector += Round; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = 0; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = 0; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = 255; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = 0; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = 0; |
|||
bytes[startIndex + 3] = 255; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is NormalizedByte2) && this.Equals((NormalizedByte2)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(NormalizedByte2 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("X"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="ushort"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <returns>The <see cref="ushort"/> containing the packed values.</returns>
|
|||
private static ushort Pack(float x, float y) |
|||
{ |
|||
int byte2 = ((ushort)Math.Round(x.Clamp(-1F, 1F) * 127F) & 0xFF) << 0; |
|||
int byte1 = ((ushort)Math.Round(y.Clamp(-1F, 1F) * 127F) & 0xFF) << 8; |
|||
|
|||
return (ushort)(byte2 | byte1); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,197 @@ |
|||
// <copyright file="NormalizedByte4.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 8-bit signed normalized values, ranging from −1 to 1.
|
|||
/// </summary>
|
|||
public struct NormalizedByte4 : IPackedPixel<uint>, IEquatable<NormalizedByte4> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half the maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(127); |
|||
|
|||
/// <summary>
|
|||
/// The vector value used for rounding.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Round = new Vector4(.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedByte4"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public NormalizedByte4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedByte4"/> struct.
|
|||
/// </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>
|
|||
public NormalizedByte4(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedByte4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedByte4"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedByte4"/> 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>
|
|||
public static bool operator ==(NormalizedByte4 left, NormalizedByte4 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedByte4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedByte4"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedByte4"/> 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>
|
|||
public static bool operator !=(NormalizedByte4 left, NormalizedByte4 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
(sbyte)((this.PackedValue >> 0) & 0xFF) / 127F, |
|||
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F, |
|||
(sbyte)((this.PackedValue >> 16) & 0xFF) / 127F, |
|||
(sbyte)((this.PackedValue >> 24) & 0xFF) / 127F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w); |
|||
vector -= Round; |
|||
vector -= Half; |
|||
vector -= Round; |
|||
vector /= Half; |
|||
this.PackFromVector4(vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= Half; |
|||
vector += Round; |
|||
vector += Half; |
|||
vector += Round; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is NormalizedByte4) && this.Equals((NormalizedByte4)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(NormalizedByte4 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("X"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="uint"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(float x, float y, float z, float w) |
|||
{ |
|||
uint byte4 = ((uint)Math.Round(x.Clamp(-1F, 1F) * 127F) & 0xFF) << 0; |
|||
uint byte3 = ((uint)Math.Round(y.Clamp(-1F, 1F) * 127F) & 0xFF) << 8; |
|||
uint byte2 = ((uint)Math.Round(z.Clamp(-1F, 1F) * 127F) & 0xFF) << 16; |
|||
uint byte1 = ((uint)Math.Round(w.Clamp(-1F, 1F) * 127F) & 0xFF) << 24; |
|||
|
|||
return byte4 | byte3 | byte2 | byte1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,206 @@ |
|||
// <copyright file="NormalizedShort2.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing two 16-bit signed normalized values, ranging from −1 to 1.
|
|||
/// </summary>
|
|||
public struct NormalizedShort2 : IPackedPixel<uint>, IEquatable<NormalizedShort2> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half the maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(127); |
|||
|
|||
/// <summary>
|
|||
/// The vector value used for rounding.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Round = new Vector4(.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedShort2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public NormalizedShort2(Vector2 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedShort2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component.</param>
|
|||
/// <param name="y">The y-component.</param>
|
|||
public NormalizedShort2(float x, float y) |
|||
{ |
|||
this.PackedValue = Pack(x, y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedShort2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedShort2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedShort2"/> 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>
|
|||
public static bool operator ==(NormalizedShort2 left, NormalizedShort2 right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedShort2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedShort2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedShort2"/> 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>
|
|||
public static bool operator !=(NormalizedShort2 left, NormalizedShort2 right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.ToVector2(), 0, 1); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w); |
|||
vector -= Round; |
|||
vector -= Half; |
|||
vector -= Round; |
|||
vector /= Half; |
|||
this.PackFromVector4(vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= Half; |
|||
vector += Round; |
|||
vector += Half; |
|||
vector += Round; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = 0; |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = 0; |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = 255; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = 0; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = 0; |
|||
bytes[startIndex + 3] = 255; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector2"/>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector2"/>.</returns>
|
|||
public Vector2 ToVector2() |
|||
{ |
|||
const float MaxVal = 0x7FFF; |
|||
|
|||
return new Vector2( |
|||
(short)(this.PackedValue & 0xFFFF) / MaxVal, |
|||
(short)(this.PackedValue >> 0x10) / MaxVal); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is NormalizedShort2) && this.Equals((NormalizedShort2)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(NormalizedShort2 other) |
|||
{ |
|||
return this.PackedValue.Equals(other.PackedValue); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("X"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="uint"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(float x, float y) |
|||
{ |
|||
const float MaxPos = 0x7FFF; |
|||
const float MinNeg = -MaxPos; |
|||
|
|||
// Clamp the value between min and max values
|
|||
// Round rather than truncate.
|
|||
uint word2 = (uint)((int)(float)Math.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF); |
|||
uint word1 = (uint)(((int)(float)Math.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10); |
|||
|
|||
return word2 | word1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,203 @@ |
|||
// <copyright file="NormalizedShort4.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 16-bit signed normalized values, ranging from −1 to 1.
|
|||
/// </summary>
|
|||
public struct NormalizedShort4 : IPackedPixel<ulong>, IEquatable<NormalizedShort4> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half the maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(127); |
|||
|
|||
/// <summary>
|
|||
/// The vector value used for rounding.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Round = new Vector4(.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedShort4"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public NormalizedShort4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="NormalizedShort4"/> struct.
|
|||
/// </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>
|
|||
public NormalizedShort4(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ulong PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedShort4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedShort4"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedShort4"/> 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>
|
|||
public static bool operator ==(NormalizedShort4 left, NormalizedShort4 right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="NormalizedShort4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="NormalizedShort4"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="NormalizedShort4"/> 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>
|
|||
public static bool operator !=(NormalizedShort4 left, NormalizedShort4 right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
const float MaxVal = 0x7FFF; |
|||
|
|||
return new Vector4( |
|||
(short)((this.PackedValue >> 0x00) & 0xFFFF) / MaxVal, |
|||
(short)((this.PackedValue >> 0x10) & 0xFFFF) / MaxVal, |
|||
(short)((this.PackedValue >> 0x20) & 0xFFFF) / MaxVal, |
|||
(short)((this.PackedValue >> 0x30) & 0xFFFF) / MaxVal); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w); |
|||
vector -= Round; |
|||
vector -= Half; |
|||
vector -= Round; |
|||
vector /= Half; |
|||
this.PackFromVector4(vector); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector *= Half; |
|||
vector += Round; |
|||
vector += Half; |
|||
vector += Round; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is NormalizedShort4) && this.Equals((NormalizedShort4)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(NormalizedShort4 other) |
|||
{ |
|||
return this.PackedValue.Equals(other.PackedValue); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("X"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="ulong"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="ulong"/> containing the packed values.</returns>
|
|||
private static ulong Pack(float x, float y, float z, float w) |
|||
{ |
|||
const float MaxPos = 0x7FFF; |
|||
const float MinNeg = -MaxPos; |
|||
|
|||
// Clamp the value between min and max values
|
|||
ulong word4 = ((ulong)(float)Math.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x00; |
|||
ulong word3 = ((ulong)(float)Math.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10; |
|||
ulong word2 = ((ulong)(float)Math.Round(z * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x20; |
|||
ulong word1 = ((ulong)(float)Math.Round(w * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x30; |
|||
|
|||
return word4 | word3 | word2 | word1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,369 @@ |
|||
// <copyright file="PackedPixelConverterHelper.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Assists with the conversion of known packed pixel formats from one to another.
|
|||
/// </summary>
|
|||
internal static class PackedPixelConverterHelper |
|||
{ |
|||
/// <summary>
|
|||
/// A non operative function. Simply returns the original vector.
|
|||
/// </summary>
|
|||
private static readonly Func<Vector4, Vector4> Noop = vector4 => vector4; |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct scaling function for the given types The compute scale function.
|
|||
/// </summary>
|
|||
/// <param name="scaleFunc">The scale function.</param>
|
|||
/// <typeparam name="TColor">The source pixel format.</typeparam>
|
|||
/// <typeparam name="TColor2">The target pixel format.</typeparam>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
public static Func<Vector4, Vector4> ComputeScaleFunction<TColor, TColor2>(Func<Vector4, Vector4> scaleFunc) |
|||
{ |
|||
// Custom type with a custom function.
|
|||
if (scaleFunc != null) |
|||
{ |
|||
return scaleFunc; |
|||
} |
|||
|
|||
Type source = typeof(TColor); |
|||
Type target = typeof(TColor2); |
|||
|
|||
// Normalized standard
|
|||
if (IsStandardNormalizedType(source)) |
|||
{ |
|||
return FromStandardNormalizedType(target); |
|||
} |
|||
|
|||
// Standard
|
|||
if (IsStandardType(source)) |
|||
{ |
|||
return FromStandardType(target); |
|||
} |
|||
|
|||
// Normalized offsets. All four components.
|
|||
if (IsOffsetNormalizedType(source)) |
|||
{ |
|||
return FromOffsetNormalizedType(target); |
|||
} |
|||
|
|||
// Offset. All four components.
|
|||
if (IsOffsetType(source)) |
|||
{ |
|||
return FromOffsetType(target); |
|||
} |
|||
|
|||
// Normalized offsets. First component pair only.
|
|||
if (IsOffsetTwoComponentNormalizedType(source)) |
|||
{ |
|||
return FromOffsetTwoComponentNormalizedType(target); |
|||
} |
|||
|
|||
// Offsets. First component pair only.
|
|||
if (IsOffsetTwoComponentType(source)) |
|||
{ |
|||
return FromOffsetTwoComponentType(target); |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct conversion function to convert from types having vector values representing all four components
|
|||
/// ranging from 0 to 1.
|
|||
/// </summary>
|
|||
/// <param name="target">The target type</param>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
private static Func<Vector4, Vector4> FromStandardNormalizedType(Type target) |
|||
{ |
|||
if (IsStandardType(target)) |
|||
{ |
|||
return vector4 => 255F * vector4; |
|||
} |
|||
|
|||
if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target)) |
|||
{ |
|||
// Expand the range then offset the center down.
|
|||
return vector4 => (2F * vector4) - Vector4.One; |
|||
} |
|||
|
|||
if (IsOffsetType(target) || IsOffsetTwoComponentType(target)) |
|||
{ |
|||
return vector4 => (65534F * vector4) - new Vector4(32767F); |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct conversion function to convert from types having vector values representing all four components
|
|||
/// ranging from 0 to 255.
|
|||
/// </summary>
|
|||
/// <param name="target">The target type</param>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
private static Func<Vector4, Vector4> FromStandardType(Type target) |
|||
{ |
|||
// Scale down
|
|||
if (IsStandardNormalizedType(target)) |
|||
{ |
|||
return vector4 => vector4 / 255F; |
|||
} |
|||
|
|||
if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target)) |
|||
{ |
|||
// Expand the range, divide, then offset the center down.
|
|||
return vector4 => ((2F * (vector4 / 255F)) - Vector4.One); |
|||
} |
|||
|
|||
if (IsOffsetType(target) || IsOffsetTwoComponentType(target)) |
|||
{ |
|||
return vector4 => (65534F * (vector4 / 255F)) - new Vector4(32767F); |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct conversion function to convert from types having vector values representing all four components
|
|||
/// ranging from -1 to 1.
|
|||
/// </summary>
|
|||
/// <param name="target">The target type</param>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
private static Func<Vector4, Vector4> FromOffsetNormalizedType(Type target) |
|||
{ |
|||
if (IsStandardNormalizedType(target)) |
|||
{ |
|||
// Compress the range then offset the center up.
|
|||
return vector4 => (vector4 / 2F) + new Vector4(.5F); |
|||
} |
|||
|
|||
if (IsStandardType(target)) |
|||
{ |
|||
// Compress the range, multiply, then offset the center up.
|
|||
return vector4 => ((vector4 / 2F) * 255F) + new Vector4(127.5F); |
|||
} |
|||
|
|||
if (IsOffsetType(target) || IsOffsetTwoComponentType(target)) |
|||
{ |
|||
// Multiply out the range, two component won't read the last two values.
|
|||
return vector4 => (vector4 * 32767F); |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct conversion function to convert from types having vector values representing all four components
|
|||
/// ranging from -32767 to 32767.
|
|||
/// </summary>
|
|||
/// <param name="target">The target type</param>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
private static Func<Vector4, Vector4> FromOffsetType(Type target) |
|||
{ |
|||
if (IsStandardNormalizedType(target)) |
|||
{ |
|||
// Compress the range then offset the center up.
|
|||
return vector4 => (vector4 / 65534F) + new Vector4(.5F); |
|||
} |
|||
|
|||
if (IsStandardType(target)) |
|||
{ |
|||
// Compress the range, multiply, then offset the center up.
|
|||
return vector4 => ((vector4 / 65534F) * 255F) + new Vector4(127.5F); |
|||
} |
|||
|
|||
if (IsOffsetNormalizedType(target) || IsOffsetTwoComponentNormalizedType(target)) |
|||
{ |
|||
// Compress the range. Two component won't read the last two values.
|
|||
return vector4 => (vector4 / 32767F); |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct conversion function to convert from types having vector with the first component pair ranging from -1 to 1.
|
|||
/// and the second component pair ranging from 0 to 1.
|
|||
/// </summary>
|
|||
/// <param name="target">The target type</param>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
private static Func<Vector4, Vector4> FromOffsetTwoComponentNormalizedType(Type target) |
|||
{ |
|||
if (IsStandardNormalizedType(target)) |
|||
{ |
|||
return vector4 => |
|||
{ |
|||
// Compress the range then offset the center up for first pair.
|
|||
Vector4 v = (vector4 / 2F) + new Vector4(.5F); |
|||
return new Vector4(v.X, v.Y, 0F, 1F); |
|||
}; |
|||
} |
|||
|
|||
if (IsStandardType(target)) |
|||
{ |
|||
return vector4 => |
|||
{ |
|||
// Compress the range, multiply, then offset the center up for first pair.
|
|||
Vector4 v = ((vector4 / 2F) * 255F) + new Vector4(127.5F); |
|||
return new Vector4(v.X, v.Y, 0F, 255F); |
|||
}; |
|||
} |
|||
|
|||
if (IsOffsetNormalizedType(target)) |
|||
{ |
|||
// Copy the first two components and set second pair to 0 and 1 equivalent.
|
|||
return vector4 => new Vector4(vector4.X, vector4.Y, -1F, 1F); |
|||
} |
|||
|
|||
if (IsOffsetTwoComponentType(target)) |
|||
{ |
|||
// Multiply. Two component won't read the last two values.
|
|||
return vector4 => (vector4 * 32767F); |
|||
} |
|||
|
|||
if (IsOffsetType(target)) |
|||
{ |
|||
return vector4 => |
|||
{ |
|||
// Multiply the first two components and set second pair to 0 and 1 equivalent.
|
|||
Vector4 v = vector4 * 32767F; |
|||
return new Vector4(v.X, v.Y, -32767F, 32767F); |
|||
}; |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct conversion function to convert from types having vector with the first component pair ranging from -32767 to 32767.
|
|||
/// and the second component pair ranging from 0 to 1.
|
|||
/// </summary>
|
|||
/// <param name="target">The target type</param>
|
|||
/// <returns>The <see cref="Func{Vector4,Vector4}"/></returns>
|
|||
private static Func<Vector4, Vector4> FromOffsetTwoComponentType(Type target) |
|||
{ |
|||
if (IsStandardNormalizedType(target)) |
|||
{ |
|||
return vector4 => |
|||
{ |
|||
Vector4 v = (vector4 / 65534F) + new Vector4(.5F); |
|||
return new Vector4(v.X, v.Y, 0, 1); |
|||
}; |
|||
} |
|||
|
|||
if (IsStandardType(target)) |
|||
{ |
|||
return vector4 => |
|||
{ |
|||
Vector4 v = ((vector4 / 65534F) * 255F) + new Vector4(127.5F); |
|||
return new Vector4(v.X, v.Y, 0, 255F); |
|||
}; |
|||
} |
|||
|
|||
if (IsOffsetType(target)) |
|||
{ |
|||
// Copy the first two components and set second pair to 0 and 1 equivalent.
|
|||
return vector4 => new Vector4(vector4.X, vector4.Y, -32767F, 32767F); |
|||
} |
|||
|
|||
if (IsOffsetNormalizedType(target)) |
|||
{ |
|||
return vector4 => |
|||
{ |
|||
// Divide the first two components and set second pair to 0 and 1 equivalent.
|
|||
Vector4 v = vector4 / 32767F; |
|||
return new Vector4(v.X, v.Y, -1F, 1F); |
|||
}; |
|||
} |
|||
|
|||
if (IsOffsetTwoComponentNormalizedType(target)) |
|||
{ |
|||
// Divide. Two component won't read the last two values.
|
|||
return vector4 => (vector4 / 32767F); |
|||
} |
|||
|
|||
return Noop; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the type as having vector component values ranging from 0 to 1.
|
|||
/// </summary>
|
|||
/// <param name="type">The type to test.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
private static bool IsStandardNormalizedType(Type type) |
|||
{ |
|||
return type == typeof(Color) |
|||
|| type == typeof(Alpha8) |
|||
|| type == typeof(Bgr565) |
|||
|| type == typeof(Bgra4444) |
|||
|| type == typeof(Bgra5551) |
|||
|| type == typeof(HalfSingle) |
|||
|| type == typeof(HalfVector2) |
|||
|| type == typeof(HalfVector4) |
|||
|| type == typeof(Rg32) |
|||
|| type == typeof(Rgba1010102) |
|||
|| type == typeof(Rgba64); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the type as having vector component values ranging from 0 to 255.
|
|||
/// </summary>
|
|||
/// <param name="type">The type to test.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
private static bool IsStandardType(Type type) |
|||
{ |
|||
return type == typeof(Byte4); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the type as having vector values representing the first component pair ranging from -1 to 1.
|
|||
/// and the second component pair ranging from 0 to 1.
|
|||
/// </summary>
|
|||
/// <param name="type">The type to test.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
private static bool IsOffsetTwoComponentNormalizedType(Type type) |
|||
{ |
|||
return type == typeof(NormalizedByte2) |
|||
|| type == typeof(NormalizedShort2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the type as having vector values representing all four components ranging from -1 to 1.
|
|||
/// </summary>
|
|||
/// <param name="type">The type to test.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
private static bool IsOffsetNormalizedType(Type type) |
|||
{ |
|||
return type == typeof(NormalizedByte4) |
|||
|| type == typeof(NormalizedShort4); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the type as having vector values representing the first component pair ranging from -32767 to 32767.
|
|||
/// and the second component pair ranging from 0 to 1.
|
|||
/// </summary>
|
|||
/// <param name="type">The type to test.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
private static bool IsOffsetTwoComponentType(Type type) |
|||
{ |
|||
return type == typeof(Short2); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Identifies the type as having vector values representing all four components ranging from -32767 to 32767.
|
|||
/// </summary>
|
|||
/// <param name="type">The type to test.</param>
|
|||
/// <returns>The <see cref="bool"/></returns>
|
|||
private static bool IsOffsetType(Type type) |
|||
{ |
|||
return type == typeof(Short4); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
Pixel formats adapted and extended from: |
|||
|
|||
https://github.com/MonoGame/MonoGame |
|||
@ -0,0 +1,173 @@ |
|||
// <copyright file="Rg32.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing two 16-bit unsigned normalized values ranging from 0 to 1.
|
|||
/// </summary>
|
|||
public struct Rg32 : IPackedPixel<uint>, IEquatable<Rg32>, IPackedVector |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rg32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
public Rg32(float x, float y) |
|||
{ |
|||
this.PackedValue = Pack(x, y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rg32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public Rg32(Vector2 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rg32"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Rg32"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Rg32"/> 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>
|
|||
public static bool operator ==(Rg32 left, Rg32 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rg32"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Rg32"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Rg32"/> 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>
|
|||
public static bool operator !=(Rg32 left, Rg32 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector2"/>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector2"/>.</returns>
|
|||
public Vector2 ToVector2() |
|||
{ |
|||
return new Vector2( |
|||
(this.PackedValue & 0xFFFF) / 65535F, |
|||
((this.PackedValue >> 16) & 0xFFFF) / 65535F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.ToVector2(), 0F, 1F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4() * 255F; |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)vector.Z; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.X; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)vector.X; |
|||
bytes[startIndex + 1] = (byte)vector.Y; |
|||
bytes[startIndex + 2] = (byte)vector.Z; |
|||
bytes[startIndex + 3] = (byte)vector.W; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Rg32) && this.Equals((Rg32)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Rg32 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector2().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="uint"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(float x, float y) |
|||
{ |
|||
return (uint)( |
|||
((int)Math.Round(x.Clamp(0, 1) * 65535F) & 0xFFFF) | |
|||
(((int)Math.Round(y.Clamp(0, 1) * 65535F) & 0xFFFF) << 16)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,172 @@ |
|||
// <copyright file="Rgba1010102.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed vector type containing unsigned normalized values ranging from 0 to 1.
|
|||
/// The x, y and z components use 10 bits, and the w component uses 2 bits.
|
|||
/// </summary>
|
|||
public struct Rgba1010102 : IPackedPixel<uint>, IEquatable<Rgba1010102>, IPackedVector |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba1010102"/> struct.
|
|||
/// </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>
|
|||
public Rgba1010102(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba1010102"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public Rgba1010102(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgba1010102"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Rgba1010102"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Rgba1010102"/> 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>
|
|||
public static bool operator ==(Rgba1010102 left, Rgba1010102 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgba1010102"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Rgba1010102"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Rgba1010102"/> 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>
|
|||
public static bool operator !=(Rgba1010102 left, Rgba1010102 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
((this.PackedValue >> 0) & 0x03FF) / 1023F, |
|||
((this.PackedValue >> 10) & 0x03FF) / 1023F, |
|||
((this.PackedValue >> 20) & 0x03FF) / 1023F, |
|||
((this.PackedValue >> 30) & 0x03) / 3F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4() * 255F; |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Rgba1010102) && this.Equals((Rgba1010102)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Rgba1010102 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector4().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="uint"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(float x, float y, float z, float w) |
|||
{ |
|||
return (uint)( |
|||
(((int)Math.Round(x.Clamp(0, 1) * 1023F) & 0x03FF) << 0) | |
|||
(((int)Math.Round(y.Clamp(0, 1) * 1023F) & 0x03FF) << 10) | |
|||
(((int)Math.Round(z.Clamp(0, 1) * 1023F) & 0x03FF) << 20) | |
|||
(((int)Math.Round(w.Clamp(0, 1) * 3F) & 0x03) << 30)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,170 @@ |
|||
// <copyright file="Rgba64.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 16-bit unsigned normalized values ranging from 0 to 1.
|
|||
/// </summary>
|
|||
public struct Rgba64 : IPackedPixel<ulong>, IEquatable<Rgba64>, IPackedVector |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba64"/> struct.
|
|||
/// </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>
|
|||
public Rgba64(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgba64"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the components values.</param>
|
|||
public Rgba64(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ulong PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgba64"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Rgba64"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Rgba64"/> 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>
|
|||
public static bool operator ==(Rgba64 left, Rgba64 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Rgba64"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Rgba64"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Rgba64"/> 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>
|
|||
public static bool operator !=(Rgba64 left, Rgba64 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
(this.PackedValue & 0xFFFF) / 65535F, |
|||
((this.PackedValue >> 16) & 0xFFFF) / 65535F, |
|||
((this.PackedValue >> 32) & 0xFFFF) / 65535F, |
|||
((this.PackedValue >> 48) & 0xFFFF) / 65535F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.PackFromVector4(new Vector4(x, y, z, w) / 255F); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4() * 255F; |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Rgba64) && this.Equals((Rgba64)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Rgba64 other) |
|||
{ |
|||
return this.PackedValue == other.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector4().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="ulong"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="ulong"/> containing the packed values.</returns>
|
|||
private static ulong Pack(float x, float y, float z, float w) |
|||
{ |
|||
return (ulong)Math.Round(x.Clamp(0, 1) * 65535F) | |
|||
((ulong)Math.Round(y.Clamp(0, 1) * 65535F) << 16) | |
|||
((ulong)Math.Round(z.Clamp(0, 1) * 65535F) << 32) | |
|||
((ulong)Math.Round(w.Clamp(0, 1) * 65535F) << 48); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,200 @@ |
|||
// <copyright file="Short2.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing two 16-bit signed integer values.
|
|||
/// </summary>
|
|||
public struct Short2 : IPackedPixel<uint>, IEquatable<Short2> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector2 MaxBytes = new Vector2(255); |
|||
|
|||
/// <summary>
|
|||
/// The half the maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector2 Half = new Vector2(127); |
|||
|
|||
/// <summary>
|
|||
/// The vector value used for rounding.
|
|||
/// </summary>
|
|||
private static readonly Vector2 Round = new Vector2(.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Short2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the component values.</param>
|
|||
public Short2(Vector2 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Short2"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component.</param>
|
|||
/// <param name="y">The y-component.</param>
|
|||
public Short2(float x, float y) |
|||
{ |
|||
this.PackedValue = Pack(x, y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public uint PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Short2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Short2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Short2"/> 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>
|
|||
public static bool operator ==(Short2 left, Short2 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Short2"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Short2"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Short2"/> 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>
|
|||
public static bool operator !=(Short2 left, Short2 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10), 0, 1); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
Vector2 vector = new Vector2(x, y) / 255; |
|||
vector *= 65534; |
|||
vector -= new Vector2(32767); |
|||
this.PackedValue = Pack(vector.X, vector.Y); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector2 vector = this.ToVector2(); |
|||
vector /= 65534; |
|||
vector *= 255; |
|||
vector += Half; |
|||
vector += Round; |
|||
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = 0; |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = 0; |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = 255; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = 0; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = 0; |
|||
bytes[startIndex + 3] = 255; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector2"/>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector2"/>.</returns>
|
|||
public Vector2 ToVector2() |
|||
{ |
|||
return new Vector2((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Short2) && this.Equals((Short2)obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Equals(Short2 other) |
|||
{ |
|||
return this == other; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("x8"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the <see cref="float"/> components into a <see cref="uint"/>.
|
|||
/// </summary>
|
|||
/// <param name="x">The x-component</param>
|
|||
/// <param name="y">The y-component</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(float x, float y) |
|||
{ |
|||
// Largest two byte positive number 0xFFFF >> 1;
|
|||
const float MaxPos = 0x7FFF; |
|||
const float MinNeg = ~(int)MaxPos; |
|||
|
|||
// Clamp the value between min and max values
|
|||
uint word2 = (uint)Math.Round(x.Clamp(MinNeg, MaxPos)) & 0xFFFF; |
|||
uint word1 = ((uint)Math.Round(y.Clamp(MinNeg, MaxPos)) & 0xFFFF) << 0x10; |
|||
|
|||
return word2 | word1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,216 @@ |
|||
// <copyright file="Short4.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 16-bit signed integer values.
|
|||
/// </summary>
|
|||
public struct Short4 : IPackedPixel<ulong>, IEquatable<Short4> |
|||
{ |
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half the maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(127); |
|||
|
|||
/// <summary>
|
|||
/// The vector value used for rounding.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Round = new Vector4(.5F); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Short4"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">A vector containing the initial values for the components.</param>
|
|||
public Short4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Short4"/> struct.
|
|||
/// </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>
|
|||
public Short4(float x, float y, float z, float w) |
|||
{ |
|||
this.PackedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public ulong PackedValue { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Short4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Short4"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Short4"/> 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>
|
|||
public static bool operator ==(Short4 left, Short4 right) |
|||
{ |
|||
return left.PackedValue == right.PackedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Short4"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Short4"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Short4"/> 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>
|
|||
public static bool operator !=(Short4 left, Short4 right) |
|||
{ |
|||
return left.PackedValue != right.PackedValue; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4( |
|||
(short)(this.PackedValue & 0xFFFF), |
|||
(short)((this.PackedValue >> 0x10) & 0xFFFF), |
|||
(short)((this.PackedValue >> 0x20) & 0xFFFF), |
|||
(short)((this.PackedValue >> 0x30) & 0xFFFF)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
Vector4 vector = new Vector4(x, y, z, w) / 255; |
|||
vector *= 65534; |
|||
vector -= new Vector4(32767); |
|||
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
Vector4 vector = this.ToVector4(); |
|||
vector /= 65534; |
|||
vector *= 255; |
|||
vector += Half; |
|||
vector += Round; |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes); |
|||
|
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = (byte)(float)Math.Round(vector.X); |
|||
bytes[startIndex + 1] = (byte)(float)Math.Round(vector.Y); |
|||
bytes[startIndex + 2] = (byte)(float)Math.Round(vector.Z); |
|||
bytes[startIndex + 3] = (byte)(float)Math.Round(vector.W); |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a value that indicates whether the current instance is equal to a specified object.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object with which to make the comparison.</param>
|
|||
/// <returns>true if the current instance is equal to the specified object; false otherwise.</returns>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Short4) && this == (Short4)obj; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a value that indicates whether the current instance is equal to a specified object.
|
|||
/// </summary>
|
|||
/// <param name="other">The object with which to make the comparison.</param>
|
|||
/// <returns>true if the current instance is equal to the specified object; false otherwise.</returns>
|
|||
public bool Equals(Short4 other) |
|||
{ |
|||
return this == other; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the hash code for the current instance.
|
|||
/// </summary>
|
|||
/// <returns>Hash code for the instance.</returns>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.PackedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns a string representation of the current instance.
|
|||
/// </summary>
|
|||
/// <returns>String that represents the object.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return this.PackedValue.ToString("x16"); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the components into a <see cref="ulong"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="ulong"/> containing the packed values.</returns>
|
|||
private static ulong Pack(float x, float y, float z, float w) |
|||
{ |
|||
// Largest two byte positive number 0xFFFF >> 1;
|
|||
const float MaxPos = 0x7FFF; |
|||
|
|||
// Two's complement
|
|||
const float MinNeg = ~(int)MaxPos; |
|||
|
|||
// Clamp the value between min and max values
|
|||
ulong word4 = ((ulong)Math.Round(x.Clamp(MinNeg, MaxPos)) & 0xFFFF) << 0x00; |
|||
ulong word3 = ((ulong)Math.Round(y.Clamp(MinNeg, MaxPos)) & 0xFFFF) << 0x10; |
|||
ulong word2 = ((ulong)Math.Round(z.Clamp(MinNeg, MaxPos)) & 0xFFFF) << 0x20; |
|||
ulong word1 = ((ulong)Math.Round(w.Clamp(MinNeg, MaxPos)) & 0xFFFF) << 0x30; |
|||
|
|||
return word4 | word3 | word2 | word1; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,253 @@ |
|||
// <copyright file="Vector4BlendTransforms.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Transform algorithms that match the equations defined in the W3C Compositing and Blending Level 1 specification.
|
|||
/// <see href="https://www.w3.org/TR/compositing-1/"/>
|
|||
/// </summary>
|
|||
public class Vector4BlendTransforms |
|||
{ |
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001F; |
|||
|
|||
/// <summary>
|
|||
/// The blending formula simply selects the source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Normal(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(source.X, source.Y, source.Z, source.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Blends two vectors by multiplication.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Multiply(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 multiply = backdrop * source; |
|||
multiply.W = backdrop.W; |
|||
return multiply; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies the complements of the backdrop and source vector values, then complements the result.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Screen(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 subtract = backdrop + source - (backdrop * source); |
|||
subtract.W = backdrop.W; |
|||
return subtract; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the colors, depending on the source vector value.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 HardLight(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendOverlay(source.X, backdrop.X), BlendOverlay(source.Y, backdrop.Y), BlendOverlay(source.Z, backdrop.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the vectors, depending on the backdrop vector value.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Overlay(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendOverlay(backdrop.X, source.X), BlendOverlay(backdrop.Y, source.Y), BlendOverlay(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the minimum of the backdrop and source vectors.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Darken(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 result = Vector4.Min(backdrop, source); |
|||
result.W = backdrop.W; |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the max of the backdrop and source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Lighten(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 result = Vector4.Max(backdrop, source); |
|||
result.W = backdrop.W; |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the maximum or minimum of the vectors, depending on the source vector value.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 SoftLight(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendSoftLight(backdrop.X, source.X), BlendSoftLight(backdrop.Y, source.Y), BlendSoftLight(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Increases the backdrop vector to reflect the source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Dodge(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendDodge(backdrop.X, source.X), BlendDodge(backdrop.Y, source.Y), BlendDodge(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Decreases the backdrop vector to reflect the source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Burn(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendBurn(backdrop.X, source.X), BlendBurn(backdrop.Y, source.Y), BlendBurn(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Subtracts the minimum of the two constituent vectors from the maximum vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Difference(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 result = Vector4.Abs(backdrop - source); |
|||
result.W = backdrop.W; |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Produces an effect similar to that of the <see cref="Difference"/> mode but lower in magnitude.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Exclusion(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendExclusion(backdrop.X, source.X), BlendExclusion(backdrop.Y, source.Y), BlendExclusion(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the color component, depending on the component value.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendOverlay(float b, float s) |
|||
{ |
|||
return b <= .5F ? (2F * b * s) : (1F - (2F * (1F - b) * (1F - s))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens or lightens the backdrop component, depending on the source component value.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendSoftLight(float b, float s) |
|||
{ |
|||
return s <= .5F ? ((2F * b * s) + (b * b * (1F - (2F * s)))) : (float)((Math.Sqrt(b) * ((2F * s) - 1F)) + (2F * b * (1F - s))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Brightens the backdrop component to reflect the source component.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendDodge(float b, float s) |
|||
{ |
|||
return Math.Abs(s - 1F) < Epsilon ? s : Math.Min(b / (1F - s), 1F); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens the backdrop component to reflect the source component.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendBurn(float b, float s) |
|||
{ |
|||
return Math.Abs(s) < Epsilon ? s : Math.Max(1F - ((1F - b) / s), 0F); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens the backdrop component to reflect the source component.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendExclusion(float b, float s) |
|||
{ |
|||
return b + s - (2F * b * s); |
|||
} |
|||
} |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,23 @@ |
|||
// <copyright file="PngInterlaceMode.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Provides enumeration of available PNG interlace modes.
|
|||
/// </summary>
|
|||
public enum PngInterlaceMode : byte |
|||
{ |
|||
/// <summary>
|
|||
/// Non interlaced
|
|||
/// </summary>
|
|||
None, |
|||
|
|||
/// <summary>
|
|||
/// Adam 7 interlacing.
|
|||
/// </summary>
|
|||
Adam7 |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// <copyright file="ImageFrame.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Diagnostics; |
|||
|
|||
/// <summary>
|
|||
/// An optimized frame for the <see cref="Image"/> class.
|
|||
/// </summary>
|
|||
[DebuggerDisplay("ImageFrame: {Width}x{Height}")] |
|||
public class ImageFrame : ImageFrame<Color, uint> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageFrame"/> class.
|
|||
/// </summary>
|
|||
public ImageFrame() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageFrame"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">
|
|||
/// The image to create the frame from.
|
|||
/// </param>
|
|||
public ImageFrame(ImageBase<Color, uint> image) |
|||
: base(image) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override PixelAccessor<Color, uint> Lock() |
|||
{ |
|||
return new PixelAccessor(this); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
internal override ImageFrame<Color, uint> Clone() |
|||
{ |
|||
return new ImageFrame(this); |
|||
} |
|||
} |
|||
} |
|||
@ -1,69 +0,0 @@ |
|||
// <copyright file="Bootstrapper.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using System.Threading.Tasks; |
|||
|
|||
using Formats; |
|||
|
|||
/// <summary>
|
|||
/// Provides initialization code which allows extending the library.
|
|||
/// </summary>
|
|||
public class Bootstrapper |
|||
{ |
|||
/// <summary>
|
|||
/// A new instance Initializes a new instance of the <see cref="Bootstrapper"/> class.
|
|||
/// with lazy initialization.
|
|||
/// </summary>
|
|||
private static readonly Lazy<Bootstrapper> Lazy = new Lazy<Bootstrapper>(() => new Bootstrapper()); |
|||
|
|||
/// <summary>
|
|||
/// The default list of supported <see cref="IImageFormat"/>
|
|||
/// </summary>
|
|||
private readonly List<IImageFormat> imageFormats; |
|||
|
|||
/// <summary>
|
|||
/// Prevents a default instance of the <see cref="Bootstrapper"/> class from being created.
|
|||
/// </summary>
|
|||
private Bootstrapper() |
|||
{ |
|||
this.imageFormats = new List<IImageFormat> |
|||
{ |
|||
new BmpFormat(), |
|||
new JpegFormat(), |
|||
new PngFormat(), |
|||
new GifFormat() |
|||
}; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the current bootstrapper instance.
|
|||
/// </summary>
|
|||
public static Bootstrapper Instance => Lazy.Value; |
|||
|
|||
/// <summary>
|
|||
/// Gets the collection of supported <see cref="IImageFormat"/>
|
|||
/// </summary>
|
|||
public IReadOnlyCollection<IImageFormat> ImageFormats => new ReadOnlyCollection<IImageFormat>(this.imageFormats); |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the global parallel options for processing tasks in parallel.
|
|||
/// </summary>
|
|||
public ParallelOptions ParallelOptions { get; set; } = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; |
|||
|
|||
/// <summary>
|
|||
/// Adds a new <see cref="IImageFormat"/> to the collection of supported image formats.
|
|||
/// </summary>
|
|||
/// <param name="format">The new format to add.</param>
|
|||
public void AddImageFormat(IImageFormat format) |
|||
{ |
|||
this.imageFormats.Add(format); |
|||
} |
|||
} |
|||
} |
|||
@ -1,408 +0,0 @@ |
|||
// <copyright file="Color.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Globalization; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in red, green, blue, and alpha order.
|
|||
/// </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>
|
|||
public partial struct Color : IPackedPixel<uint>, IEquatable<Color> |
|||
{ |
|||
private const int RedShift = 0; |
|||
private const int GreenShift = 8; |
|||
private const int BlueShift = 16; |
|||
private const int AlphaShift = 24; |
|||
|
|||
/// <summary>
|
|||
/// The maximum byte value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 MaxBytes = new Vector4(255); |
|||
|
|||
/// <summary>
|
|||
/// The half vector value.
|
|||
/// </summary>
|
|||
private static readonly Vector4 Half = new Vector4(0.5f); |
|||
|
|||
/// <summary>
|
|||
/// The packed value.
|
|||
/// </summary>
|
|||
private uint packedValue; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> 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>
|
|||
public Color(byte r, byte g, byte b, byte a = 255) |
|||
{ |
|||
this.packedValue = Pack(r, g, b, a); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="hex">
|
|||
/// The hexadecimal representation of the combined color components arranged
|
|||
/// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax.
|
|||
/// </param>
|
|||
public Color(string hex) |
|||
{ |
|||
Guard.NotNullOrEmpty(hex, nameof(hex)); |
|||
|
|||
hex = ToRgbaHex(hex); |
|||
|
|||
if (hex == null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out this.packedValue)) |
|||
{ |
|||
throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex)); |
|||
} |
|||
|
|||
// Order parsed from hex string will be backwards, so reverse it.
|
|||
this.packedValue = Pack(this.A, this.B, this.G, this.R); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> 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>
|
|||
public Color(float r, float g, float b, float a = 1) |
|||
{ |
|||
this.packedValue = Pack(r, g, b, a); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// The vector containing the components for the packed vector.
|
|||
/// </param>
|
|||
public Color(Vector3 vector) |
|||
{ |
|||
this.packedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="vector">
|
|||
/// The vector containing the components for the packed vector.
|
|||
/// </param>
|
|||
public Color(Vector4 vector) |
|||
{ |
|||
this.packedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the red component.
|
|||
/// </summary>
|
|||
public byte R |
|||
{ |
|||
get |
|||
{ |
|||
return (byte)(this.packedValue >> RedShift); |
|||
} |
|||
|
|||
set |
|||
{ |
|||
this.packedValue = this.packedValue & 0xFFFFFF00 | (uint)value << RedShift; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the green component.
|
|||
/// </summary>
|
|||
public byte G |
|||
{ |
|||
get |
|||
{ |
|||
return (byte)(this.packedValue >> GreenShift); |
|||
} |
|||
|
|||
set |
|||
{ |
|||
this.packedValue = this.packedValue & 0xFFFF00FF | (uint)value << GreenShift; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the blue component.
|
|||
/// </summary>
|
|||
public byte B |
|||
{ |
|||
get |
|||
{ |
|||
return (byte)(this.packedValue >> BlueShift); |
|||
} |
|||
|
|||
set |
|||
{ |
|||
this.packedValue = this.packedValue & 0xFF00FFFF | (uint)value << BlueShift; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the alpha component.
|
|||
/// </summary>
|
|||
public byte A |
|||
{ |
|||
get |
|||
{ |
|||
return (byte)(this.packedValue >> AlphaShift); |
|||
} |
|||
|
|||
set |
|||
{ |
|||
this.packedValue = this.packedValue & 0x00FFFFFF | (uint)value << AlphaShift; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public uint PackedValue |
|||
{ |
|||
get |
|||
{ |
|||
return this.packedValue; |
|||
} |
|||
|
|||
set |
|||
{ |
|||
this.packedValue = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Color"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Color"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Color"/> 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>
|
|||
public static bool operator ==(Color left, Color right) |
|||
{ |
|||
return left.packedValue == right.packedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Color"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The <see cref="Color"/> on the left side of the operand.</param>
|
|||
/// <param name="right">The <see cref="Color"/> 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>
|
|||
public static bool operator !=(Color left, Color right) |
|||
{ |
|||
return left.packedValue != right.packedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a new instance of the <see cref="Color"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="hex">
|
|||
/// The hexadecimal representation of the combined color components arranged
|
|||
/// in rgb, rgba, rrggbb, or rrggbbaa format to match web syntax.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static Color FromHex(string hex) |
|||
{ |
|||
return new Color(hex); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void PackFromBytes(byte x, byte y, byte z, byte w) |
|||
{ |
|||
this.packedValue = Pack(x, y, z, w); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the value of this instance to a hexadecimal string.
|
|||
/// </summary>
|
|||
/// <returns>A hexadecimal string representation of the value.</returns>
|
|||
public string ToHex() |
|||
{ |
|||
uint hexOrder = Pack(this.A, this.B, this.G, this.R); |
|||
return hexOrder.ToString("X8"); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder) |
|||
{ |
|||
switch (componentOrder) |
|||
{ |
|||
case ComponentOrder.ZYX: |
|||
bytes[startIndex] = this.B; |
|||
bytes[startIndex + 1] = this.G; |
|||
bytes[startIndex + 2] = this.R; |
|||
break; |
|||
case ComponentOrder.ZYXW: |
|||
bytes[startIndex] = this.B; |
|||
bytes[startIndex + 1] = this.G; |
|||
bytes[startIndex + 2] = this.R; |
|||
bytes[startIndex + 3] = this.A; |
|||
break; |
|||
case ComponentOrder.XYZ: |
|||
bytes[startIndex] = this.R; |
|||
bytes[startIndex + 1] = this.G; |
|||
bytes[startIndex + 2] = this.B; |
|||
break; |
|||
case ComponentOrder.XYZW: |
|||
bytes[startIndex] = this.R; |
|||
bytes[startIndex + 1] = this.G; |
|||
bytes[startIndex + 2] = this.B; |
|||
bytes[startIndex + 3] = this.A; |
|||
break; |
|||
default: |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
this.packedValue = Pack(ref vector); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return (obj is Color) && this.Equals((Color)obj); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Color other) |
|||
{ |
|||
return this.packedValue == other.packedValue; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a string representation of the packed vector.
|
|||
/// </summary>
|
|||
/// <returns>A string representation of the packed vector.</returns>
|
|||
public override string ToString() |
|||
{ |
|||
return this.ToVector4().ToString(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.packedValue.GetHashCode(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a <see cref="Vector4"/> into a uint.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the values to pack.</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(ref Vector4 vector) |
|||
{ |
|||
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One); |
|||
vector *= MaxBytes; |
|||
vector += Half; |
|||
return (uint)(((byte)vector.X << RedShift) |
|||
| ((byte)vector.Y << GreenShift) |
|||
| ((byte)vector.Z << BlueShift) |
|||
| (byte)vector.W << AlphaShift); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs a <see cref="Vector3"/> into a uint.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector containing the values to pack.</param>
|
|||
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
|
|||
private static uint Pack(ref Vector3 vector) |
|||
{ |
|||
Vector4 value = new Vector4(vector, 1); |
|||
return Pack(ref value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the four floats into a <see cref="uint"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="uint"/></returns>
|
|||
private static uint Pack(float x, float y, float z, float w) |
|||
{ |
|||
Vector4 value = new Vector4(x, y, z, w); |
|||
return Pack(ref value); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Packs the four floats into a <see cref="uint"/>.
|
|||
/// </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>
|
|||
/// <returns>The <see cref="uint"/></returns>
|
|||
private static uint Pack(byte x, byte y, byte z, byte w) |
|||
{ |
|||
return (uint)(x << RedShift | y << GreenShift | z << BlueShift | w << AlphaShift); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the specified hex value to an rrggbbaa hex value.
|
|||
/// </summary>
|
|||
/// <param name="hex">The hex value to convert.</param>
|
|||
/// <returns>
|
|||
/// A rrggbbaa hex value.
|
|||
/// </returns>
|
|||
private static string ToRgbaHex(string hex) |
|||
{ |
|||
hex = hex.StartsWith("#") ? hex.Substring(1) : hex; |
|||
|
|||
if (hex.Length == 8) |
|||
{ |
|||
return hex; |
|||
} |
|||
|
|||
if (hex.Length == 6) |
|||
{ |
|||
return hex + "FF"; |
|||
} |
|||
|
|||
if (hex.Length < 3 || hex.Length > 4) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
string red = char.ToString(hex[0]); |
|||
string green = char.ToString(hex[1]); |
|||
string blue = char.ToString(hex[2]); |
|||
string alpha = hex.Length == 3 ? "F" : char.ToString(hex[3]); |
|||
|
|||
return red + red + green + green + blue + blue + alpha + alpha; |
|||
} |
|||
} |
|||
} |
|||
@ -1,179 +0,0 @@ |
|||
// <copyright file="ColorConstants.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// Provides useful color definitions.
|
|||
/// </summary>
|
|||
public static class ColorConstants |
|||
{ |
|||
/// <summary>
|
|||
/// Provides a lazy, one time method of returning the colors.
|
|||
/// </summary>
|
|||
private static readonly Lazy<Color[]> SafeColors = new Lazy<Color[]>(GetWebSafeColors); |
|||
|
|||
/// <summary>
|
|||
/// Gets a collection of named, web safe, colors as defined in the CSS Color Module Level 4.
|
|||
/// </summary>
|
|||
public static Color[] WebSafeColors => SafeColors.Value; |
|||
|
|||
/// <summary>
|
|||
/// Returns an array of web safe colors.
|
|||
/// </summary>
|
|||
/// <returns></returns>
|
|||
private static Color[] GetWebSafeColors() |
|||
{ |
|||
return new List<Color> |
|||
{ |
|||
Color.AliceBlue, |
|||
Color.AntiqueWhite, |
|||
Color.Aqua, |
|||
Color.Aquamarine, |
|||
Color.Azure, |
|||
Color.Beige, |
|||
Color.Bisque, |
|||
Color.Black, |
|||
Color.BlanchedAlmond, |
|||
Color.Blue, |
|||
Color.BlueViolet, |
|||
Color.Brown, |
|||
Color.BurlyWood, |
|||
Color.CadetBlue, |
|||
Color.Chartreuse, |
|||
Color.Chocolate, |
|||
Color.Coral, |
|||
Color.CornflowerBlue, |
|||
Color.Cornsilk, |
|||
Color.Crimson, |
|||
Color.Cyan, |
|||
Color.DarkBlue, |
|||
Color.DarkCyan, |
|||
Color.DarkGoldenrod, |
|||
Color.DarkGray, |
|||
Color.DarkGreen, |
|||
Color.DarkKhaki, |
|||
Color.DarkMagenta, |
|||
Color.DarkOliveGreen, |
|||
Color.DarkOrange, |
|||
Color.DarkOrchid, |
|||
Color.DarkRed, |
|||
Color.DarkSalmon, |
|||
Color.DarkSeaGreen, |
|||
Color.DarkSlateBlue, |
|||
Color.DarkSlateGray, |
|||
Color.DarkTurquoise, |
|||
Color.DarkViolet, |
|||
Color.DeepPink, |
|||
Color.DeepSkyBlue, |
|||
Color.DimGray, |
|||
Color.DodgerBlue, |
|||
Color.Firebrick, |
|||
Color.FloralWhite, |
|||
Color.ForestGreen, |
|||
Color.Fuchsia, |
|||
Color.Gainsboro, |
|||
Color.GhostWhite, |
|||
Color.Gold, |
|||
Color.Goldenrod, |
|||
Color.Gray, |
|||
Color.Green, |
|||
Color.GreenYellow, |
|||
Color.Honeydew, |
|||
Color.HotPink, |
|||
Color.IndianRed, |
|||
Color.Indigo, |
|||
Color.Ivory, |
|||
Color.Khaki, |
|||
Color.Lavender, |
|||
Color.LavenderBlush, |
|||
Color.LawnGreen, |
|||
Color.LemonChiffon, |
|||
Color.LightBlue, |
|||
Color.LightCoral, |
|||
Color.LightCyan, |
|||
Color.LightGoldenrodYellow, |
|||
Color.LightGray, |
|||
Color.LightGreen, |
|||
Color.LightPink, |
|||
Color.LightSalmon, |
|||
Color.LightSeaGreen, |
|||
Color.LightSkyBlue, |
|||
Color.LightSlateGray, |
|||
Color.LightSteelBlue, |
|||
Color.LightYellow, |
|||
Color.Lime, |
|||
Color.LimeGreen, |
|||
Color.Linen, |
|||
Color.Magenta, |
|||
Color.Maroon, |
|||
Color.MediumAquamarine, |
|||
Color.MediumBlue, |
|||
Color.MediumOrchid, |
|||
Color.MediumPurple, |
|||
Color.MediumSeaGreen, |
|||
Color.MediumSlateBlue, |
|||
Color.MediumSpringGreen, |
|||
Color.MediumTurquoise, |
|||
Color.MediumVioletRed, |
|||
Color.MidnightBlue, |
|||
Color.MintCream, |
|||
Color.MistyRose, |
|||
Color.Moccasin, |
|||
Color.NavajoWhite, |
|||
Color.Navy, |
|||
Color.OldLace, |
|||
Color.Olive, |
|||
Color.OliveDrab, |
|||
Color.Orange, |
|||
Color.OrangeRed, |
|||
Color.Orchid, |
|||
Color.PaleGoldenrod, |
|||
Color.PaleGreen, |
|||
Color.PaleTurquoise, |
|||
Color.PaleVioletRed, |
|||
Color.PapayaWhip, |
|||
Color.PeachPuff, |
|||
Color.Peru, |
|||
Color.Pink, |
|||
Color.Plum, |
|||
Color.PowderBlue, |
|||
Color.Purple, |
|||
Color.RebeccaPurple, |
|||
Color.Red, |
|||
Color.RosyBrown, |
|||
Color.RoyalBlue, |
|||
Color.SaddleBrown, |
|||
Color.Salmon, |
|||
Color.SandyBrown, |
|||
Color.SeaGreen, |
|||
Color.SeaShell, |
|||
Color.Sienna, |
|||
Color.Silver, |
|||
Color.SkyBlue, |
|||
Color.SlateBlue, |
|||
Color.SlateGray, |
|||
Color.Snow, |
|||
Color.SpringGreen, |
|||
Color.SteelBlue, |
|||
Color.Tan, |
|||
Color.Teal, |
|||
Color.Thistle, |
|||
Color.Tomato, |
|||
Color.Transparent, |
|||
Color.Turquoise, |
|||
Color.Violet, |
|||
Color.Wheat, |
|||
Color.White, |
|||
Color.WhiteSmoke, |
|||
Color.Yellow, |
|||
Color.YellowGreen |
|||
}.ToArray(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,728 +0,0 @@ |
|||
// <copyright file="ColorDefinitions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in red, green, blue, and alpha order.
|
|||
/// </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>
|
|||
public partial struct Color |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0F8FF.
|
|||
/// </summary>
|
|||
public static readonly Color AliceBlue = new Color(240, 248, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAEBD7.
|
|||
/// </summary>
|
|||
public static readonly Color AntiqueWhite = new Color(250, 235, 215, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FFFF.
|
|||
/// </summary>
|
|||
public static readonly Color Aqua = new Color(0, 255, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7FFFD4.
|
|||
/// </summary>
|
|||
public static readonly Color Aquamarine = new Color(127, 255, 212, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0FFFF.
|
|||
/// </summary>
|
|||
public static readonly Color Azure = new Color(240, 255, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5F5DC.
|
|||
/// </summary>
|
|||
public static readonly Color Beige = new Color(245, 245, 220, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4C4.
|
|||
/// </summary>
|
|||
public static readonly Color Bisque = new Color(255, 228, 196, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #000000.
|
|||
/// </summary>
|
|||
public static readonly Color Black = new Color(0, 0, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFEBCD.
|
|||
/// </summary>
|
|||
public static readonly Color BlanchedAlmond = new Color(255, 235, 205, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0000FF.
|
|||
/// </summary>
|
|||
public static readonly Color Blue = new Color(0, 0, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8A2BE2.
|
|||
/// </summary>
|
|||
public static readonly Color BlueViolet = new Color(138, 43, 226, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A52A2A.
|
|||
/// </summary>
|
|||
public static readonly Color Brown = new Color(165, 42, 42, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DEB887.
|
|||
/// </summary>
|
|||
public static readonly Color BurlyWood = new Color(222, 184, 135, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #5F9EA0.
|
|||
/// </summary>
|
|||
public static readonly Color CadetBlue = new Color(95, 158, 160, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7FFF00.
|
|||
/// </summary>
|
|||
public static readonly Color Chartreuse = new Color(127, 255, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D2691E.
|
|||
/// </summary>
|
|||
public static readonly Color Chocolate = new Color(210, 105, 30, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF7F50.
|
|||
/// </summary>
|
|||
public static readonly Color Coral = new Color(255, 127, 80, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6495ED.
|
|||
/// </summary>
|
|||
public static readonly Color CornflowerBlue = new Color(100, 149, 237, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF8DC.
|
|||
/// </summary>
|
|||
public static readonly Color Cornsilk = new Color(255, 248, 220, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DC143C.
|
|||
/// </summary>
|
|||
public static readonly Color Crimson = new Color(220, 20, 60, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FFFF.
|
|||
/// </summary>
|
|||
public static readonly Color Cyan = new Color(0, 255, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00008B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkBlue = new Color(0, 0, 139, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008B8B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkCyan = new Color(0, 139, 139, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B8860B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkGoldenrod = new Color(184, 134, 11, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A9A9A9.
|
|||
/// </summary>
|
|||
public static readonly Color DarkGray = new Color(169, 169, 169, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #006400.
|
|||
/// </summary>
|
|||
public static readonly Color DarkGreen = new Color(0, 100, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BDB76B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkKhaki = new Color(189, 183, 107, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B008B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkMagenta = new Color(139, 0, 139, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #556B2F.
|
|||
/// </summary>
|
|||
public static readonly Color DarkOliveGreen = new Color(85, 107, 47, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF8C00.
|
|||
/// </summary>
|
|||
public static readonly Color DarkOrange = new Color(255, 140, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9932CC.
|
|||
/// </summary>
|
|||
public static readonly Color DarkOrchid = new Color(153, 50, 204, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B0000.
|
|||
/// </summary>
|
|||
public static readonly Color DarkRed = new Color(139, 0, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E9967A.
|
|||
/// </summary>
|
|||
public static readonly Color DarkSalmon = new Color(233, 150, 122, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8FBC8B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkSeaGreen = new Color(143, 188, 139, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #483D8B.
|
|||
/// </summary>
|
|||
public static readonly Color DarkSlateBlue = new Color(72, 61, 139, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #2F4F4F.
|
|||
/// </summary>
|
|||
public static readonly Color DarkSlateGray = new Color(47, 79, 79, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00CED1.
|
|||
/// </summary>
|
|||
public static readonly Color DarkTurquoise = new Color(0, 206, 209, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9400D3.
|
|||
/// </summary>
|
|||
public static readonly Color DarkViolet = new Color(148, 0, 211, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF1493.
|
|||
/// </summary>
|
|||
public static readonly Color DeepPink = new Color(255, 20, 147, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00BFFF.
|
|||
/// </summary>
|
|||
public static readonly Color DeepSkyBlue = new Color(0, 191, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #696969.
|
|||
/// </summary>
|
|||
public static readonly Color DimGray = new Color(105, 105, 105, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #1E90FF.
|
|||
/// </summary>
|
|||
public static readonly Color DodgerBlue = new Color(30, 144, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B22222.
|
|||
/// </summary>
|
|||
public static readonly Color Firebrick = new Color(178, 34, 34, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFAF0.
|
|||
/// </summary>
|
|||
public static readonly Color FloralWhite = new Color(255, 250, 240, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #228B22.
|
|||
/// </summary>
|
|||
public static readonly Color ForestGreen = new Color(34, 139, 34, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF00FF.
|
|||
/// </summary>
|
|||
public static readonly Color Fuchsia = new Color(255, 0, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DCDCDC.
|
|||
/// </summary>
|
|||
public static readonly Color Gainsboro = new Color(220, 220, 220, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F8F8FF.
|
|||
/// </summary>
|
|||
public static readonly Color GhostWhite = new Color(248, 248, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFD700.
|
|||
/// </summary>
|
|||
public static readonly Color Gold = new Color(255, 215, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DAA520.
|
|||
/// </summary>
|
|||
public static readonly Color Goldenrod = new Color(218, 165, 32, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #808080.
|
|||
/// </summary>
|
|||
public static readonly Color Gray = new Color(128, 128, 128, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008000.
|
|||
/// </summary>
|
|||
public static readonly Color Green = new Color(0, 128, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #ADFF2F.
|
|||
/// </summary>
|
|||
public static readonly Color GreenYellow = new Color(173, 255, 47, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0FFF0.
|
|||
/// </summary>
|
|||
public static readonly Color Honeydew = new Color(240, 255, 240, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF69B4.
|
|||
/// </summary>
|
|||
public static readonly Color HotPink = new Color(255, 105, 180, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #CD5C5C.
|
|||
/// </summary>
|
|||
public static readonly Color IndianRed = new Color(205, 92, 92, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4B0082.
|
|||
/// </summary>
|
|||
public static readonly Color Indigo = new Color(75, 0, 130, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFF0.
|
|||
/// </summary>
|
|||
public static readonly Color Ivory = new Color(255, 255, 240, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F0E68C.
|
|||
/// </summary>
|
|||
public static readonly Color Khaki = new Color(240, 230, 140, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E6E6FA.
|
|||
/// </summary>
|
|||
public static readonly Color Lavender = new Color(230, 230, 250, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF0F5.
|
|||
/// </summary>
|
|||
public static readonly Color LavenderBlush = new Color(255, 240, 245, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7CFC00.
|
|||
/// </summary>
|
|||
public static readonly Color LawnGreen = new Color(124, 252, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFACD.
|
|||
/// </summary>
|
|||
public static readonly Color LemonChiffon = new Color(255, 250, 205, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #ADD8E6.
|
|||
/// </summary>
|
|||
public static readonly Color LightBlue = new Color(173, 216, 230, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F08080.
|
|||
/// </summary>
|
|||
public static readonly Color LightCoral = new Color(240, 128, 128, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #E0FFFF.
|
|||
/// </summary>
|
|||
public static readonly Color LightCyan = new Color(224, 255, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAFAD2.
|
|||
/// </summary>
|
|||
public static readonly Color LightGoldenrodYellow = new Color(250, 250, 210, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D3D3D3.
|
|||
/// </summary>
|
|||
public static readonly Color LightGray = new Color(211, 211, 211, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #90EE90.
|
|||
/// </summary>
|
|||
public static readonly Color LightGreen = new Color(144, 238, 144, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFB6C1.
|
|||
/// </summary>
|
|||
public static readonly Color LightPink = new Color(255, 182, 193, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFA07A.
|
|||
/// </summary>
|
|||
public static readonly Color LightSalmon = new Color(255, 160, 122, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #20B2AA.
|
|||
/// </summary>
|
|||
public static readonly Color LightSeaGreen = new Color(32, 178, 170, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #87CEFA.
|
|||
/// </summary>
|
|||
public static readonly Color LightSkyBlue = new Color(135, 206, 250, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #778899.
|
|||
/// </summary>
|
|||
public static readonly Color LightSlateGray = new Color(119, 136, 153, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B0C4DE.
|
|||
/// </summary>
|
|||
public static readonly Color LightSteelBlue = new Color(176, 196, 222, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFE0.
|
|||
/// </summary>
|
|||
public static readonly Color LightYellow = new Color(255, 255, 224, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FF00.
|
|||
/// </summary>
|
|||
public static readonly Color Lime = new Color(0, 255, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #32CD32.
|
|||
/// </summary>
|
|||
public static readonly Color LimeGreen = new Color(50, 205, 50, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FAF0E6.
|
|||
/// </summary>
|
|||
public static readonly Color Linen = new Color(250, 240, 230, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF00FF.
|
|||
/// </summary>
|
|||
public static readonly Color Magenta = new Color(255, 0, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #800000.
|
|||
/// </summary>
|
|||
public static readonly Color Maroon = new Color(128, 0, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #66CDAA.
|
|||
/// </summary>
|
|||
public static readonly Color MediumAquamarine = new Color(102, 205, 170, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0000CD.
|
|||
/// </summary>
|
|||
public static readonly Color MediumBlue = new Color(0, 0, 205, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BA55D3.
|
|||
/// </summary>
|
|||
public static readonly Color MediumOrchid = new Color(186, 85, 211, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9370DB.
|
|||
/// </summary>
|
|||
public static readonly Color MediumPurple = new Color(147, 112, 219, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #3CB371.
|
|||
/// </summary>
|
|||
public static readonly Color MediumSeaGreen = new Color(60, 179, 113, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #7B68EE.
|
|||
/// </summary>
|
|||
public static readonly Color MediumSlateBlue = new Color(123, 104, 238, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FA9A.
|
|||
/// </summary>
|
|||
public static readonly Color MediumSpringGreen = new Color(0, 250, 154, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #48D1CC.
|
|||
/// </summary>
|
|||
public static readonly Color MediumTurquoise = new Color(72, 209, 204, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #C71585.
|
|||
/// </summary>
|
|||
public static readonly Color MediumVioletRed = new Color(199, 21, 133, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #191970.
|
|||
/// </summary>
|
|||
public static readonly Color MidnightBlue = new Color(25, 25, 112, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5FFFA.
|
|||
/// </summary>
|
|||
public static readonly Color MintCream = new Color(245, 255, 250, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4E1.
|
|||
/// </summary>
|
|||
public static readonly Color MistyRose = new Color(255, 228, 225, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFE4B5.
|
|||
/// </summary>
|
|||
public static readonly Color Moccasin = new Color(255, 228, 181, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFDEAD.
|
|||
/// </summary>
|
|||
public static readonly Color NavajoWhite = new Color(255, 222, 173, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #000080.
|
|||
/// </summary>
|
|||
public static readonly Color Navy = new Color(0, 0, 128, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FDF5E6.
|
|||
/// </summary>
|
|||
public static readonly Color OldLace = new Color(253, 245, 230, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #808000.
|
|||
/// </summary>
|
|||
public static readonly Color Olive = new Color(128, 128, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6B8E23.
|
|||
/// </summary>
|
|||
public static readonly Color OliveDrab = new Color(107, 142, 35, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFA500.
|
|||
/// </summary>
|
|||
public static readonly Color Orange = new Color(255, 165, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF4500.
|
|||
/// </summary>
|
|||
public static readonly Color OrangeRed = new Color(255, 69, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DA70D6.
|
|||
/// </summary>
|
|||
public static readonly Color Orchid = new Color(218, 112, 214, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #EEE8AA.
|
|||
/// </summary>
|
|||
public static readonly Color PaleGoldenrod = new Color(238, 232, 170, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #98FB98.
|
|||
/// </summary>
|
|||
public static readonly Color PaleGreen = new Color(152, 251, 152, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #AFEEEE.
|
|||
/// </summary>
|
|||
public static readonly Color PaleTurquoise = new Color(175, 238, 238, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DB7093.
|
|||
/// </summary>
|
|||
public static readonly Color PaleVioletRed = new Color(219, 112, 147, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFEFD5.
|
|||
/// </summary>
|
|||
public static readonly Color PapayaWhip = new Color(255, 239, 213, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFDAB9.
|
|||
/// </summary>
|
|||
public static readonly Color PeachPuff = new Color(255, 218, 185, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #CD853F.
|
|||
/// </summary>
|
|||
public static readonly Color Peru = new Color(205, 133, 63, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFC0CB.
|
|||
/// </summary>
|
|||
public static readonly Color Pink = new Color(255, 192, 203, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #DDA0DD.
|
|||
/// </summary>
|
|||
public static readonly Color Plum = new Color(221, 160, 221, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #B0E0E6.
|
|||
/// </summary>
|
|||
public static readonly Color PowderBlue = new Color(176, 224, 230, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #800080.
|
|||
/// </summary>
|
|||
public static readonly Color Purple = new Color(128, 0, 128, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #0.
|
|||
/// </summary>
|
|||
public static readonly Color RebeccaPurple = new Color(102, 51, 153, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF0000.
|
|||
/// </summary>
|
|||
public static readonly Color Red = new Color(255, 0, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #BC8F8F.
|
|||
/// </summary>
|
|||
public static readonly Color RosyBrown = new Color(188, 143, 143, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4169E1.
|
|||
/// </summary>
|
|||
public static readonly Color RoyalBlue = new Color(65, 105, 225, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #8B4513.
|
|||
/// </summary>
|
|||
public static readonly Color SaddleBrown = new Color(139, 69, 19, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FA8072.
|
|||
/// </summary>
|
|||
public static readonly Color Salmon = new Color(250, 128, 114, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F4A460.
|
|||
/// </summary>
|
|||
public static readonly Color SandyBrown = new Color(244, 164, 96, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #2E8B57.
|
|||
/// </summary>
|
|||
public static readonly Color SeaGreen = new Color(46, 139, 87, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFF5EE.
|
|||
/// </summary>
|
|||
public static readonly Color SeaShell = new Color(255, 245, 238, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #A0522D.
|
|||
/// </summary>
|
|||
public static readonly Color Sienna = new Color(160, 82, 45, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #C0C0C0.
|
|||
/// </summary>
|
|||
public static readonly Color Silver = new Color(192, 192, 192, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #87CEEB.
|
|||
/// </summary>
|
|||
public static readonly Color SkyBlue = new Color(135, 206, 235, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #6A5ACD.
|
|||
/// </summary>
|
|||
public static readonly Color SlateBlue = new Color(106, 90, 205, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #708090.
|
|||
/// </summary>
|
|||
public static readonly Color SlateGray = new Color(112, 128, 144, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFAFA.
|
|||
/// </summary>
|
|||
public static readonly Color Snow = new Color(255, 250, 250, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #00FF7F.
|
|||
/// </summary>
|
|||
public static readonly Color SpringGreen = new Color(0, 255, 127, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #4682B4.
|
|||
/// </summary>
|
|||
public static readonly Color SteelBlue = new Color(70, 130, 180, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D2B48C.
|
|||
/// </summary>
|
|||
public static readonly Color Tan = new Color(210, 180, 140, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #008080.
|
|||
/// </summary>
|
|||
public static readonly Color Teal = new Color(0, 128, 128, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #D8BFD8.
|
|||
/// </summary>
|
|||
public static readonly Color Thistle = new Color(216, 191, 216, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FF6347.
|
|||
/// </summary>
|
|||
public static readonly Color Tomato = new Color(255, 99, 71, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFFF.
|
|||
/// </summary>
|
|||
public static readonly Color Transparent = new Color(255, 255, 255, 0); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #40E0D0.
|
|||
/// </summary>
|
|||
public static readonly Color Turquoise = new Color(64, 224, 208, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #EE82EE.
|
|||
/// </summary>
|
|||
public static readonly Color Violet = new Color(238, 130, 238, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5DEB3.
|
|||
/// </summary>
|
|||
public static readonly Color Wheat = new Color(245, 222, 179, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFFFF.
|
|||
/// </summary>
|
|||
public static readonly Color White = new Color(255, 255, 255, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #F5F5F5.
|
|||
/// </summary>
|
|||
public static readonly Color WhiteSmoke = new Color(245, 245, 245, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #FFFF00.
|
|||
/// </summary>
|
|||
public static readonly Color Yellow = new Color(255, 255, 0, 255); |
|||
|
|||
/// <summary>
|
|||
/// Represents a <see cref="Color"/> matching the W3C definition that has an hex value of #9ACD32.
|
|||
/// </summary>
|
|||
public static readonly Color YellowGreen = new Color(154, 205, 50, 255); |
|||
} |
|||
} |
|||
@ -1,74 +0,0 @@ |
|||
// <copyright file="ColorTransforms.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in red, green, blue, and alpha order.
|
|||
/// </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>
|
|||
public partial struct Color |
|||
{ |
|||
/// <summary>
|
|||
/// Blends two colors by multiplication.
|
|||
/// <remarks>
|
|||
/// The source color is multiplied by the destination color and replaces the destination.
|
|||
/// The resultant color is always at least as dark as either the source or destination color.
|
|||
/// Multiplying any color with black results in black. Multiplying any color with white preserves the
|
|||
/// original color.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <param name="destination">The destination color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static Color Multiply(Color source, Color destination) |
|||
{ |
|||
if (destination == Color.Black) |
|||
{ |
|||
return Color.Black; |
|||
} |
|||
|
|||
if (destination == Color.White) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
// TODO: This will use less memory than using Vector4
|
|||
// but we should test speed vs memory to see which is best balance.
|
|||
byte r = (byte)(source.R * destination.R).Clamp(0, 255); |
|||
byte g = (byte)(source.G * destination.G).Clamp(0, 255); |
|||
byte b = (byte)(source.B * destination.B).Clamp(0, 255); |
|||
byte a = (byte)(source.A * destination.A).Clamp(0, 255); |
|||
|
|||
return new Color(r, g, b, a); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Linearly interpolates from one color to another based on the given weighting.
|
|||
/// </summary>
|
|||
/// <param name="from">The first color value.</param>
|
|||
/// <param name="to">The second color value.</param>
|
|||
/// <param name="amount">
|
|||
/// A value between 0 and 1 indicating the weight of the second source vector.
|
|||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="Color"/>
|
|||
/// </returns>
|
|||
public static Color Lerp(Color from, Color to, float amount) |
|||
{ |
|||
return new Color(Vector4.Lerp(from.ToVector4(), to.ToVector4(), amount)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,292 +0,0 @@ |
|||
// <copyright file="ColorspaceTransforms.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Packed vector type containing four 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in red, green, blue, and alpha order.
|
|||
/// </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>
|
|||
public partial struct Color |
|||
{ |
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001F; |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="Bgra32"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="Color"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Bgra32"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(Bgra32 color) |
|||
{ |
|||
return new Color(color.R, color.G, color.B, color.A); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Cmyk"/> to a
|
|||
/// <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="cmykColor">The instance of <see cref="Cmyk"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(Cmyk cmykColor) |
|||
{ |
|||
float r = (1 - cmykColor.C) * (1 - cmykColor.K); |
|||
float g = (1 - cmykColor.M) * (1 - cmykColor.K); |
|||
float b = (1 - cmykColor.Y) * (1 - cmykColor.K); |
|||
return new Color(r, g, b, 1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="YCbCr"/> to a
|
|||
/// <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="YCbCr"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(YCbCr color) |
|||
{ |
|||
byte y = color.Y; |
|||
int cb = color.Cb - 128; |
|||
int cr = color.Cr - 128; |
|||
|
|||
byte r = (byte)(y + (1.402F * cr)).Clamp(0, 255); |
|||
byte g = (byte)(y - (0.34414F * cb) - (0.71414F * cr)).Clamp(0, 255); |
|||
byte b = (byte)(y + (1.772F * cb)).Clamp(0, 255); |
|||
|
|||
return new Color(r, g, b); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="CieXyz"/> to a
|
|||
/// <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="CieXyz"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(CieXyz color) |
|||
{ |
|||
float x = color.X / 100F; |
|||
float y = color.Y / 100F; |
|||
float z = color.Z / 100F; |
|||
|
|||
// Then XYZ to RGB (multiplication by 100 was done above already)
|
|||
float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F); |
|||
float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F); |
|||
float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F); |
|||
|
|||
Vector4 vector = new Vector4(r, g, b, 1).Compress(); |
|||
return new Color(vector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Hsv"/> to a
|
|||
/// <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="Hsv"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(Hsv color) |
|||
{ |
|||
float s = color.S; |
|||
float v = color.V; |
|||
|
|||
if (Math.Abs(s) < Epsilon) |
|||
{ |
|||
return new Color(v, v, v, 1); |
|||
} |
|||
|
|||
float h = (Math.Abs(color.H - 360) < Epsilon) ? 0 : color.H / 60; |
|||
int i = (int)Math.Truncate(h); |
|||
float f = h - i; |
|||
|
|||
float p = v * (1.0F - s); |
|||
float q = v * (1.0F - (s * f)); |
|||
float t = v * (1.0F - (s * (1.0F - f))); |
|||
|
|||
float r, g, b; |
|||
switch (i) |
|||
{ |
|||
case 0: |
|||
r = v; |
|||
g = t; |
|||
b = p; |
|||
break; |
|||
|
|||
case 1: |
|||
r = q; |
|||
g = v; |
|||
b = p; |
|||
break; |
|||
|
|||
case 2: |
|||
r = p; |
|||
g = v; |
|||
b = t; |
|||
break; |
|||
|
|||
case 3: |
|||
r = p; |
|||
g = q; |
|||
b = v; |
|||
break; |
|||
|
|||
case 4: |
|||
r = t; |
|||
g = p; |
|||
b = v; |
|||
break; |
|||
|
|||
default: |
|||
r = v; |
|||
g = p; |
|||
b = q; |
|||
break; |
|||
} |
|||
|
|||
return new Color(r, g, b, 1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Hsl"/> to a
|
|||
/// <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="Hsl"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(Hsl color) |
|||
{ |
|||
float rangedH = color.H / 360F; |
|||
float r = 0; |
|||
float g = 0; |
|||
float b = 0; |
|||
float s = color.S; |
|||
float l = color.L; |
|||
|
|||
if (Math.Abs(l) > Epsilon) |
|||
{ |
|||
if (Math.Abs(s) < Epsilon) |
|||
{ |
|||
r = g = b = l; |
|||
} |
|||
else |
|||
{ |
|||
float temp2 = (l < 0.5f) ? l * (1f + s) : l + s - (l * s); |
|||
float temp1 = (2f * l) - temp2; |
|||
|
|||
r = GetColorComponent(temp1, temp2, rangedH + 0.3333333F); |
|||
g = GetColorComponent(temp1, temp2, rangedH); |
|||
b = GetColorComponent(temp1, temp2, rangedH - 0.3333333F); |
|||
} |
|||
} |
|||
|
|||
return new Color(r, g, b, 1); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="CieLab"/> to a
|
|||
/// <see cref="Color"/>.
|
|||
/// </summary>
|
|||
/// <param name="cieLabColor">The instance of <see cref="CieLab"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Color"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Color(CieLab cieLabColor) |
|||
{ |
|||
// First convert back to XYZ...
|
|||
float y = (cieLabColor.L + 16F) / 116F; |
|||
float x = (cieLabColor.A / 500F) + y; |
|||
float z = y - (cieLabColor.B / 200F); |
|||
|
|||
float x3 = x * x * x; |
|||
float y3 = y * y * y; |
|||
float z3 = z * z * z; |
|||
|
|||
x = x3 > 0.008856F ? x3 : (x - 0.137931F) / 7.787F; |
|||
y = (cieLabColor.L > 7.999625F) ? y3 : (cieLabColor.L / 903.3F); |
|||
z = (z3 > 0.008856F) ? z3 : (z - 0.137931F) / 7.787F; |
|||
|
|||
x *= 0.95047F; |
|||
z *= 1.08883F; |
|||
|
|||
// Then XYZ to RGB (multiplication by 100 was done above already)
|
|||
float r = (x * 3.2406F) + (y * -1.5372F) + (z * -0.4986F); |
|||
float g = (x * -0.9689F) + (y * 1.8758F) + (z * 0.0415F); |
|||
float b = (x * 0.0557F) + (y * -0.2040F) + (z * 1.0570F); |
|||
|
|||
return new Color(new Vector4(r, g, b, 1F).Compress()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the color component from the given values.
|
|||
/// </summary>
|
|||
/// <param name="first">The first value.</param>
|
|||
/// <param name="second">The second value.</param>
|
|||
/// <param name="third">The third value.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float GetColorComponent(float first, float second, float third) |
|||
{ |
|||
third = MoveIntoRange(third); |
|||
if (third < 0.1666667F) |
|||
{ |
|||
return first + ((second - first) * 6.0f * third); |
|||
} |
|||
|
|||
if (third < 0.5) |
|||
{ |
|||
return second; |
|||
} |
|||
|
|||
if (third < 0.6666667F) |
|||
{ |
|||
return first + ((second - first) * (0.6666667F - third) * 6.0f); |
|||
} |
|||
|
|||
return first; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Moves the specific value within the acceptable range for
|
|||
/// conversion.
|
|||
/// <remarks>Used for converting <see cref="Hsl"/> colors to this type.</remarks>
|
|||
/// </summary>
|
|||
/// <param name="value">The value to shift.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float MoveIntoRange(float value) |
|||
{ |
|||
if (value < 0.0) |
|||
{ |
|||
value += 1.0f; |
|||
} |
|||
else if (value > 1.0) |
|||
{ |
|||
value -= 1.0f; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
} |
|||
} |
|||
@ -1,167 +0,0 @@ |
|||
// <copyright file="Bgra32.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents an BGRA (blue, green, red, alpha) color.
|
|||
/// </summary>
|
|||
public struct Bgra32 : IEquatable<Bgra32> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a 32 bit <see cref="Bgra32"/> that has B, G, R, and A values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Bgra32 Empty = default(Bgra32); |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private Vector4 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="b">The blue component of this <see cref="Bgra32"/>.</param>
|
|||
/// <param name="g">The green component of this <see cref="Bgra32"/>.</param>
|
|||
/// <param name="r">The red component of this <see cref="Bgra32"/>.</param>
|
|||
/// <param name="a">The alpha component of this <see cref="Bgra32"/>.</param>
|
|||
public Bgra32(byte b, byte g, byte r, byte a = 255) |
|||
: this() |
|||
{ |
|||
this.backingVector = Vector4.Clamp(new Vector4(b, g, r, a), Vector4.Zero, new Vector4(255)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the blue component of the color
|
|||
/// </summary>
|
|||
public byte B => (byte)this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the green component of the color
|
|||
/// </summary>
|
|||
public byte G => (byte)this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the red component of the color
|
|||
/// </summary>
|
|||
public byte R => (byte)this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets the alpha component of the color
|
|||
/// </summary>
|
|||
public byte A => (byte)this.backingVector.W; |
|||
|
|||
/// <summary>
|
|||
/// Gets the <see cref="Bgra32"/> integer representation of the color.
|
|||
/// </summary>
|
|||
public int Bgra => (this.R << 16) | (this.G << 8) | (this.B << 0) | (this.A << 24); |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Bgra32"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="Bgra32"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Color"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Bgra32"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Bgra32(Color color) |
|||
{ |
|||
return new Bgra32(color.B, color.G, color.R, color.A); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra32"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Bgra32"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Bgra32"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(Bgra32 left, Bgra32 right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Bgra32"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Bgra32"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Bgra32"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(Bgra32 left, Bgra32 right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Bgra32) |
|||
{ |
|||
Bgra32 color = (Bgra32)obj; |
|||
|
|||
return this.backingVector == color.backingVector; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Bgra32 [ Empty ]"; |
|||
} |
|||
|
|||
return $"Bgra32 [ B={this.B}, G={this.G}, R={this.R}, A={this.A} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Bgra32 other) |
|||
{ |
|||
return this.backingVector.Equals(other.backingVector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Bgra32"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private static int GetHashCode(Bgra32 color) => color.backingVector.GetHashCode(); |
|||
} |
|||
} |
|||
@ -1,192 +0,0 @@ |
|||
// <copyright file="CieLab.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents an CIE LAB 1976 color.
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lab_color_space"/>
|
|||
/// </summary>
|
|||
public struct CieLab : IEquatable<CieLab>, IAlmostEquatable<CieLab, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="CieLab"/> that has L, A, B values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieLab Empty = default(CieLab); |
|||
|
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001f; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieLab"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="l">The lightness dimension.</param>
|
|||
/// <param name="a">The a (green - magenta) component.</param>
|
|||
/// <param name="b">The b (blue - yellow) component.</param>
|
|||
public CieLab(float l, float a, float b) |
|||
: this() |
|||
{ |
|||
this.backingVector = Vector3.Clamp(new Vector3(l, a, b), new Vector3(0, -100, -100), new Vector3(100)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness dimension.
|
|||
/// <remarks>A value ranging between 0 (black), 100 (diffuse white) or higher (specular white).</remarks>
|
|||
/// </summary>
|
|||
public float L => this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the a color component.
|
|||
/// <remarks>Negative is green, positive magenta.</remarks>
|
|||
/// </summary>
|
|||
public float A => this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the b color component.
|
|||
/// <remarks>Negative is blue, positive is yellow</remarks>
|
|||
/// </summary>
|
|||
public float B => this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieLab"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="CieLab"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Color"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="CieLab"/>.
|
|||
/// </returns>
|
|||
public static implicit operator CieLab(Color color) |
|||
{ |
|||
// First convert to CIE XYZ
|
|||
Vector4 vector = color.ToVector4().Expand(); |
|||
float x = (vector.X * 0.4124F) + (vector.Y * 0.3576F) + (vector.Z * 0.1805F); |
|||
float y = (vector.X * 0.2126F) + (vector.Y * 0.7152F) + (vector.Z * 0.0722F); |
|||
float z = (vector.X * 0.0193F) + (vector.Y * 0.1192F) + (vector.Z * 0.9505F); |
|||
|
|||
// Now to LAB
|
|||
x /= 0.95047F; |
|||
//y /= 1F;
|
|||
z /= 1.08883F; |
|||
|
|||
x = x > 0.008856F ? (float)Math.Pow(x, 0.3333333F) : ((903.3F * x) + 16F) / 116F; |
|||
y = y > 0.008856F ? (float)Math.Pow(y, 0.3333333F) : ((903.3F * y) + 16F) / 116F; |
|||
z = z > 0.008856F ? (float)Math.Pow(z, 0.3333333F) : ((903.3F * z) + 16F) / 116F; |
|||
|
|||
float l = Math.Max(0, (116F * y) - 16F); |
|||
float a = 500F * (x - y); |
|||
float b = 200F * (y - z); |
|||
|
|||
return new CieLab(l, a, b); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLab"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieLab"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieLab"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(CieLab left, CieLab right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieLab"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieLab"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieLab"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(CieLab left, CieLab right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieLab [Empty]"; |
|||
} |
|||
|
|||
return $"CieLab [ L={this.L:#0.##}, A={this.A:#0.##}, B={this.B:#0.##}]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieLab) |
|||
{ |
|||
return this.Equals((CieLab)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(CieLab other) |
|||
{ |
|||
return this.AlmostEquals(other, Epsilon); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool AlmostEquals(CieLab other, float precision) |
|||
{ |
|||
Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X < precision |
|||
&& result.Y < precision |
|||
&& result.Z < precision; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="CieLab"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private static int GetHashCode(CieLab color) => color.backingVector.GetHashCode(); |
|||
} |
|||
} |
|||
@ -1,184 +0,0 @@ |
|||
// <copyright file="CieXyz.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents an CIE 1931 color
|
|||
/// <see href="https://en.wikipedia.org/wiki/CIE_1931_color_space"/>
|
|||
/// </summary>
|
|||
public struct CieXyz : IEquatable<CieXyz>, IAlmostEquatable<CieXyz, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="CieXyz"/> that has Y, Cb, and Cr values set to zero.
|
|||
/// </summary>
|
|||
public static readonly CieXyz Empty = default(CieXyz); |
|||
|
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001f; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="CieXyz"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="y">The y luminance component.</param>
|
|||
/// <param name="x">X is a mix (a linear combination) of cone response curves chosen to be nonnegative</param>
|
|||
/// <param name="z">Z is quasi-equal to blue stimulation, or the S cone of the human eye.</param>
|
|||
public CieXyz(float x, float y, float z) |
|||
: this() |
|||
{ |
|||
// Not clamping as documentation about this space seems to indicate "usual" ranges
|
|||
this.backingVector = new Vector3(x, y, z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the Y luminance component.
|
|||
/// <remarks>A value ranging between 380 and 780.</remarks>
|
|||
/// </summary>
|
|||
public float X => this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Cb chroma component.
|
|||
/// <remarks>A value ranging between 380 and 780.</remarks>
|
|||
/// </summary>
|
|||
public float Y => this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the Cr chroma component.
|
|||
/// <remarks>A value ranging between 380 and 780.</remarks>
|
|||
/// </summary>
|
|||
public float Z => this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="CieXyz"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="CieXyz"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Color"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="CieXyz"/>.
|
|||
/// </returns>
|
|||
public static implicit operator CieXyz(Color color) |
|||
{ |
|||
Vector4 vector = color.ToVector4().Expand(); |
|||
|
|||
float x = (vector.X * 0.4124F) + (vector.Y * 0.3576F) + (vector.Z * 0.1805F); |
|||
float y = (vector.X * 0.2126F) + (vector.Y * 0.7152F) + (vector.Z * 0.0722F); |
|||
float z = (vector.X * 0.0193F) + (vector.Y * 0.1192F) + (vector.Z * 0.9505F); |
|||
|
|||
x *= 100F; |
|||
y *= 100F; |
|||
z *= 100F; |
|||
|
|||
return new CieXyz(x, y, z); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieXyz"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieXyz"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieXyz"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(CieXyz left, CieXyz right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="CieXyz"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="CieXyz"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="CieXyz"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(CieXyz left, CieXyz right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "CieXyz [ Empty ]"; |
|||
} |
|||
|
|||
return $"CieXyz [ X={this.X:#0.##}, Y={this.Y:#0.##}, Z={this.Z:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is CieXyz) |
|||
{ |
|||
return this.Equals((CieXyz)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(CieXyz other) |
|||
{ |
|||
return this.AlmostEquals(other, Epsilon); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool AlmostEquals(CieXyz other, float precision) |
|||
{ |
|||
Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X < precision |
|||
&& result.Y < precision |
|||
&& result.Z < precision; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Hsv"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private static int GetHashCode(CieXyz color) => color.backingVector.GetHashCode(); |
|||
} |
|||
} |
|||
@ -1,195 +0,0 @@ |
|||
// <copyright file="Cmyk.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents an CMYK (cyan, magenta, yellow, keyline) color.
|
|||
/// </summary>
|
|||
public struct Cmyk : IEquatable<Cmyk>, IAlmostEquatable<Cmyk, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Cmyk"/> that has C, M, Y, and K values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Cmyk Empty = default(Cmyk); |
|||
|
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001f; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private Vector4 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Cmyk"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="c">The cyan component.</param>
|
|||
/// <param name="m">The magenta component.</param>
|
|||
/// <param name="y">The yellow component.</param>
|
|||
/// <param name="k">The keyline black component.</param>
|
|||
public Cmyk(float c, float m, float y, float k) |
|||
: this() |
|||
{ |
|||
this.backingVector = Vector4.Clamp(new Vector4(c, m, y, k), Vector4.Zero, Vector4.One); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the cyan color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float C => this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the magenta color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float M => this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the yellow color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float Y => this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets the keyline black color component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float K => this.backingVector.W; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Cmyk"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="Cmyk"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Bgra32"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Cmyk"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Cmyk(Color color) |
|||
{ |
|||
float c = 1f - (color.R / 255F); |
|||
float m = 1f - (color.G / 255F); |
|||
float y = 1f - (color.B / 255F); |
|||
|
|||
float k = Math.Min(c, Math.Min(m, y)); |
|||
|
|||
if (Math.Abs(k - 1.0f) <= Epsilon) |
|||
{ |
|||
return new Cmyk(0, 0, 0, 1); |
|||
} |
|||
|
|||
c = (c - k) / (1 - k); |
|||
m = (m - k) / (1 - k); |
|||
y = (y - k) / (1 - k); |
|||
|
|||
return new Cmyk(c, m, y, k); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Cmyk"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Cmyk"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Cmyk"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(Cmyk left, Cmyk right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Cmyk"/> objects for inequality
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Cmyk"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Cmyk"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(Cmyk left, Cmyk right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Cmyk [Empty]"; |
|||
} |
|||
|
|||
return $"Cmyk [ C={this.C:#0.##}, M={this.M:#0.##}, Y={this.Y:#0.##}, K={this.K:#0.##}]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Cmyk) |
|||
{ |
|||
return this.Equals((Cmyk)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Cmyk other) |
|||
{ |
|||
return this.AlmostEquals(other, Epsilon); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool AlmostEquals(Cmyk other, float precision) |
|||
{ |
|||
Vector4 result = Vector4.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X < precision |
|||
&& result.Y < precision |
|||
&& result.Z < precision |
|||
&& result.W < precision; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Cmyk"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private static int GetHashCode(Cmyk color) => color.backingVector.GetHashCode(); |
|||
} |
|||
} |
|||
@ -1,213 +0,0 @@ |
|||
// <copyright file="Hsl.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents a Hsl (hue, saturation, lightness) color.
|
|||
/// </summary>
|
|||
public struct Hsl : IEquatable<Hsl>, IAlmostEquatable<Hsl, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Hsl"/> that has H, S, and L values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Hsl Empty = default(Hsl); |
|||
|
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001F; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Hsl"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="h">The h hue component.</param>
|
|||
/// <param name="s">The s saturation component.</param>
|
|||
/// <param name="l">The l value (lightness) component.</param>
|
|||
public Hsl(float h, float s, float l) |
|||
{ |
|||
this.backingVector = Vector3.Clamp(new Vector3(h, s, l), Vector3.Zero, new Vector3(360, 1, 1)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the hue component.
|
|||
/// <remarks>A value ranging between 0 and 360.</remarks>
|
|||
/// </summary>
|
|||
public float H => this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the saturation component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float S => this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the lightness component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float L => this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Hsl"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="Hsl"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="Color"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Hsl"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Hsl(Color color) |
|||
{ |
|||
float r = color.R / 255F; |
|||
float g = color.G / 255F; |
|||
float b = color.B / 255F; |
|||
|
|||
float max = Math.Max(r, Math.Max(g, b)); |
|||
float min = Math.Min(r, Math.Min(g, b)); |
|||
float chroma = max - min; |
|||
float h = 0; |
|||
float s = 0; |
|||
float l = (max + min) / 2; |
|||
|
|||
if (Math.Abs(chroma) < Epsilon) |
|||
{ |
|||
return new Hsl(0, s, l); |
|||
} |
|||
|
|||
if (Math.Abs(r - max) < Epsilon) |
|||
{ |
|||
h = (g - b) / chroma; |
|||
} |
|||
else if (Math.Abs(g - max) < Epsilon) |
|||
{ |
|||
h = 2 + ((b - r) / chroma); |
|||
} |
|||
else if (Math.Abs(b - max) < Epsilon) |
|||
{ |
|||
h = 4 + ((r - g) / chroma); |
|||
} |
|||
|
|||
h *= 60; |
|||
if (h < 0.0) |
|||
{ |
|||
h += 360; |
|||
} |
|||
|
|||
if (l <= .5f) |
|||
{ |
|||
s = chroma / (max + min); |
|||
} |
|||
else |
|||
{ |
|||
s = chroma / (2 - chroma); |
|||
} |
|||
|
|||
return new Hsl(h, s, l); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsl"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Hsl"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Hsl"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(Hsl left, Hsl right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsl"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Hsl"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Hsl"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(Hsl left, Hsl right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Hsl [ Empty ]"; |
|||
} |
|||
|
|||
return $"Hsl [ H={this.H:#0.##}, S={this.S:#0.##}, L={this.L:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Hsl) |
|||
{ |
|||
return this.Equals((Hsl)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Hsl other) |
|||
{ |
|||
return this.AlmostEquals(other, Epsilon); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool AlmostEquals(Hsl other, float precision) |
|||
{ |
|||
Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X < precision |
|||
&& result.Y < precision |
|||
&& result.Z < precision; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Hsl"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private static int GetHashCode(Hsl color) => color.backingVector.GetHashCode(); |
|||
} |
|||
} |
|||
@ -1,206 +0,0 @@ |
|||
// <copyright file="Hsv.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Represents a HSV (hue, saturation, value) color. Also known as HSB (hue, saturation, brightness).
|
|||
/// </summary>
|
|||
public struct Hsv : IEquatable<Hsv>, IAlmostEquatable<Hsv, float> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="Hsv"/> that has H, S, and V values set to zero.
|
|||
/// </summary>
|
|||
public static readonly Hsv Empty = default(Hsv); |
|||
|
|||
/// <summary>
|
|||
/// The epsilon for comparing floating point numbers.
|
|||
/// </summary>
|
|||
private const float Epsilon = 0.001F; |
|||
|
|||
/// <summary>
|
|||
/// The backing vector for SIMD support.
|
|||
/// </summary>
|
|||
private Vector3 backingVector; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Hsv"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="h">The h hue component.</param>
|
|||
/// <param name="s">The s saturation component.</param>
|
|||
/// <param name="v">The v value (brightness) component.</param>
|
|||
public Hsv(float h, float s, float v) |
|||
{ |
|||
this.backingVector = Vector3.Clamp(new Vector3(h, s, v), Vector3.Zero, new Vector3(360, 1, 1)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the hue component.
|
|||
/// <remarks>A value ranging between 0 and 360.</remarks>
|
|||
/// </summary>
|
|||
public float H => this.backingVector.X; |
|||
|
|||
/// <summary>
|
|||
/// Gets the saturation component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float S => this.backingVector.Y; |
|||
|
|||
/// <summary>
|
|||
/// Gets the value (brightness) component.
|
|||
/// <remarks>A value ranging between 0 and 1.</remarks>
|
|||
/// </summary>
|
|||
public float V => this.backingVector.Z; |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="Hsv"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="Hsv"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">The instance of <see cref="Color"/> to convert.</param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="Hsv"/>.
|
|||
/// </returns>
|
|||
public static implicit operator Hsv(Color color) |
|||
{ |
|||
float r = color.R / 255F; |
|||
float g = color.G / 255F; |
|||
float b = color.B / 255F; |
|||
|
|||
float max = Math.Max(r, Math.Max(g, b)); |
|||
float min = Math.Min(r, Math.Min(g, b)); |
|||
float chroma = max - min; |
|||
float h = 0; |
|||
float s = 0; |
|||
float v = max; |
|||
|
|||
if (Math.Abs(chroma) < Epsilon) |
|||
{ |
|||
return new Hsv(0, s, v); |
|||
} |
|||
|
|||
if (Math.Abs(r - max) < Epsilon) |
|||
{ |
|||
h = (g - b) / chroma; |
|||
} |
|||
else if (Math.Abs(g - max) < Epsilon) |
|||
{ |
|||
h = 2 + ((b - r) / chroma); |
|||
} |
|||
else if (Math.Abs(b - max) < Epsilon) |
|||
{ |
|||
h = 4 + ((r - g) / chroma); |
|||
} |
|||
|
|||
h *= 60; |
|||
if (h < 0.0) |
|||
{ |
|||
h += 360; |
|||
} |
|||
|
|||
s = chroma / v; |
|||
|
|||
return new Hsv(h, s, v); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsv"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Hsv"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Hsv"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(Hsv left, Hsv right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="Hsv"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="Hsv"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="Hsv"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(Hsv left, Hsv right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "Hsv [ Empty ]"; |
|||
} |
|||
|
|||
return $"Hsv [ H={this.H:#0.##}, S={this.S:#0.##}, V={this.V:#0.##} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is Hsv) |
|||
{ |
|||
return this.Equals((Hsv)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Hsv other) |
|||
{ |
|||
return this.AlmostEquals(other, Epsilon); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool AlmostEquals(Hsv other, float precision) |
|||
{ |
|||
Vector3 result = Vector3.Abs(this.backingVector - other.backingVector); |
|||
|
|||
return result.X < precision |
|||
&& result.Y < precision |
|||
&& result.Z < precision; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Hsv"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private static int GetHashCode(Hsv color) => color.backingVector.GetHashCode(); |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
// <copyright file="IAlmostEquatable.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Defines a generalized method that a value type or class implements to create
|
|||
/// a type-specific method for determining approximate equality of instances.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The type of objects to compare.</typeparam>
|
|||
/// <typeparam name="TPrecision">The object specifying the type to specify precision with.</typeparam>
|
|||
public interface IAlmostEquatable<in TColor, in TPrecision> |
|||
where TPrecision : struct, IComparable<TPrecision> |
|||
{ |
|||
/// <summary>
|
|||
/// Indicates whether the current object is equal to another object of the same type
|
|||
/// when compared to the specified precision level.
|
|||
/// </summary>
|
|||
/// <param name="other">An object to compare with this object.</param>
|
|||
/// <param name="precision">The object specifying the level of precision.</param>
|
|||
/// <returns>
|
|||
/// true if the current object is equal to the other parameter; otherwise, false.
|
|||
/// </returns>
|
|||
bool AlmostEquals(TColor other, TPrecision precision); |
|||
} |
|||
} |
|||
@ -1,157 +0,0 @@ |
|||
// <copyright file="YCbCr.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
|
|||
/// <summary>
|
|||
/// Represents an YCbCr (luminance, blue chroma, red chroma) color conforming to the full range standard used in digital imaging systems.
|
|||
/// <see href="http://en.wikipedia.org/wiki/YCbCr"/>
|
|||
/// </summary>
|
|||
public struct YCbCr : IEquatable<YCbCr> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="YCbCr"/> that has Y, Cb, and Cr values set to zero.
|
|||
/// </summary>
|
|||
public static readonly YCbCr Empty = default(YCbCr); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="YCbCr"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="y">The y luminance component.</param>
|
|||
/// <param name="cb">The cb chroma component.</param>
|
|||
/// <param name="cr">The cr chroma component.</param>
|
|||
public YCbCr(byte y, byte cb, byte cr) |
|||
: this() |
|||
{ |
|||
this.Y = y; |
|||
this.Cb = cb; |
|||
this.Cr = cr; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the Y luminance component.
|
|||
/// <remarks>A value ranging between 0 and 255.</remarks>
|
|||
/// </summary>
|
|||
public byte Y { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the Cb chroma component.
|
|||
/// <remarks>A value ranging between 0 and 255.</remarks>
|
|||
/// </summary>
|
|||
public byte Cb { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the Cr chroma component.
|
|||
/// <remarks>A value ranging between 0 and 255.</remarks>
|
|||
/// </summary>
|
|||
public byte Cr { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="YCbCr"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Allows the implicit conversion of an instance of <see cref="Color"/> to a
|
|||
/// <see cref="YCbCr"/>.
|
|||
/// </summary>
|
|||
/// <param name="color">
|
|||
/// The instance of <see cref="Color"/> to convert.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// An instance of <see cref="YCbCr"/>.
|
|||
/// </returns>
|
|||
public static implicit operator YCbCr(Color color) |
|||
{ |
|||
byte r = color.R; |
|||
byte g = color.G; |
|||
byte b = color.B; |
|||
|
|||
byte y = (byte)((0.299F * r) + (0.587F * g) + (0.114F * b)); |
|||
byte cb = (byte)(128 + ((-0.168736F * r) - (0.331264F * g) + (0.5F * b))); |
|||
byte cr = (byte)(128 + ((0.5F * r) - (0.418688F * g) - (0.081312F * b))); |
|||
|
|||
return new YCbCr(y, cb, cr); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="YCbCr"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="YCbCr"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="YCbCr"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator ==(YCbCr left, YCbCr right) |
|||
{ |
|||
return left.Equals(right); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="YCbCr"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="YCbCr"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="YCbCr"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
public static bool operator !=(YCbCr left, YCbCr right) |
|||
{ |
|||
return !left.Equals(right); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.Y.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.Cb.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ this.Cr.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "YCbCr [ Empty ]"; |
|||
} |
|||
|
|||
return $"YCbCr [ Y={this.Y}, Cb={this.Cb}, Cr={this.Cr} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
if (obj is YCbCr) |
|||
{ |
|||
return this.Equals((YCbCr)obj); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(YCbCr other) |
|||
{ |
|||
return this.Y == other.Y && this.Cb == other.Cb && this.Cr == other.Cr; |
|||
} |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
// <copyright file="ComponentOrder.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Enumerates the various component orders.
|
|||
/// </summary>
|
|||
public enum ComponentOrder |
|||
{ |
|||
/// <summary>
|
|||
/// Z-> Y-> X order. Equivalent to B-> G-> R in <see cref="Color"/>
|
|||
/// </summary>
|
|||
ZYX, |
|||
|
|||
/// <summary>
|
|||
/// Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in <see cref="Color"/>
|
|||
/// </summary>
|
|||
ZYXW, |
|||
|
|||
/// <summary>
|
|||
/// X-> Y-> Z order. Equivalent to R-> G-> B in <see cref="Color"/>
|
|||
/// </summary>
|
|||
XYZ, |
|||
|
|||
/// <summary>
|
|||
/// X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in <see cref="Color"/>
|
|||
/// </summary>
|
|||
XYZW, |
|||
} |
|||
} |
|||
@ -1,31 +0,0 @@ |
|||
// <copyright file="IPackedBytes.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// An interface that converts packed vector types to and from <see cref="T:byte[]"/> values,
|
|||
/// allowing multiple encodings to be manipulated in a generic manner.
|
|||
/// </summary>
|
|||
public interface IPackedBytes |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the packed representation from the gives bytes.
|
|||
/// </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>
|
|||
void PackFromBytes(byte x, byte y, byte z, byte w); |
|||
|
|||
/// <summary>
|
|||
/// Sets the packed representation into the gives bytes.
|
|||
/// </summary>
|
|||
/// <param name="bytes">The bytes to set the color in.</param>
|
|||
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
|
|||
/// <param name="componentOrder">The order of the components.</param>
|
|||
void ToBytes(byte[] bytes, int startIndex, ComponentOrder componentOrder); |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
// <copyright file="IPackedPixel.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// An interface that represents a packed pixel type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
public interface IPackedPixel<TPacked> : IPackedVector<TPacked>, IPackedBytes |
|||
where TPacked : struct |
|||
{ |
|||
} |
|||
} |
|||
@ -1,42 +0,0 @@ |
|||
// <copyright file="IPackedVector.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// An interface that converts packed vector types to and from <see cref="Vector4"/> values,
|
|||
/// allowing multiple encodings to be manipulated in a generic manner.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
public interface IPackedVector<TPacked> : IPackedVector |
|||
where TPacked : struct |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the packed representation of the value.
|
|||
/// </summary>
|
|||
TPacked PackedValue { get; set; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// An interface that converts packed vector types to and from <see cref="Vector4"/> values.
|
|||
/// </summary>
|
|||
public interface IPackedVector |
|||
{ |
|||
/// <summary>
|
|||
/// Sets the packed representation from a <see cref="Vector4"/>.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector to create the packed representation from.</param>
|
|||
void PackFromVector4(Vector4 vector); |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a <see cref="Vector4"/>.
|
|||
/// The vector components are typically expanded in least to greatest significance order.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
Vector4 ToVector4(); |
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
// <copyright file="RgbaComponent.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Enumerates the RGBA (red, green, blue, alpha) color components.
|
|||
/// </summary>
|
|||
public enum RgbaComponent |
|||
{ |
|||
/// <summary>
|
|||
/// The red component.
|
|||
/// </summary>
|
|||
R = 0, |
|||
|
|||
/// <summary>
|
|||
/// The green component.
|
|||
/// </summary>
|
|||
G = 1, |
|||
|
|||
/// <summary>
|
|||
/// The blue component.
|
|||
/// </summary>
|
|||
B = 2, |
|||
|
|||
/// <summary>
|
|||
/// The alpha component.
|
|||
/// </summary>
|
|||
A = 3 |
|||
} |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
// <copyright file="ImageFormatException.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// The exception that is thrown when the library tries to load
|
|||
/// an image, which has an invalid format.
|
|||
/// </summary>
|
|||
public class ImageFormatException : Exception |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageFormatException"/> class.
|
|||
/// </summary>
|
|||
public ImageFormatException() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageFormatException"/> class with the name of the
|
|||
/// parameter that causes this exception.
|
|||
/// </summary>
|
|||
/// <param name="errorMessage">The error message that explains the reason for this exception.</param>
|
|||
public ImageFormatException(string errorMessage) |
|||
: base(errorMessage) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageFormatException"/> class with a specified
|
|||
/// error message and the exception that is the cause of this exception.
|
|||
/// </summary>
|
|||
/// <param name="errorMessage">The error message that explains the reason for this exception.</param>
|
|||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic)
|
|||
/// if no inner exception is specified.</param>
|
|||
public ImageFormatException(string errorMessage, Exception innerException) |
|||
: base(errorMessage, innerException) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
// <copyright file="ImageProcessingException.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// The exception that is thrown when an error occurs when applying a process to an image.
|
|||
/// </summary>
|
|||
public class ImageProcessingException : Exception |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageProcessingException"/> class.
|
|||
/// </summary>
|
|||
public ImageProcessingException() |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageProcessingException"/> class with the name of the
|
|||
/// parameter that causes this exception.
|
|||
/// </summary>
|
|||
/// <param name="errorMessage">The error message that explains the reason for this exception.</param>
|
|||
public ImageProcessingException(string errorMessage) |
|||
: base(errorMessage) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageProcessingException"/> class with a specified
|
|||
/// error message and the exception that is the cause of this exception.
|
|||
/// </summary>
|
|||
/// <param name="errorMessage">The error message that explains the reason for this exception.</param>
|
|||
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic)
|
|||
/// if no inner exception is specified.</param>
|
|||
public ImageProcessingException(string errorMessage, Exception innerException) |
|||
: base(errorMessage, innerException) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,91 +0,0 @@ |
|||
// <copyright file="ByteExtensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="byte"/> struct.
|
|||
/// </summary>
|
|||
internal static class ByteExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Converts a byte array to a new array where each value in the original array is represented
|
|||
/// by a the specified number of bits.
|
|||
/// </summary>
|
|||
/// <param name="source">The bytes to convert from. Cannot be null.</param>
|
|||
/// <param name="bits">The number of bits per value.</param>
|
|||
/// <returns>The resulting <see cref="T:byte[]"/> array. Is never null.</returns>
|
|||
/// <exception cref="System.ArgumentNullException"><paramref name="source"/> is null.</exception>
|
|||
/// <exception cref="System.ArgumentException"><paramref name="bits"/> is less than or equals than zero.</exception>
|
|||
public static byte[] ToArrayByBitsLength(this byte[] source, int bits) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
Guard.MustBeGreaterThan(bits, 0, "bits"); |
|||
|
|||
byte[] result; |
|||
|
|||
if (bits < 8) |
|||
{ |
|||
result = new byte[source.Length * 8 / bits]; |
|||
int mask = 0xFF >> (8 - bits); |
|||
int resultOffset = 0; |
|||
|
|||
// ReSharper disable once ForCanBeConvertedToForeach
|
|||
for (int i = 0; i < source.Length; i++) |
|||
{ |
|||
byte b = source[i]; |
|||
for (int shift = 0; shift < 8; shift += bits) |
|||
{ |
|||
int colorIndex = (b >> (8 - bits - shift)) & mask; |
|||
|
|||
result[resultOffset] = (byte)colorIndex; |
|||
|
|||
resultOffset++; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
result = source; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Optimized <see cref="T:byte[]"/> reversal algorithm.
|
|||
/// </summary>
|
|||
/// <param name="source">The byte array.</param>
|
|||
public static void ReverseBytes(this byte[] source) |
|||
{ |
|||
ReverseBytes(source, 0, source.Length); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Optimized <see cref="T:byte[]"/> reversal algorithm.
|
|||
/// </summary>
|
|||
/// <param name="source">The byte array.</param>
|
|||
/// <param name="index">The index.</param>
|
|||
/// <param name="length">The length.</param>
|
|||
/// <exception cref="System.ArgumentNullException"><paramref name="source"/> is null.</exception>
|
|||
public static void ReverseBytes(this byte[] source, int index, int length) |
|||
{ |
|||
Guard.NotNull(source, nameof(source)); |
|||
|
|||
int i = index; |
|||
int j = index + length - 1; |
|||
while (i < j) |
|||
{ |
|||
byte temp = source[i]; |
|||
source[i] = source[j]; |
|||
source[j] = temp; |
|||
i++; |
|||
j--; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,173 +0,0 @@ |
|||
// <copyright file="ComparableExtensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for classes that implement <see cref="IComparable{T}"/>.
|
|||
/// </summary>
|
|||
internal static class ComparableExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Restricts a <see cref="byte"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="byte"/> representing the clamped value.
|
|||
/// </returns>
|
|||
public static byte Clamp(this byte value, byte min, byte max) |
|||
{ |
|||
// Order is important here as someone might set min to higher than max.
|
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="uint"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/> representing the clamped value.
|
|||
/// </returns>
|
|||
public static uint Clamp(this uint value, uint min, uint max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="int"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/> representing the clamped value.
|
|||
/// </returns>
|
|||
public static int Clamp(this int value, int min, int max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="float"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/> representing the clamped value.
|
|||
/// </returns>
|
|||
///
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static float Clamp(this float value, float min, float max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Restricts a <see cref="double"/> to be within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="value">The The value to clamp.</param>
|
|||
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
|
|||
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="double"/> representing the clamped value.
|
|||
/// </returns>
|
|||
public static double Clamp(this double value, double min, double max) |
|||
{ |
|||
if (value > max) |
|||
{ |
|||
return max; |
|||
} |
|||
|
|||
if (value < min) |
|||
{ |
|||
return min; |
|||
} |
|||
|
|||
return value; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts an <see cref="int"/> to a <see cref="byte"/> first restricting the value between the
|
|||
/// minimum and maximum allowable ranges.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="int"/> this method extends.</param>
|
|||
/// <returns>The <see cref="byte"/></returns>
|
|||
public static byte ToByte(this int value) |
|||
{ |
|||
return (byte)value.Clamp(0, 255); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts an <see cref="float"/> to a <see cref="byte"/> first restricting the value between the
|
|||
/// minimum and maximum allowable ranges.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="float"/> this method extends.</param>
|
|||
/// <returns>The <see cref="byte"/></returns>
|
|||
public static byte ToByte(this float value) |
|||
{ |
|||
return (byte)value.Clamp(0, 255); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts an <see cref="double"/> to a <see cref="byte"/> first restricting the value between the
|
|||
/// minimum and maximum allowable ranges.
|
|||
/// </summary>
|
|||
/// <param name="value">The <see cref="double"/> this method extends.</param>
|
|||
/// <returns>The <see cref="byte"/></returns>
|
|||
public static byte ToByte(this double value) |
|||
{ |
|||
return (byte)value.Clamp(0, 255); |
|||
} |
|||
} |
|||
} |
|||
@ -1,88 +0,0 @@ |
|||
// <copyright file="EnumerableExtensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// Encapsulates a series of time saving extension methods to the <see cref="T:System.Collections.IEnumerable"/> interface.
|
|||
/// </summary>
|
|||
public static class EnumerableExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Generates a sequence of integral numbers within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="fromInclusive">
|
|||
/// The start index, inclusive.
|
|||
/// </param>
|
|||
/// <param name="toExclusive">
|
|||
/// The end index, exclusive.
|
|||
/// </param>
|
|||
/// <param name="step">
|
|||
/// The incremental step.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="IEnumerable{Int32}"/> that contains a range of sequential integral numbers.
|
|||
/// </returns>
|
|||
public static IEnumerable<int> SteppedRange(int fromInclusive, int toExclusive, int step) |
|||
{ |
|||
// Borrowed from Enumerable.Range
|
|||
long num = (fromInclusive + toExclusive) - 1L; |
|||
if ((toExclusive < 0) || (num > 0x7fffffffL)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(toExclusive)); |
|||
} |
|||
|
|||
return RangeIterator(fromInclusive, i => i < toExclusive, step); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sequence of integral numbers within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="fromInclusive">
|
|||
/// The start index, inclusive.
|
|||
/// </param>
|
|||
/// <param name="toDelegate">
|
|||
/// A method that has one parameter and returns a <see cref="bool"/> calculating the end index
|
|||
/// </param>
|
|||
/// <param name="step">
|
|||
/// The incremental step.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="IEnumerable{Int32}"/> that contains a range of sequential integral numbers.
|
|||
/// </returns>
|
|||
public static IEnumerable<int> SteppedRange(int fromInclusive, Func<int, bool> toDelegate, int step) |
|||
{ |
|||
return RangeIterator(fromInclusive, toDelegate, step); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Generates a sequence of integral numbers within a specified range.
|
|||
/// </summary>
|
|||
/// <param name="fromInclusive">
|
|||
/// The start index, inclusive.
|
|||
/// </param>
|
|||
/// <param name="toDelegate">
|
|||
/// A method that has one parameter and returns a <see cref="bool"/> calculating the end index
|
|||
/// </param>
|
|||
/// <param name="step">
|
|||
/// The incremental step.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="IEnumerable{Int32}"/> that contains a range of sequential integral numbers.
|
|||
/// </returns>
|
|||
private static IEnumerable<int> RangeIterator(int fromInclusive, Func<int, bool> toDelegate, int step) |
|||
{ |
|||
int i = fromInclusive; |
|||
while (toDelegate(i)) |
|||
{ |
|||
yield return i; |
|||
i += step; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
// <copyright file="StreamExtensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.IO; |
|||
|
|||
internal static class StreamExtensions |
|||
{ |
|||
public static void Skip(this Stream stream, int count) |
|||
{ |
|||
if (count < 1) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (stream.CanSeek) |
|||
{ |
|||
stream.Position += count; |
|||
} |
|||
else |
|||
{ |
|||
byte[] foo = new byte[count]; |
|||
stream.Read(foo, 0, count); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,83 +0,0 @@ |
|||
// <copyright file="Vector4Extensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Vector4"/> struct.
|
|||
/// </summary>
|
|||
public static class Vector4Extensions |
|||
{ |
|||
/// <summary>
|
|||
/// Compresses a linear color signal to its sRGB equivalent.
|
|||
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
|||
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
|||
/// </summary>
|
|||
/// <param name="linear">The <see cref="Vector4"/> whose signal to compress.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Compress(this Vector4 linear) |
|||
{ |
|||
// TODO: Is there a faster way to do this?
|
|||
return new Vector4(Compress(linear.X), Compress(linear.Y), Compress(linear.Z), linear.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands an sRGB color signal to its linear equivalent.
|
|||
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
|||
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
|||
/// </summary>
|
|||
/// <param name="gamma">The <see cref="Color"/> whose signal to expand.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
public static Vector4 Expand(this Vector4 gamma) |
|||
{ |
|||
// TODO: Is there a faster way to do this?
|
|||
return new Vector4(Expand(gamma.X), Expand(gamma.Y), Expand(gamma.Z), gamma.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the compressed sRGB value from an linear signal.
|
|||
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
|||
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
|||
/// </summary>
|
|||
/// <param name="signal">The signal value to compress.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float Compress(float signal) |
|||
{ |
|||
if (signal <= 0.0031308F) |
|||
{ |
|||
return signal * 12.92F; |
|||
} |
|||
|
|||
return (1.055F * (float)Math.Pow(signal, 0.41666666F)) - 0.055F; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the expanded linear value from an sRGB signal.
|
|||
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
|||
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
|||
/// </summary>
|
|||
/// <param name="signal">The signal value to expand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static float Expand(float signal) |
|||
{ |
|||
if (signal <= 0.04045F) |
|||
{ |
|||
return signal / 12.92F; |
|||
} |
|||
|
|||
return (float)Math.Pow((signal + 0.055F) / 1.055F, 2.4F); |
|||
} |
|||
} |
|||
} |
|||
@ -1,205 +0,0 @@ |
|||
// <copyright file="Guard.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Diagnostics; |
|||
|
|||
/// <summary>
|
|||
/// Provides methods to protect against invalid parameters.
|
|||
/// </summary>
|
|||
[DebuggerStepThrough] |
|||
internal static class Guard |
|||
{ |
|||
/// <summary>
|
|||
/// Verifies, that the method parameter with specified object value is not null
|
|||
/// and throws an exception if it is found to be so.
|
|||
/// </summary>
|
|||
/// <param name="target">The target object, which cannot be null.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <param name="message">The error message, if any to add to the exception.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null</exception>
|
|||
public static void NotNull(object target, string parameterName, string message = "") |
|||
{ |
|||
if (target == null) |
|||
{ |
|||
if (!string.IsNullOrWhiteSpace(message)) |
|||
{ |
|||
throw new ArgumentNullException(parameterName, message); |
|||
} |
|||
|
|||
throw new ArgumentNullException(parameterName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies, that the string method parameter with specified object value and message
|
|||
/// is not null, not empty and does not contain only blanks and throws an exception
|
|||
/// if the object is null.
|
|||
/// </summary>
|
|||
/// <param name="target">The target string, which should be checked against being null or empty.</param>
|
|||
/// <param name="parameterName">Name of the parameter.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="target"/> is null.</exception>
|
|||
/// <exception cref="ArgumentException"><paramref name="target"/> is empty or contains only blanks.</exception>
|
|||
public static void NotNullOrEmpty(string target, string parameterName) |
|||
{ |
|||
if (target == null) |
|||
{ |
|||
throw new ArgumentNullException(parameterName); |
|||
} |
|||
|
|||
if (string.IsNullOrWhiteSpace(target)) |
|||
{ |
|||
throw new ArgumentException("Value cannot be null or empty and cannot contain only blanks.", parameterName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies that the specified value is less than a maximum value
|
|||
/// and throws an exception if it is not.
|
|||
/// </summary>
|
|||
/// <param name="value">The target value, which should be validated.</param>
|
|||
/// <param name="max">The maximum value.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="value"/> is greater than the maximum value.
|
|||
/// </exception>
|
|||
public static void MustBeLessThan<TValue>(TValue value, TValue max, string parameterName) |
|||
where TValue : IComparable<TValue> |
|||
{ |
|||
if (value.CompareTo(max) >= 0) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(parameterName, $"Value must be less than {max}."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies that the specified value is less than or equal to a maximum value
|
|||
/// and throws an exception if it is not.
|
|||
/// </summary>
|
|||
/// <param name="value">The target value, which should be validated.</param>
|
|||
/// <param name="max">The maximum value.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="value"/> is greater than the maximum value.
|
|||
/// </exception>
|
|||
public static void MustBeLessThanOrEqualTo<TValue>(TValue value, TValue max, string parameterName) |
|||
where TValue : IComparable<TValue> |
|||
{ |
|||
if (value.CompareTo(max) > 0) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(parameterName, $"Value must be less than or equal to {max}."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies that the specified value is greater than a minimum value
|
|||
/// and throws an exception if it is not.
|
|||
/// </summary>
|
|||
/// <param name="value">The target value, which should be validated.</param>
|
|||
/// <param name="min">The minimum value.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="value"/> is less than the minimum value.
|
|||
/// </exception>
|
|||
public static void MustBeGreaterThan<TValue>(TValue value, TValue min, string parameterName) |
|||
where TValue : IComparable<TValue> |
|||
{ |
|||
if (value.CompareTo(min) <= 0) |
|||
{ |
|||
throw new ArgumentOutOfRangeException( |
|||
parameterName, |
|||
$"Value must be greater than {min}."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies that the specified value is greater than or equal to a minimum value
|
|||
/// and throws an exception if it is not.
|
|||
/// </summary>
|
|||
/// <param name="value">The target value, which should be validated.</param>
|
|||
/// <param name="min">The minimum value.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="value"/> is less than the minimum value.
|
|||
/// </exception>
|
|||
public static void MustBeGreaterThanOrEqualTo<TValue>(TValue value, TValue min, string parameterName) |
|||
where TValue : IComparable<TValue> |
|||
{ |
|||
if (value.CompareTo(min) < 0) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(parameterName, $"Value must be greater than or equal to {min}."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies that the specified value is greater than or equal to a minimum value and less than
|
|||
/// or equal to a maximum value and throws an exception if it is not.
|
|||
/// </summary>
|
|||
/// <param name="value">The target value, which should be validated.</param>
|
|||
/// <param name="min">The minimum value.</param>
|
|||
/// <param name="max">The maximum value.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="value"/> is less than the minimum value of greater than the maximum value.
|
|||
/// </exception>
|
|||
public static void MustBeBetweenOrEqualTo<TValue>(TValue value, TValue min, TValue max, string parameterName) |
|||
where TValue : IComparable<TValue> |
|||
{ |
|||
if (value.CompareTo(min) < 0 || value.CompareTo(max) > 0) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(parameterName, $"Value must be greater than or equal to {min} and less than or equal to {max}."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies, that the method parameter with specified target value is true
|
|||
/// and throws an exception if it is found to be so.
|
|||
/// </summary>
|
|||
/// <param name="target">
|
|||
/// The target value, which cannot be false.
|
|||
/// </param>
|
|||
/// <param name="parameterName">
|
|||
/// The name of the parameter that is to be checked.
|
|||
/// </param>
|
|||
/// <param name="message">
|
|||
/// The error message, if any to add to the exception.
|
|||
/// </param>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="target"/> is false
|
|||
/// </exception>
|
|||
public static void IsTrue(bool target, string parameterName, string message) |
|||
{ |
|||
if (!target) |
|||
{ |
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Verifies, that the method parameter with specified target value is false
|
|||
/// and throws an exception if it is found to be so.
|
|||
/// </summary>
|
|||
/// <param name="target">The target value, which cannot be true.</param>
|
|||
/// <param name="parameterName">The name of the parameter that is to be checked.</param>
|
|||
/// <param name="message">The error message, if any to add to the exception.</param>
|
|||
/// <exception cref="ArgumentException">
|
|||
/// <paramref name="target"/> is true
|
|||
/// </exception>
|
|||
public static void IsFalse(bool target, string parameterName, string message) |
|||
{ |
|||
if (target) |
|||
{ |
|||
throw new ArgumentException(message, parameterName); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,293 +0,0 @@ |
|||
// <copyright file="ImageMaths.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Linq; |
|||
using System.Numerics; |
|||
|
|||
/// <summary>
|
|||
/// Provides common mathematical methods.
|
|||
/// </summary>
|
|||
internal static class ImageMaths |
|||
{ |
|||
/// <summary>
|
|||
/// Returns how many bits are required to store the specified number of colors.
|
|||
/// Performs a Log2() on the value.
|
|||
/// </summary>
|
|||
/// <param name="colors">The number of colors.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="int"/>
|
|||
/// </returns>
|
|||
public static int GetBitsNeededForColorDepth(int colors) |
|||
{ |
|||
return (int)Math.Ceiling(Math.Log(colors, 2)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Implementation of 1D Gaussian G(x) function
|
|||
/// </summary>
|
|||
/// <param name="x">The x provided to G(x).</param>
|
|||
/// <param name="sigma">The spread of the blur.</param>
|
|||
/// <returns>The Gaussian G(x)</returns>
|
|||
public static float Gaussian(float x, float sigma) |
|||
{ |
|||
const float Numerator = 1.0f; |
|||
float denominator = (float)(Math.Sqrt(2 * Math.PI) * sigma); |
|||
|
|||
float exponentNumerator = -x * x; |
|||
float exponentDenominator = (float)(2 * Math.Pow(sigma, 2)); |
|||
|
|||
float left = Numerator / denominator; |
|||
float right = (float)Math.Exp(exponentNumerator / exponentDenominator); |
|||
|
|||
return left * right; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the result of a B-C filter against the given value.
|
|||
/// <see href="http://www.imagemagick.org/Usage/filter/#cubic_bc"/>
|
|||
/// </summary>
|
|||
/// <param name="x">The value to process.</param>
|
|||
/// <param name="b">The B-Spline curve variable.</param>
|
|||
/// <param name="c">The Cardinal curve variable.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
public static float GetBcValue(float x, float b, float c) |
|||
{ |
|||
float temp; |
|||
|
|||
if (x < 0F) |
|||
{ |
|||
x = -x; |
|||
} |
|||
|
|||
temp = x * x; |
|||
if (x < 1F) |
|||
{ |
|||
x = ((12 - (9 * b) - (6 * c)) * (x * temp)) + ((-18 + (12 * b) + (6 * c)) * temp) + (6 - (2 * b)); |
|||
return x / 6F; |
|||
} |
|||
|
|||
if (x < 2F) |
|||
{ |
|||
x = ((-b - (6 * c)) * (x * temp)) + (((6 * b) + (30 * c)) * temp) + (((-12 * b) - (48 * c)) * x) + ((8 * b) + (24 * c)); |
|||
return x / 6F; |
|||
} |
|||
|
|||
return 0F; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the result of a sine cardinal function for the given value.
|
|||
/// </summary>
|
|||
/// <param name="x">The value to calculate the result for.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
public static float SinC(float x) |
|||
{ |
|||
const float Epsilon = .00001F; |
|||
|
|||
if (Math.Abs(x) > Epsilon) |
|||
{ |
|||
x *= (float)Math.PI; |
|||
return Clean((float)Math.Sin(x) / x); |
|||
} |
|||
|
|||
return 1.0f; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the given degrees converted to radians.
|
|||
/// </summary>
|
|||
/// <param name="degrees">The angle in degrees.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/> representing the degree as radians.
|
|||
/// </returns>
|
|||
public static float DegreesToRadians(float degrees) |
|||
{ |
|||
return degrees * (float)(Math.PI / 180); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the bounding <see cref="Rectangle"/> from the given points.
|
|||
/// </summary>
|
|||
/// <param name="topLeft">
|
|||
/// The <see cref="Point"/> designating the top left position.
|
|||
/// </param>
|
|||
/// <param name="bottomRight">
|
|||
/// The <see cref="Point"/> designating the bottom right position.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The bounding <see cref="Rectangle"/>.
|
|||
/// </returns>
|
|||
public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) |
|||
{ |
|||
return new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the bounding <see cref="Rectangle"/> from the given matrix.
|
|||
/// </summary>
|
|||
/// <param name="rectangle">The source rectangle.</param>
|
|||
/// <param name="matrix">The transformation matrix.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rectangle"/>.
|
|||
/// </returns>
|
|||
public static Rectangle GetBoundingRectangle(Rectangle rectangle, Matrix3x2 matrix) |
|||
{ |
|||
Vector2 leftTop = Vector2.Transform(new Vector2(rectangle.Left, rectangle.Top), matrix); |
|||
Vector2 rightTop = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Top), matrix); |
|||
Vector2 leftBottom = Vector2.Transform(new Vector2(rectangle.Left, rectangle.Bottom), matrix); |
|||
Vector2 rightBottom = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Bottom), matrix); |
|||
|
|||
Vector2[] allCorners = { leftTop, rightTop, leftBottom, rightBottom }; |
|||
float extentX = allCorners.Select(v => v.X).Max() - allCorners.Select(v => v.X).Min(); |
|||
float extentY = allCorners.Select(v => v.Y).Max() - allCorners.Select(v => v.Y).Min(); |
|||
return new Rectangle(0, 0, (int)extentX, (int)extentY); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finds the bounding rectangle based on the first instance of any color component other
|
|||
/// than the given one.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
/// <param name="bitmap">The <see cref="Image"/> to search within.</param>
|
|||
/// <param name="componentValue">The color component value to remove.</param>
|
|||
/// <param name="channel">The <see cref="RgbaComponent"/> channel to test against.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rectangle"/>.
|
|||
/// </returns>
|
|||
public static Rectangle GetFilteredBoundingRectangle<TColor, TPacked>(ImageBase<TColor, TPacked> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) |
|||
where TColor : struct, IPackedPixel<TPacked> |
|||
where TPacked : struct |
|||
{ |
|||
const float Epsilon = .00001f; |
|||
int width = bitmap.Width; |
|||
int height = bitmap.Height; |
|||
Point topLeft = default(Point); |
|||
Point bottomRight = default(Point); |
|||
|
|||
Func<PixelAccessor<TColor, TPacked>, int, int, float, bool> delegateFunc; |
|||
|
|||
// Determine which channel to check against
|
|||
switch (channel) |
|||
{ |
|||
case RgbaComponent.R: |
|||
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().X - b) > Epsilon; |
|||
break; |
|||
|
|||
case RgbaComponent.G: |
|||
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Y - b) > Epsilon; |
|||
break; |
|||
|
|||
case RgbaComponent.B: |
|||
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().Z - b) > Epsilon; |
|||
break; |
|||
|
|||
default: |
|||
delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToVector4().W - b) > Epsilon; |
|||
break; |
|||
} |
|||
|
|||
Func<PixelAccessor<TColor, TPacked>, int> getMinY = pixels => |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return y; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
}; |
|||
|
|||
Func<PixelAccessor<TColor, TPacked>, int> getMaxY = pixels => |
|||
{ |
|||
for (int y = height - 1; y > -1; y--) |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return y; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return height; |
|||
}; |
|||
|
|||
Func<PixelAccessor<TColor, TPacked>, int> getMinX = pixels => |
|||
{ |
|||
for (int x = 0; x < width; x++) |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return 0; |
|||
}; |
|||
|
|||
Func<PixelAccessor<TColor, TPacked>, int> getMaxX = pixels => |
|||
{ |
|||
for (int x = width - 1; x > -1; x--) |
|||
{ |
|||
for (int y = 0; y < height; y++) |
|||
{ |
|||
if (delegateFunc(pixels, x, y, componentValue)) |
|||
{ |
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return height; |
|||
}; |
|||
|
|||
using (PixelAccessor<TColor, TPacked> bitmapPixels = bitmap.Lock()) |
|||
{ |
|||
topLeft.Y = getMinY(bitmapPixels); |
|||
topLeft.X = getMinX(bitmapPixels); |
|||
bottomRight.Y = (getMaxY(bitmapPixels) + 1).Clamp(0, height); |
|||
bottomRight.X = (getMaxX(bitmapPixels) + 1).Clamp(0, width); |
|||
} |
|||
|
|||
return GetBoundingRectangle(topLeft, bottomRight); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ensures that any passed double is correctly rounded to zero
|
|||
/// </summary>
|
|||
/// <param name="x">The value to clean.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>
|
|||
/// </returns>.
|
|||
private static float Clean(float x) |
|||
{ |
|||
const float Epsilon = .00001F; |
|||
|
|||
if (Math.Abs(x) < Epsilon) |
|||
{ |
|||
return 0F; |
|||
} |
|||
|
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
@ -1,48 +0,0 @@ |
|||
// <copyright file="Alpha.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using Processors; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Alters the alpha component of the image.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="percent">The new opacity of the image. Must be between 0 and 100.</param>
|
|||
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
|
|||
public static Image<TColor, TPacked> Alpha<TColor, TPacked>(this Image<TColor, TPacked> source, int percent) |
|||
where TColor : struct, IPackedPixel<TPacked> |
|||
where TPacked : struct |
|||
{ |
|||
return Alpha(source, percent, source.Bounds); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Alters the alpha component of the image.
|
|||
/// </summary>
|
|||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="percent">The new opacity of the image. Must be between 0 and 100.</param>
|
|||
/// <param name="rectangle">
|
|||
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
|||
/// </param>
|
|||
/// <returns>The <see cref="Image"/>.</returns>
|
|||
public static Image<TColor, TPacked> Alpha<TColor, TPacked>(this Image<TColor, TPacked> source, int percent, Rectangle rectangle) |
|||
where TColor : struct, IPackedPixel<TPacked> |
|||
where TPacked : struct |
|||
{ |
|||
return source.Process(rectangle, new AlphaProcessor<TColor, TPacked>(percent)); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue