Browse Source

Merge pull request #729 from jongleur1983/718-gray8-gray16

#718 #730: Add Gray8 and Gray16 Pixel Formats and clean up IPixel
pull/746/head
James Jackson-South 8 years ago
committed by GitHub
parent
commit
d65cf676fa
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 67
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  2. 24
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  3. 4
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  4. 34
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  5. 34
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  6. 116
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  7. 51
      src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
  8. 14
      src/ImageSharp/ImageFrame{TPixel}.cs
  9. 72
      src/ImageSharp/ImageSharp.csproj
  10. 171
      src/ImageSharp/PixelFormats/Alpha8.cs
  11. 253
      src/ImageSharp/PixelFormats/Argb32.cs
  12. 179
      src/ImageSharp/PixelFormats/Bgr24.cs
  13. 204
      src/ImageSharp/PixelFormats/Bgr565.cs
  14. 210
      src/ImageSharp/PixelFormats/Bgra32.cs
  15. 186
      src/ImageSharp/PixelFormats/Bgra4444.cs
  16. 194
      src/ImageSharp/PixelFormats/Bgra5551.cs
  17. 168
      src/ImageSharp/PixelFormats/Byte4.cs
  18. 177
      src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.cs
  19. 85
      src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.tt
  20. 177
      src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.cs
  21. 85
      src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.tt
  22. 177
      src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.cs
  23. 85
      src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.tt
  24. 177
      src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.cs
  25. 85
      src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.tt
  26. 177
      src/ImageSharp/PixelFormats/Generated/Gray8.PixelOperations.Generated.cs
  27. 85
      src/ImageSharp/PixelFormats/Generated/Gray8.PixelOperations.Generated.tt
  28. 621
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
  29. 92
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
  30. 177
      src/ImageSharp/PixelFormats/Generated/Rgb24.PixelOperations.Generated.cs
  31. 85
      src/ImageSharp/PixelFormats/Generated/Rgb24.PixelOperations.Generated.tt
  32. 177
      src/ImageSharp/PixelFormats/Generated/Rgb48.PixelOperations.Generated.cs
  33. 85
      src/ImageSharp/PixelFormats/Generated/Rgb48.PixelOperations.Generated.tt
  34. 124
      src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
  35. 70
      src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
  36. 177
      src/ImageSharp/PixelFormats/Generated/Rgba64.PixelOperations.Generated.cs
  37. 85
      src/ImageSharp/PixelFormats/Generated/Rgba64.PixelOperations.Generated.tt
  38. 177
      src/ImageSharp/PixelFormats/Gray16.cs
  39. 152
      src/ImageSharp/PixelFormats/Gray8.cs
  40. 202
      src/ImageSharp/PixelFormats/HalfSingle.cs
  41. 12
      src/ImageSharp/PixelFormats/HalfTypeHelper.cs
  42. 216
      src/ImageSharp/PixelFormats/HalfVector2.cs
  43. 188
      src/ImageSharp/PixelFormats/HalfVector4.cs
  44. 78
      src/ImageSharp/PixelFormats/IPixel.cs
  45. 253
      src/ImageSharp/PixelFormats/NormalizedByte2.cs
  46. 234
      src/ImageSharp/PixelFormats/NormalizedByte4.cs
  47. 239
      src/ImageSharp/PixelFormats/NormalizedShort2.cs
  48. 243
      src/ImageSharp/PixelFormats/NormalizedShort4.cs
  49. 54
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
  50. 216
      src/ImageSharp/PixelFormats/Rg32.cs
  51. 186
      src/ImageSharp/PixelFormats/Rgb24.cs
  52. 189
      src/ImageSharp/PixelFormats/Rgb48.cs
  53. 208
      src/ImageSharp/PixelFormats/Rgba1010102.cs
  54. 16
      src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs
  55. 253
      src/ImageSharp/PixelFormats/Rgba32.cs
  56. 239
      src/ImageSharp/PixelFormats/Rgba64.cs
  57. 721
      src/ImageSharp/PixelFormats/RgbaVector.Definitions.cs
  58. 18
      src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs
  59. 346
      src/ImageSharp/PixelFormats/RgbaVector.cs
  60. 238
      src/ImageSharp/PixelFormats/Short2.cs
  61. 236
      src/ImageSharp/PixelFormats/Short4.cs
  62. 11
      src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs
  63. 9
      src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs
  64. 9
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
  65. 12
      src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs
  66. 15
      src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs
  67. 49
      src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs
  68. 48
      src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs
  69. 32
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
  70. 14
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
  71. 28
      tests/ImageSharp.Benchmarks/General/PixelConversion/ITestPixel.cs
  72. 81
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs
  73. 58
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromVector4.cs
  74. 61
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32.cs
  75. 113
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32_AsPartOfCompositeOperation.cs
  76. 83
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4.cs
  77. 95
      tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4_AsPartOfCompositeOperation.cs
  78. 89
      tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs
  79. 72
      tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs
  80. 21
      tests/ImageSharp.Sandbox46/Program.cs
  81. 40
      tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs
  82. 10
      tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs
  83. 8
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  84. 174
      tests/ImageSharp.Tests/Issues/Issue594.cs
  85. 1
      tests/ImageSharp.Tests/Numerics/RationalTests.cs
  86. 191
      tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs
  87. 155
      tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs
  88. 76
      tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs
  89. 107
      tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs
  90. 76
      tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs
  91. 155
      tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs
  92. 155
      tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs
  93. 155
      tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs
  94. 151
      tests/ImageSharp.Tests/PixelFormats/ColorConstructorTests.cs
  95. 216
      tests/ImageSharp.Tests/PixelFormats/ColorEqualityTests.cs
  96. 88
      tests/ImageSharp.Tests/PixelFormats/ColorPackingTests.cs
  97. 129
      tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs
  98. 127
      tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs
  99. 107
      tests/ImageSharp.Tests/PixelFormats/HalfSingleTests.cs
  100. 107
      tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs

67
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -14,6 +14,73 @@ namespace SixLabors.ImageSharp
/// </summary>
internal static class ImageMaths
{
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="byte"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static byte Get8BitBT709Luminance(byte r, byte g, byte b) => (byte)((r * .2126F) + (g * .7152F) + (b * .0722F));
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="ushort"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F));
/// <summary>
/// Scales a value from a 16 bit <see cref="ushort"/> to it's 8 bit <see cref="byte"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit compoonent value.</param>
/// <returns>The <see cref="byte"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static byte DownScaleFrom16BitTo8Bit(ushort component)
{
// To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
//
// (V * 255) / 65535
//
// This reduces to round(V / 257), or floor((V + 128.5)/257)
//
// Represent V as the two byte value vhi.vlo. Make a guess that the
// result is the top byte of V, vhi, then the correction to this value
// is:
//
// error = floor(((V-vhi.vhi) + 128.5) / 257)
// = floor(((vlo-vhi) + 128.5) / 257)
//
// This can be approximated using integer arithmetic (and a signed
// shift):
//
// error = (vlo-vhi+128) >> 8;
//
// The approximate differs from the exact answer only when (vlo-vhi) is
// 128; it then gives a correction of +1 when the exact correction is
// 0. This gives 128 errors. The exact answer (correct for all 16-bit
// input values) is:
//
// error = (vlo-vhi+128)*65535 >> 24;
//
// An alternative arithmetic calculation which also gives no errors is:
//
// (V * 255 + 32895) >> 16
return (byte)(((component * 255) + 32895) >> 16);
}
/// <summary>
/// Scales a value from an 8 bit <see cref="byte"/> to it's 16 bit <see cref="ushort"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit compoonent value.</param>
/// <returns>The <see cref="ushort"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257);
/// <summary>
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
/// </summary>

24
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -219,8 +219,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
where TPixel : struct, IPixel<TPixel>
{
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);
using (Buffer2D<byte> buffer = this.memoryAllocator.Allocate2D<byte>(width, height, AllocationOptions.Clean))
{
this.UncompressRle8(width, buffer.GetSpan());
@ -233,8 +231,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
for (int x = 0; x < width; x++)
{
rgba.Bgr = Unsafe.As<byte, Bgr24>(ref colors[bufferRow[x] * 4]);
color.PackFromRgba32(rgba);
color.PackFromBgr24(Unsafe.As<byte, Bgr24>(ref colors[bufferRow[x] * 4]));
pixelRow[x] = color;
}
}
@ -352,8 +349,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(arrayWidth + padding, AllocationOptions.Clean))
{
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);
Span<byte> rowSpan = row.GetSpan();
for (int y = 0; y < height; y++)
@ -363,7 +358,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int offset = 0;
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
// TODO: Could use PixelOperations here!
for (int x = 0; x < arrayWidth; x++)
{
int colOffset = x * ppb;
@ -371,9 +365,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
int colorIndex = ((rowSpan[offset] >> (8 - bits - (shift * bits))) & mask) * 4;
// Stored in b-> g-> r order.
rgba.Bgr = Unsafe.As<byte, Bgr24>(ref colors[colorIndex]);
color.PackFromRgba32(rgba);
color.PackFromBgr24(Unsafe.As<byte, Bgr24>(ref colors[colorIndex]));
pixelRow[newX] = color;
}
@ -397,7 +389,6 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int padding = CalculatePadding(width, 2);
int stride = (width * 2) + padding;
TPixel color = default;
var rgba = new Rgba32(0, 0, 0, 255);
using (IManagedByteBuffer buffer = this.memoryAllocator.AllocateManagedByteBuffer(stride))
{
@ -412,11 +403,12 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
short temp = BitConverter.ToInt16(buffer.Array, offset);
rgba.R = GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10);
rgba.G = GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5);
rgba.B = GetBytesFrom5BitValue(temp & Rgb16BMask);
var rgb = new Rgb24(
GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10),
GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5),
GetBytesFrom5BitValue(temp & Rgb16BMask));
color.PackFromRgba32(rgba);
color.PackFromRgb24(rgb);
pixelRow[x] = color;
offset += 2;
}
@ -537,7 +529,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.metaData = meta;
short bitsPerPixel = this.infoHeader.BitsPerPixel;
var bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance);
BmpMetaData bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance);
// We can only encode at these bit rates so far.
if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24)

4
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -101,9 +101,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
var fileHeader = new BmpFileHeader(
type: 19778, // BM
offset: 54,
fileSize: 54 + infoHeader.ImageSize,
reserved: 0,
fileSize: 54 + infoHeader.ImageSize);
offset: 54);
#if NETCOREAPP2_1
Span<byte> buffer = stackalloc byte[40];

34
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -481,22 +481,36 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.GetPixelRowSpan(writeY));
var rgba = new Rgba32(0, 0, 0, 255);
bool transFlag = this.graphicsControlExtension.TransparencyFlag;
// #403 The left + width value can be larger than the image width
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
if (!transFlag)
{
int index = Unsafe.Add(ref indicesRef, i);
if (!this.graphicsControlExtension.TransparencyFlag
|| this.graphicsControlExtension.TransparencyIndex != index)
// #403 The left + width value can be larger than the image width
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
{
int index = Unsafe.Add(ref indicesRef, i);
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
rgba.Rgb = colorTable[index];
pixel.PackFromRgba32(rgba);
Rgb24 rgb = colorTable[index];
pixel.PackFromRgb24(rgb);
i++;
}
}
else
{
byte transIndex = this.graphicsControlExtension.TransparencyIndex;
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
{
int index = Unsafe.Add(ref indicesRef, i);
if (transIndex != index)
{
ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
Rgb24 rgb = colorTable[index];
pixel.PackFromRgb24(rgb);
}
i++;
i++;
}
}
}

34
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -210,16 +211,20 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
// Transparent pixels are much more likely to be found at the end of a palette
int index = -1;
Rgba32 trans = default;
int length = quantized.Palette.Length;
ref TPixel paletteRef = ref MemoryMarshal.GetReference(quantized.Palette.AsSpan());
for (int i = quantized.Palette.Length - 1; i >= 0; i--)
using (IMemoryOwner<Rgba32> rgbaBuffer = this.memoryAllocator.Allocate<Rgba32>(length))
{
ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
entry.ToRgba32(ref trans);
if (trans.Equals(default))
Span<Rgba32> rgbaSpan = rgbaBuffer.GetSpan();
ref Rgba32 paletteRef = ref MemoryMarshal.GetReference(rgbaSpan);
PixelOperations<TPixel>.Instance.ToRgba32(quantized.Palette, rgbaSpan, length);
for (int i = quantized.Palette.Length - 1; i >= 0; i--)
{
index = i;
if (Unsafe.Add(ref paletteRef, i).Equals(default))
{
index = i;
}
}
}
@ -406,24 +411,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
private void WriteColorTable<TPixel>(QuantizedFrame<TPixel> image, Stream stream)
where TPixel : struct, IPixel<TPixel>
{
int pixelCount = image.Palette.Length;
// The maximium number of colors for the bit depth
int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * 3;
Rgb24 rgb = default;
int pixelCount = image.Palette.Length;
using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength))
{
ref TPixel paletteRef = ref MemoryMarshal.GetReference(image.Palette.AsSpan());
ref Rgb24 rgb24Ref = ref Unsafe.As<byte, Rgb24>(ref MemoryMarshal.GetReference(colorTable.GetSpan()));
for (int i = 0; i < pixelCount; i++)
{
ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
entry.ToRgb24(ref rgb);
Unsafe.Add(ref rgb24Ref, i) = rgb;
}
// Write the palette to the stream
PixelOperations<TPixel>.Instance.ToRgb24Bytes(image.Palette.AsSpan(), colorTable.GetSpan(), pixelCount);
stream.Write(colorTable.Array, 0, colorTableLength);
}
}

116
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
@ -312,11 +313,6 @@ namespace SixLabors.ImageSharp.Formats.Png
private void CollectGrayscaleBytes<TPixel>(ReadOnlySpan<TPixel> rowSpan)
where TPixel : struct, IPixel<TPixel>
{
// Use ITU-R recommendation 709 to match libpng.
const float RX = .2126F;
const float GX = .7152F;
const float BX = .0722F;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
Span<byte> rawScanlineSpan = this.rawScanline.GetSpan();
ref byte rawScanlineSpanRef = ref MemoryMarshal.GetReference(rawScanlineSpan);
@ -327,12 +323,18 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.use16Bit)
{
// 16 bit grayscale
Rgb48 rgb = default;
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2)
using (IMemoryOwner<Gray16> luminanceBuffer = this.memoryAllocator.Allocate<Gray16>(rowSpan.Length))
{
Unsafe.Add(ref rowSpanRef, x).ToRgb48(ref rgb);
ushort luminance = (ushort)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B));
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
Span<Gray16> luminanceSpan = luminanceBuffer.GetSpan();
ref Gray16 luminanceRef = ref MemoryMarshal.GetReference(luminanceSpan);
PixelOperations<TPixel>.Instance.ToGray16(rowSpan, luminanceSpan, rowSpan.Length);
// Can't map directly to byte array as it's big endian.
for (int x = 0, o = 0; x < luminanceSpan.Length; x++, o += 2)
{
Gray16 luminance = Unsafe.Add(ref luminanceRef, x);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance.PackedValue);
}
}
}
else
@ -340,12 +342,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.bitDepth == 8)
{
// 8 bit grayscale
Rgb24 rgb = default;
for (int x = 0; x < rowSpan.Length; x++)
{
Unsafe.Add(ref rowSpanRef, x).ToRgb24(ref rgb);
Unsafe.Add(ref rawScanlineSpanRef, x) = (byte)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B));
}
PixelOperations<TPixel>.Instance.ToGray8Bytes(rowSpan, rawScanlineSpan, rowSpan.Length);
}
else
{
@ -356,14 +353,9 @@ namespace SixLabors.ImageSharp.Formats.Png
Span<byte> tempSpan = temp.GetSpan();
ref byte tempSpanRef = ref MemoryMarshal.GetReference(tempSpan);
Rgb24 rgb = default;
for (int x = 0; x < rowSpan.Length; x++)
{
Unsafe.Add(ref rowSpanRef, x).ToRgb24(ref rgb);
float luminance = ((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)) / scaleFactor;
Unsafe.Add(ref tempSpanRef, x) = (byte)luminance;
this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth);
}
// We need to first create an array of luminance bytes then scale them down to the correct bit depth.
PixelOperations<TPixel>.Instance.ToGray8Bytes(rowSpan, tempSpan, rowSpan.Length);
this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor);
}
}
}
@ -373,23 +365,31 @@ namespace SixLabors.ImageSharp.Formats.Png
if (this.use16Bit)
{
// 16 bit grayscale + alpha
Rgba64 rgba = default;
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 4)
// TODO: Should we consider in the future a GrayAlpha32 type.
using (IMemoryOwner<Rgba64> rgbaBuffer = this.memoryAllocator.Allocate<Rgba64>(rowSpan.Length))
{
Unsafe.Add(ref rowSpanRef, x).ToRgba64(ref rgba);
ushort luminance = (ushort)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B));
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A);
Span<Rgba64> rgbaSpan = rgbaBuffer.GetSpan();
ref Rgba64 rgbaRef = ref MemoryMarshal.GetReference(rgbaSpan);
PixelOperations<TPixel>.Instance.ToRgba64(rowSpan, rgbaSpan, rowSpan.Length);
// Can't map directly to byte array as it's big endian.
for (int x = 0, o = 0; x < rgbaSpan.Length; x++, o += 4)
{
Rgba64 rgba = Unsafe.Add(ref rgbaRef, x);
ushort luminance = ImageMaths.Get16BitBT709Luminance(rgba.R, rgba.G, rgba.B);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A);
}
}
}
else
{
// 8 bit grayscale + alpha
Rgba32 rgba = default;
// TODO: Should we consider in the future a GrayAlpha16 type.
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2)
{
Unsafe.Add(ref rowSpanRef, x).ToRgba32(ref rgba);
Unsafe.Add(ref rawScanlineSpanRef, o) = (byte)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B));
var rgba = Unsafe.Add(ref rowSpanRef, x).ToRgba32();
Unsafe.Add(ref rawScanlineSpanRef, o) = ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
Unsafe.Add(ref rawScanlineSpanRef, o + 1) = rgba.A;
}
}
@ -425,15 +425,21 @@ namespace SixLabors.ImageSharp.Formats.Png
case 8:
{
// 16 bit Rgba
Rgba64 rgba = default;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8)
using (IMemoryOwner<Rgba64> rgbaBuffer = this.memoryAllocator.Allocate<Rgba64>(rowSpan.Length))
{
Unsafe.Add(ref rowSpanRef, x).ToRgba64(ref rgba);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgba.R);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.G);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgba.B);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 6, 2), rgba.A);
Span<Rgba64> rgbaSpan = rgbaBuffer.GetSpan();
ref Rgba64 rgbaRef = ref MemoryMarshal.GetReference(rgbaSpan);
PixelOperations<TPixel>.Instance.ToRgba64(rowSpan, rgbaSpan, rowSpan.Length);
// Can't map directly to byte array as it's big endian.
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8)
{
Rgba64 rgba = Unsafe.Add(ref rgbaRef, x);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgba.R);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.G);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgba.B);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 6, 2), rgba.A);
}
}
break;
@ -442,14 +448,20 @@ namespace SixLabors.ImageSharp.Formats.Png
default:
{
// 16 bit Rgb
Rgb48 rgb = default;
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6)
using (IMemoryOwner<Rgb48> rgbBuffer = this.memoryAllocator.Allocate<Rgb48>(rowSpan.Length))
{
Unsafe.Add(ref rowSpanRef, x).ToRgb48(ref rgb);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgb.R);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgb.G);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgb.B);
Span<Rgb48> rgbSpan = rgbBuffer.GetSpan();
ref Rgb48 rgbRef = ref MemoryMarshal.GetReference(rgbSpan);
PixelOperations<TPixel>.Instance.ToRgb48(rowSpan, rgbSpan, rowSpan.Length);
// Can't map directly to byte array as it's big endian.
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6)
{
Rgb48 rgb = Unsafe.Add(ref rgbRef, x);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgb.R);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgb.G);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgb.B);
}
}
break;
@ -624,7 +636,6 @@ namespace SixLabors.ImageSharp.Formats.Png
TPixel[] palette = quantized.Palette;
int paletteLength = Math.Min(palette.Length, 256);
int colorTableLength = paletteLength * 3;
Rgba32 rgba = default;
bool anyAlpha = false;
using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength))
@ -639,7 +650,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (quantizedSpan.IndexOf((byte)i) > -1)
{
int offset = i * 3;
palette[i].ToRgba32(ref rgba);
var rgba = palette[i].ToRgba32();
byte alpha = rgba.A;
@ -851,7 +862,8 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <param name="source">The source span in 8 bits.</param>
/// <param name="result">The resultant span in <paramref name="bits"/>.</param>
/// <param name="bits">The bit depth.</param>
private void ScaleDownFrom8BitArray(ReadOnlySpan<byte> source, Span<byte> result, int bits)
/// <param name="scale">The scaling factor.</param>
private void ScaleDownFrom8BitArray(ReadOnlySpan<byte> source, Span<byte> result, int bits, float scale = 1)
{
ref byte sourceRef = ref MemoryMarshal.GetReference(source);
ref byte resultRef = ref MemoryMarshal.GetReference(result);
@ -864,7 +876,7 @@ namespace SixLabors.ImageSharp.Formats.Png
for (int i = 0; i < source.Length; i++)
{
int value = Unsafe.Add(ref sourceRef, i) & mask;
int value = ((int)MathF.Round(Unsafe.Add(ref sourceRef, i) / scale)) & mask;
v |= value << shift;
if (shift == 0)

51
src/ImageSharp/Formats/Png/PngScanlineProcessor.cs

@ -32,30 +32,19 @@ namespace SixLabors.ImageSharp.Formats.Png
{
if (header.BitDepth == 16)
{
Rgb48 rgb48 = default;
for (int x = 0, o = 0; x < header.Width; x++, o += 2)
{
ushort luminance = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, 2));
rgb48.R = luminance;
rgb48.G = luminance;
rgb48.B = luminance;
pixel.PackFromRgb48(rgb48);
pixel.PackFromGray16(new Gray16(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
// TODO: We should really be using Rgb24 here but IPixel does not have a PackFromRgb24 method.
var rgba32 = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = 0; x < header.Width; x++)
{
byte luminance = (byte)(Unsafe.Add(ref scanlineSpanRef, x) * scaleFactor);
rgba32.R = luminance;
rgba32.G = luminance;
rgba32.B = luminance;
pixel.PackFromRgba32(rgba32);
pixel.PackFromGray8(new Gray8(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@ -116,30 +105,19 @@ namespace SixLabors.ImageSharp.Formats.Png
{
if (header.BitDepth == 16)
{
Rgb48 rgb48 = default;
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o += 2)
{
ushort luminance = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, 2));
rgb48.R = luminance;
rgb48.G = luminance;
rgb48.B = luminance;
pixel.PackFromRgb48(rgb48);
pixel.PackFromGray16(new Gray16(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
// TODO: We should really be using Rgb24 here but IPixel does not have a PackFromRgb24 method.
var rgba32 = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o++)
{
byte luminance = (byte)(Unsafe.Add(ref scanlineSpanRef, o) * scaleFactor);
rgba32.R = luminance;
rgba32.G = luminance;
rgba32.B = luminance;
pixel.PackFromRgba32(rgba32);
pixel.PackFromGray8(new Gray8(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@ -311,14 +289,12 @@ namespace SixLabors.ImageSharp.Formats.Png
}
else
{
// TODO: We should have PackFromRgb24.
var rgba = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = 0; x < header.Width; x++)
{
int index = Unsafe.Add(ref scanlineSpanRef, x);
rgba.Rgb = Unsafe.Add(ref palettePixelsRef, index);
Rgb24 rgb = Unsafe.Add(ref palettePixelsRef, index);
pixel.PackFromRgba32(rgba);
pixel.PackFromRgb24(rgb);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@ -358,13 +334,12 @@ namespace SixLabors.ImageSharp.Formats.Png
}
else
{
var rgba = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o++)
{
int index = Unsafe.Add(ref scanlineSpanRef, o);
rgba.Rgb = Unsafe.Add(ref palettePixelsRef, index);
Rgb24 rgb = Unsafe.Add(ref palettePixelsRef, index);
pixel.PackFromRgba32(rgba);
pixel.PackFromRgb24(rgb);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@ -511,14 +486,14 @@ namespace SixLabors.ImageSharp.Formats.Png
}
else
{
var rgba = new Rgba32(0, 0, 0, byte.MaxValue);
Rgb24 rgb = default;
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o += bytesPerPixel)
{
rgba.R = Unsafe.Add(ref scanlineSpanRef, o);
rgba.G = Unsafe.Add(ref scanlineSpanRef, o + bytesPerSample);
rgba.B = Unsafe.Add(ref scanlineSpanRef, o + (2 * bytesPerSample));
rgb.R = Unsafe.Add(ref scanlineSpanRef, o);
rgb.G = Unsafe.Add(ref scanlineSpanRef, o + bytesPerSample);
rgb.B = Unsafe.Add(ref scanlineSpanRef, o + (2 * bytesPerSample));
pixel.PackFromRgba32(rgba);
pixel.PackFromRgb24(rgb);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}

14
src/ImageSharp/ImageFrame{TPixel}.cs

@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
@ -289,22 +287,16 @@ namespace SixLabors.ImageSharp
var target = new ImageFrame<TPixel2>(configuration, this.Width, this.Height, this.MetaData.DeepClone());
ParallelHelper.IterateRowsWithTempBuffer<Vector4>(
ParallelHelper.IterateRows(
this.Bounds(),
configuration,
(rows, tempRowBuffer) =>
(rows) =>
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> sourceRow = this.GetPixelRowSpan(y);
Span<TPixel2> targetRow = target.GetPixelRowSpan(y);
Span<Vector4> tempRowSpan = tempRowBuffer.Span;
PixelOperations<TPixel>.Instance.ToScaledVector4(sourceRow, tempRowSpan, sourceRow.Length);
PixelOperations<TPixel2>.Instance.PackFromScaledVector4(
tempRowSpan,
targetRow,
targetRow.Length);
PixelOperations<TPixel>.Instance.To(sourceRow, targetRow, sourceRow.Length);
}
});

72
src/ImageSharp/ImageSharp.csproj

@ -76,10 +76,42 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PixelOperations{TPixel}.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Argb32.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Argb32.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Bgr24.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Bgr24.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Bgra32.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Bgra32.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Gray8.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Gray8.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Gray16.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Gray16.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgb24.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgb24.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgba32.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgb48.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgb48.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgba64.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgba64.PixelOperations.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\PixelBlenders\PorterDuffFunctions.Generated.tt">
<LastGenOutput>PorterDuffFunctions.Generated.cs</LastGenOutput>
<Generator>TextTemplatingFileGenerator</Generator>
@ -110,11 +142,51 @@
<AutoGen>True</AutoGen>
<DependentUpon>PixelOperations{TPixel}.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Argb32.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Argb32.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Bgr24.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Bgr24.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Bgra32.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Bgra32.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Gray8.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Gray8.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Gray16.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Gray16.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Rgb24.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Rgb24.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Rgba32.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Rgb48.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Rgb48.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\Rgba64.PixelOperations.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Rgba64.PixelOperations.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\PixelBlenders\DefaultPixelBlenders.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>

171
src/ImageSharp/PixelFormats/Alpha8.cs

@ -18,11 +18,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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);
}
/// <param name="alpha">The alpha component.</param>
public Alpha8(byte alpha) => this.PackedValue = alpha;
/// <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; }
@ -39,11 +42,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Alpha8 left, Alpha8 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Alpha8 left, Alpha8 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Alpha8"/> objects for equality.
@ -53,161 +53,91 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Alpha8 left, Alpha8 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Alpha8 left, Alpha8 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Alpha8> CreatePixelOperations() => new PixelOperations<Alpha8>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(vector.W);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(0, 0, 0, this.PackedValue / 255F);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(0, 0, 0, this.PackedValue / 255F);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackedValue = source.A;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackedValue = source.A;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackedValue = source.A;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackedValue = byte.MaxValue;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackedValue = source.A;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackedValue = source.A;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
dest = default(Rgb24);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackedValue = byte.MaxValue;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
dest.R = 0;
dest.G = 0;
dest.B = 0;
dest.A = this.PackedValue;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackedValue = byte.MaxValue;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
dest.R = 0;
dest.G = 0;
dest.B = 0;
dest.A = this.PackedValue;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackedValue = byte.MaxValue;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
dest = default(Bgr24);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackedValue = source.A;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
dest.R = 0;
dest.G = 0;
dest.B = 0;
dest.A = this.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(0, 0, 0, this.PackedValue);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackedValue = byte.MaxValue;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest)
{
dest.R = 0;
dest.G = 0;
dest.B = 0;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <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 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Alpha8 other && this.Equals(other);
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Alpha8 other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Alpha8 other) => this.PackedValue.Equals(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();
}
public override string ToString() => $"Alpha8({this.PackedValue})";
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <summary>
@ -215,10 +145,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="alpha">The float containing the value to pack.</param>
/// <returns>The <see cref="byte"/> containing the packed values.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static byte Pack(float alpha)
{
return (byte)Math.Round(alpha.Clamp(0, 1) * 255F);
}
[MethodImpl(InliningOptions.ShortMethod)]
private static byte Pack(float alpha) => (byte)Math.Round(alpha.Clamp(0, 1F) * 255F);
}
}

253
src/ImageSharp/PixelFormats/Argb32.cs

@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// as it avoids the need to create new values for modification operations.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
public struct Argb32 : IPixel<Argb32>, IPackedVector<uint>
public partial struct Argb32 : IPixel<Argb32>, IPackedVector<uint>
{
/// <summary>
/// Gets or sets the alpha component.
@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Argb32(byte r, byte g, byte b)
{
this.R = r;
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Argb32(byte r, byte g, byte b, byte a)
{
this.R = r;
@ -89,12 +89,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Argb32(float r, float g, float b, float a = 1)
: this()
{
this.Pack(r, g, b, a);
}
: this() => this.Pack(r, g, b, a);
/// <summary>
/// Initializes a new instance of the <see cref="Argb32"/> struct.
@ -102,12 +99,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Argb32(Vector3 vector)
: this()
{
this.Pack(ref vector);
}
: this() => this.Pack(ref vector);
/// <summary>
/// Initializes a new instance of the <see cref="Argb32"/> struct.
@ -115,12 +109,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Argb32(Vector4 vector)
: this()
{
this.Pack(ref vector);
}
: this() => this.Pack(ref vector);
/// <summary>
/// Initializes a new instance of the <see cref="Argb32"/> struct.
@ -128,22 +119,19 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="packed">
/// The packed value.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Argb32(uint packed)
: this()
{
this.Argb = packed;
}
: this() => this.Argb = packed;
/// <summary>
/// Gets or sets the packed representation of the Argb32 struct.
/// </summary>
public uint Argb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As<Argb32, uint>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As<Argb32, uint>(ref this) = value;
}
@ -157,20 +145,13 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <summary>
/// Compares two <see cref="Argb32"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="Argb32"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="Argb32"/> on the right side of the operand.
/// </param>
/// <param name="left">The <see cref="Argb32"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Argb32"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Argb32 left, Argb32 right)
{
return left.Argb == right.Argb;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Argb32 left, Argb32 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Argb32"/> objects for equality.
@ -180,62 +161,44 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Argb32 left, Argb32 right)
{
return left.Argb != right.Argb;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Argb32 left, Argb32 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Argb32> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.Pack(ref vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc />
public PixelOperations<Argb32> CreatePixelOperations() => new PixelOperations<Argb32>();
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackedValue = source.PackedValue;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackedValue = source.PackedValue;
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.R = source.R;
@ -244,136 +207,88 @@ namespace SixLabors.ImageSharp.PixelFormats
this.A = source.A;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
this.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
dest = this;
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
}
/// <summary>
/// Converts the pixel to <see cref="Rgba32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
/// <summary>
/// Converts the pixel to <see cref="Bgra32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Bgra32 ToBgra32() => new Bgra32(this.R, this.G, this.B, this.A);
/// <summary>
/// Converts the pixel to <see cref="Argb32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32 ToArgb32() => this;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
this.A = (byte)(((source.A * 255) + 32895) >> 16);
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is Argb32 argb32 && this.Equals(argb32);
}
public override bool Equals(object obj) => obj is Argb32 argb32 && this.Equals(argb32);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Argb32 other)
{
return this.Argb == other.Argb;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Argb32 other) => this.Argb == other.Argb;
/// <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.R},{this.G},{this.B},{this.A})";
}
public override string ToString() => $"Argb({this.A}, {this.R}, {this.G}, {this.B})";
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.Argb.GetHashCode();
/// <summary>
/// Gets the <see cref="Vector4"/> representation without normalizing to [0, 1]
/// </summary>
/// <returns>A <see cref="Vector4"/> of values in [0, 255] </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Vector4 ToByteScaledVector4()
{
return new Vector4(this.R, this.G, this.B, this.A);
}
/// <summary>
/// Packs the four floats into a color.
/// </summary>
@ -381,7 +296,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(float x, float y, float z, float w)
{
var value = new Vector4(x, y, z, w);
@ -392,7 +307,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// Packs a <see cref="Vector3"/> into a uint.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector3 vector)
{
var value = new Vector4(vector, 1);
@ -403,7 +318,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// Packs a <see cref="Vector4"/> into a color.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector4 vector)
{
vector *= MaxBytes;

179
src/ImageSharp/PixelFormats/Bgr24.cs

@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </para>
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct Bgr24 : IPixel<Bgr24>
public partial struct Bgr24 : IPixel<Bgr24>
{
/// <summary>
/// The blue component.
@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Bgr24(byte r, byte g, byte b)
{
this.R = r;
@ -49,39 +49,54 @@ namespace SixLabors.ImageSharp.PixelFormats
this.B = b;
}
/// <summary>
/// Compares two <see cref="Bgr24"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Bgr24"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Bgr24"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Bgr24 left, Bgr24 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Bgr24"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Bgr24"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Bgr24"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Bgr24 left, Bgr24 right) => !left.Equals(right);
/// <inheritdoc/>
public PixelOperations<Bgr24> CreatePixelOperations() => new PixelOperations<Bgr24>();
public PixelOperations<Bgr24> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Bgr24 other)
{
return this.R == other.R && this.G == other.G && this.B == other.B;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is Bgr24 other && this.Equals(other);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
return HashHelpers.Combine(hash, this.B.GetHashCode());
Rgba32 rgba = default;
rgba.PackFromVector4(vector);
this.PackFromRgba32(rgba);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this = source.Bgr;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Rgba32(this.R, this.G, this.B, byte.MaxValue).ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.R = source.R;
@ -90,7 +105,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this = source;
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.R = source.R;
@ -99,109 +118,75 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
return this.ToVector4();
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
Rgba32 rgba = default;
rgba.PackFromVector4(vector);
this.PackFromRgba32(rgba);
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
return new Rgba32(this.R, this.G, this.B, 255).ToVector4();
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
this.R = source.R;
this.G = source.G;
this.B = source.B;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = byte.MaxValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this = source.Bgr;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, byte.MaxValue);
/// <inheritdoc/>
public void ToBgr24(ref Bgr24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
dest = this;
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
public void ToBgra32(ref Bgra32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = byte.MaxValue;
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgb48(Rgb48 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Bgr24 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
public override bool Equals(object obj) => obj is Bgr24 other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba64(Rgba64 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
}
/// <inheritdoc />
public override string ToString() => $"Bgra({this.B}, {this.G}, {this.R})";
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override string ToString()
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode()
{
return $"({this.B},{this.G},{this.R})";
int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
return HashHelpers.Combine(hash, this.B.GetHashCode());
}
}
}

204
src/ImageSharp/PixelFormats/Bgr565.cs

@ -8,7 +8,8 @@ using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.PixelFormats
{
/// <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.
/// 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.
/// <para>
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
/// </para>
@ -22,8 +23,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
public Bgr565(float x, float y, float z)
: this(new Vector3(x, y, z))
{
this.PackedValue = Pack(x, y, z);
}
/// <summary>
@ -32,10 +33,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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);
}
public Bgr565(Vector3 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc/>
public ushort PackedValue { get; set; }
@ -48,11 +46,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Bgr565 left, Bgr565 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Bgr565 left, Bgr565 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Bgr565"/> objects for equality.
@ -62,183 +57,112 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Bgr565 left, Bgr565 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Bgr565 left, Bgr565 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Bgr565> CreatePixelOperations() => new PixelOperations<Bgr565>();
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector3 ToVector3()
{
return new Vector3(
((this.PackedValue >> 11) & 0x1F) * (1F / 31F),
((this.PackedValue >> 5) & 0x3F) * (1F / 63F),
(this.PackedValue & 0x1F) * (1F / 31F));
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z);
var vector3 = new Vector3(vector.X, vector.Y, vector.Z);
this.PackedValue = Pack(ref vector3);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.ToVector3(), 1F);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.ToVector3(), 1F);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromVector4(source.ToVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromVector4(source.ToVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromVector4(source.ToVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
/// <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>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector3 ToVector3()
{
return obj is Bgr565 other && this.Equals(other);
return new Vector3(
((this.PackedValue >> 11) & 0x1F) * (1F / 31F),
((this.PackedValue >> 5) & 0x3F) * (1F / 63F),
(this.PackedValue & 0x1F) * (1F / 31F));
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Bgr565 other)
{
return this.PackedValue == other.PackedValue;
}
public override bool Equals(object obj) => obj is Bgr565 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Bgr565 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString()
{
return this.ToVector3().ToString();
var vector = this.ToVector3();
return FormattableString.Invariant($"Bgr565({vector.Z:#0.##}, {vector.Y:#0.##}, {vector.X:#0.##})");
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => 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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ushort Pack(float x, float y, float z)
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector3 vector)
{
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));
vector = Vector3.Clamp(vector, Vector3.Zero, Vector3.One);
return (ushort)((((int)Math.Round(vector.X * 31F) & 0x1F) << 11)
| (((int)Math.Round(vector.Y * 63F) & 0x3F) << 5)
| ((int)Math.Round(vector.Z * 31F) & 0x1F));
}
}
}

210
src/ImageSharp/PixelFormats/Bgra32.cs

@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </para>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Bgra32 : IPixel<Bgra32>, IPackedVector<uint>
public partial struct Bgra32 : IPixel<Bgra32>, IPackedVector<uint>
{
/// <summary>
/// Gets or sets the blue component.
@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Bgra32(byte r, byte g, byte b)
{
this.R = r;
@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Bgra32(byte r, byte g, byte b, byte a)
{
this.R = r;
@ -84,10 +84,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public uint Bgra
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As<Bgra32, uint>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As<Bgra32, uint>(ref this) = value;
}
@ -98,62 +98,50 @@ namespace SixLabors.ImageSharp.PixelFormats
set => this.Bgra = value;
}
/// <inheritdoc/>
public PixelOperations<Bgra32> CreatePixelOperations() => new PixelOperations<Bgra32>();
/// <inheritdoc/>
public bool Equals(Bgra32 other)
{
return this.Bgra == other.Bgra;
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj is Bgra32 other && this.Equals(other);
/// <inheritdoc/>
public override int GetHashCode() => this.Bgra.GetHashCode();
/// <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 <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Bgra32 left, Bgra32 right) => left.Equals(right);
/// <summary>
/// Gets the <see cref="Vector4"/> representation without normalizing to [0, 1]
/// Compares two <see cref="Bgra32"/> objects for equality.
/// </summary>
/// <returns>A <see cref="Vector4"/> of values in [0, 255] </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Vector4 ToByteScaledVector4()
{
return new Vector4(this.R, this.G, this.B, this.A);
}
/// <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 <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Bgra32 left, Bgra32 right) => !left.Equals(right);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
public PixelOperations<Bgra32> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.Pack(ref vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.R = source.R;
this.G = source.G;
@ -162,113 +150,101 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackedValue = source.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this = source;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest) => dest = Unsafe.As<Bgra32, Bgr24>(ref this);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest) => dest = this;
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = byte.MaxValue;
}
/// <summary>
/// Converts the pixel to <see cref="Rgba32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
/// <summary>
/// Converts the pixel to <see cref="Argb32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32 ToArgb32() => new Argb32(this.R, this.G, this.B, this.A);
/// <summary>
/// Converts the pixel to <see cref="Bgra32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Bgra32 ToBgra32() => this;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
this.A = (byte)(((source.A * 255) + 32895) >> 16);
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
public override bool Equals(object obj) => obj is Bgra32 other && this.Equals(other);
/// <inheritdoc/>
public bool Equals(Bgra32 other) => this.Bgra.Equals(other.Bgra);
/// <inheritdoc/>
public override int GetHashCode() => this.Bgra.GetHashCode();
/// <inheritdoc />
public override string ToString() => $"Bgra32({this.B}, {this.G}, {this.R}, {this.A})";
/// <summary>
/// Packs a <see cref="Vector4"/> into a color.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector4 vector)
{
vector *= MaxBytes;
@ -280,11 +256,5 @@ namespace SixLabors.ImageSharp.PixelFormats
this.B = (byte)vector.Z;
this.A = (byte)vector.W;
}
/// <inheritdoc />
public override string ToString()
{
return $"({this.B},{this.G},{this.R},{this.A})";
}
}
}

186
src/ImageSharp/PixelFormats/Bgra4444.cs

@ -23,18 +23,15 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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(new Vector4(x, y, z, 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);
}
public Bgra4444(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc/>
public ushort PackedValue { get; set; }
@ -47,11 +44,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Bgra4444 left, Bgra4444 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Bgra4444 left, Bgra4444 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Bgra4444"/> objects for equality.
@ -61,177 +55,103 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Bgra4444 left, Bgra4444 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Bgra4444 left, Bgra4444 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Bgra4444> CreatePixelOperations() => new PixelOperations<Bgra4444>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
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);
(this.PackedValue >> 8) & 0x0F,
(this.PackedValue >> 4) & 0x0F,
this.PackedValue & 0x0F,
(this.PackedValue >> 12) & 0x0F) * Max;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Bgra4444 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Bgra4444 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Bgra4444 other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Bgra4444 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString()
{
return this.ToVector4().ToString();
var vector = this.ToVector4();
return FormattableString.Invariant($"Bgra4444({vector.Z:#0.##}, {vector.Y:#0.##}, {vector.X:#0.##}, {vector.W:#0.##})");
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => 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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ushort Pack(float x, float y, float z, float w)
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
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));
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
return (ushort)((((int)Math.Round(vector.W * 15F) & 0x0F) << 12)
| (((int)Math.Round(vector.X * 15F) & 0x0F) << 8)
| (((int)Math.Round(vector.Y * 15F) & 0x0F) << 4)
| ((int)Math.Round(vector.Z * 15F) & 0x0F));
}
}
}
}

194
src/ImageSharp/PixelFormats/Bgra5551.cs

@ -8,7 +8,8 @@ using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.PixelFormats
{
/// <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.
/// 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.
/// <para>
/// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
/// </para>
@ -23,8 +24,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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(new Vector4(x, y, z, w))
{
this.PackedValue = Pack(x, y, z, w);
}
/// <summary>
@ -33,10 +34,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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);
}
public Bgra5551(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc/>
public ushort PackedValue { get; set; }
@ -49,11 +47,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Bgra5551 left, Bgra5551 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Bgra5551 left, Bgra5551 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Bgra5551"/> objects for equality.
@ -63,31 +58,26 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Bgra5551 left, Bgra5551 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Bgra5551 left, Bgra5551 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Bgra5551> CreatePixelOperations() => new PixelOperations<Bgra5551>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@ -98,150 +88,72 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Bgra5551 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Bgra5551 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Bgra5551 other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Bgra5551 other) => this.PackedValue.Equals(other.PackedValue);
/// <summary>
/// Gets a string representation of the packed vector.
/// </summary>
/// <returns>A string representation of the packed vector.</returns>
/// <inheritdoc />
public override string ToString()
{
return this.ToVector4().ToString();
var vector = this.ToVector4();
return FormattableString.Invariant($"Bgra5551({vector.Z:#0.##}, {vector.Y:#0.##}, {vector.X:#0.##}, {vector.W:#0.##})");
}
/// <summary>
/// Gets a hash code of the packed vector.
/// </summary>
/// <returns>The hash code for the packed vector.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => 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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ushort Pack(float x, float y, float z, float w)
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
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));
(((int)Math.Round(vector.X * 31F) & 0x1F) << 10)
| (((int)Math.Round(vector.Y * 31F) & 0x1F) << 5)
| (((int)Math.Round(vector.Z * 31F) & 0x1F) << 0)
| (((int)Math.Round(vector.W) & 0x1) << 15));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4() => this.ToVector4() * 255f;
}
}
}

168
src/ImageSharp/PixelFormats/Byte4.cs

@ -21,10 +21,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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);
}
public Byte4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <summary>
/// Initializes a new instance of the <see cref="Byte4"/> struct.
@ -50,11 +47,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Byte4 left, Byte4 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Byte4 left, Byte4 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Byte4"/> objects for equality.
@ -64,38 +58,26 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Byte4 left, Byte4 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Byte4 left, Byte4 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Byte4> CreatePixelOperations() => new PixelOperations<Byte4>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector * 255F);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector * 255F);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4() / 255F;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4() / 255F;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(ref vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@ -106,119 +88,61 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToByteScaledVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToByteScaledVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToByteScaledVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
var vector = this.ToVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Byte4 byte4 && this.Equals(byte4);
}
public override bool Equals(object obj) => obj is Byte4 byte4 && this.Equals(byte4);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Byte4 other)
{
return this == other;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Byte4 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <summary>
/// Returns a string representation of the current instance.
/// </summary>
/// <returns>String that represents the object.</returns>
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("x8");
var vector = this.ToVector4();
return FormattableString.Invariant($"Bgra5551({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
/// <summary>
@ -226,18 +150,18 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The <see cref="uint"/> containing the packed values.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
const float Max = 255F;
const float Min = 0F;
// Clamp the value between min and max values
// TODO: Use Vector4.Clamp() here!
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;
vector = Vector4.Clamp(vector, Vector4.Zero, new Vector4(Max));
uint byte4 = (uint)Math.Round(vector.X) & 0xFF;
uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 0x8;
uint byte2 = ((uint)Math.Round(vector.Z) & 0xFF) << 0x10;
uint byte1 = ((uint)Math.Round(vector.W) & 0xFF) << 0x18;
return byte4 | byte3 | byte2 | byte1;
}

177
src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Argb32
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Argb32>
{
/// <inheritdoc />
internal override void PackFromArgb32(ReadOnlySpan<Argb32> source, Span<Argb32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Argb32> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Argb32> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Argb32> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Argb32> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Argb32> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Argb32> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Argb32> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Argb32> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Argb32> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Argb32> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromArgb32(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Argb32
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Argb32>
{
/// <inheritdoc />
internal override void PackFromArgb32(ReadOnlySpan<Argb32> source, Span<Argb32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Argb32> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

177
src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Bgr24
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Bgr24>
{
/// <inheritdoc />
internal override void PackFromBgr24(ReadOnlySpan<Bgr24> source, Span<Bgr24> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Bgr24> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Bgr24> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Bgr24> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Bgr24> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Bgr24> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Bgr24> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Bgr24> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Bgr24> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Bgr24> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Bgr24> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgr24(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Bgr24
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Bgr24>
{
/// <inheritdoc />
internal override void PackFromBgr24(ReadOnlySpan<Bgr24> source, Span<Bgr24> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Bgr24> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

177
src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Bgra32
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Bgra32>
{
/// <inheritdoc />
internal override void PackFromBgra32(ReadOnlySpan<Bgra32> source, Span<Bgra32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Bgra32> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Bgra32> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Bgra32> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Bgra32> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Bgra32> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Bgra32> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Bgra32> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Bgra32> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Bgra32> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Bgra32> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBgra32(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Bgra32
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Bgra32>
{
/// <inheritdoc />
internal override void PackFromBgra32(ReadOnlySpan<Bgra32> source, Span<Bgra32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Bgra32> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

177
src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Gray16
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Gray16>
{
/// <inheritdoc />
internal override void PackFromGray16(ReadOnlySpan<Gray16> source, Span<Gray16> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Gray16> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Gray16> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Gray16> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Gray16> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Gray16> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Gray16> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Gray16> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Gray16> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Gray16> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Gray16> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray16(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Gray16
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Gray16>
{
/// <inheritdoc />
internal override void PackFromGray16(ReadOnlySpan<Gray16> source, Span<Gray16> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Gray16> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

177
src/ImageSharp/PixelFormats/Generated/Gray8.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Gray8
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Gray8>
{
/// <inheritdoc />
internal override void PackFromGray8(ReadOnlySpan<Gray8> source, Span<Gray8> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Gray8> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Gray8> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Gray8> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Gray8> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Gray8> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Gray8> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Gray8> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Gray8> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Gray8> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Gray8.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Gray8> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Gray8 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromGray8(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Gray8
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Gray8>
{
/// <inheritdoc />
internal override void PackFromGray8(ReadOnlySpan<Gray8> source, Span<Gray8> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Gray8> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

621
src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs

@ -10,296 +10,357 @@ namespace SixLabors.ImageSharp.PixelFormats
public partial class PixelOperations<TPixel>
{
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgba64"/> data to a span of <typeparamref name="TPixel"/>-s.
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Argb32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgba64"/> data.</param>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Argb32"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromRgba64(ReadOnlySpan<Rgba64> source, Span<TPixel> destPixels, int count)
internal virtual void PackFromArgb32(ReadOnlySpan<Argb32> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Rgba64>.Black;
ref Argb32 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba64(temp);
ref Argb32 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromArgb32(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgba64(ReadOnlySpan{Rgba64}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgba64"/> layout.
/// <summary>
/// A helper for <see cref="PackFromArgb32(ReadOnlySpan{Argb32}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Argb32"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromRgba64Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
internal void PackFromArgb32Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgba64(MemoryMarshal.Cast<byte, Rgba64>(sourceBytes), destPixels, count);
this.PackFromArgb32(MemoryMarshal.Cast<byte, Argb32>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgba64"/>-s.
/// Bulk version of <see cref="IPixel.ToRgba64(ref Rgba64)"/>.
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Argb32"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Rgba64"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Argb32"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgba64(ReadOnlySpan<TPixel> sourcePixels, Span<Rgba64> dest, int count)
internal virtual void ToArgb32(ReadOnlySpan<TPixel> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Argb32 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToRgba64(ref dp);
ref Argb32 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="ToRgba64(ReadOnlySpan{TPixel}, Span{Rgba64}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgba64"/> layout.
/// <summary>
/// A helper for <see cref="ToArgb32(ReadOnlySpan{TPixel}, Span{Argb32}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Argb32"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgba64Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToArgb32Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToRgba64(sourceColors, MemoryMarshal.Cast<byte, Rgba64>(destBytes), count);
this.ToArgb32(sourcePixels, MemoryMarshal.Cast<byte, Argb32>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgb48"/> data to a span of <typeparamref name="TPixel"/>-s.
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Bgr24"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgb48"/> data.</param>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Bgr24"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromRgb48(ReadOnlySpan<Rgb48> source, Span<TPixel> destPixels, int count)
internal virtual void PackFromBgr24(ReadOnlySpan<Bgr24> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Rgb48>.Black;
ref Bgr24 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgb48(temp);
ref Bgr24 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromBgr24(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgb48(ReadOnlySpan{Rgb48}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgb48"/> layout.
/// <summary>
/// A helper for <see cref="PackFromBgr24(ReadOnlySpan{Bgr24}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Bgr24"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromRgb48Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
internal void PackFromBgr24Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgb48(MemoryMarshal.Cast<byte, Rgb48>(sourceBytes), destPixels, count);
this.PackFromBgr24(MemoryMarshal.Cast<byte, Bgr24>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgb48"/>-s.
/// Bulk version of <see cref="IPixel.ToRgb48(ref Rgb48)"/>.
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Bgr24"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Rgb48"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Bgr24"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgb48(ReadOnlySpan<TPixel> sourcePixels, Span<Rgb48> dest, int count)
internal virtual void ToBgr24(ReadOnlySpan<TPixel> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Bgr24 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToRgb48(ref dp);
ref Bgr24 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="ToRgb48(ReadOnlySpan{TPixel}, Span{Rgb48}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgb48"/> layout.
/// <summary>
/// A helper for <see cref="ToBgr24(ReadOnlySpan{TPixel}, Span{Bgr24}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Bgr24"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgb48Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToBgr24Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToRgb48(sourceColors, MemoryMarshal.Cast<byte, Rgb48>(destBytes), count);
this.ToBgr24(sourcePixels, MemoryMarshal.Cast<byte, Bgr24>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgba32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Bgra32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgba32"/> data.</param>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Bgra32"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromRgba32(ReadOnlySpan<Rgba32> source, Span<TPixel> destPixels, int count)
internal virtual void PackFromBgra32(ReadOnlySpan<Bgra32> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Rgba32>.Black;
ref Bgra32 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba32(temp);
ref Bgra32 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromBgra32(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgba32(ReadOnlySpan{Rgba32}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgba32"/> layout.
/// <summary>
/// A helper for <see cref="PackFromBgra32(ReadOnlySpan{Bgra32}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Bgra32"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromRgba32Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
internal void PackFromBgra32Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgba32(MemoryMarshal.Cast<byte, Rgba32>(sourceBytes), destPixels, count);
this.PackFromBgra32(MemoryMarshal.Cast<byte, Bgra32>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgba32"/>-s.
/// Bulk version of <see cref="IPixel.ToRgba32(ref Rgba32)"/>.
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Bgra32"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Rgba32"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Bgra32"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgba32(ReadOnlySpan<TPixel> sourcePixels, Span<Rgba32> dest, int count)
internal virtual void ToBgra32(ReadOnlySpan<TPixel> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Bgra32 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToRgba32(ref dp);
ref Bgra32 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="ToRgba32(ReadOnlySpan{TPixel}, Span{Rgba32}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgba32"/> layout.
/// <summary>
/// A helper for <see cref="ToBgra32(ReadOnlySpan{TPixel}, Span{Bgra32}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Bgra32"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgba32Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToBgra32Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToRgba32(sourceColors, MemoryMarshal.Cast<byte, Rgba32>(destBytes), count);
this.ToBgra32(sourcePixels, MemoryMarshal.Cast<byte, Bgra32>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Bgra32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Gray8"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Bgra32"/> data.</param>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Gray8"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromBgra32(ReadOnlySpan<Bgra32> source, Span<TPixel> destPixels, int count)
internal virtual void PackFromGray8(ReadOnlySpan<Gray8> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
ref Gray8 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Bgra32>.Black;
for (int i = 0; i < count; i++)
{
ref Gray8 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromGray8(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromGray8(ReadOnlySpan{Gray8}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Gray8"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromGray8Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromGray8(MemoryMarshal.Cast<byte, Gray8>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Gray8"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="destPixels">The destination span of <see cref="Gray8"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToGray8(ReadOnlySpan<TPixel> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp = Unsafe.Add(ref sourceRef, i);
dp.PackFromBgra32(temp);
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="PackFromBgra32(ReadOnlySpan{Bgra32}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Bgra32"/> layout.
/// <summary>
/// A helper for <see cref="ToGray8(ReadOnlySpan{TPixel}, Span{Gray8}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Gray8"/> layout.
/// </summary>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToGray8Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToGray8(sourcePixels, MemoryMarshal.Cast<byte, Gray8>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Gray16"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Gray16"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromGray16(ReadOnlySpan<Gray16> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Gray16 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Gray16 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromGray16(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromGray16(ReadOnlySpan{Gray16}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Gray16"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromBgra32Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
internal void PackFromGray16Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromBgra32(MemoryMarshal.Cast<byte, Bgra32>(sourceBytes), destPixels, count);
this.PackFromGray16(MemoryMarshal.Cast<byte, Gray16>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Bgra32"/>-s.
/// Bulk version of <see cref="IPixel.ToBgra32(ref Bgra32)"/>.
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Gray16"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Bgra32"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Gray16"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToBgra32(ReadOnlySpan<TPixel> sourcePixels, Span<Bgra32> dest, int count)
internal virtual void ToGray16(ReadOnlySpan<TPixel> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Gray16 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToBgra32(ref dp);
ref Gray16 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="ToBgra32(ReadOnlySpan{TPixel}, Span{Bgra32}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Bgra32"/> layout.
/// <summary>
/// A helper for <see cref="ToGray16(ReadOnlySpan{TPixel}, Span{Gray16}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Gray16"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToBgra32Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToGray16Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToBgra32(sourceColors, MemoryMarshal.Cast<byte, Bgra32>(destBytes), count);
this.ToGray16(sourcePixels, MemoryMarshal.Cast<byte, Gray16>(destBytes), count);
}
/// <summary>
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgb24"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgb24"/> data.</param>
@ -307,23 +368,21 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromRgb24(ReadOnlySpan<Rgb24> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Rgba32>.Black;
ref Rgb24 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp.Rgb = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba32(temp);
ref Rgb24 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromRgb24(sp);
}
}
/// <summary>
/// <summary>
/// A helper for <see cref="PackFromRgb24(ReadOnlySpan{Rgb24}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgb24"/> layout.
/// </summary>
@ -335,186 +394,250 @@ namespace SixLabors.ImageSharp.PixelFormats
{
this.PackFromRgb24(MemoryMarshal.Cast<byte, Rgb24>(sourceBytes), destPixels, count);
}
/// <summary>
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgb24"/>-s.
/// Bulk version of <see cref="IPixel.ToRgb24(ref Rgb24)"/>.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Rgb24"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Rgb24"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgb24(ReadOnlySpan<TPixel> sourcePixels, Span<Rgb24> dest, int count)
internal virtual void ToRgb24(ReadOnlySpan<TPixel> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Rgb24 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToRgb24(ref dp);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// <summary>
/// A helper for <see cref="ToRgb24(ReadOnlySpan{TPixel}, Span{Rgb24}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgb24"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgb24Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgb24Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToRgb24(sourceColors, MemoryMarshal.Cast<byte, Rgb24>(destBytes), count);
this.ToRgb24(sourcePixels, MemoryMarshal.Cast<byte, Rgb24>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Bgr24"/> data to a span of <typeparamref name="TPixel"/>-s.
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgba32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Bgr24"/> data.</param>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgba32"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromBgr24(ReadOnlySpan<Bgr24> source, Span<TPixel> destPixels, int count)
internal virtual void PackFromRgba32(ReadOnlySpan<Rgba32> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Rgba32>.Black;
ref Rgba32 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp.Bgr = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba32(temp);
ref Rgba32 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromRgba32(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromBgr24(ReadOnlySpan{Bgr24}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Bgr24"/> layout.
/// <summary>
/// A helper for <see cref="PackFromRgba32(ReadOnlySpan{Rgba32}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgba32"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromBgr24Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
internal void PackFromRgba32Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromBgr24(MemoryMarshal.Cast<byte, Bgr24>(sourceBytes), destPixels, count);
this.PackFromRgba32(MemoryMarshal.Cast<byte, Rgba32>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Bgr24"/>-s.
/// Bulk version of <see cref="IPixel.ToBgr24(ref Bgr24)"/>.
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgba32"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Bgr24"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Rgba32"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToBgr24(ReadOnlySpan<TPixel> sourcePixels, Span<Bgr24> dest, int count)
internal virtual void ToRgba32(ReadOnlySpan<TPixel> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Rgba32 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToBgr24(ref dp);
ref Rgba32 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="ToBgr24(ReadOnlySpan{TPixel}, Span{Bgr24}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Bgr24"/> layout.
/// <summary>
/// A helper for <see cref="ToRgba32(ReadOnlySpan{TPixel}, Span{Rgba32}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgba32"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToBgr24Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgba32Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToBgr24(sourceColors, MemoryMarshal.Cast<byte, Bgr24>(destBytes), count);
this.ToRgba32(sourcePixels, MemoryMarshal.Cast<byte, Rgba32>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Argb32"/> data to a span of <typeparamref name="TPixel"/>-s.
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgb48"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Argb32"/> data.</param>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgb48"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromArgb32(ReadOnlySpan<Argb32> source, Span<TPixel> destPixels, int count)
internal virtual void PackFromRgb48(ReadOnlySpan<Rgb48> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<Argb32>.Black;
ref Rgb48 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
temp = Unsafe.Add(ref sourceRef, i);
dp.PackFromArgb32(temp);
ref Rgb48 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromRgb48(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromArgb32(ReadOnlySpan{Argb32}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Argb32"/> layout.
/// <summary>
/// A helper for <see cref="PackFromRgb48(ReadOnlySpan{Rgb48}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgb48"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromArgb32Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
internal void PackFromRgb48Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromArgb32(MemoryMarshal.Cast<byte, Argb32>(sourceBytes), destPixels, count);
this.PackFromRgb48(MemoryMarshal.Cast<byte, Rgb48>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Argb32"/>-s.
/// Bulk version of <see cref="IPixel.ToArgb32(ref Argb32)"/>.
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgb48"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Argb32"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="Rgb48"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToArgb32(ReadOnlySpan<TPixel> sourcePixels, Span<Argb32> dest, int count)
internal virtual void ToRgb48(ReadOnlySpan<TPixel> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destBaseRef = ref MemoryMarshal.GetReference(dest);
ref Rgb48 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destBaseRef, i);
sp.ToArgb32(ref dp);
ref Rgb48 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// A helper for <see cref="ToArgb32(ReadOnlySpan{TPixel}, Span{Argb32}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Argb32"/> layout.
/// <summary>
/// A helper for <see cref="ToRgb48(ReadOnlySpan{TPixel}, Span{Rgb48}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgb48"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToArgb32Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgb48Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToRgb48(sourcePixels, MemoryMarshal.Cast<byte, Rgb48>(destBytes), count);
}
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="Rgba64"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgba64"/> data.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromRgba64(ReadOnlySpan<Rgba64> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgba64 sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromRgba64(sp);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgba64(ReadOnlySpan{Rgba64}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgba64"/> layout.
/// </summary>
/// <param name="sourceBytes">The <see cref="ReadOnlySpan{T}"/> to the source bytes.</param>
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void PackFromRgba64Bytes(ReadOnlySpan<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgba64(MemoryMarshal.Cast<byte, Rgba64>(sourceBytes), destPixels, count);
}
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgba64"/>-s.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="destPixels">The destination span of <see cref="Rgba64"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgba64(ReadOnlySpan<TPixel> sourcePixels, Span<Rgba64> destPixels, int count)
{
this.ToArgb32(sourceColors, MemoryMarshal.Cast<byte, Argb32>(destBytes), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
}
/// <summary>
/// A helper for <see cref="ToRgba64(ReadOnlySpan{TPixel}, Span{Rgba64}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgba64"/> layout.
/// </summary>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void ToRgba64Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.ToRgba64(sourcePixels, MemoryMarshal.Cast<byte, Rgba64>(destBytes), count);
}
}
}

92
src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt

@ -11,11 +11,11 @@
<#@ output extension=".cs" #>
<#
void GeneratePackFromMethods(string pixelType, string tempPixelType, string assignToTempCode)
void GeneratePackFromMethods(string pixelType)
{
#>
/// <summary>
/// <summary>
/// Converts 'count' elements in 'source` span of <see cref="<#=pixelType#>"/> data to a span of <typeparamref name="TPixel"/>-s.
/// </summary>
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="<#=pixelType#>"/> data.</param>
@ -23,23 +23,21 @@
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source);
ref TPixel destRef = ref MemoryMarshal.GetReference(destPixels);
// For conversion methods writing only to RGB channels, we need to keep the alpha channel opaque!
var temp = NamedColors<<#=tempPixelType#>>.Black;
ref <#=pixelType#> sourceBaseRef = ref MemoryMarshal.GetReference(source);
ref TPixel destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
<#=assignToTempCode#>
dp.PackFrom<#=tempPixelType#>(temp);
ref <#=pixelType#> sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref TPixel dp = ref Unsafe.Add(ref destBaseRef, i);
dp.PackFrom<#=pixelType#>(sp);
}
}
/// <summary>
/// <summary>
/// A helper for <see cref="PackFrom<#=pixelType#>(ReadOnlySpan{<#=pixelType#>}, Span{TPixel}, int)"/> that expects a byte span.
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="<#=pixelType#>"/> layout.
/// </summary>
@ -51,48 +49,48 @@
{
this.PackFrom<#=pixelType#>(MemoryMarshal.Cast<byte, <#=pixelType#>>(sourceBytes), destPixels, count);
}
<#
<#
}
void GenerateToDestFormatMethods(string pixelType)
{
#>
/// <summary>
/// <summary>
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="<#=pixelType#>"/>-s.
/// Bulk version of <see cref="IPixel.To<#=pixelType#>(ref <#=pixelType#>)"/>.
/// </summary>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="<#=pixelType#>"/> data.</param>
/// <param name="destPixels">The destination span of <see cref="<#=pixelType#>"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void To<#=pixelType#>(ReadOnlySpan<TPixel> sourcePixels, Span<<#=pixelType#>> dest, int count)
internal virtual void To<#=pixelType#>(ReadOnlySpan<TPixel> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref TPixel sourceBaseRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destBaseRef = ref MemoryMarshal.GetReference(dest);
ref <#=pixelType#> destBaseRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destBaseRef, i);
sp.To<#=pixelType#>(ref dp);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// <summary>
/// A helper for <see cref="To<#=pixelType#>(ReadOnlySpan{TPixel}, Span{<#=pixelType#>}, int)"/> that expects a byte span as destination.
/// The layout of the data in 'destBytes' must be compatible with <see cref="<#=pixelType#>"/> layout.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="sourcePixels">The <see cref="Span{T}"/> to the source pixels.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void To<#=pixelType#>Bytes(ReadOnlySpan<TPixel> sourceColors, Span<byte> destBytes, int count)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void To<#=pixelType#>Bytes(ReadOnlySpan<TPixel> sourcePixels, Span<byte> destBytes, int count)
{
this.To<#=pixelType#>(sourceColors, MemoryMarshal.Cast<byte, <#=pixelType#>>(destBytes), count);
this.To<#=pixelType#>(sourcePixels, MemoryMarshal.Cast<byte, <#=pixelType#>>(destBytes), count);
}
<#
<#
}
#>
@ -107,30 +105,34 @@ namespace SixLabors.ImageSharp.PixelFormats
using System.Runtime.InteropServices;
public partial class PixelOperations<TPixel>
{
<#
GeneratePackFromMethods("Rgba64", "Rgba64", "temp = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgba64");
{<#
GeneratePackFromMethods("Rgb48", "Rgb48", "temp = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgb48");
GeneratePackFromMethods("Argb32");
GenerateToDestFormatMethods("Argb32");
GeneratePackFromMethods("Rgba32", "Rgba32", "temp = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgba32");
GeneratePackFromMethods("Bgr24");
GenerateToDestFormatMethods("Bgr24");
GeneratePackFromMethods("Bgra32", "Bgra32", "temp = Unsafe.Add(ref sourceRef, i);");
GeneratePackFromMethods("Bgra32");
GenerateToDestFormatMethods("Bgra32");
GeneratePackFromMethods("Rgb24", "Rgba32", "temp.Rgb = Unsafe.Add(ref sourceRef, i);");
GeneratePackFromMethods("Gray8");
GenerateToDestFormatMethods("Gray8");
GeneratePackFromMethods("Gray16");
GenerateToDestFormatMethods("Gray16");
GeneratePackFromMethods("Rgb24");
GenerateToDestFormatMethods("Rgb24");
GeneratePackFromMethods("Bgr24", "Rgba32", "temp.Bgr = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Bgr24");
GeneratePackFromMethods("Rgba32");
GenerateToDestFormatMethods("Rgba32");
GeneratePackFromMethods("Argb32", "Argb32", "temp = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Argb32");
#>
GeneratePackFromMethods("Rgb48");
GenerateToDestFormatMethods("Rgb48");
}
GeneratePackFromMethods("Rgba64");
GenerateToDestFormatMethods("Rgba64");
#> }
}

177
src/ImageSharp/PixelFormats/Generated/Rgb24.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgb24
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Rgb24>
{
/// <inheritdoc />
internal override void PackFromRgb24(ReadOnlySpan<Rgb24> source, Span<Rgb24> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Rgb24> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Rgb24> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Rgb24> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Rgb24> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Rgb24> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Rgb24> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Rgb24> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Rgb24> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Rgb24> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Rgb24.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Rgb24> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb24(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgb24
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Rgb24>
{
/// <inheritdoc />
internal override void PackFromRgb24(ReadOnlySpan<Rgb24> source, Span<Rgb24> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Rgb24> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

177
src/ImageSharp/PixelFormats/Generated/Rgb48.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgb48
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Rgb48>
{
/// <inheritdoc />
internal override void PackFromRgb48(ReadOnlySpan<Rgb48> source, Span<Rgb48> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Rgb48> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Rgb48> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Rgb48> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Rgb48> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Rgb48> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Rgb48> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Rgb48> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Rgb48> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Rgb48> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Rgb48.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Rgb48> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb48 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb48 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgb48(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgb48
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Rgb48>
{
/// <inheritdoc />
internal override void PackFromRgb48(ReadOnlySpan<Rgb48> source, Span<Rgb48> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Rgb48> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgba64");
#>
}
}
}

124
src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs

@ -13,134 +13,162 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </content>
public partial struct Rgba32
{
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
internal partial class PixelOperations
{
/// <inheritdoc />
internal override void PackFromRgba32(ReadOnlySpan<Rgba32> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void PackFromRgb24(ReadOnlySpan<Rgb24> source, Span<Rgba32> destPixels, int count)
internal override void ToArgb32(ReadOnlySpan<Rgba32> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref MemoryMarshal.GetReference(source);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
Unsafe.As<Rgba32, Rgb24>(ref dp) = sp; dp.A = 255;
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgb24> dest, int count)
internal override void ToBgr24(ReadOnlySpan<Rgba32> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(dest);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp = Unsafe.As<Rgba32, Rgb24>(ref sp);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void PackFromBgr24(ReadOnlySpan<Bgr24> source, Span<Rgba32> destPixels, int count)
internal override void ToBgra32(ReadOnlySpan<Rgba32> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(source);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.Bgr = sp; dp.A = 255;
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Rgba32> sourcePixels, Span<Bgr24> dest, int count)
internal override void ToGray8(ReadOnlySpan<Rgba32> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(dest);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.Bgr;
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void PackFromBgra32(ReadOnlySpan<Bgra32> source, Span<Rgba32> destPixels, int count)
internal override void ToGray16(ReadOnlySpan<Rgba32> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(source);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToRgba32();
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Rgba32> sourcePixels, Span<Bgra32> dest, int count)
internal override void ToRgb24(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(dest);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToBgra32();
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void PackFromArgb32(ReadOnlySpan<Argb32> source, Span<Rgba32> destPixels, int count)
internal override void ToRgb48(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Argb32 sourceRef = ref MemoryMarshal.GetReference(source);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToRgba32();
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Rgba32> sourcePixels, Span<Argb32> dest, int count)
internal override void ToRgba64(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(dest);
ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToArgb32();
ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba32(sp);
}
}

70
src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt

@ -9,45 +9,24 @@
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GeneratePackFromMethod(string pixelType, string converterCode)
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void PackFrom<#=pixelType#>(ReadOnlySpan<<#=pixelType#>> source, Span<Rgba32> destPixels, int count)
internal override void To<#=pixelType#>(ReadOnlySpan<Rgba32> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref <#=pixelType#> sourceRef = ref MemoryMarshal.GetReference(source);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref <#=pixelType#> sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
<#=converterCode#>
}
}
<#
}
void GenerateConvertToMethod(string pixelType, string converterCode)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Rgba32> sourcePixels, Span<<#=pixelType#>> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(dest);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
<#=converterCode#>
dp.PackFromRgba32(sp);
}
}
<#
@ -68,20 +47,37 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </content>
public partial struct Rgba32
{
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
internal partial class PixelOperations
{
<#
GeneratePackFromMethod("Rgb24", "Unsafe.As<Rgba32, Rgb24>(ref dp) = sp; dp.A = 255;");
GenerateConvertToMethod("Rgb24", "dp = Unsafe.As<Rgba32, Rgb24>(ref sp);");
/// <inheritdoc />
internal override void PackFromRgba32(ReadOnlySpan<Rgba32> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
GeneratePackFromMethod("Bgr24", "dp.Bgr = sp; dp.A = 255;");
GenerateConvertToMethod("Bgr24", "dp = sp.Bgr;");
GeneratePackFromMethod("Bgra32", "dp = sp.ToRgba32();");
GenerateConvertToMethod("Bgra32", "dp = sp.ToBgra32();");
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
GeneratePackFromMethod("Argb32", "dp = sp.ToRgba32();");
GenerateConvertToMethod("Argb32", "dp = sp.ToArgb32();");
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgb48");
GenerateConvertToMethod("Rgba64");
#>
}

177
src/ImageSharp/PixelFormats/Generated/Rgba64.PixelOperations.Generated.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgba64
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Rgba64>
{
/// <inheritdoc />
internal override void PackFromRgba64(ReadOnlySpan<Rgba64> source, Span<Rgba64> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Rgba64> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToArgb32(ReadOnlySpan<Rgba64> sourcePixels, Span<Argb32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToBgr24(ReadOnlySpan<Rgba64> sourcePixels, Span<Bgr24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToBgra32(ReadOnlySpan<Rgba64> sourcePixels, Span<Bgra32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToGray8(ReadOnlySpan<Rgba64> sourcePixels, Span<Gray8> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToGray16(ReadOnlySpan<Rgba64> sourcePixels, Span<Gray16> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToRgb24(ReadOnlySpan<Rgba64> sourcePixels, Span<Rgb24> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Rgba64> sourcePixels, Span<Rgba32> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
/// <inheritdoc />
internal override void ToRgb48(ReadOnlySpan<Rgba64> sourcePixels, Span<Rgb48> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
}
}
}

85
src/ImageSharp/PixelFormats/Generated/Rgba64.PixelOperations.Generated.tt

@ -0,0 +1,85 @@
<#
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
#>
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
void GenerateConvertToMethod(string pixelType)
{
#>
/// <inheritdoc />
internal override void To<#=pixelType#>(ReadOnlySpan<Rgba64> sourcePixels, Span<<#=pixelType#>> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
ref Rgba64 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
for (int i = 0; i < count; i++)
{
ref Rgba64 sp = ref Unsafe.Add(ref sourceRef, i);
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromRgba64(sp);
}
}
<#
}
#>
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
namespace SixLabors.ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgba64
{
/// <summary>
/// Provides optimized overrides for bulk operations.
/// </summary>
internal class PixelOperations : PixelOperations<Rgba64>
{
/// <inheritdoc />
internal override void PackFromRgba64(ReadOnlySpan<Rgba64> source, Span<Rgba64> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgba64(ReadOnlySpan<Rgba64> sourcePixels, Span<Rgba64> destPixels, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
sourcePixels.Slice(0, count).CopyTo(destPixels);
}
<#
GenerateConvertToMethod("Argb32");
GenerateConvertToMethod("Bgr24");
GenerateConvertToMethod("Bgra32");
GenerateConvertToMethod("Gray8");
GenerateConvertToMethod("Gray16");
GenerateConvertToMethod("Rgb24");
GenerateConvertToMethod("Rgba32");
GenerateConvertToMethod("Rgb48");
#>
}
}
}

177
src/ImageSharp/PixelFormats/Gray16.cs

@ -0,0 +1,177 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.PixelFormats
{
/// <summary>
/// Packed pixel type containing a single 16 bit normalized gray values.
/// <para>
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
/// </para>
/// </summary>
public partial struct Gray16 : IPixel<Gray16>, IPackedVector<ushort>
{
private const float Max = ushort.MaxValue;
private const float Average = 1 / 3F;
/// <summary>
/// Initializes a new instance of the <see cref="Gray16"/> struct.
/// </summary>
/// <param name="luminance">The luminance component</param>
public Gray16(ushort luminance) => this.PackedValue = luminance;
/// <inheritdoc />
public ushort PackedValue { get; set; }
/// <summary>
/// Compares two <see cref="Gray16"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Gray16"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Gray16"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Gray16 left, Gray16 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Gray16"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Gray16"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Gray16"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Gray16 left, Gray16 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Gray16> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max * Average;
this.PackedValue = (ushort)MathF.Round(vector.X + vector.Y + vector.Z);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
float scaled = this.PackedValue / Max;
return new Vector4(scaled, scaled, scaled, 1F);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackedValue = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackedValue = source.PackedValue;
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32()
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(this.PackedValue);
return new Rgba32(rgb, rgb, rgb, byte.MaxValue);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackedValue = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackedValue = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc />
public override bool Equals(object obj) => obj is Gray16 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Gray16 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString() => $"Gray16({this.PackedValue})";
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
(ushort)MathF.Round(vector.X),
(ushort)MathF.Round(vector.Y),
(ushort)MathF.Round(vector.Z));
}
}
}

152
src/ImageSharp/PixelFormats/Gray8.cs

@ -0,0 +1,152 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.PixelFormats
{
/// <summary>
/// Packed pixel type containing a single 8 bit normalized gray values.
/// <para>
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
/// </para>
/// </summary>
public partial struct Gray8 : IPixel<Gray8>, IPackedVector<byte>
{
private static readonly Vector4 MaxBytes = new Vector4(255F);
private static readonly Vector4 Half = new Vector4(0.5F);
private const float Average = 1 / 3F;
/// <summary>
/// Initializes a new instance of the <see cref="Gray8"/> struct.
/// </summary>
/// <param name="luminance">The luminance component.</param>
public Gray8(byte luminance) => this.PackedValue = luminance;
/// <inheritdoc />
public byte PackedValue { get; set; }
/// <summary>
/// Compares two <see cref="Gray8"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Gray8"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Gray8"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Gray8 left, Gray8 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Gray8"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Gray8"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Gray8"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Gray8 left, Gray8 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Gray8> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes) * Average;
this.PackedValue = (byte)(vector.X + vector.Y + vector.Z);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
float rgb = this.PackedValue / 255F;
return new Vector4(rgb, rgb, rgb, 1F);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackedValue = source.PackedValue;
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.PackedValue, this.PackedValue, this.PackedValue, byte.MaxValue);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
=> this.PackedValue = ImageMaths.Get8BitBT709Luminance(
ImageMaths.DownScaleFrom16BitTo8Bit(source.R),
ImageMaths.DownScaleFrom16BitTo8Bit(source.G),
ImageMaths.DownScaleFrom16BitTo8Bit(source.B));
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
=> this.PackedValue = ImageMaths.Get8BitBT709Luminance(
ImageMaths.DownScaleFrom16BitTo8Bit(source.R),
ImageMaths.DownScaleFrom16BitTo8Bit(source.G),
ImageMaths.DownScaleFrom16BitTo8Bit(source.B));
/// <inheritdoc />
public override bool Equals(object obj) => obj is Gray8 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Gray8 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString() => $"Gray8({this.PackedValue}";
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
this.PackedValue = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
}
}
}

202
src/ImageSharp/PixelFormats/HalfSingle.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@ -14,24 +15,11 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct HalfSingle : IPixel<HalfSingle>, IPackedVector<ushort>
{
/// <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);
}
public HalfSingle(float single) => this.PackedValue = HalfTypeHelper.Pack(single);
/// <inheritdoc/>
public ushort PackedValue { get; set; }
@ -39,206 +27,114 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(HalfSingle left, HalfSingle right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(HalfSingle left, HalfSingle right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(HalfSingle left, HalfSingle right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(HalfSingle left, HalfSingle right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<HalfSingle> CreatePixelOperations() => new PixelOperations<HalfSingle>();
/// <summary>
/// Expands the packed representation into a <see cref="float"/>.
/// </summary>
/// <returns>The <see cref="float"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float ToSingle()
{
return HalfTypeHelper.Unpack(this.PackedValue);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
float scaled = vector.X;
scaled *= 2F;
scaled -= 1F;
scaled--;
this.PackedValue = HalfTypeHelper.Pack(scaled);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
float single = this.ToSingle() + 1F;
single /= 2F;
return new Vector4(single, 0, 0, 1);
return new Vector4(single, 0, 0, 1F);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = HalfTypeHelper.Pack(vector.X);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = HalfTypeHelper.Pack(vector.X);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.ToSingle(), 0, 0, 1);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.ToSingle(), 0, 0, 1F);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <summary>
/// Expands the packed representation into a <see cref="float"/>.
/// </summary>
/// <returns>The <see cref="float"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public float ToSingle() => HalfTypeHelper.Unpack(this.PackedValue);
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is HalfSingle other && this.Equals(other);
}
public override bool Equals(object obj) => obj is HalfSingle other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(HalfSingle other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(HalfSingle other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString()
{
return this.ToSingle().ToString();
}
public override string ToString() => FormattableString.Invariant($"HalfSingle({this.ToSingle():#0.##})");
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

12
src/ImageSharp/PixelFormats/HalfTypeHelper.cs

@ -9,7 +9,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <summary>
/// Helper methods for packing and unpacking floating point values
/// </summary>
internal class HalfTypeHelper
internal static class HalfTypeHelper
{
/// <summary>
/// Packs a <see cref="float"/> into an <see cref="ushort"/>
@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.PixelFormats
return (ushort)s;
}
m = m | 0x00800000;
m |= 0x00800000;
int t = 14 - e;
int a = (1 << (t - 1)) - 1;
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.PixelFormats
if ((m & 0x00800000) != 0)
{
m = 0;
e += 1;
e++;
}
if (e > 30)
@ -97,11 +97,11 @@ namespace SixLabors.ImageSharp.PixelFormats
while ((mantissa & 1024) == 0)
{
exponent--;
mantissa = mantissa << 1;
mantissa <<= 1;
}
mantissa &= 0xfffffbff;
result = ((uint)((((uint)value & 0x8000) << 16) | ((exponent + 127) << 23))) | (mantissa << 13);
result = (((uint)value & 0x8000) << 16) | ((exponent + 127) << 23) | (mantissa << 13);
}
else
{
@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
else
{
result = ((((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0x1f) - 15) + 127) << 23)) | (mantissa << 13);
result = (((uint)value & 0x8000) << 16) | ((((((uint)value >> 10) & 0x1f) - 15) + 127) << 23) | (mantissa << 13);
}
var uif = new Uif { U = result };

216
src/ImageSharp/PixelFormats/HalfVector2.cs

@ -15,34 +15,18 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct HalfVector2 : IPixel<HalfVector2>, IPackedVector<uint>
{
/// <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);
}
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);
}
public HalfVector2(Vector2 vector) => this.PackedValue = Pack(vector.X, vector.Y);
/// <inheritdoc/>
public uint PackedValue { get; set; }
@ -50,57 +34,30 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(HalfVector2 left, HalfVector2 right)
{
return left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(HalfVector2 left, HalfVector2 right) => 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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(HalfVector2 left, HalfVector2 right)
{
return !left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(HalfVector2 left, HalfVector2 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<HalfVector2> CreatePixelOperations() => new PixelOperations<HalfVector2>();
/// <summary>
/// Expands the packed representation into a <see cref="Vector2"/>.
/// </summary>
/// <returns>The <see cref="Vector2"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 ToVector2()
{
Vector2 vector;
vector.X = HalfTypeHelper.Unpack((ushort)this.PackedValue);
vector.Y = HalfTypeHelper.Unpack((ushort)(this.PackedValue >> 0x10));
return vector;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F;
@ -109,7 +66,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector2();
@ -119,14 +76,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(vector.X, vector.Y);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
var vector = this.ToVector2();
@ -134,140 +88,82 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override string ToString()
/// <summary>
/// Expands the packed representation into a <see cref="Vector2"/>.
/// </summary>
/// <returns>The <see cref="Vector2"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector2 ToVector2()
{
return this.ToVector2().ToString();
Vector2 vector;
vector.X = HalfTypeHelper.Unpack((ushort)this.PackedValue);
vector.Y = HalfTypeHelper.Unpack((ushort)(this.PackedValue >> 0x10));
return vector;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
public override bool Equals(object obj) => obj is HalfVector2 other && this.Equals(other);
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is HalfVector2 other && this.Equals(other);
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(HalfVector2 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(HalfVector2 other)
public override string ToString()
{
return this.PackedValue.Equals(other.PackedValue);
var vector = this.ToVector2();
return FormattableString.Invariant($"HalfVector2({vector.X:#0.##}, {vector.Y:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(float x, float y)
{
uint num2 = HalfTypeHelper.Pack(x);
uint num = (uint)(HalfTypeHelper.Pack(y) << 0x10);
return num2 | num;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

188
src/ImageSharp/PixelFormats/HalfVector4.cs

@ -15,16 +15,6 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct HalfVector4 : IPixel<HalfVector4>, IPackedVector<ulong>
{
/// <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>
@ -33,64 +23,46 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="z">The z-component.</param>
/// <param name="w">The w-component.</param>
public HalfVector4(float x, float y, float z, float w)
: this(new Vector4(x, y, z, w))
{
var 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);
}
public HalfVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc/>
public ulong PackedValue { get; set; }
/// <summary>
/// Compares two <see cref="HalfVector2"/> objects for equality.
/// Compares two <see cref="HalfVector4"/> 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>
/// <param name="left">The <see cref="HalfVector4"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="HalfVector4"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(HalfVector4 left, HalfVector4 right)
{
return left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(HalfVector4 left, HalfVector4 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="HalfVector2"/> objects for equality.
/// Compares two <see cref="HalfVector4"/> 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>
/// <param name="left">The <see cref="HalfVector4"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="HalfVector4"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(HalfVector4 left, HalfVector4 right)
{
return !left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(HalfVector4 left, HalfVector4 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<HalfVector4> CreatePixelOperations() => new PixelOperations<HalfVector4>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
vector *= 2F;
@ -99,7 +71,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector4();
@ -109,14 +81,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(ref vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@ -127,124 +96,69 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override string ToString()
{
return this.ToVector4().ToString();
}
public override bool Equals(object obj) => obj is HalfVector4 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(HalfVector4 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override bool Equals(object obj)
public override string ToString()
{
return obj is HalfVector4 other && this.Equals(other);
var vector = this.ToVector4();
return FormattableString.Invariant($"HalfVector4({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(HalfVector4 other)
{
return this.PackedValue.Equals(other.PackedValue);
}
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private static ulong Pack(ref Vector4 vector)
{
ulong num4 = HalfTypeHelper.Pack(vector.X);
@ -253,15 +167,5 @@ namespace SixLabors.ImageSharp.PixelFormats
ulong num1 = (ulong)HalfTypeHelper.Pack(vector.W) << 0x30;
return num4 | num3 | num2 | num1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

78
src/ImageSharp/PixelFormats/IPixel.cs

@ -28,12 +28,6 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public interface IPixel
{
/// <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>
/// Sets the packed representation from a scaled <see cref="Vector4"/>.
/// </summary>
@ -48,6 +42,12 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>The <see cref="Vector4"/>.</returns>
Vector4 ToScaledVector4();
/// <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.
@ -55,30 +55,18 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>The <see cref="Vector4"/>.</returns>
Vector4 ToVector4();
/// <summary>
/// Packs the pixel from an <see cref="Rgba32"/> value.
/// </summary>
/// <param name="source">The <see cref="Rgba32"/> value.</param>
void PackFromRgba32(Rgba32 source);
/// <summary>
/// Packs the pixel from an <see cref="Rgb48"/> value.
/// </summary>
/// <param name="source">The <see cref="Rgb48"/> value.</param>
void PackFromRgb48(Rgb48 source);
/// <summary>
/// Packs the pixel from an <see cref="Rgba64"/> value.
/// </summary>
/// <param name="source">The <see cref="Rgba64"/> value.</param>
void PackFromRgba64(Rgba64 source);
/// <summary>
/// Packs the pixel from an <see cref="Argb32"/> value.
/// </summary>
/// <param name="source">The <see cref="Argb32"/> value.</param>
void PackFromArgb32(Argb32 source);
/// <summary>
/// Packs the pixel from an <see cref="Bgr24"/> value.
/// </summary>
/// <param name="source">The <see cref="Bgr24"/> value.</param>
void PackFromBgr24(Bgr24 source);
/// <summary>
/// Packs the pixel from an <see cref="Bgra32"/> value.
/// </summary>
@ -86,45 +74,45 @@ namespace SixLabors.ImageSharp.PixelFormats
void PackFromBgra32(Bgra32 source);
/// <summary>
/// Converts the pixel to <see cref="Rgb24"/> format.
/// Packs the Pixel from an <see cref="Gray8"/> value.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToRgb24(ref Rgb24 dest);
/// <param name="source">The <see cref="Gray8"/> value.</param>
void PackFromGray8(Gray8 source);
/// <summary>
/// Converts the pixel to <see cref="Rgba32"/> format.
/// Packs the Pixel from an <see cref="Gray16"/> value.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToRgba32(ref Rgba32 dest);
/// <param name="source">The <see cref="Gray16"/> value.</param>
void PackFromGray16(Gray16 source);
/// <summary>
/// Converts the pixel to <see cref="Rgb48"/> format.
/// Packs the pixel from an <see cref="Rgb24"/> value.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToRgb48(ref Rgb48 dest);
/// <param name="source">The <see cref="Rgb24"/> value.</param>
void PackFromRgb24(Rgb24 source);
/// <summary>
/// Converts the pixel to <see cref="Rgba64"/> format.
/// Packs the pixel from an <see cref="Rgba32"/> value.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToRgba64(ref Rgba64 dest);
/// <param name="source">The <see cref="Rgba32"/> value.</param>
void PackFromRgba32(Rgba32 source);
/// <summary>
/// Converts the pixel to <see cref="Argb32"/> format.
/// Expands the packed representation into an <see cref="Rgba32"/>.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToArgb32(ref Argb32 dest);
/// <returns>The <see cref="Rgba32"/>.</returns>
Rgba32 ToRgba32();
/// <summary>
/// Converts the pixel to <see cref="Bgr24"/> format.
/// Packs the pixel from an <see cref="Rgb48"/> value.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToBgr24(ref Bgr24 dest);
/// <param name="source">The <see cref="Rgb48"/> value.</param>
void PackFromRgb48(Rgb48 source);
/// <summary>
/// Converts the pixel to <see cref="Bgra32"/> format.
/// Packs the pixel from an <see cref="Rgba64"/> value.
/// </summary>
/// <param name="dest">The destination pixel to write to</param>
void ToBgra32(ref Bgra32 dest);
/// <param name="source">The <see cref="Rgba64"/> value.</param>
void PackFromRgba64(Rgba64 source);
}
}

253
src/ImageSharp/PixelFormats/NormalizedByte2.cs

@ -15,39 +15,24 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct NormalizedByte2 : IPixel<NormalizedByte2>, IPackedVector<ushort>
{
/// <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);
private static readonly Vector2 Half = new Vector2(127);
private static readonly Vector2 MinusOne = new Vector2(-1F);
/// <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)
/// <param name="x">The x-component.</param>
/// <param name="y">The y-component.</param>
public NormalizedByte2(float x, float y)
: this(new Vector2(x, y))
{
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);
}
/// <param name="vector">The vector containing the component values.</param>
public NormalizedByte2(Vector2 vector) => this.PackedValue = Pack(vector);
/// <inheritdoc/>
public ushort PackedValue { get; set; }
@ -55,66 +40,39 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(NormalizedByte2 left, NormalizedByte2 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(NormalizedByte2 left, NormalizedByte2 right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(NormalizedByte2 left, NormalizedByte2 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(NormalizedByte2 left, NormalizedByte2 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<NormalizedByte2> CreatePixelOperations() => new PixelOperations<NormalizedByte2>();
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 ToVector2()
{
return new Vector2(
(sbyte)((this.PackedValue >> 0) & 0xFF) / 127F,
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F;
scaled -= Vector2.One;
this.PackedValue = Pack(scaled.X, scaled.Y);
this.PackedValue = Pack(scaled);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector2();
@ -124,172 +82,97 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y);
var vector2 = new Vector2(vector.X, vector.Y);
this.PackedValue = Pack(vector2);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.ToVector2(), 0F, 1F);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.ToVector2(), 0F, 1F);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
/// <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>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector2 ToVector2()
{
return obj is NormalizedByte2 other && this.Equals(other);
return new Vector2(
(sbyte)((this.PackedValue >> 0) & 0xFF) / 127F,
(sbyte)((this.PackedValue >> 8) & 0xFF) / 127F);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(NormalizedByte2 other)
{
return this.PackedValue == other.PackedValue;
}
public override bool Equals(object obj) => obj is NormalizedByte2 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(NormalizedByte2 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("X");
var vector = this.ToVector2();
return FormattableString.Invariant($"NormalizedByte2({vector.X:#0.##}, {vector.Y:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ushort Pack(float x, float y)
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(Vector2 vector)
{
int byte2 = ((ushort)Math.Round(x.Clamp(-1F, 1F) * 127F) & 0xFF) << 0;
int byte1 = ((ushort)Math.Round(y.Clamp(-1F, 1F) * 127F) & 0xFF) << 8;
vector = Vector2.Clamp(vector, MinusOne, Vector2.One) * Half;
return (ushort)(byte2 | byte1);
}
int byte2 = ((ushort)Math.Round(vector.X) & 0xFF) << 0;
int byte1 = ((ushort)Math.Round(vector.Y) & 0xFF) << 8;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
return (ushort)(byte2 | byte1);
}
}
}

234
src/ImageSharp/PixelFormats/NormalizedByte4.cs

@ -15,29 +15,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct NormalizedByte4 : IPixel<NormalizedByte4>, IPackedVector<uint>
{
/// <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);
}
private static readonly Vector4 MinusOne = new Vector4(-1F);
/// <summary>
/// Initializes a new instance of the <see cref="NormalizedByte4"/> struct.
@ -47,54 +26,46 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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(new Vector4(x, y, z, w))
{
this.PackedValue = Pack(x, y, z, w);
}
/// <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(ref vector);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(NormalizedByte4 left, NormalizedByte4 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(NormalizedByte4 left, NormalizedByte4 right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(NormalizedByte4 left, NormalizedByte4 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(NormalizedByte4 left, NormalizedByte4 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<NormalizedByte4> CreatePixelOperations() => new PixelOperations<NormalizedByte4>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
vector *= 2F;
@ -103,7 +74,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector4();
@ -113,14 +84,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@ -131,162 +99,74 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is NormalizedByte4 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is NormalizedByte4 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(NormalizedByte4 other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(NormalizedByte4 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("X");
var vector = this.ToVector4();
return FormattableString.Invariant($"NormalizedByte4({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w)
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
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;
vector = Vector4.Clamp(vector, MinusOne, Vector4.One) * Half;
return byte4 | byte3 | byte2 | byte1;
}
uint byte4 = ((uint)Math.Round(vector.X) & 0xFF) << 0;
uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 8;
uint byte2 = ((uint)Math.Round(vector.Z) & 0xFF) << 16;
uint byte1 = ((uint)Math.Round(vector.W) & 0xFF) << 24;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
return byte4 | byte3 | byte2 | byte1;
}
}
}

239
src/ImageSharp/PixelFormats/NormalizedShort2.cs

@ -15,39 +15,24 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct NormalizedShort2 : IPixel<NormalizedShort2>, IPackedVector<uint>
{
/// <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);
private static readonly Vector2 Max = new Vector2(0x7FFF);
private static readonly Vector2 Min = Vector2.Negate(Max);
/// <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)
/// <param name="x">The x-component.</param>
/// <param name="y">The y-component.</param>
public NormalizedShort2(float x, float y)
: this(new Vector2(x, y))
{
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);
}
/// <param name="vector">The vector containing the component values.</param>
public NormalizedShort2(Vector2 vector) => this.PackedValue = Pack(vector);
/// <inheritdoc/>
public uint PackedValue { get; set; }
@ -55,53 +40,39 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(NormalizedShort2 left, NormalizedShort2 right)
{
return left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(NormalizedShort2 left, NormalizedShort2 right) => 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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(NormalizedShort2 left, NormalizedShort2 right)
{
return !left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(NormalizedShort2 left, NormalizedShort2 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<NormalizedShort2> CreatePixelOperations() => new PixelOperations<NormalizedShort2>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
Vector2 scaled = new Vector2(vector.X, vector.Y) * 2F;
scaled -= Vector2.One;
this.PackedValue = Pack(scaled.X, scaled.Y);
this.PackedValue = Pack(scaled);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector2();
@ -111,130 +82,63 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y);
var vector2 = new Vector2(vector.X, vector.Y);
this.PackedValue = Pack(vector2);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.ToVector2(), 0, 1);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.ToVector2(), 0, 1);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector2 ToVector2()
{
const float MaxVal = 0x7FFF;
@ -245,61 +149,34 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is NormalizedShort2 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is NormalizedShort2 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(NormalizedShort2 other)
{
return this.PackedValue.Equals(other.PackedValue);
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(NormalizedShort2 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.PackedValue.GetHashCode();
}
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("X");
var vector = this.ToVector2();
return FormattableString.Invariant($"NormalizedShort2({vector.X:#0.##}, {vector.Y:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y)
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(Vector2 vector)
{
const float MaxPos = 0x7FFF;
const float MinNeg = -MaxPos;
vector *= Max;
vector = Vector2.Clamp(vector, Min, Max);
// Clamp the value between min and max values
// Round rather than truncate.
uint word2 = (uint)((int)MathF.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF);
uint word1 = (uint)(((int)MathF.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10);
uint word2 = (uint)((int)MathF.Round(vector.X) & 0xFFFF);
uint word1 = (uint)(((int)MathF.Round(vector.Y) & 0xFFFF) << 0x10);
return word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

243
src/ImageSharp/PixelFormats/NormalizedShort4.cs

@ -15,29 +15,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct NormalizedShort4 : IPixel<NormalizedShort4>, IPackedVector<ulong>
{
/// <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);
}
private static readonly Vector4 Max = new Vector4(0x7FFF);
private static readonly Vector4 Min = Vector4.Negate(Max);
/// <summary>
/// Initializes a new instance of the <see cref="NormalizedShort4"/> struct.
@ -47,54 +26,46 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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(new Vector4(x, y, z, w))
{
this.PackedValue = Pack(x, y, z, w);
}
/// <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(ref vector);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(NormalizedShort4 left, NormalizedShort4 right)
{
return left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(NormalizedShort4 left, NormalizedShort4 right) => 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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(NormalizedShort4 left, NormalizedShort4 right)
{
return !left.Equals(right);
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(NormalizedShort4 left, NormalizedShort4 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<NormalizedShort4> CreatePixelOperations() => new PixelOperations<NormalizedShort4>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
vector *= 2F;
@ -103,7 +74,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector4();
@ -113,14 +84,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
const float MaxVal = 0x7FFF;
@ -133,169 +101,76 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
Vector4 vector = source.ToByteScaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
vector /= Half;
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is NormalizedShort4 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is NormalizedShort4 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(NormalizedShort4 other)
{
return this.PackedValue.Equals(other.PackedValue);
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(NormalizedShort4 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.PackedValue.GetHashCode();
}
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("X");
var vector = this.ToVector4();
return FormattableString.Invariant($"NormalizedShort4({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Pack(float x, float y, float z, float w)
[MethodImpl(InliningOptions.ShortMethod)]
private static ulong Pack(ref Vector4 vector)
{
const float MaxPos = 0x7FFF;
const float MinNeg = -MaxPos;
vector *= Max;
vector = Vector4.Clamp(vector, Min, Max);
// Clamp the value between min and max values
ulong word4 = ((ulong)MathF.Round(x * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)MathF.Round(y * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)MathF.Round(z * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)MathF.Round(w * MaxPos).Clamp(MinNeg, MaxPos) & 0xFFFF) << 0x30;
// Round rather than truncate.
ulong word4 = ((ulong)MathF.Round(vector.X) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)MathF.Round(vector.Y) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)MathF.Round(vector.Z) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)MathF.Round(vector.W) & 0xFFFF) << 0x30;
return word4 | word3 | word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}
}

54
src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs

@ -105,6 +105,60 @@ namespace SixLabors.ImageSharp.PixelFormats
}
}
/// <summary>
/// Performs a bulk conversion of a collection of one pixel format into another.
/// </summary>
/// <typeparam name="TPixel2">The pixel format.</typeparam>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destinationColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void To<TPixel2>(ReadOnlySpan<TPixel> sourceColors, Span<TPixel2> destinationColors, int count)
where TPixel2 : struct, IPixel<TPixel2>
{
GuardSpans(sourceColors, nameof(sourceColors), destinationColors, nameof(destinationColors), count);
ref TPixel sourceRef = ref MemoryMarshal.GetReference(sourceColors);
// Gray8 and Gray16 are special implementations of IPixel in that they do not conform to the
// standard RGBA colorspace format and must be converted from RGBA using the special ITU BT709 alogrithm.
// One of the requirements of PackFromScaledVector4/ToScaledVector4 is that it unaware of this and
// packs/unpacks the pixel without and conversion so we employ custom methods do do this.
if (typeof(TPixel2).Equals(typeof(Gray16)))
{
ref Gray16 gray16Ref = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<TPixel2, Gray16>(destinationColors));
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray16 dp = ref Unsafe.Add(ref gray16Ref, i);
dp.ConvertFromRgbaScaledVector4(sp.ToScaledVector4());
}
return;
}
if (typeof(TPixel2).Equals(typeof(Gray8)))
{
ref Gray8 gray8Ref = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<TPixel2, Gray8>(destinationColors));
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
ref Gray8 dp = ref Unsafe.Add(ref gray8Ref, i);
dp.ConvertFromRgbaScaledVector4(sp.ToScaledVector4());
}
return;
}
// Normal converson
ref TPixel2 destRef = ref MemoryMarshal.GetReference(destinationColors);
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
ref TPixel2 dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromScaledVector4(sp.ToScaledVector4());
}
}
/// <summary>
/// Verifies that the given 'source' and 'destination' spans are at least of 'minLength' size.
/// Throwing an <see cref="ArgumentException"/> if the condition is not met.

216
src/ImageSharp/PixelFormats/Rg32.cs

@ -15,24 +15,23 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct Rg32 : IPixel<Rg32>, IPackedVector<uint>
{
private static readonly Vector2 Max = new Vector2(ushort.MaxValue);
/// <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(new Vector2(x, 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);
}
public Rg32(Vector2 vector) => this.PackedValue = Pack(vector);
/// <inheritdoc/>
public uint PackedValue { get; set; }
@ -40,214 +39,119 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rg32 left, Rg32 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Rg32 left, Rg32 right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rg32 left, Rg32 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Rg32 left, Rg32 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Rg32> CreatePixelOperations() => new PixelOperations<Rg32>();
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 ToVector2()
{
return new Vector2(
(this.PackedValue & 0xFFFF) / 65535F,
((this.PackedValue >> 16) & 0xFFFF) / 65535F);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y);
var vector2 = new Vector2(vector.X, vector.Y);
this.PackedValue = Pack(vector2);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.ToVector2(), 0F, 1F);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.ToVector2(), 0F, 1F);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <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>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector2 ToVector2() => new Vector2(this.PackedValue & 0xFFFF, (this.PackedValue >> 16) & 0xFFFF) / Max;
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Rg32 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Rg32 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rg32 other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rg32 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString()
{
return this.ToVector2().ToString();
var vector = this.ToVector2();
return FormattableString.Invariant($"Rg32({vector.X:#0.##}, {vector.Y:#0.##})");
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.PackedValue.GetHashCode();
}
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => 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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y)
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(Vector2 vector)
{
return (uint)(
((int)Math.Round(x.Clamp(0, 1) * 65535F) & 0xFFFF) |
(((int)Math.Round(y.Clamp(0, 1) * 65535F) & 0xFFFF) << 16));
vector = Vector2.Clamp(vector, Vector2.Zero, Vector2.One) * Max;
return (uint)(((int)Math.Round(vector.X) & 0xFFFF) | (((int)Math.Round(vector.Y) & 0xFFFF) << 16));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4() => this.ToVector4() * 255F;
}
}
}

186
src/ImageSharp/PixelFormats/Rgb24.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -16,7 +15,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </para>
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct Rgb24 : IPixel<Rgb24>
public partial struct Rgb24 : IPixel<Rgb24>
{
/// <summary>
/// The red component.
@ -36,13 +35,16 @@ namespace SixLabors.ImageSharp.PixelFormats
[FieldOffset(2)]
public byte B;
private static readonly Vector4 MaxBytes = new Vector4(byte.MaxValue);
private static readonly Vector4 Half = new Vector4(0.5F);
/// <summary>
/// Initializes a new instance of the <see cref="Rgb24"/> struct.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgb24(byte r, byte g, byte b)
{
this.R = r;
@ -56,48 +58,59 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="color">The instance of <see cref="ColorSpaces.Rgb"/> to convert.</param>
/// <returns>An instance of <see cref="Rgb24"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public static implicit operator Rgb24(ColorSpaces.Rgb color)
{
var vector = new Vector4(color.ToVector3(), 1);
var vector = new Vector4(color.ToVector3(), 1F);
Rgb24 rgb = default;
rgb.PackFromScaledVector4(vector);
return rgb;
}
/// <summary>
/// Compares two <see cref="Rgb24"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Rgb24"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Rgb24"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Rgb24 left, Rgb24 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Rgb24"/> objects for equality.
/// </summary>
/// <param name="left">The <see cref="Rgb24"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="Rgb24"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Rgb24 left, Rgb24 right) => !left.Equals(right);
/// <inheritdoc/>
public PixelOperations<Rgb24> CreatePixelOperations() => new PixelOperations<Rgb24>();
public PixelOperations<Rgb24> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgb24 other)
{
return this.R == other.R && this.G == other.G && this.B == other.B;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is Rgb24 other && this.Equals(other);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
return HashHelpers.Combine(hash, this.B.GetHashCode());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this = Unsafe.As<Rgba32, Rgb24>(ref source);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Rgba32(this.R, this.G, this.B, byte.MaxValue).ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.R = source.R;
@ -106,8 +119,8 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.R = source.R;
this.G = source.G;
@ -115,102 +128,95 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
return this.ToVector4();
this.R = source.R;
this.G = source.G;
this.B = source.B;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
Rgba32 rgba = default;
rgba.PackFromVector4(vector);
this.PackFromRgba32(rgba);
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
return new Rgba32(this.R, this.G, this.B, byte.MaxValue).ToVector4();
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest) => dest = this;
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this = source;
/// <inheritdoc/>
public void ToRgba32(ref Rgba32 dest)
{
dest.Rgb = this;
dest.A = byte.MaxValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this = source.Rgb;
/// <inheritdoc/>
public void ToArgb32(ref Argb32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, byte.MaxValue);
/// <inheritdoc/>
public void ToBgr24(ref Bgr24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
public void ToBgra32(ref Bgra32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = byte.MaxValue;
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgb48(Rgb48 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
}
public override bool Equals(object obj) => obj is Rgb24 other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rgb24 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba64(Rgba64 source)
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode()
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
return HashHelpers.Combine(hash, this.B.GetHashCode());
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
public override string ToString() => $"Rgb24({this.R}, {this.G}, {this.B})";
/// <inheritdoc/>
public override string ToString()
/// <summary>
/// Packs a <see cref="Vector4"/> into a color.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector4 vector)
{
return $"({this.R},{this.G},{this.B})";
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;
this.B = (byte)vector.Z;
}
}
}

189
src/ImageSharp/PixelFormats/Rgb48.cs

@ -15,9 +15,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </para>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Rgb48 : IPixel<Rgb48>
public partial struct Rgb48 : IPixel<Rgb48>
{
private const float Max = 65535F;
private const float Max = ushort.MaxValue;
/// <summary>
/// Gets or sets the red component.
@ -48,29 +48,6 @@ namespace SixLabors.ImageSharp.PixelFormats
this.B = b;
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgb48"/> struct.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
public Rgb48(float r, float g, float b)
: this()
{
this.R = (ushort)MathF.Round(r.Clamp(0, 1) * Max);
this.G = (ushort)MathF.Round(g.Clamp(0, 1) * Max);
this.B = (ushort)MathF.Round(b.Clamp(0, 1) * Max);
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgb48"/> struct.
/// </summary>
/// <param name="vector">The vector containing the components values.</param>
public Rgb48(Vector3 vector)
: this(vector.X, vector.Y, vector.Z)
{
}
/// <summary>
/// Compares two <see cref="Rgb48"/> objects for equality.
/// </summary>
@ -79,13 +56,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rgb48 left, Rgb48 right)
{
return left.R == right.R
&& left.G == right.G
&& left.B == right.B;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Rgb48 left, Rgb48 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Rgb48"/> objects for equality.
@ -95,40 +67,22 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgb48 left, Rgb48 right)
{
return left.R != right.R
|| left.G != right.G
|| left.B != right.B;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Rgb48 left, Rgb48 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Rgb48> CreatePixelOperations() => new PixelOperations<Rgb48>();
public PixelOperations<Rgb48> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R / Max, this.G / Max, this.B / Max, 1);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
@ -138,114 +92,103 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R / Max, this.G / Max, this.B / Max, 1F);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.PackFromVector4(source.ToVector4());
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this = source.Rgb;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
dest.A = 255;
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
dest.A = 255;
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32()
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
dest.A = 255;
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
return new Rgba32(r, g, b, byte.MaxValue);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this = source;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest = this;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest)
{
dest.Rgb = this;
dest.A = ushort.MaxValue;
}
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Rgb48 rgb48 && this.Equals(rgb48);
}
public override bool Equals(object obj) => obj is Rgb48 rgb48 && this.Equals(rgb48);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgb48 other)
{
return this.R == other.R
&& this.G == other.G
&& this.B == other.B;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rgb48 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
/// <inheritdoc />
public override string ToString() => this.ToVector4().ToString();
public override string ToString() => $"Rgb48({this.R}, {this.G}, {this.B})";
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode()
{
return HashHelpers.Combine(

208
src/ImageSharp/PixelFormats/Rgba1010102.cs

@ -16,6 +16,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct Rgba1010102 : IPixel<Rgba1010102>, IPackedVector<uint>
{
private static readonly Vector4 Multiplier = new Vector4(1023F, 1023F, 1023F, 3F);
/// <summary>
/// Initializes a new instance of the <see cref="Rgba1010102"/> struct.
/// </summary>
@ -24,18 +26,15 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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(new Vector4(x, y, z, 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);
}
public Rgba1010102(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc/>
public uint PackedValue { get; set; }
@ -43,206 +42,119 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rgba1010102 left, Rgba1010102 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Rgba1010102 left, Rgba1010102 right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgba1010102 left, Rgba1010102 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Rgba1010102 left, Rgba1010102 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Rgba1010102> CreatePixelOperations() => new PixelOperations<Rgba1010102>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
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);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
return new Vector4(
(this.PackedValue >> 0) & 0x03FF,
(this.PackedValue >> 10) & 0x03FF,
(this.PackedValue >> 20) & 0x03FF,
(this.PackedValue >> 30) & 0x03) / Multiplier;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Rgba1010102 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Rgba1010102 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgba1010102 other)
{
return this.PackedValue == other.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rgba1010102 other) => this.PackedValue == other.PackedValue;
/// <inheritdoc />
public override string ToString()
{
return this.ToVector4().ToString();
var vector = this.ToVector4();
return FormattableString.Invariant($"Rgba1010102({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
return this.PackedValue.GetHashCode();
}
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => 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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y, float z, float w)
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
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));
(((int)Math.Round(vector.X) & 0x03FF) << 0)
| (((int)Math.Round(vector.Y) & 0x03FF) << 10)
| (((int)Math.Round(vector.Z) & 0x03FF) << 20)
| (((int)Math.Round(vector.W) & 0x03) << 30));
}
}
}

16
src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs

@ -56,22 +56,6 @@ namespace SixLabors.ImageSharp.PixelFormats
{
this.PackFromVector4(sourceVectors, destinationColors, count);
}
/// <inheritdoc />
internal override void PackFromRgba32(ReadOnlySpan<Rgba32> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
source.Slice(0, count).CopyTo(destPixels);
}
/// <inheritdoc />
internal override void ToRgba32(ReadOnlySpan<Rgba32> sourcePixels, Span<Rgba32> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
sourcePixels.Slice(0, count).CopyTo(dest);
}
}
}
}

253
src/ImageSharp/PixelFormats/Rgba32.cs

@ -41,34 +41,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public byte A;
/// <summary>
/// The shift count for the red component
/// </summary>
private const int RedShift = 0;
/// <summary>
/// The shift count for the green component
/// </summary>
private const int GreenShift = 8;
/// <summary>
/// The shift count for the blue component
/// </summary>
private const int BlueShift = 16;
/// <summary>
/// The shift count for the alpha component
/// </summary>
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 MaxBytes = new Vector4(byte.MaxValue);
private static readonly Vector4 Half = new Vector4(0.5F);
/// <summary>
@ -77,7 +50,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32(byte r, byte g, byte b)
{
this.R = r;
@ -93,7 +66,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32(byte r, byte g, byte b, byte a)
{
this.R = r;
@ -109,7 +82,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32(float r, float g, float b, float a = 1)
: this() => this.Pack(r, g, b, a);
@ -119,7 +92,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32(Vector3 vector)
: this() => this.Pack(ref vector);
@ -129,7 +102,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32(Vector4 vector)
: this() => this = PackNew(ref vector);
@ -139,7 +112,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="packed">
/// The packed value.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32(uint packed)
: this() => this.Rgba = packed;
@ -148,10 +121,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public uint Rgba
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As<Rgba32, uint>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As<Rgba32, uint>(ref this) = value;
}
@ -160,10 +133,12 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public Rgb24 Rgb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
// If this is changed to ShortMethod then several jpeg encoding tests fail
// on 32 bit Net 4.6.2 and NET 4.7.1
[MethodImpl(InliningOptions.ColdPath)]
get => Unsafe.As<Rgba32, Rgb24>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As<Rgba32, Rgb24>(ref this) = value;
}
@ -172,10 +147,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public Bgr24 Bgr
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => new Bgr24(this.R, this.G, this.B);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set
{
this.R = value.R;
@ -187,10 +162,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
public uint PackedValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => this.Rgba;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => this.Rgba = value;
}
@ -200,10 +175,11 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
/// <param name="color">The instance of <see cref="ColorSpaces.Rgb"/> to convert.</param>
/// <returns>An instance of <see cref="Rgba32"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public static implicit operator Rgba32(ColorSpaces.Rgb color)
{
var vector = new Vector4(color.ToVector3(), 1);
var vector = new Vector4(color.ToVector3(), 1F);
Rgba32 rgba = default;
rgba.PackFromScaledVector4(vector);
return rgba;
@ -217,8 +193,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rgba32 left, Rgba32 right) => left.Rgba == right.Rgba;
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Rgba32 left, Rgba32 right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="Rgba32"/> objects for equality.
@ -228,8 +204,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgba32 left, Rgba32 right) => left.Rgba != right.Rgba;
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Rgba32 left, Rgba32 right) => !left.Equals(right);
/// <summary>
/// Creates a new instance of the <see cref="Rgba32"/> struct.
@ -247,11 +223,23 @@ namespace SixLabors.ImageSharp.PixelFormats
public PixelOperations<Rgba32> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source) => this = source;
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.R = source.R;
@ -261,7 +249,15 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.Bgr = source;
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.R = source.R;
@ -270,148 +266,93 @@ namespace SixLabors.ImageSharp.PixelFormats
this.A = source.A;
}
/// <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 = (uint)(this.A << 0 | this.B << 8 | this.G << 16 | this.R << 24);
return hexOrder.ToString("X8");
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest) => dest = Unsafe.As<Rgba32, Rgb24>(ref this);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest) => dest = this;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
this.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = byte.MaxValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
this.Rgb = source;
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
/// <summary>
/// Gets the value of this struct as <see cref="Bgra32"/>.
/// Useful for changing the component order.
/// </summary>
/// <returns>A <see cref="Bgra32"/> value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Bgra32 ToBgra32() => new Bgra32(this.R, this.G, this.B, this.A);
/// <summary>
/// Gets the value of this struct as <see cref="Argb32"/>.
/// Useful for changing the component order.
/// </summary>
/// <returns>A <see cref="Argb32"/> value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32 ToArgb32() => new Argb32(this.R, this.G, this.B, this.A);
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this = source;
/// <summary>
/// Converts the pixel to <see cref="Rgba32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => this;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
// Taken from libpng pngtran.c line: 2419
this.R = (byte)(((source.R * 255) + 32895) >> 16);
this.G = (byte)(((source.G * 255) + 32895) >> 16);
this.B = (byte)(((source.B * 255) + 32895) >> 16);
this.A = (byte)(((source.A * 255) + 32895) >> 16);
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <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 = (uint)(this.A << 0 | this.B << 8 | this.G << 16 | this.R << 24);
return hexOrder.ToString("X8");
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj is Rgba32 rgba32 && this.Equals(rgba32);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgba32 other) => this.Rgba == other.Rgba;
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rgba32 other) => this.Rgba.Equals(other.Rgba);
/// <inheritdoc/>
public override string ToString() => $"({this.R},{this.G},{this.B},{this.A})";
public override string ToString() => $"Rgba32({this.R}, {this.G}, {this.B}, {this.A})";
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.Rgba.GetHashCode();
/// <summary>
/// Gets the <see cref="Vector4"/> representation without normalizing to [0, 1]
/// </summary>
/// <returns>A <see cref="Vector4"/> of values in [0, 255] </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Vector4 ToByteScaledVector4() => new Vector4(this.R, this.G, this.B, this.A);
/// <summary>
/// Packs a <see cref="Vector4"/> into a color returning a new instance as a result.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
/// <returns>The <see cref="Rgba32"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private static Rgba32 PackNew(ref Vector4 vector)
{
vector *= MaxBytes;
@ -428,7 +369,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="y">The y-component</param>
/// <param name="z">The z-component</param>
/// <param name="w">The w-component</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(float x, float y, float z, float w)
{
var value = new Vector4(x, y, z, w);
@ -439,10 +380,10 @@ namespace SixLabors.ImageSharp.PixelFormats
/// Packs a <see cref="Vector3"/> into a uint.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector3 vector)
{
var value = new Vector4(vector, 1);
var value = new Vector4(vector, 1F);
this.Pack(ref value);
}
@ -450,7 +391,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// Packs a <see cref="Vector4"/> into a color.
/// </summary>
/// <param name="vector">The vector containing the values to pack.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector4 vector)
{
vector *= MaxBytes;

239
src/ImageSharp/PixelFormats/Rgba64.cs

@ -15,9 +15,9 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </para>
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Rgba64 : IPixel<Rgba64>, IPackedVector<ulong>
public partial struct Rgba64 : IPixel<Rgba64>, IPackedVector<ulong>
{
private const float Max = 65535F;
private const float Max = ushort.MaxValue;
/// <summary>
/// Gets or sets the red component.
@ -47,7 +47,6 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
public Rgba64(ushort r, ushort g, ushort b, ushort a)
: this()
{
this.R = r;
this.G = g;
@ -55,126 +54,63 @@ namespace SixLabors.ImageSharp.PixelFormats
this.A = a;
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba64"/> 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 Rgba64(float r, float g, float b, float a)
: this()
{
this.R = (ushort)MathF.Round(r.Clamp(0, 1) * Max);
this.G = (ushort)MathF.Round(g.Clamp(0, 1) * Max);
this.B = (ushort)MathF.Round(b.Clamp(0, 1) * Max);
this.A = (ushort)MathF.Round(a.Clamp(0, 1) * Max);
}
/// <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(vector.X, vector.Y, vector.Z, vector.W)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba64"/> struct.
/// </summary>
/// <param name="packed">The packed value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba64(ulong packed)
: this()
{
this.PackedValue = packed;
}
/// <summary>
/// Gets or sets the RGB components of this struct as <see cref="Rgb48"/>
/// </summary>
public Rgb48 Rgb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As<Rgba64, Rgb48>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As<Rgba64, Rgb48>(ref this) = value;
}
/// <inheritdoc/>
public ulong PackedValue
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As<Rgba64, ulong>(ref this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As<Rgba64, ulong>(ref this) = value;
}
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Rgba64 left, Rgba64 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Rgba64 left, Rgba64 right) => 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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Rgba64 left, Rgba64 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Rgba64 left, Rgba64 right) => left.PackedValue != right.PackedValue;
/// <inheritdoc />
public PixelOperations<Rgba64> CreatePixelOperations() => new PixelOperations<Rgba64>();
public PixelOperations<Rgba64> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R, this.G, this.B, this.A) / Max;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
@ -185,116 +121,115 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(source.ToVector4());
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / Max;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.PackFromVector4(source.ToVector4());
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source)
{
this.PackFromVector4(source.ToVector4());
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ushort.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba64(Rgba64 source) => this = source;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source)
{
// Taken from libpng pngtran.c line: 2419
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
dest.A = (byte)(((this.A * 255) + 32895) >> 16);
ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = ushort.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgb48(Rgb48 source)
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source)
{
this.Rgb = source;
this.R = source.PackedValue;
this.G = source.PackedValue;
this.B = source.PackedValue;
this.A = ushort.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest = this.Rgb;
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest = this;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
dest.A = (byte)(((this.A * 255) + 32895) >> 16);
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ushort.MaxValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source)
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32()
{
dest.R = (byte)(((this.R * 255) + 32895) >> 16);
dest.G = (byte)(((this.G * 255) + 32895) >> 16);
dest.B = (byte)(((this.B * 255) + 32895) >> 16);
dest.A = (byte)(((this.A * 255) + 32895) >> 16);
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A);
return new Rgba32(r, g, b, a);
}
/// <inheritdoc />
public override bool Equals(object obj)
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
return obj is Rgba64 rgba64 && this.Equals(rgba64);
this.Rgb = source;
this.A = ushort.MaxValue;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this = source;
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgba64 other)
{
return this.PackedValue == other.PackedValue;
}
public override bool Equals(object obj) => obj is Rgba64 rgba64 && this.Equals(rgba64);
/// <inheritdoc />
public override string ToString()
{
return $"({this.R},{this.G},{this.B},{this.A})";
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Rgba64 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
public override string ToString() => $"Rgba64({this.R}, {this.G}, {this.B}, {this.A})";
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
}
}

721
src/ImageSharp/PixelFormats/RgbaVector.Definitions.cs

@ -1,721 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.PixelFormats
{
/// <content>
/// Provides operators and composition algorithms.
/// </content>
public partial struct RgbaVector
{
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F0F8FF.
/// </summary>
public static readonly RgbaVector AliceBlue = NamedColors<RgbaVector>.AliceBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FAEBD7.
/// </summary>
public static readonly RgbaVector AntiqueWhite = NamedColors<RgbaVector>.AntiqueWhite;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00FFFF.
/// </summary>
public static readonly RgbaVector Aqua = NamedColors<RgbaVector>.Aqua;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #7FFFD4.
/// </summary>
public static readonly RgbaVector Aquamarine = NamedColors<RgbaVector>.Aquamarine;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F0FFFF.
/// </summary>
public static readonly RgbaVector Azure = NamedColors<RgbaVector>.Azure;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F5F5DC.
/// </summary>
public static readonly RgbaVector Beige = NamedColors<RgbaVector>.Beige;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFE4C4.
/// </summary>
public static readonly RgbaVector Bisque = NamedColors<RgbaVector>.Bisque;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #000000.
/// </summary>
public static readonly RgbaVector Black = NamedColors<RgbaVector>.Black;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFEBCD.
/// </summary>
public static readonly RgbaVector BlanchedAlmond = NamedColors<RgbaVector>.BlanchedAlmond;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #0000FF.
/// </summary>
public static readonly RgbaVector Blue = NamedColors<RgbaVector>.Blue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #8A2BE2.
/// </summary>
public static readonly RgbaVector BlueViolet = NamedColors<RgbaVector>.BlueViolet;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #A52A2A.
/// </summary>
public static readonly RgbaVector Brown = NamedColors<RgbaVector>.Brown;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DEB887.
/// </summary>
public static readonly RgbaVector BurlyWood = NamedColors<RgbaVector>.BurlyWood;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #5F9EA0.
/// </summary>
public static readonly RgbaVector CadetBlue = NamedColors<RgbaVector>.CadetBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #7FFF00.
/// </summary>
public static readonly RgbaVector Chartreuse = NamedColors<RgbaVector>.Chartreuse;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #D2691E.
/// </summary>
public static readonly RgbaVector Chocolate = NamedColors<RgbaVector>.Chocolate;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF7F50.
/// </summary>
public static readonly RgbaVector Coral = NamedColors<RgbaVector>.Coral;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #6495ED.
/// </summary>
public static readonly RgbaVector CornflowerBlue = NamedColors<RgbaVector>.CornflowerBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFF8DC.
/// </summary>
public static readonly RgbaVector Cornsilk = NamedColors<RgbaVector>.Cornsilk;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DC143C.
/// </summary>
public static readonly RgbaVector Crimson = NamedColors<RgbaVector>.Crimson;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00FFFF.
/// </summary>
public static readonly RgbaVector Cyan = NamedColors<RgbaVector>.Cyan;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00008B.
/// </summary>
public static readonly RgbaVector DarkBlue = NamedColors<RgbaVector>.DarkBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #008B8B.
/// </summary>
public static readonly RgbaVector DarkCyan = NamedColors<RgbaVector>.DarkCyan;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #B8860B.
/// </summary>
public static readonly RgbaVector DarkGoldenrod = NamedColors<RgbaVector>.DarkGoldenrod;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #A9A9A9.
/// </summary>
public static readonly RgbaVector DarkGray = NamedColors<RgbaVector>.DarkGray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #006400.
/// </summary>
public static readonly RgbaVector DarkGreen = NamedColors<RgbaVector>.DarkGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #BDB76B.
/// </summary>
public static readonly RgbaVector DarkKhaki = NamedColors<RgbaVector>.DarkKhaki;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #8B008B.
/// </summary>
public static readonly RgbaVector DarkMagenta = NamedColors<RgbaVector>.DarkMagenta;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #556B2F.
/// </summary>
public static readonly RgbaVector DarkOliveGreen = NamedColors<RgbaVector>.DarkOliveGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF8C00.
/// </summary>
public static readonly RgbaVector DarkOrange = NamedColors<RgbaVector>.DarkOrange;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #9932CC.
/// </summary>
public static readonly RgbaVector DarkOrchid = NamedColors<RgbaVector>.DarkOrchid;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #8B0000.
/// </summary>
public static readonly RgbaVector DarkRed = NamedColors<RgbaVector>.DarkRed;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #E9967A.
/// </summary>
public static readonly RgbaVector DarkSalmon = NamedColors<RgbaVector>.DarkSalmon;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #8FBC8B.
/// </summary>
public static readonly RgbaVector DarkSeaGreen = NamedColors<RgbaVector>.DarkSeaGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #483D8B.
/// </summary>
public static readonly RgbaVector DarkSlateBlue = NamedColors<RgbaVector>.DarkSlateBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #2F4F4F.
/// </summary>
public static readonly RgbaVector DarkSlateGray = NamedColors<RgbaVector>.DarkSlateGray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00CED1.
/// </summary>
public static readonly RgbaVector DarkTurquoise = NamedColors<RgbaVector>.DarkTurquoise;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #9400D3.
/// </summary>
public static readonly RgbaVector DarkViolet = NamedColors<RgbaVector>.DarkViolet;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF1493.
/// </summary>
public static readonly RgbaVector DeepPink = NamedColors<RgbaVector>.DeepPink;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00BFFF.
/// </summary>
public static readonly RgbaVector DeepSkyBlue = NamedColors<RgbaVector>.DeepSkyBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #696969.
/// </summary>
public static readonly RgbaVector DimGray = NamedColors<RgbaVector>.DimGray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #1E90FF.
/// </summary>
public static readonly RgbaVector DodgerBlue = NamedColors<RgbaVector>.DodgerBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #B22222.
/// </summary>
public static readonly RgbaVector Firebrick = NamedColors<RgbaVector>.Firebrick;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFAF0.
/// </summary>
public static readonly RgbaVector FloralWhite = NamedColors<RgbaVector>.FloralWhite;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #228B22.
/// </summary>
public static readonly RgbaVector ForestGreen = NamedColors<RgbaVector>.ForestGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF00FF.
/// </summary>
public static readonly RgbaVector Fuchsia = NamedColors<RgbaVector>.Fuchsia;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DCDCDC.
/// </summary>
public static readonly RgbaVector Gainsboro = NamedColors<RgbaVector>.Gainsboro;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F8F8FF.
/// </summary>
public static readonly RgbaVector GhostWhite = NamedColors<RgbaVector>.GhostWhite;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFD700.
/// </summary>
public static readonly RgbaVector Gold = NamedColors<RgbaVector>.Gold;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DAA520.
/// </summary>
public static readonly RgbaVector Goldenrod = NamedColors<RgbaVector>.Goldenrod;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #808080.
/// </summary>
public static readonly RgbaVector Gray = NamedColors<RgbaVector>.Gray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #008000.
/// </summary>
public static readonly RgbaVector Green = NamedColors<RgbaVector>.Green;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #ADFF2F.
/// </summary>
public static readonly RgbaVector GreenYellow = NamedColors<RgbaVector>.GreenYellow;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F0FFF0.
/// </summary>
public static readonly RgbaVector Honeydew = NamedColors<RgbaVector>.Honeydew;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF69B4.
/// </summary>
public static readonly RgbaVector HotPink = NamedColors<RgbaVector>.HotPink;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #CD5C5C.
/// </summary>
public static readonly RgbaVector IndianRed = NamedColors<RgbaVector>.IndianRed;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #4B0082.
/// </summary>
public static readonly RgbaVector Indigo = NamedColors<RgbaVector>.Indigo;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFFF0.
/// </summary>
public static readonly RgbaVector Ivory = NamedColors<RgbaVector>.Ivory;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F0E68C.
/// </summary>
public static readonly RgbaVector Khaki = NamedColors<RgbaVector>.Khaki;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #E6E6FA.
/// </summary>
public static readonly RgbaVector Lavender = NamedColors<RgbaVector>.Lavender;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFF0F5.
/// </summary>
public static readonly RgbaVector LavenderBlush = NamedColors<RgbaVector>.LavenderBlush;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #7CFC00.
/// </summary>
public static readonly RgbaVector LawnGreen = NamedColors<RgbaVector>.LawnGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFACD.
/// </summary>
public static readonly RgbaVector LemonChiffon = NamedColors<RgbaVector>.LemonChiffon;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #ADD8E6.
/// </summary>
public static readonly RgbaVector LightBlue = NamedColors<RgbaVector>.LightBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F08080.
/// </summary>
public static readonly RgbaVector LightCoral = NamedColors<RgbaVector>.LightCoral;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #E0FFFF.
/// </summary>
public static readonly RgbaVector LightCyan = NamedColors<RgbaVector>.LightCyan;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FAFAD2.
/// </summary>
public static readonly RgbaVector LightGoldenrodYellow = NamedColors<RgbaVector>.LightGoldenrodYellow;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #D3D3D3.
/// </summary>
public static readonly RgbaVector LightGray = NamedColors<RgbaVector>.LightGray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #90EE90.
/// </summary>
public static readonly RgbaVector LightGreen = NamedColors<RgbaVector>.LightGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFB6C1.
/// </summary>
public static readonly RgbaVector LightPink = NamedColors<RgbaVector>.LightPink;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFA07A.
/// </summary>
public static readonly RgbaVector LightSalmon = NamedColors<RgbaVector>.LightSalmon;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #20B2AA.
/// </summary>
public static readonly RgbaVector LightSeaGreen = NamedColors<RgbaVector>.LightSeaGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #87CEFA.
/// </summary>
public static readonly RgbaVector LightSkyBlue = NamedColors<RgbaVector>.LightSkyBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #778899.
/// </summary>
public static readonly RgbaVector LightSlateGray = NamedColors<RgbaVector>.LightSlateGray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #B0C4DE.
/// </summary>
public static readonly RgbaVector LightSteelBlue = NamedColors<RgbaVector>.LightSteelBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFFE0.
/// </summary>
public static readonly RgbaVector LightYellow = NamedColors<RgbaVector>.LightYellow;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00FF00.
/// </summary>
public static readonly RgbaVector Lime = NamedColors<RgbaVector>.Lime;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #32CD32.
/// </summary>
public static readonly RgbaVector LimeGreen = NamedColors<RgbaVector>.LimeGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FAF0E6.
/// </summary>
public static readonly RgbaVector Linen = NamedColors<RgbaVector>.Linen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF00FF.
/// </summary>
public static readonly RgbaVector Magenta = NamedColors<RgbaVector>.Magenta;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #800000.
/// </summary>
public static readonly RgbaVector Maroon = NamedColors<RgbaVector>.Maroon;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #66CDAA.
/// </summary>
public static readonly RgbaVector MediumAquamarine = NamedColors<RgbaVector>.MediumAquamarine;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #0000CD.
/// </summary>
public static readonly RgbaVector MediumBlue = NamedColors<RgbaVector>.MediumBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #BA55D3.
/// </summary>
public static readonly RgbaVector MediumOrchid = NamedColors<RgbaVector>.MediumOrchid;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #9370DB.
/// </summary>
public static readonly RgbaVector MediumPurple = NamedColors<RgbaVector>.MediumPurple;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #3CB371.
/// </summary>
public static readonly RgbaVector MediumSeaGreen = NamedColors<RgbaVector>.MediumSeaGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #7B68EE.
/// </summary>
public static readonly RgbaVector MediumSlateBlue = NamedColors<RgbaVector>.MediumSlateBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00FA9A.
/// </summary>
public static readonly RgbaVector MediumSpringGreen = NamedColors<RgbaVector>.MediumSpringGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #48D1CC.
/// </summary>
public static readonly RgbaVector MediumTurquoise = NamedColors<RgbaVector>.MediumTurquoise;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #C71585.
/// </summary>
public static readonly RgbaVector MediumVioletRed = NamedColors<RgbaVector>.MediumVioletRed;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #191970.
/// </summary>
public static readonly RgbaVector MidnightBlue = NamedColors<RgbaVector>.MidnightBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F5FFFA.
/// </summary>
public static readonly RgbaVector MintCream = NamedColors<RgbaVector>.MintCream;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFE4E1.
/// </summary>
public static readonly RgbaVector MistyRose = NamedColors<RgbaVector>.MistyRose;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFE4B5.
/// </summary>
public static readonly RgbaVector Moccasin = NamedColors<RgbaVector>.Moccasin;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFDEAD.
/// </summary>
public static readonly RgbaVector NavajoWhite = NamedColors<RgbaVector>.NavajoWhite;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #000080.
/// </summary>
public static readonly RgbaVector Navy = NamedColors<RgbaVector>.Navy;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FDF5E6.
/// </summary>
public static readonly RgbaVector OldLace = NamedColors<RgbaVector>.OldLace;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #808000.
/// </summary>
public static readonly RgbaVector Olive = NamedColors<RgbaVector>.Olive;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #6B8E23.
/// </summary>
public static readonly RgbaVector OliveDrab = NamedColors<RgbaVector>.OliveDrab;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFA500.
/// </summary>
public static readonly RgbaVector Orange = NamedColors<RgbaVector>.Orange;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF4500.
/// </summary>
public static readonly RgbaVector OrangeRed = NamedColors<RgbaVector>.OrangeRed;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DA70D6.
/// </summary>
public static readonly RgbaVector Orchid = NamedColors<RgbaVector>.Orchid;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #EEE8AA.
/// </summary>
public static readonly RgbaVector PaleGoldenrod = NamedColors<RgbaVector>.PaleGoldenrod;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #98FB98.
/// </summary>
public static readonly RgbaVector PaleGreen = NamedColors<RgbaVector>.PaleGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #AFEEEE.
/// </summary>
public static readonly RgbaVector PaleTurquoise = NamedColors<RgbaVector>.PaleTurquoise;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DB7093.
/// </summary>
public static readonly RgbaVector PaleVioletRed = NamedColors<RgbaVector>.PaleVioletRed;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFEFD5.
/// </summary>
public static readonly RgbaVector PapayaWhip = NamedColors<RgbaVector>.PapayaWhip;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFDAB9.
/// </summary>
public static readonly RgbaVector PeachPuff = NamedColors<RgbaVector>.PeachPuff;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #CD853F.
/// </summary>
public static readonly RgbaVector Peru = NamedColors<RgbaVector>.Peru;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFC0CB.
/// </summary>
public static readonly RgbaVector Pink = NamedColors<RgbaVector>.Pink;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #DDA0DD.
/// </summary>
public static readonly RgbaVector Plum = NamedColors<RgbaVector>.Plum;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #B0E0E6.
/// </summary>
public static readonly RgbaVector PowderBlue = NamedColors<RgbaVector>.PowderBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #800080.
/// </summary>
public static readonly RgbaVector Purple = NamedColors<RgbaVector>.Purple;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #663399.
/// </summary>
public static readonly RgbaVector RebeccaPurple = NamedColors<RgbaVector>.RebeccaPurple;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF0000.
/// </summary>
public static readonly RgbaVector Red = NamedColors<RgbaVector>.Red;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #BC8F8F.
/// </summary>
public static readonly RgbaVector RosyBrown = NamedColors<RgbaVector>.RosyBrown;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #4169E1.
/// </summary>
public static readonly RgbaVector RoyalBlue = NamedColors<RgbaVector>.RoyalBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #8B4513.
/// </summary>
public static readonly RgbaVector SaddleBrown = NamedColors<RgbaVector>.SaddleBrown;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FA8072.
/// </summary>
public static readonly RgbaVector Salmon = NamedColors<RgbaVector>.Salmon;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F4A460.
/// </summary>
public static readonly RgbaVector SandyBrown = NamedColors<RgbaVector>.SandyBrown;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #2E8B57.
/// </summary>
public static readonly RgbaVector SeaGreen = NamedColors<RgbaVector>.SeaGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFF5EE.
/// </summary>
public static readonly RgbaVector SeaShell = NamedColors<RgbaVector>.SeaShell;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #A0522D.
/// </summary>
public static readonly RgbaVector Sienna = NamedColors<RgbaVector>.Sienna;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #C0C0C0.
/// </summary>
public static readonly RgbaVector Silver = NamedColors<RgbaVector>.Silver;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #87CEEB.
/// </summary>
public static readonly RgbaVector SkyBlue = NamedColors<RgbaVector>.SkyBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #6A5ACD.
/// </summary>
public static readonly RgbaVector SlateBlue = NamedColors<RgbaVector>.SlateBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #708090.
/// </summary>
public static readonly RgbaVector SlateGray = NamedColors<RgbaVector>.SlateGray;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFAFA.
/// </summary>
public static readonly RgbaVector Snow = NamedColors<RgbaVector>.Snow;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #00FF7F.
/// </summary>
public static readonly RgbaVector SpringGreen = NamedColors<RgbaVector>.SpringGreen;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #4682B4.
/// </summary>
public static readonly RgbaVector SteelBlue = NamedColors<RgbaVector>.SteelBlue;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #D2B48C.
/// </summary>
public static readonly RgbaVector Tan = NamedColors<RgbaVector>.Tan;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #008080.
/// </summary>
public static readonly RgbaVector Teal = NamedColors<RgbaVector>.Teal;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #D8BFD8.
/// </summary>
public static readonly RgbaVector Thistle = NamedColors<RgbaVector>.Thistle;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FF6347.
/// </summary>
public static readonly RgbaVector Tomato = NamedColors<RgbaVector>.Tomato;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFFFF.
/// </summary>
public static readonly RgbaVector Transparent = NamedColors<RgbaVector>.Transparent;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #40E0D0.
/// </summary>
public static readonly RgbaVector Turquoise = NamedColors<RgbaVector>.Turquoise;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #EE82EE.
/// </summary>
public static readonly RgbaVector Violet = NamedColors<RgbaVector>.Violet;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F5DEB3.
/// </summary>
public static readonly RgbaVector Wheat = NamedColors<RgbaVector>.Wheat;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFFFF.
/// </summary>
public static readonly RgbaVector White = NamedColors<RgbaVector>.White;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #F5F5F5.
/// </summary>
public static readonly RgbaVector WhiteSmoke = NamedColors<RgbaVector>.WhiteSmoke;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #FFFF00.
/// </summary>
public static readonly RgbaVector Yellow = NamedColors<RgbaVector>.Yellow;
/// <summary>
/// Represents a <see cref="RgbaVector"/> matching the W3C definition that has an hex value of #9ACD32.
/// </summary>
public static readonly RgbaVector YellowGreen = NamedColors<RgbaVector>.YellowGreen;
}
}

18
src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs

@ -18,11 +18,23 @@ namespace SixLabors.ImageSharp.PixelFormats
internal class PixelOperations : PixelOperations<RgbaVector>
{
/// <inheritdoc />
internal override unsafe void ToVector4(ReadOnlySpan<RgbaVector> sourceColors, Span<Vector4> destVectors, int count)
internal override void PackFromScaledVector4(ReadOnlySpan<Vector4> sourceVectors, Span<RgbaVector> destinationColors, int count)
{
GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count);
GuardSpans(sourceVectors, nameof(sourceVectors), destinationColors, nameof(destinationColors), count);
MemoryMarshal.Cast<RgbaVector, Vector4>(sourceColors).Slice(0, count).CopyTo(destVectors);
MemoryMarshal.Cast<Vector4, RgbaVector>(sourceVectors).Slice(0, count).CopyTo(destinationColors);
}
/// <inheritdoc />
internal override void ToScaledVector4(ReadOnlySpan<RgbaVector> sourceColors, Span<Vector4> destinationVectors, int count)
=> this.ToVector4(sourceColors, destinationVectors, count);
/// <inheritdoc />
internal override void ToVector4(ReadOnlySpan<RgbaVector> sourceColors, Span<Vector4> destinationVectors, int count)
{
GuardSpans(sourceColors, nameof(sourceColors), destinationVectors, nameof(destinationVectors), count);
MemoryMarshal.Cast<RgbaVector, Vector4>(sourceColors).Slice(0, count).CopyTo(destinationVectors);
}
}
}

346
src/ImageSharp/PixelFormats/RgbaVector.cs

@ -4,6 +4,7 @@
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.PixelFormats
{
@ -18,36 +19,32 @@ namespace SixLabors.ImageSharp.PixelFormats
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
/// as it avoids the need to create new values for modification operations.
/// </remarks>
[StructLayout(LayoutKind.Sequential)]
public partial struct RgbaVector : IPixel<RgbaVector>
{
/// <summary>
/// The maximum byte value.
/// Gets or sets the red component.
/// </summary>
private static readonly Vector4 MaxBytes = new Vector4(255);
public float R;
/// <summary>
/// The half vector value.
/// Gets or sets the green component.
/// </summary>
private static readonly Vector4 Half = new Vector4(0.5F);
public float G;
/// <summary>
/// The backing vector for SIMD support.
/// Gets or sets the blue component.
/// </summary>
private Vector4 backingVector;
public float B;
/// <summary>
/// Initializes a new instance of the <see cref="RgbaVector"/> struct.
/// Gets or sets the alpha component.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public RgbaVector(byte r, byte g, byte b, byte a = 255)
: this()
{
this.backingVector = new Vector4(r, g, b, a) / MaxBytes;
}
public float A;
private const float MaxBytes = byte.MaxValue;
private static readonly Vector4 Max = new Vector4(MaxBytes);
private static readonly Vector4 Half = new Vector4(0.5F);
/// <summary>
/// Initializes a new instance of the <see cref="RgbaVector"/> struct.
@ -56,128 +53,25 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public RgbaVector(float r, float g, float b, float a = 1)
: this()
{
this.backingVector = new Vector4(r, g, b, a);
}
/// <summary>
/// Initializes a new instance of the <see cref="RgbaVector"/> struct.
/// </summary>
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public RgbaVector(Vector3 vector)
: this()
{
this.backingVector = new Vector4(vector, 1);
}
/// <summary>
/// Initializes a new instance of the <see cref="RgbaVector"/> struct.
/// </summary>
/// <param name="vector">
/// The vector containing the components for the packed vector.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public RgbaVector(Vector4 vector)
: this()
{
this.backingVector = vector;
}
/// <summary>
/// Gets or sets the red component.
/// </summary>
public float R
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return this.backingVector.X;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.backingVector.X = value;
}
}
/// <summary>
/// Gets or sets the green component.
/// </summary>
public float G
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return this.backingVector.Y;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.backingVector.Y = value;
}
}
/// <summary>
/// Gets or sets the blue component.
/// </summary>
public float B
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return this.backingVector.Z;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.backingVector.Z = value;
}
}
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
public float A
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return this.backingVector.W;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.backingVector.W = value;
}
this.R = r;
this.G = g;
this.B = b;
this.A = a;
}
/// <summary>
/// Compares two <see cref="RgbaVector"/> objects for equality.
/// </summary>
/// <param name="left">
/// The <see cref="RgbaVector"/> on the left side of the operand.
/// </param>
/// <param name="right">
/// The <see cref="RgbaVector"/> on the right side of the operand.
/// </param>
/// <param name="left">The <see cref="RgbaVector"/> on the left side of the operand.</param>
/// <param name="right">The <see cref="RgbaVector"/> on the right side of the operand.</param>
/// <returns>
/// True if the <paramref name="left"/> parameter is equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(RgbaVector left, RgbaVector right)
{
return left.backingVector == right.backingVector;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(RgbaVector left, RgbaVector right) => left.Equals(right);
/// <summary>
/// Compares two <see cref="RgbaVector"/> objects for equality.
@ -187,11 +81,8 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(RgbaVector left, RgbaVector right)
{
return left.backingVector != right.backingVector;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(RgbaVector left, RgbaVector right) => !left.Equals(right);
/// <summary>
/// Creates a new instance of the <see cref="RgbaVector"/> struct.
@ -203,174 +94,111 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <returns>
/// The <see cref="RgbaVector"/>.
/// </returns>
public static RgbaVector FromHex(string hex)
{
return ColorBuilder<RgbaVector>.FromHex(hex);
}
public static RgbaVector FromHex(string hex) => ColorBuilder<RgbaVector>.FromHex(hex);
/// <inheritdoc />
public PixelOperations<RgbaVector> CreatePixelOperations() => new RgbaVector.PixelOperations();
public PixelOperations<RgbaVector> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.backingVector = source.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
this.backingVector = source.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4() => this.ToVector4();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
this.backingVector = source.ToVector4();
vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
this.R = vector.X;
this.G = vector.Y;
this.B = vector.Z;
this.A = vector.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()
{
// Hex is RRGGBBAA
Vector4 vector = this.backingVector * MaxBytes;
vector += Half;
uint hexOrder = (uint)((byte)vector.W | (byte)vector.Z << 8 | (byte)vector.Y << 16 | (byte)vector.X << 24);
return hexOrder.ToString("X8");
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromScaledVector4(Vector4 vector)
{
this.PackFromVector4(vector);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToScaledVector4()
{
return this.ToVector4();
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
/// <summary>
/// Converts the value of this instance to a hexadecimal string.
/// </summary>
/// <returns>A hexadecimal string representation of the value.</returns>
public string ToHex()
{
this.backingVector = vector;
// Hex is RRGGBBAA
Vector4 vector = this.ToVector4() * Max;
vector += Half;
uint hexOrder = (uint)((byte)vector.W | (byte)vector.Z << 8 | (byte)vector.Y << 16 | (byte)vector.X << 24);
return hexOrder.ToString("X8");
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return this.backingVector;
}
public override bool Equals(object obj) => obj is RgbaVector other && this.Equals(other);
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is RgbaVector other && this.Equals(other);
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(RgbaVector other) =>
this.R.Equals(other.R)
&& this.G.Equals(other.G)
&& this.B.Equals(other.B)
&& this.A.Equals(other.A);
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(RgbaVector other)
{
return this.backingVector == other.backingVector;
}
/// <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();
var vector = this.ToVector4();
return FormattableString.Invariant($"RgbaVector({this.R:#0.##}, {this.G:#0.##}, {this.B:#0.##}, {this.A:#0.##})");
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.backingVector.GetHashCode();
int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
hash = HashHelpers.Combine(hash, this.B.GetHashCode());
return HashHelpers.Combine(hash, this.A.GetHashCode());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4() => Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes;
}
}

238
src/ImageSharp/PixelFormats/Short2.cs

@ -15,39 +15,30 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct Short2 : IPixel<Short2>, IPackedVector<uint>
{
/// <summary>
/// The maximum byte value.
/// </summary>
private static readonly Vector2 MaxBytes = new Vector2(255);
// Largest two byte positive number 0xFFFF >> 1;
private const float MaxPos = 0x7FFF;
/// <summary>
/// The half the maximum byte value.
/// </summary>
private static readonly Vector2 Half = new Vector2(127);
// Two's complement
private const float MinNeg = ~(int)MaxPos;
/// <summary>
/// The vector value used for rounding.
/// </summary>
private static readonly Vector2 Round = new Vector2(.5F);
private static readonly Vector2 Max = new Vector2(MaxPos);
private static readonly Vector2 Min = new Vector2(MinNeg);
/// <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)
/// <param name="x">The x-component.</param>
/// <param name="y">The y-component.</param>
public Short2(float x, float y)
: this(new Vector2(x, y))
{
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);
}
/// <param name="vector">The vector containing the component values.</param>
public Short2(Vector2 vector) => this.PackedValue = Pack(vector);
/// <inheritdoc/>
public uint PackedValue { get; set; }
@ -55,53 +46,39 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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>
/// <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.
/// True if the <paramref name="left"/> parameter is not equal to the <paramref name="right"/> parameter; otherwise, false.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Short2 left, Short2 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Short2 left, Short2 right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Short2 left, Short2 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Short2 left, Short2 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Short2> CreatePixelOperations() => new PixelOperations<Short2>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
Vector2 scaled = new Vector2(vector.X, vector.Y) * 65534F;
scaled -= new Vector2(32767F);
this.PackedValue = Pack(scaled.X, scaled.Y);
this.PackedValue = Pack(scaled);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector2();
@ -111,182 +88,91 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y);
var vector2 = new Vector2(vector.X, vector.Y);
this.PackedValue = Pack(vector2);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10), 0, 1);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4() => new Vector4((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10), 0, 1);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
Vector2 vector = new Vector2(source.R, source.G) / 255;
vector *= 65534;
vector -= new Vector2(32767);
this.PackedValue = Pack(vector.X, vector.Y);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
Vector2 vector = new Vector2(source.R, source.G) / 255;
vector *= 65534;
vector -= new Vector2(32767);
this.PackedValue = Pack(vector.X, vector.Y);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
Vector2 vector = new Vector2(source.R, source.G) / 255;
vector *= 65534;
vector -= new Vector2(32767);
this.PackedValue = Pack(vector.X, vector.Y);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector2 vector = this.ToByteScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector2 vector = this.ToByteScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector2 vector = this.ToByteScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector2 vector = this.ToByteScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector2 vector = this.ToByteScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector2 ToVector2()
{
return new Vector2((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10));
}
[MethodImpl(InliningOptions.ShortMethod)]
public Vector2 ToVector2() => new Vector2((short)(this.PackedValue & 0xFFFF), (short)(this.PackedValue >> 0x10));
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Short2 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Short2 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Short2 other)
{
return this == other;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Short2 other) => this.PackedValue.Equals(other.PackedValue);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("x8");
var vector = this.ToVector2();
return FormattableString.Invariant($"Short2({vector.X:#0.##}, {vector.Y:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint Pack(float x, float y)
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(Vector2 vector)
{
// 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;
vector = Vector2.Clamp(vector, Min, Max);
uint word2 = (uint)Math.Round(vector.X) & 0xFFFF;
uint word1 = ((uint)Math.Round(vector.Y) & 0xFFFF) << 0x10;
return word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector2 ToByteScaledVector2()
{
var vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
return vector;
}
}
}

236
src/ImageSharp/PixelFormats/Short4.cs

@ -15,29 +15,14 @@ namespace SixLabors.ImageSharp.PixelFormats
/// </summary>
public struct Short4 : IPixel<Short4>, IPackedVector<ulong>
{
/// <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);
// Largest two byte positive number 0xFFFF >> 1;
private const float MaxPos = 0x7FFF;
/// <summary>
/// The vector value used for rounding.
/// </summary>
private static readonly Vector4 Round = new Vector4(.5F);
// Two's complement
private const float MinNeg = ~(int)MaxPos;
/// <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);
}
private static readonly Vector4 Max = new Vector4(MaxPos);
private static readonly Vector4 Min = new Vector4(MinNeg);
/// <summary>
/// Initializes a new instance of the <see cref="Short4"/> struct.
@ -47,54 +32,46 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <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(new Vector4(x, y, z, w))
{
this.PackedValue = Pack(x, y, z, w);
}
/// <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(ref vector);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Short4 left, Short4 right)
{
return left.PackedValue == right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator ==(Short4 left, Short4 right) => left.Equals(right);
/// <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>
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Short4 left, Short4 right)
{
return left.PackedValue != right.PackedValue;
}
[MethodImpl(InliningOptions.ShortMethod)]
public static bool operator !=(Short4 left, Short4 right) => !left.Equals(right);
/// <inheritdoc />
public PixelOperations<Short4> CreatePixelOperations() => new PixelOperations<Short4>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromScaledVector4(Vector4 vector)
{
vector *= 65534F;
@ -103,7 +80,7 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToScaledVector4()
{
var scaled = this.ToVector4();
@ -113,14 +90,11 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@ -131,168 +105,78 @@ namespace SixLabors.ImageSharp.PixelFormats
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
var vector = source.ToVector4();
vector *= 65534;
vector -= new Vector4(32767);
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromArgb32(Argb32 source)
{
var vector = source.ToVector4();
vector *= 65534;
vector -= new Vector4(32767);
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBgra32(Bgra32 source)
{
var vector = source.ToVector4();
vector *= 65534;
vector -= new Vector4(32767);
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToArgb32(ref Argb32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToByteScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
dest.A = (byte)MathF.Round(vector.W);
}
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
/// <inheritdoc />
public override bool Equals(object obj)
{
return obj is Short4 other && this.Equals(other);
}
public override bool Equals(object obj) => obj is Short4 other && this.Equals(other);
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Short4 other)
{
return this == other;
}
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(Short4 other) => this.PackedValue.Equals(other);
/// <summary>
/// Gets the hash code for the current instance.
/// </summary>
/// <returns>Hash code for the instance.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
/// <summary>
/// Returns a string representation of the current instance.
/// </summary>
/// <returns>String that represents the object.</returns>
/// <inheritdoc />
public override string ToString()
{
return this.PackedValue.ToString("x16");
var vector = this.ToVector4();
return FormattableString.Invariant($"Short4({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
/// <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>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong Pack(float x, float y, float z, float w)
[MethodImpl(InliningOptions.ShortMethod)]
private static ulong Pack(ref Vector4 vector)
{
// Largest two byte positive number 0xFFFF >> 1;
const float MaxPos = 0x7FFF;
// Two's complement
const float MinNeg = ~(int)MaxPos;
vector = Vector4.Clamp(vector, Min, Max);
// 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;
ulong word4 = ((ulong)Math.Round(vector.X) & 0xFFFF) << 0x00;
ulong word3 = ((ulong)Math.Round(vector.Y) & 0xFFFF) << 0x10;
ulong word2 = ((ulong)Math.Round(vector.Z) & 0xFFFF) << 0x20;
ulong word1 = ((ulong)Math.Round(vector.W) & 0xFFFF) << 0x30;
return word4 | word3 | word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToByteScaledVector4()
{
var vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
return Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
}
}
}

11
src/ImageSharp/Processing/Processors/Binarization/BinaryErrorDiffusionProcessor.cs

@ -76,8 +76,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
float threshold = this.Threshold * 255F;
Rgba32 rgba = default;
byte threshold = (byte)MathF.Round(this.Threshold * 255F);
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
@ -89,10 +88,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
// Collect the values before looping so we can reduce our calculation count for identical sibling pixels
TPixel sourcePixel = source[startX, startY];
TPixel previousPixel = sourcePixel;
sourcePixel.ToRgba32(ref rgba);
var rgba = sourcePixel.ToRgba32();
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
for (int y = startY; y < endY; y++)
{
@ -106,8 +105,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
// rather than calculating it again. This is an inexpensive optimization.
if (!previousPixel.Equals(sourcePixel))
{
sourcePixel.ToRgba32(ref rgba);
luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
rgba = sourcePixel.ToRgba32();
luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
// Setup the previous pointer
previousPixel = sourcePixel;

9
src/ImageSharp/Processing/Processors/Binarization/BinaryOrderedDitherProcessor.cs

@ -56,7 +56,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
Rgba32 rgba = default;
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
@ -68,10 +67,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
// Collect the values before looping so we can reduce our calculation count for identical sibling pixels
TPixel sourcePixel = source[startX, startY];
TPixel previousPixel = sourcePixel;
sourcePixel.ToRgba32(ref rgba);
var rgba = sourcePixel.ToRgba32();
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
for (int y = startY; y < endY; y++)
{
@ -85,8 +84,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
// rather than calculating it again. This is an inexpensive optimization.
if (!previousPixel.Equals(sourcePixel))
{
sourcePixel.ToRgba32(ref rgba);
luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
rgba = sourcePixel.ToRgba32();
luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
// Setup the previous pointer
previousPixel = sourcePixel;

9
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs

@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
Rectangle sourceRectangle,
Configuration configuration)
{
float threshold = this.Threshold * 255F;
byte threshold = (byte)MathF.Round(this.Threshold * 255F);
TPixel upper = this.UpperColor;
TPixel lower = this.LowerColor;
@ -83,17 +83,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> row = source.GetPixelRowSpan(y);
Rgba32 rgba = default;
for (int x = startX; x < endX; x++)
{
ref TPixel color = ref row[x];
color.ToRgba32(ref rgba);
var rgba = color.ToRgba32();
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly
? rgba.A
: (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
color = luminance >= threshold ? upper : lower;
}
}

12
src/ImageSharp/Processing/Processors/Dithering/ErrorDiffusionPaletteProcessor.cs

@ -4,7 +4,6 @@
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Dithering;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Dithering
@ -64,8 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
float threshold = this.Threshold * 255F;
Rgba32 rgba = default;
byte threshold = (byte)MathF.Round(this.Threshold * 255F);
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
@ -78,10 +76,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
TPixel sourcePixel = source[startX, startY];
TPixel previousPixel = sourcePixel;
PixelPair<TPixel> pair = this.GetClosestPixelPair(ref sourcePixel);
sourcePixel.ToRgba32(ref rgba);
var rgba = sourcePixel.ToRgba32();
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
for (int y = startY; y < endY; y++)
{
@ -103,8 +101,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
continue;
}
sourcePixel.ToRgba32(ref rgba);
luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
rgba = sourcePixel.ToRgba32();
luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
// Setup the previous pointer
previousPixel = sourcePixel;

15
src/ImageSharp/Processing/Processors/Dithering/OrderedDitherPaletteProcessor.cs

@ -4,7 +4,6 @@
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Dithering;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.Dithering
@ -32,10 +31,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <param name="dither">The ordered ditherer.</param>
/// <param name="palette">The palette to select substitute colors from.</param>
public OrderedDitherPaletteProcessor(IOrderedDither dither, TPixel[] palette)
: base(palette)
{
this.Dither = dither ?? throw new ArgumentNullException(nameof(dither));
}
: base(palette) => this.Dither = dither ?? throw new ArgumentNullException(nameof(dither));
/// <summary>
/// Gets the ditherer.
@ -45,7 +41,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <inheritdoc/>
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
Rgba32 rgba = default;
bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
@ -58,10 +53,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
TPixel sourcePixel = source[startX, startY];
TPixel previousPixel = sourcePixel;
PixelPair<TPixel> pair = this.GetClosestPixelPair(ref sourcePixel);
sourcePixel.ToRgba32(ref rgba);
var rgba = sourcePixel.ToRgba32();
// Convert to grayscale using ITU-R Recommendation BT.709 if required
float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
for (int y = startY; y < endY; y++)
{
@ -83,8 +78,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
continue;
}
sourcePixel.ToRgba32(ref rgba);
luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);
rgba = sourcePixel.ToRgba32();
luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
// Setup the previous pointer
previousPixel = sourcePixel;

49
src/ImageSharp/Processing/Processors/Quantization/OctreeFrameQuantizer{TPixel}.cs

@ -73,14 +73,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
ref TPixel scanBaseRef = ref MemoryMarshal.GetReference(row);
// And loop through each column
Rgba32 rgba = default;
for (int x = 0; x < width; x++)
{
ref TPixel pixel = ref Unsafe.Add(ref scanBaseRef, x);
pixel.ToRgba32(ref rgba);
// Add the color to the Octree
this.octree.AddColor(ref pixel, ref rgba);
this.octree.AddColor(ref pixel);
}
}
}
@ -97,9 +95,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
// pass of the algorithm by avoiding transforming rows of identical color.
TPixel sourcePixel = source[0, 0];
TPixel previousPixel = sourcePixel;
Rgba32 rgba = default;
this.transparentIndex = this.GetTransparentIndex();
byte pixelValue = this.QuantizePixel(ref sourcePixel, ref rgba);
byte pixelValue = this.QuantizePixel(ref sourcePixel);
TPixel transformedPixel = palette[pixelValue];
for (int y = 0; y < height; y++)
@ -117,7 +114,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
if (!previousPixel.Equals(sourcePixel))
{
// Quantize the pixel
pixelValue = this.QuantizePixel(ref sourcePixel, ref rgba);
pixelValue = this.QuantizePixel(ref sourcePixel);
// And setup the previous pointer
previousPixel = sourcePixel;
@ -146,10 +143,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Process the pixel in the second pass of the algorithm.
/// </summary>
/// <param name="pixel">The pixel to quantize.</param>
/// <param name="rgba">The color to compare against.</param>
/// <returns>The <see cref="byte"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private byte QuantizePixel(ref TPixel pixel, ref Rgba32 rgba)
private byte QuantizePixel(ref TPixel pixel)
{
if (this.Dither)
{
@ -158,13 +154,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
return this.GetClosestPixel(ref pixel);
}
pixel.ToRgba32(ref rgba);
var rgba = pixel.ToRgba32();
if (rgba.Equals(default))
{
return this.transparentIndex;
}
return (byte)this.octree.GetPaletteIndex(ref pixel, ref rgba);
return (byte)this.octree.GetPaletteIndex(ref pixel);
}
/// <summary>
@ -239,8 +235,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Add a given color value to the Octree
/// </summary>
/// <param name="pixel">The pixel data.</param>
/// <param name="rgba">The color.</param>
public void AddColor(ref TPixel pixel, ref Rgba32 rgba)
public void AddColor(ref TPixel pixel)
{
// Check if this request is for the same color as the last
if (this.previousColor.Equals(pixel))
@ -250,18 +245,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
if (this.previousNode is null)
{
this.previousColor = pixel;
this.root.AddColor(ref pixel, this.maxColorBits, 0, this, ref rgba);
this.root.AddColor(ref pixel, this.maxColorBits, 0, this);
}
else
{
// Just update the previous node
this.previousNode.Increment(ref pixel, ref rgba);
this.previousNode.Increment(ref pixel);
}
}
else
{
this.previousColor = pixel;
this.root.AddColor(ref pixel, this.maxColorBits, 0, this, ref rgba);
this.root.AddColor(ref pixel, this.maxColorBits, 0, this);
}
}
@ -294,12 +289,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Get the palette index for the passed color
/// </summary>
/// <param name="pixel">The pixel data.</param>
/// <param name="rgba">The color to map to.</param>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetPaletteIndex(ref TPixel pixel, ref Rgba32 rgba) => this.root.GetPaletteIndex(ref pixel, 0, ref rgba);
public int GetPaletteIndex(ref TPixel pixel) => this.root.GetPaletteIndex(ref pixel, 0);
/// <summary>
/// Keep track of the previous node that was quantized
@ -426,13 +420,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <param name="colorBits">The number of significant color bits</param>
/// <param name="level">The level in the tree</param>
/// <param name="octree">The tree to which this node belongs</param>
/// <param name="rgba">The color to map to.</param>
public void AddColor(ref TPixel pixel, int colorBits, int level, Octree octree, ref Rgba32 rgba)
public void AddColor(ref TPixel pixel, int colorBits, int level, Octree octree)
{
// Update the color information if this is a leaf
if (this.leaf)
{
this.Increment(ref pixel, ref rgba);
this.Increment(ref pixel);
// Setup the previous node
octree.TrackPrevious(this);
@ -441,7 +434,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
{
// Go to the next level down in the tree
int shift = 7 - level;
pixel.ToRgba32(ref rgba);
var rgba = pixel.ToRgba32();
int index = ((rgba.B & Mask[level]) >> (shift - 2))
| ((rgba.G & Mask[level]) >> (shift - 1))
@ -456,7 +449,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
}
// Add the color to the child node
child.AddColor(ref pixel, colorBits, level + 1, octree, ref rgba);
child.AddColor(ref pixel, colorBits, level + 1, octree);
}
}
@ -525,19 +518,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// </summary>
/// <param name="pixel">The pixel data.</param>
/// <param name="level">The level.</param>
/// <param name="rgba">The color to map to.</param>
/// <returns>
/// The <see cref="int"/> representing the index of the pixel in the palette.
/// </returns>
[MethodImpl(MethodImplOptions.NoInlining)]
public int GetPaletteIndex(ref TPixel pixel, int level, ref Rgba32 rgba)
public int GetPaletteIndex(ref TPixel pixel, int level)
{
int index = this.paletteIndex;
if (!this.leaf)
{
int shift = 7 - level;
pixel.ToRgba32(ref rgba);
var rgba = pixel.ToRgba32();
int pixelIndex = ((rgba.B & Mask[level]) >> (shift - 2))
| ((rgba.G & Mask[level]) >> (shift - 1))
@ -546,7 +538,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
OctreeNode child = this.children[pixelIndex];
if (child != null)
{
index = child.GetPaletteIndex(ref pixel, level + 1, ref rgba);
index = child.GetPaletteIndex(ref pixel, level + 1);
}
else
{
@ -561,11 +553,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// Increment the pixel count and add to the color information
/// </summary>
/// <param name="pixel">The pixel to add.</param>
/// <param name="rgba">The color to map to.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Increment(ref TPixel pixel, ref Rgba32 rgba)
public void Increment(ref TPixel pixel)
{
pixel.ToRgba32(ref rgba);
var rgba = pixel.ToRgba32();
this.pixelCount++;
this.red += rgba.R;
this.green += rgba.G;

48
src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs

@ -442,33 +442,36 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
// Build up the 3-D color histogram
// Loop through each row
for (int y = 0; y < height; y++)
using (IMemoryOwner<Rgba32> rgbaBuffer = source.MemoryAllocator.Allocate<Rgba32>(source.Width))
{
Span<TPixel> row = source.GetPixelRowSpan(y);
ref TPixel scanBaseRef = ref MemoryMarshal.GetReference(row);
// And loop through each column
Rgba32 rgba = default;
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
ref TPixel pixel = ref Unsafe.Add(ref scanBaseRef, x);
pixel.ToRgba32(ref rgba);
Span<TPixel> row = source.GetPixelRowSpan(y);
Span<Rgba32> rgbaSpan = rgbaBuffer.GetSpan();
PixelOperations<TPixel>.Instance.ToRgba32(row, rgbaSpan, source.Width);
ref Rgba32 scanBaseRef = ref MemoryMarshal.GetReference(rgbaSpan);
// And loop through each column
for (int x = 0; x < width; x++)
{
ref Rgba32 rgba = ref Unsafe.Add(ref scanBaseRef, x);
int r = rgba.R >> (8 - IndexBits);
int g = rgba.G >> (8 - IndexBits);
int b = rgba.B >> (8 - IndexBits);
int a = rgba.A >> (8 - IndexAlphaBits);
int r = rgba.R >> (8 - IndexBits);
int g = rgba.G >> (8 - IndexBits);
int b = rgba.B >> (8 - IndexBits);
int a = rgba.A >> (8 - IndexAlphaBits);
int index = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1);
int index = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1);
vwtSpan[index]++;
vmrSpan[index] += rgba.R;
vmgSpan[index] += rgba.G;
vmbSpan[index] += rgba.B;
vmaSpan[index] += rgba.A;
vwtSpan[index]++;
vmrSpan[index] += rgba.R;
vmgSpan[index] += rgba.G;
vmbSpan[index] += rgba.B;
vmaSpan[index] += rgba.A;
var vector = new Vector4(rgba.R, rgba.G, rgba.B, rgba.A);
m2Span[index] += Vector4.Dot(vector, vector);
var vector = new Vector4(rgba.R, rgba.G, rgba.B, rgba.A);
m2Span[index] += Vector4.Dot(vector, vector);
}
}
}
}
@ -876,8 +879,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
}
// Expected order r->g->b->a
Rgba32 rgba = default;
pixel.ToRgba32(ref rgba);
var rgba = pixel.ToRgba32();
int r = rgba.R >> (8 - IndexBits);
int g = rgba.G >> (8 - IndexBits);

32
tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs

@ -4,10 +4,7 @@
// ReSharper disable InconsistentNaming
using System.Buffers;
using System;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@ -38,35 +35,10 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
}
[Benchmark(Baseline = true)]
public void PerElement()
{
Span<TPixel> s = this.source.GetSpan();
Span<byte> d = this.destination.GetSpan();
var rgb = default(Rgb24);
for (int i = 0; i < this.Count; i++)
{
TPixel c = s[i];
int i3 = i * 3;
c.ToRgb24(ref rgb);
d[i3] = rgb.R;
d[i3 + 1] = rgb.G;
d[i3 + 2] = rgb.B;
}
}
public void CommonBulk() => new PixelOperations<TPixel>().ToRgb24Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
[Benchmark]
public void CommonBulk()
{
new PixelOperations<TPixel>().ToRgb24Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
}
[Benchmark]
public void OptimizedBulk()
{
PixelOperations<TPixel>.Instance.ToRgb24Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
}
public void OptimizedBulk() => PixelOperations<TPixel>.Instance.ToRgb24Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
}
public class ToXyz_Rgba32 : ToXyz<Rgba32>

14
tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs

@ -42,13 +42,11 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
Span<TPixel> s = this.source.GetSpan();
Span<byte> d = this.destination.GetSpan();
var rgba = default(Rgba32);
for (int i = 0; i < this.Count; i++)
{
TPixel c = s[i];
int i4 = i * 4;
c.ToRgba32(ref rgba);
var rgba = c.ToRgba32();
d[i4] = rgba.R;
d[i4 + 1] = rgba.G;
d[i4 + 2] = rgba.B;
@ -57,16 +55,10 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
}
[Benchmark]
public void CommonBulk()
{
new PixelOperations<TPixel>().ToRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
}
public void CommonBulk() => new PixelOperations<TPixel>().ToRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
[Benchmark]
public void OptimizedBulk()
{
PixelOperations<TPixel>.Instance.ToRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
}
public void OptimizedBulk() => PixelOperations<TPixel>.Instance.ToRgba32Bytes(this.source.GetSpan(), this.destination.GetSpan(), this.Count);
}
public class ToXyzw_Rgba32 : ToXyzw<Rgba32>

28
tests/ImageSharp.Benchmarks/General/PixelConversion/ITestPixel.cs

@ -0,0 +1,28 @@
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
interface ITestPixel<T>
where T : struct, ITestPixel<T>
{
void FromRgba32(Rgba32 source);
void FromRgba32(ref Rgba32 source);
void FromBytes(byte r, byte g, byte b, byte a);
void FromVector4(Vector4 source);
void FromVector4(ref Vector4 source);
Rgba32 ToRgba32();
void CopyToRgba32(ref Rgba32 dest);
Vector4 ToVector4();
void CopyToVector4(ref Vector4 dest);
}
}

81
tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs → tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs

@ -1,86 +1,15 @@
// ReSharper disable InconsistentNaming
using SixLabors.ImageSharp.PixelFormats;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Benchmarks.General
{
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
public class PixelConversion_ConvertFromRgba32
{
interface ITestPixel<T>
where T : struct, ITestPixel<T>
{
void FromRgba32(Rgba32 source);
void FromRgba32(ref Rgba32 source);
void FromBytes(byte r, byte g, byte b, byte a);
}
[StructLayout(LayoutKind.Sequential)]
struct TestArgb : ITestPixel<TestArgb>
{
private byte a, r, g, b;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 p)
{
this.r = p.R;
this.g = p.G;
this.b = p.B;
this.a = p.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 p)
{
this.r = p.R;
this.g = p.G;
this.b = p.B;
this.a = p.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a)
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
[StructLayout(LayoutKind.Sequential)]
struct TestRgba : ITestPixel<TestRgba>
{
private byte r, g, b, a;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 source)
{
this = Unsafe.As<Rgba32, TestRgba>(ref source);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 source)
{
this = Unsafe.As<Rgba32, TestRgba>(ref source);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a)
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
}
struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{

58
tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs → tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromVector4.cs

@ -1,62 +1,48 @@
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.General
{
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
public class PixelConversion_ConvertFromVector4
{
interface ITestPixel<T>
where T : struct, ITestPixel<T>
{
void FromVector4(Vector4 source);
using BenchmarkDotNet.Attributes;
void FromVector4(ref Vector4 source);
}
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
public class PixelConversion_ConvertFromVector4
{
[StructLayout(LayoutKind.Sequential)]
struct TestArgb : ITestPixel<TestArgb>
struct TestRgbaVector : ITestPixel<TestRgbaVector>
{
private byte a, r, g, b;
private Vector4 v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 p)
{
this.r = (byte)p.X;
this.g = (byte)p.Y;
this.b = (byte)p.Z;
this.a = (byte)p.W;
this.v = p;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 p)
{
this.r = (byte)p.X;
this.g = (byte)p.Y;
this.b = (byte)p.Z;
this.a = (byte)p.W;
this.v = p;
}
}
[StructLayout(LayoutKind.Sequential)]
struct TestRgbaVector : ITestPixel<TestRgbaVector>
{
private Vector4 v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 p)
{
this.v = p;
}
public Vector4 ToVector4() => this.v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 p)
public void CopyToVector4(ref Vector4 dest)
{
this.v = p;
dest = this.v;
}
public void FromRgba32(Rgba32 source) => throw new System.NotImplementedException();
public void FromRgba32(ref Rgba32 source) => throw new System.NotImplementedException();
public void FromBytes(byte r, byte g, byte b, byte a) => throw new System.NotImplementedException();
public Rgba32 ToRgba32() => throw new System.NotImplementedException();
public void CopyToRgba32(ref Rgba32 dest) => throw new System.NotImplementedException();
}
struct ConversionRunner<T>

61
tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertToRgba32.cs → tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32.cs

@ -1,14 +1,14 @@
// ReSharper disable InconsistentNaming
using SixLabors.ImageSharp.PixelFormats;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Benchmarks.General
{
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
/// <summary>
/// When implementing TPixel --> Rgba32 style conversions on IPixel, should which API should we prefer?
/// 1. Rgba32 ToRgba32();
@ -18,53 +18,6 @@ namespace SixLabors.ImageSharp.Benchmarks.General
/// </summary>
public class PixelConversion_ConvertToRgba32
{
interface ITestPixel<T>
where T : struct, ITestPixel<T>
{
Rgba32 ToRgba32();
void CopyToRgba32(ref Rgba32 dest);
}
[StructLayout(LayoutKind.Sequential)]
struct TestArgb : ITestPixel<TestArgb>
{
private byte a, r, g, b;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32()
{
return new Rgba32(this.r, this.g, this.b, this.a);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToRgba32(ref Rgba32 dest)
{
dest.R = this.r;
dest.G = this.g;
dest.B = this.b;
dest.A = this.a;
}
}
[StructLayout(LayoutKind.Sequential)]
struct TestRgba : ITestPixel<TestRgba>
{
private byte r, g, b, a;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32()
{
return Unsafe.As<TestRgba, Rgba32>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToRgba32(ref Rgba32 dest)
{
dest = Unsafe.As<TestRgba, Rgba32>(ref this);
}
}
struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{
@ -111,7 +64,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General
private ConversionRunner<TestArgb> permutedRunner;
[Params(128)]
[Params(32)]
public int Count { get; set; }
[GlobalSetup]

113
tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToRgba32_AsPartOfCompositeOperation.cs

@ -0,0 +1,113 @@
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
public class PixelConversion_ConvertToRgba32_AsPartOfCompositeOperation
{
struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{
private T[] source;
private Rgba32[] dest;
public ConversionRunner(int count)
{
this.source = new T[count];
this.dest = new Rgba32[count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunRetvalConversion()
{
int count = this.source.Length;
ref T sourceBaseRef = ref this.source[0];
ref Rgba32 destBaseRef = ref this.dest[0];
Rgba32 temp;
for (int i = 0; i < count; i++)
{
temp = Unsafe.Add(ref sourceBaseRef, i).ToRgba32();
// manipulate pixel before saving to dest buffer:
temp.A = 0;
Unsafe.Add(ref destBaseRef, i) = temp;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunCopyToConversion()
{
int count = this.source.Length;
ref T sourceBaseRef = ref this.source[0];
ref Rgba32 destBaseRef = ref this.dest[0];
Rgba32 temp = default;
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref sourceBaseRef, i).CopyToRgba32(ref temp);
// manipulate pixel before saving to dest buffer:
temp.A = 0;
Unsafe.Add(ref destBaseRef, i) = temp;
}
}
}
private ConversionRunner<TestRgba> compatibleMemoryLayoutRunner;
private ConversionRunner<TestArgb> permutedRunner;
[Params(32)]
public int Count { get; set; }
[GlobalSetup]
public void Setup()
{
this.compatibleMemoryLayoutRunner = new ConversionRunner<TestRgba>(this.Count);
this.permutedRunner = new ConversionRunner<TestArgb>(this.Count);
}
[Benchmark(Baseline = true)]
public void CompatibleRetval()
{
this.compatibleMemoryLayoutRunner.RunRetvalConversion();
}
[Benchmark]
public void CompatibleCopyTo()
{
this.compatibleMemoryLayoutRunner.RunCopyToConversion();
}
[Benchmark]
public void PermutedRetval()
{
this.permutedRunner.RunRetvalConversion();
}
[Benchmark]
public void PermutedCopyTo()
{
this.permutedRunner.RunCopyToConversion();
}
}
// RESULTS:
// Method | Count | Mean | Error | StdDev | Scaled | ScaledSD |
// ----------------- |------ |----------:|----------:|----------:|-------:|---------:|
// CompatibleRetval | 32 | 53.05 ns | 0.1865 ns | 0.1557 ns | 1.00 | 0.00 |
// CompatibleCopyTo | 32 | 36.12 ns | 0.3596 ns | 0.3003 ns | 0.68 | 0.01 |
// PermutedRetval | 32 | 303.61 ns | 5.1697 ns | 4.8358 ns | 5.72 | 0.09 |
// PermutedCopyTo | 32 | 38.05 ns | 0.8053 ns | 1.2297 ns | 0.72 | 0.02 |
}

83
tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4.cs

@ -0,0 +1,83 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
public class PixelConversion_ConvertToVector4
{
struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{
private T[] source;
private Vector4[] dest;
public ConversionRunner(int count)
{
this.source = new T[count];
this.dest = new Vector4[count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunRetvalConversion()
{
int count = this.source.Length;
ref T sourceBaseRef = ref this.source[0];
ref Vector4 destBaseRef = ref this.dest[0];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref destBaseRef, i) = Unsafe.Add(ref sourceBaseRef, i).ToVector4();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunCopyToConversion()
{
int count = this.source.Length;
ref T sourceBaseRef = ref this.source[0];
ref Vector4 destBaseRef = ref this.dest[0];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref sourceBaseRef, i).CopyToVector4(ref Unsafe.Add(ref destBaseRef, i));
}
}
}
private ConversionRunner<TestRgba> runner;
[Params(32)]
public int Count { get; set; }
[GlobalSetup]
public void Setup()
{
this.runner = new ConversionRunner<TestRgba>(this.Count);
}
[Benchmark(Baseline = true)]
public void UseRetval()
{
this.runner.RunRetvalConversion();
}
[Benchmark]
public void UseCopyTo()
{
this.runner.RunCopyToConversion();
}
// RESULTS:
// Method | Count | Mean | Error | StdDev | Scaled |
// ---------- |------ |---------:|----------:|----------:|-------:|
// UseRetval | 32 | 94.99 ns | 1.1199 ns | 0.9352 ns | 1.00 |
// UseCopyTo | 32 | 59.47 ns | 0.6104 ns | 0.5710 ns | 0.63 |
}
}

95
tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertToVector4_AsPartOfCompositeOperation.cs

@ -0,0 +1,95 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
public class PixelConversion_ConvertToVector4_AsPartOfCompositeOperation
{
struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{
private T[] source;
private Vector4[] dest;
public ConversionRunner(int count)
{
this.source = new T[count];
this.dest = new Vector4[count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunRetvalConversion()
{
int count = this.source.Length;
ref T sourceBaseRef = ref this.source[0];
ref Vector4 destBaseRef = ref this.dest[0];
Vector4 temp;
for (int i = 0; i < count; i++)
{
temp = Unsafe.Add(ref sourceBaseRef, i).ToVector4();
// manipulate pixel before saving to dest buffer:
temp.W = 0;
Unsafe.Add(ref destBaseRef, i) = temp;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunCopyToConversion()
{
int count = this.source.Length;
ref T sourceBaseRef = ref this.source[0];
ref Vector4 destBaseRef = ref this.dest[0];
Vector4 temp = default;
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref sourceBaseRef, i).CopyToVector4(ref temp);
// manipulate pixel before saving to dest buffer:
temp.W = 0;
Unsafe.Add(ref destBaseRef, i) = temp;
}
}
}
private ConversionRunner<TestRgba> runner;
[Params(32)]
public int Count { get; set; }
[GlobalSetup]
public void Setup()
{
this.runner = new ConversionRunner<TestRgba>(this.Count);
}
[Benchmark(Baseline = true)]
public void UseRetval()
{
this.runner.RunRetvalConversion();
}
[Benchmark]
public void UseCopyTo()
{
this.runner.RunCopyToConversion();
}
// RESULTS:
// Method | Count | Mean | Error | StdDev | Scaled |
// ---------- |------ |----------:|----------:|----------:|-------:|
// UseRetval | 32 | 100.35 ns | 0.4844 ns | 0.4532 ns | 1.00 |
// UseCopyTo | 32 | 53.95 ns | 0.1269 ns | 0.1125 ns | 0.54 |
}
}

89
tests/ImageSharp.Benchmarks/General/PixelConversion/TestArgb.cs

@ -0,0 +1,89 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
[StructLayout(LayoutKind.Sequential)]
struct TestArgb : ITestPixel<TestArgb>
{
private byte a, r, g, b;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 p)
{
this.r = p.R;
this.g = p.G;
this.b = p.B;
this.a = p.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 p)
{
this.r = p.R;
this.g = p.G;
this.b = p.B;
this.a = p.A;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a)
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 p)
{
this.r = (byte)p.X;
this.g = (byte)p.Y;
this.b = (byte)p.Z;
this.a = (byte)p.W;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 p)
{
this.r = (byte)p.X;
this.g = (byte)p.Y;
this.b = (byte)p.Z;
this.a = (byte)p.W;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32()
{
return new Rgba32(this.r, this.g, this.b, this.a);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToRgba32(ref Rgba32 dest)
{
dest.R = this.r;
dest.G = this.g;
dest.B = this.b;
dest.A = this.a;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.r, this.g, this.b, this.a);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToVector4(ref Vector4 dest)
{
dest.X = this.r;
dest.Y = this.g;
dest.Z = this.b;
dest.W = this.a;
}
}
}

72
tests/ImageSharp.Benchmarks/General/PixelConversion/TestRgba.cs

@ -0,0 +1,72 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
{
[StructLayout(LayoutKind.Sequential)]
struct TestRgba : ITestPixel<TestRgba>
{
private byte r, g, b, a;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(Rgba32 source)
{
this = Unsafe.As<Rgba32, TestRgba>(ref source);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromRgba32(ref Rgba32 source)
{
this = Unsafe.As<Rgba32, TestRgba>(ref source);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromBytes(byte r, byte g, byte b, byte a)
{
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
public void FromVector4(Vector4 source)
{
throw new System.NotImplementedException();
}
public void FromVector4(ref Vector4 source)
{
throw new System.NotImplementedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32()
{
return Unsafe.As<TestRgba, Rgba32>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToRgba32(ref Rgba32 dest)
{
dest = Unsafe.As<TestRgba, Rgba32>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.r, this.g, this.b, this.a);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyToVector4(ref Vector4 dest)
{
dest.X = this.r;
dest.Y = this.g;
dest.Z = this.b;
dest.W = this.a;
}
}
}

21
tests/ImageSharp.Sandbox46/Program.cs

@ -6,14 +6,9 @@
namespace SixLabors.ImageSharp.Sandbox46
{
using System;
using System.Runtime.DesignerServices;
using SixLabors.ImageSharp.Tests;
using SixLabors.ImageSharp.Tests.Colors;
using SixLabors.ImageSharp.Tests.Formats.Jpg;
using SixLabors.ImageSharp.Tests.PixelFormats;
using SixLabors.ImageSharp.Tests.Processing.Processors.Transforms;
using SixLabors.ImageSharp.Tests.Processing.Transforms;
using Xunit.Abstractions;
@ -21,15 +16,9 @@ namespace SixLabors.ImageSharp.Sandbox46
{
private class ConsoleOutput : ITestOutputHelper
{
public void WriteLine(string message)
{
Console.WriteLine(message);
}
public void WriteLine(string message) => Console.WriteLine(message);
public void WriteLine(string format, params object[] args)
{
Console.WriteLine(format, args);
}
public void WriteLine(string format, params object[] args) => Console.WriteLine(format, args);
}
/// <summary>
@ -58,20 +47,20 @@ namespace SixLabors.ImageSharp.Sandbox46
private static void RunResizeProfilingTest()
{
ResizeProfilingBenchmarks test = new ResizeProfilingBenchmarks(new ConsoleOutput());
var test = new ResizeProfilingBenchmarks(new ConsoleOutput());
test.ResizeBicubic(2000, 2000);
}
private static void RunToVector4ProfilingTest()
{
PixelOperationsTests.Rgba32 tests = new PixelOperationsTests.Rgba32(new ConsoleOutput());
var tests = new PixelOperationsTests.Rgba32OperationsTests(new ConsoleOutput());
tests.Benchmark_ToVector4();
}
private static void RunDecodeJpegProfilingTests()
{
Console.WriteLine("RunDecodeJpegProfilingTests...");
JpegProfilingBenchmarks benchmarks = new JpegProfilingBenchmarks(new ConsoleOutput());
var benchmarks = new JpegProfilingBenchmarks(new ConsoleOutput());
foreach (object[] data in JpegProfilingBenchmarks.DecodeJpegData)
{
string fileName = (string)data[0];

40
tests/ImageSharp.Tests/Drawing/FillLinearGradientBrushTests.cs

@ -283,10 +283,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing
{
// it's diagonal, so for any (a, a) on the gradient line, for all (a-x, b+x) - +/- depending on the diagonal direction - must be the same color)
TPixel colorOnDiagonal = image[i, i];
// TODO: This is incorrect. from -0 to < 0 ??
int orthoCount = 0;
for (int offset = -orthoCount; offset < orthoCount; offset++)
{
Assert.Equal(colorOnDiagonal, image[i + horizontalSign * offset, i + verticalSign * offset]);
Assert.Equal(colorOnDiagonal, image[i + (horizontalSign * offset), i + (verticalSign * offset)]);
}
}
@ -302,8 +304,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing
[Theory]
[WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .2f, .5f, .9f }, new[] { 0, 0, 1, 1 })]
[WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 499, 499, 0, new[] { 0f, 0.2f, 0.5f, 0.9f }, new[] { 0, 1, 2, 3 })]
[WithBlankImages(500, 500, PixelTypes.Rgba32, 499, 499, 0, 0, new[] { 0f, 0.7f, 0.8f, 0.9f}, new[] { 0, 1, 2, 0 })]
[WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .5f, 1f}, new[]{0, 1, 3})]
[WithBlankImages(500, 500, PixelTypes.Rgba32, 499, 499, 0, 0, new[] { 0f, 0.7f, 0.8f, 0.9f }, new[] { 0, 1, 2, 0 })]
[WithBlankImages(500, 500, PixelTypes.Rgba32, 0, 0, 499, 499, new[] { 0f, .5f, 1f }, new[] { 0, 1, 3 })]
public void ArbitraryGradients<TPixel>(
TestImageProvider<TPixel> provider,
int startX, int startY,
@ -312,36 +314,36 @@ namespace SixLabors.ImageSharp.Tests.Drawing
int[] stopColorCodes)
where TPixel : struct, IPixel<TPixel>
{
TPixel[] colors = {
NamedColors<TPixel>.Navy, NamedColors<TPixel>.LightGreen, NamedColors<TPixel>.Yellow,
NamedColors<TPixel>.Red
};
TPixel[] colors =
{
NamedColors<TPixel>.Navy, NamedColors<TPixel>.LightGreen, NamedColors<TPixel>.Yellow,
NamedColors<TPixel>.Red
};
var coloringVariant = new StringBuilder();
ColorStop<TPixel>[] colorStops = new ColorStop<TPixel>[stopPositions.Length];
Rgba32 rgba = default;
var colorStops = new ColorStop<TPixel>[stopPositions.Length];
for (int i = 0; i < stopPositions.Length; i++)
{
TPixel color = colors[stopColorCodes[i % colors.Length]];
float position = stopPositions[i];
color.ToRgba32(ref rgba);
colorStops[i] = new ColorStop<TPixel>(position, color);
coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", rgba.ToHex(), position);
coloringVariant.AppendFormat(CultureInfo.InvariantCulture, "{0}@{1};", color.ToRgba32().ToHex(), position);
}
FormattableString variant = $"({startX},{startY})_TO_({endX},{endY})__[{coloringVariant}]";
provider.VerifyOperation(
image =>
{
var unicolorLinearGradientBrush = new LinearGradientBrush<TPixel>(
new SixLabors.Primitives.Point(startX, startY),
new SixLabors.Primitives.Point(endX, endY),
GradientRepetitionMode.None,
colorStops);
{
var unicolorLinearGradientBrush = new LinearGradientBrush<TPixel>(
new SixLabors.Primitives.Point(startX, startY),
new SixLabors.Primitives.Point(endX, endY),
GradientRepetitionMode.None,
colorStops);
image.Mutate(x => x.Fill(unicolorLinearGradientBrush));
},
image.Mutate(x => x.Fill(unicolorLinearGradientBrush));
},
variant,
false,
false);

10
tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs

@ -1,9 +1,9 @@
using System;
using System.Runtime.CompilerServices;
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using SixLabors.Memory;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Helpers
@ -35,4 +35,4 @@ namespace SixLabors.ImageSharp.Tests.Helpers
}
}
}
}
}

8
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFrameworks>net462;net471;netcoreapp2.1</TargetFrameworks>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<LangVersion>7.3</LangVersion>
<LangVersion>latest</LangVersion>
<DebugType Condition="$(codecov) != ''">full</DebugType>
<DebugType Condition="$(codecov) == ''">portable</DebugType>
<DebugSymbols>True</DebugSymbols>
@ -11,15 +11,15 @@
<Platforms>AnyCPU;x64;x86</Platforms>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x86'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<WarningsAsErrors />
</PropertyGroup>
<ItemGroup>

174
tests/ImageSharp.Tests/Issues/Issue594.cs

@ -48,46 +48,46 @@ namespace SixLabors.ImageSharp.Tests.Issues
Assert.Equal((uint)958796544, new NormalizedByte4(0.0008f, 0.15f, 0.30f, 0.45f).PackedValue);
var rgb = default(Rgb24);
var rgba = default(Rgba32);
var bgr = default(Bgr24);
var bgra = default(Bgra32);
var argb = default(Argb32);
//var rgb = default(Rgb24);
//var rgba = default(Rgba32);
//var bgr = default(Bgr24);
//var bgra = default(Bgra32);
//var argb = default(Argb32);
new NormalizedByte4(x, y, z, w).ToRgb24(ref rgb);
Assert.Equal(rgb, new Rgb24(141, 90, 192));
//new NormalizedByte4(x, y, z, w).ToRgb24(ref rgb);
//Assert.Equal(rgb, new Rgb24(141, 90, 192));
new NormalizedByte4(x, y, z, w).ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(141, 90, 192, 39));
//new NormalizedByte4(x, y, z, w).ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(141, 90, 192, 39));
new NormalizedByte4(x, y, z, w).ToBgr24(ref bgr);
Assert.Equal(bgr, new Bgr24(141, 90, 192));
//new NormalizedByte4(x, y, z, w).ToBgr24(ref bgr);
//Assert.Equal(bgr, new Bgr24(141, 90, 192));
new NormalizedByte4(x, y, z, w).ToBgra32(ref bgra);
Assert.Equal(bgra, new Bgra32(141, 90, 192, 39)); // this assert fails in Release build on linux (#594)
//new NormalizedByte4(x, y, z, w).ToBgra32(ref bgra);
//Assert.Equal(bgra, new Bgra32(141, 90, 192, 39)); // this assert fails in Release build on linux (#594)
new NormalizedByte4(x, y, z, w).ToArgb32(ref argb);
Assert.Equal(argb, new Argb32(141, 90, 192, 39));
//new NormalizedByte4(x, y, z, w).ToArgb32(ref argb);
//Assert.Equal(argb, new Argb32(141, 90, 192, 39));
// http://community.monogame.net/t/normalizedbyte4-texture2d-gives-different-results-from-xna/8012/8
var r = default(NormalizedByte4);
r.PackFromRgba32(new Rgba32(9, 115, 202, 127));
r.ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(9, 115, 202, 127));
r.PackedValue = 0xff4af389;
r.ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(9, 115, 202, 127));
r = default(NormalizedByte4);
r.PackFromArgb32(new Argb32(9, 115, 202, 127));
r.ToArgb32(ref argb);
Assert.Equal(argb, new Argb32(9, 115, 202, 127));
r = default(NormalizedByte4);
r.PackFromBgra32(new Bgra32(9, 115, 202, 127));
r.ToBgra32(ref bgra);
Assert.Equal(bgra, new Bgra32(9, 115, 202, 127));
//var r = default(NormalizedByte4);
//r.PackFromRgba32(new Rgba32(9, 115, 202, 127));
//r.ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(9, 115, 202, 127));
//r.PackedValue = 0xff4af389;
//r.ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(9, 115, 202, 127));
//r = default(NormalizedByte4);
//r.PackFromArgb32(new Argb32(9, 115, 202, 127));
//r.ToArgb32(ref argb);
//Assert.Equal(argb, new Argb32(9, 115, 202, 127));
//r = default(NormalizedByte4);
//r.PackFromBgra32(new Bgra32(9, 115, 202, 127));
//r.ToBgra32(ref bgra);
//Assert.Equal(bgra, new Bgra32(9, 115, 202, 127));
}
// This test fails for unknown reason in Release mode on linux and is meant to help reproducing the issue
@ -127,41 +127,41 @@ namespace SixLabors.ImageSharp.Tests.Issues
Assert.Equal(0xa6674000d99a0ccd, new NormalizedShort4(x, y, z, w).PackedValue);
Assert.Equal((ulong)4150390751449251866, new NormalizedShort4(0.0008f, 0.15f, 0.30f, 0.45f).PackedValue);
var rgb = default(Rgb24);
var rgba = default(Rgba32);
var bgr = default(Bgr24);
var bgra = default(Bgra32);
var argb = default(Argb32);
//var rgb = default(Rgb24);
//var rgba = default(Rgba32);
//var bgr = default(Bgr24);
//var bgra = default(Bgra32);
//var argb = default(Argb32);
new NormalizedShort4(x, y, z, w).ToRgb24(ref rgb);
Assert.Equal(rgb, new Rgb24(141, 90, 192));
//new NormalizedShort4(x, y, z, w).ToRgb24(ref rgb);
//Assert.Equal(rgb, new Rgb24(141, 90, 192));
new NormalizedShort4(x, y, z, w).ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(141, 90, 192, 39)); // this assert fails in Release build on linux (#594)
//new NormalizedShort4(x, y, z, w).ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(141, 90, 192, 39)); // this assert fails in Release build on linux (#594)
new NormalizedShort4(x, y, z, w).ToBgr24(ref bgr);
Assert.Equal(bgr, new Bgr24(141, 90, 192));
//new NormalizedShort4(x, y, z, w).ToBgr24(ref bgr);
//Assert.Equal(bgr, new Bgr24(141, 90, 192));
new NormalizedShort4(x, y, z, w).ToBgra32(ref bgra);
Assert.Equal(bgra, new Bgra32(141, 90, 192, 39));
//new NormalizedShort4(x, y, z, w).ToBgra32(ref bgra);
//Assert.Equal(bgra, new Bgra32(141, 90, 192, 39));
new NormalizedShort4(x, y, z, w).ToArgb32(ref argb);
Assert.Equal(argb, new Argb32(141, 90, 192, 39));
//new NormalizedShort4(x, y, z, w).ToArgb32(ref argb);
//Assert.Equal(argb, new Argb32(141, 90, 192, 39));
var r = default(NormalizedShort4);
r.PackFromRgba32(new Rgba32(9, 115, 202, 127));
r.ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(9, 115, 202, 127));
//var r = default(NormalizedShort4);
//r.PackFromRgba32(new Rgba32(9, 115, 202, 127));
//r.ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(9, 115, 202, 127));
r = default(NormalizedShort4);
r.PackFromBgra32(new Bgra32(9, 115, 202, 127));
r.ToBgra32(ref bgra);
Assert.Equal(bgra, new Bgra32(9, 115, 202, 127));
//r = default(NormalizedShort4);
//r.PackFromBgra32(new Bgra32(9, 115, 202, 127));
//r.ToBgra32(ref bgra);
//Assert.Equal(bgra, new Bgra32(9, 115, 202, 127));
r = default(NormalizedShort4);
r.PackFromArgb32(new Argb32(9, 115, 202, 127));
r.ToArgb32(ref argb);
Assert.Equal(argb, new Argb32(9, 115, 202, 127));
//r = default(NormalizedShort4);
//r.PackFromArgb32(new Argb32(9, 115, 202, 127));
//r.ToArgb32(ref argb);
//Assert.Equal(argb, new Argb32(9, 115, 202, 127));
}
// This test fails for unknown reason in Release mode on linux and is meant to help reproducing the issue
@ -212,41 +212,41 @@ namespace SixLabors.ImageSharp.Tests.Issues
w = 193;
Assert.Equal((ulong)0x00c173b7316d2d1b, new Short4(x, y, z, w).PackedValue);
var rgb = default(Rgb24);
var rgba = default(Rgba32);
var bgr = default(Bgr24);
var bgra = default(Bgra32);
var argb = default(Argb32);
//var rgb = default(Rgb24);
//var rgba = default(Rgba32);
//var bgr = default(Bgr24);
//var bgra = default(Bgra32);
//var argb = default(Argb32);
new Short4(x, y, z, w).ToRgb24(ref rgb);
Assert.Equal(rgb, new Rgb24(172, 177, 243)); // this assert fails in Release build on linux (#594)
//new Short4(x, y, z, w).ToRgb24(ref rgb);
//Assert.Equal(rgb, new Rgb24(172, 177, 243)); // this assert fails in Release build on linux (#594)
new Short4(x, y, z, w).ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(172, 177, 243, 128));
//new Short4(x, y, z, w).ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(172, 177, 243, 128));
new Short4(x, y, z, w).ToBgr24(ref bgr);
Assert.Equal(bgr, new Bgr24(172, 177, 243));
//new Short4(x, y, z, w).ToBgr24(ref bgr);
//Assert.Equal(bgr, new Bgr24(172, 177, 243));
new Short4(x, y, z, w).ToBgra32(ref bgra);
Assert.Equal(bgra, new Bgra32(172, 177, 243, 128));
//new Short4(x, y, z, w).ToBgra32(ref bgra);
//Assert.Equal(bgra, new Bgra32(172, 177, 243, 128));
new Short4(x, y, z, w).ToArgb32(ref argb);
Assert.Equal(argb, new Argb32(172, 177, 243, 128));
//new Short4(x, y, z, w).ToArgb32(ref argb);
//Assert.Equal(argb, new Argb32(172, 177, 243, 128));
var r = default(Short4);
r.PackFromRgba32(new Rgba32(20, 38, 0, 255));
r.ToRgba32(ref rgba);
Assert.Equal(rgba, new Rgba32(20, 38, 0, 255));
//var r = default(Short4);
//r.PackFromRgba32(new Rgba32(20, 38, 0, 255));
//r.ToRgba32(ref rgba);
//Assert.Equal(rgba, new Rgba32(20, 38, 0, 255));
r = default(Short4);
r.PackFromBgra32(new Bgra32(20, 38, 0, 255));
r.ToBgra32(ref bgra);
Assert.Equal(bgra, new Bgra32(20, 38, 0, 255));
//r = default(Short4);
//r.PackFromBgra32(new Bgra32(20, 38, 0, 255));
//r.ToBgra32(ref bgra);
//Assert.Equal(bgra, new Bgra32(20, 38, 0, 255));
r = default(Short4);
r.PackFromArgb32(new Argb32(20, 38, 0, 255));
r.ToArgb32(ref argb);
Assert.Equal(argb, new Argb32(20, 38, 0, 255));
//r = default(Short4);
//r.PackFromArgb32(new Argb32(20, 38, 0, 255));
//r.ToArgb32(ref argb);
//Assert.Equal(argb, new Argb32(20, 38, 0, 255));
}
// Comparison helpers with small tolerance to allow for floating point rounding during computations.

1
tests/ImageSharp.Tests/Numerics/RationalTests.cs

@ -1,7 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.MetaData.Profiles.Exif;
using SixLabors.ImageSharp.Primitives;
using Xunit;

191
tests/ImageSharp.Tests/PixelFormats/Alpha8Tests.cs

@ -10,200 +10,87 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
public class Alpha8Tests
{
[Fact]
public void Alpha8_PackedValue()
public void Alpha8_Constructor()
{
// Test the limits.
Assert.Equal(0x0, new Alpha8(0F).PackedValue);
Assert.Equal(0xFF, new Alpha8(1F).PackedValue);
Assert.Equal(byte.MinValue, new Alpha8(0F).PackedValue);
Assert.Equal(byte.MaxValue, new Alpha8(1F).PackedValue);
// Test clamping.
Assert.Equal(0x0, new Alpha8(-1234F).PackedValue);
Assert.Equal(0xFF, new Alpha8(1234F).PackedValue);
Assert.Equal(byte.MinValue, new Alpha8(-1234F).PackedValue);
Assert.Equal(byte.MaxValue, new Alpha8(1234F).PackedValue);
// Test ordering
Assert.Equal(124, new Alpha8(124F / 0xFF).PackedValue);
Assert.Equal(124, new Alpha8(124F / byte.MaxValue).PackedValue);
Assert.Equal(26, new Alpha8(0.1F).PackedValue);
}
[Fact]
public void Alpha8_ToVector4()
public void Alpha8_Equality()
{
// arrange
var alpha = new Alpha8(.5F);
// act
var actual = alpha.ToVector4();
var left = new Alpha8(16);
var right = new Alpha8(32);
// assert
Assert.Equal(0, actual.X);
Assert.Equal(0, actual.Y);
Assert.Equal(0, actual.Z);
Assert.Equal(.5F, actual.W, 2);
}
[Fact]
public void Alpha8_ToScaledVector4()
{
// arrange
var alpha = new Alpha8(.5F);
// act
Vector4 actual = alpha.ToScaledVector4();
// assert
Assert.Equal(0, actual.X);
Assert.Equal(0, actual.Y);
Assert.Equal(0, actual.Z);
Assert.Equal(.5F, actual.W, 2);
Assert.True(left == new Alpha8(16));
Assert.True(left != right);
Assert.Equal(left, (object)new Alpha8(16));
}
[Fact]
public void Alpha8_PackFromScaledVector4()
{
// arrange
// Arrange
Alpha8 alpha = default;
int expected = 128;
Vector4 scaled = new Alpha8(.5F).ToScaledVector4();
// act
// Act
alpha.PackFromScaledVector4(scaled);
byte actual = alpha.PackedValue;
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToRgb24()
{
// arrange
Rgb24 actual = default;
Alpha8 alpha = default;
var expected = new Rgb24(0, 0, 0);
Vector4 scaled = new Alpha8(.5F).ToScaledVector4();
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToRgba32()
{
// arrange
Rgba32 actual = default;
Alpha8 alpha = default;
var expected = new Rgba32(0, 0, 0, 128);
Vector4 scaled = new Alpha8(.5F).ToScaledVector4();
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToBgr24()
{
// arrange
Bgr24 actual = default;
Alpha8 alpha = default;
var expected = new Bgr24(0, 0, 0);
Vector4 scaled = new Alpha8(.5F).ToScaledVector4();
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToBgra32()
{
// arrange
Bgra32 actual = default;
Alpha8 alpha = default;
var expected = new Bgra32(0, 0, 0, 128);
Vector4 scaled = new Alpha8(.5F).ToScaledVector4();
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToArgb32()
{
// arrange
Alpha8 alpha = default;
Argb32 actual = default;
var expected = new Argb32(0, 0, 0, 128);
Vector4 scaled = new Alpha8(.5F).ToScaledVector4();
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToArgb32(ref actual);
// assert
// Assert
Assert.Equal(expected, actual);
}
[Fact]
public void Alpha8_PackFromScaledVector4_ToRgba64()
public void Alpha8_ToScaledVector4()
{
// arrange
Alpha8 alpha = default;
Rgba64 actual = default;
var expected = new Rgba64(0, 0, 0, 65535);
Vector4 scaled = new Alpha8(1F).ToScaledVector4();
// Arrange
var alpha = new Alpha8(.5F);
// act
alpha.PackFromScaledVector4(scaled);
alpha.ToRgba64(ref actual);
// Act
Vector4 actual = alpha.ToScaledVector4();
// assert
Assert.Equal(expected, actual);
// Assert
Assert.Equal(0, actual.X);
Assert.Equal(0, actual.Y);
Assert.Equal(0, actual.Z);
Assert.Equal(.5F, actual.W, 2);
}
[Fact]
public void Alpha8_PackFromRgb48_ToRgb48()
public void Alpha8_ToVector4()
{
// arrange
var alpha = default(Alpha8);
var actual = default(Rgb48);
var expected = new Rgb48(0, 0, 0);
// Arrange
var alpha = new Alpha8(.5F);
// act
alpha.PackFromRgb48(expected);
alpha.ToRgb48(ref actual);
// Act
var actual = alpha.ToVector4();
// assert
Assert.Equal(expected, actual);
// Assert
Assert.Equal(0, actual.X);
Assert.Equal(0, actual.Y);
Assert.Equal(0, actual.Z);
Assert.Equal(.5F, actual.W, 2);
}
[Fact]
public void Alpha8_PackFromRgba64_ToRgba64()
public void Alpha8_ToRgba32()
{
// arrange
var alpha = default(Alpha8);
var actual = default(Rgba64);
var expected = new Rgba64(0, 0, 0, 65535);
// act
alpha.PackFromRgba64(expected);
alpha.ToRgba64(ref actual);
var input = new Alpha8(128);
var expected = new Rgba32(0, 0, 0, 128);
// assert
var actual = input.ToRgba32();
Assert.Equal(expected, actual);
}
}

155
tests/ImageSharp.Tests/PixelFormats/Argb32Tests.cs

@ -66,160 +66,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vector4.Zero, new Argb32(Vector4.One * -1234.0f).ToVector4());
Assert.Equal(Vector4.One, new Argb32(Vector4.One * +1234.0f).ToVector4());
}
[Fact]
public void Argb32_ToRgb24()
{
// arrange
var argb = new Argb32(+0.1f, -0.3f, +0.5f, -0.7f);
var actual = default(Rgb24);
var expected = new Rgb24(0x1a, 0, 0x80);
// act
argb.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_ToRgba32()
{
// arrange
var argb = new Argb32(+0.1f, -0.3f, +0.5f, -0.7f);
var actual = default(Rgba32);
var expected = new Rgba32(0x1a, 0, 0x80, 0);
// act
argb.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_ToBgr24()
{
// arrange
var argb = new Argb32(+0.1f, -0.3f, +0.5f, -0.7f);
var actual = default(Bgr24);
var expected = new Bgr24(0x1a, 0, 0x80);
// act
argb.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_ToBgra32()
{
// arrange
var argb = new Argb32(+0.1f, -0.3f, +0.5f, -0.7f);
var actual = default(Bgra32);
var expected = new Bgra32(0x1a, 0, 0x80, 0);
// act
argb.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_ToArgb32()
{
// arrange
var argb = new Argb32(+0.1f, -0.3f, +0.5f, -0.7f);
var actual = default(Argb32);
var expected = new Argb32(0x1a, 0, 0x80, 0);
// act
argb.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_PackFromRgba32_ToRgba32()
{
// arrange
var argb = default(Argb32);
var actual = default(Rgba32);
var expected = new Rgba32(0x1a, 0, 0x80, 0);
// act
argb.PackFromRgba32(expected);
argb.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_PackFromBgra32_ToBgra32()
{
// arrange
var argb = default(Argb32);
var actual = default(Bgra32);
var expected = new Bgra32(0x1a, 0, 0x80, 0);
// act
argb.PackFromBgra32(expected);
argb.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_PackFromArgb32_ToArgb32()
{
// arrange
var argb = default(Argb32);
var actual = default(Argb32);
var expected = new Argb32(0x1a, 0, 0x80, 0);
// act
argb.PackFromArgb32(expected);
argb.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_PackFromRgb48_ToRgb48()
{
// arrange
var argb = default(Argb32);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
argb.PackFromRgb48(expected);
argb.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Argb32_PackFromRgba64_ToRgba64()
{
// arrange
var argb = default(Argb32);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
argb.PackFromRgba64(expected);
argb.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

76
tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs

@ -95,81 +95,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vec(1, 2, 3), rgb.ToVector4());
}
[Fact]
public void ToRgb24()
{
var rgb = new Bgr24(1, 2, 3);
var dest = default(Rgb24);
rgb.ToRgb24(ref dest);
Assert.Equal(new Rgb24(1, 2, 3), dest);
}
[Fact]
public void ToRgba32()
{
var rgb = new Bgr24(1, 2, 3);
var rgba = default(Rgba32);
rgb.ToRgba32(ref rgba);
Assert.Equal(new Rgba32(1, 2, 3, 255), rgba);
}
[Fact]
public void ToBgr24()
{
var rgb = new Bgr24(1, 2, 3);
var bgr = default(Bgr24);
rgb.ToBgr24(ref bgr);
Assert.Equal(new Bgr24(1, 2, 3), bgr);
}
[Fact]
public void ToBgra32()
{
var rgb = new Bgr24(1, 2, 3);
var bgra = default(Bgra32);
rgb.ToBgra32(ref bgra);
Assert.Equal(new Bgra32(1, 2, 3, 255), bgra);
}
[Fact]
public void Bgr24_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(Bgr24);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr24_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgr24);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 65535);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

107
tests/ImageSharp.Tests/PixelFormats/Bgr565Tests.cs

@ -69,112 +69,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vector3.Zero, new Bgr565(Vector3.One * -1234F).ToVector3());
Assert.Equal(Vector3.One, new Bgr565(Vector3.One * 1234F).ToVector3());
}
[Fact]
public void Bgr565_ToRgb24()
{
// arrange
var bgra = new Bgr565(0.1F, -0.3F, 0.5F);
var actual = default(Rgb24);
var expected = new Rgb24(25, 0, 132);
// act
bgra.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_ToRgba32()
{
// arrange
var bgra = new Bgr565(0.1F, -0.3F, 0.5F);
var actual = default(Rgba32);
var expected = new Rgba32(25, 0, 132, 255);
// act
bgra.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_ToBgr24()
{
// arrange
var bgra = new Bgr565(0.1F, -0.3F, 0.5F);
var actual = default(Bgr24);
var expected = new Bgr24(25, 0, 132);
// act
bgra.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_ToBgra32()
{
// arrange
var bgra = new Bgr565(0.1F, -0.3F, 0.5F);
var actual = default(Bgra32);
var expected = new Bgra32(25, 0, 132, 255);
// act
bgra.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_ToArgb32()
{
// arrange
var bgra = new Bgr565(0.1F, -0.3F, 0.5F);
var actual = default(Argb32);
var expected = new Argb32(25, 0, 132, 255);
// act
bgra.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(Bgr565);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgr565_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgr565);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 65535);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

76
tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs

@ -102,81 +102,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vec(1, 2, 3, 4), rgb.ToVector4());
}
[Fact]
public void ToRgb24()
{
var c = new Bgra32(1, 2, 3, 4);
var dest = default(Rgb24);
c.ToRgb24(ref dest);
Assert.Equal(new Rgb24(1, 2, 3), dest);
}
[Fact]
public void ToRgba32()
{
var c = new Bgra32(1, 2, 3, 4);
var rgba = default(Rgba32);
c.ToRgba32(ref rgba);
Assert.Equal(new Rgba32(1, 2, 3, 4), rgba);
}
[Fact]
public void ToBgr24()
{
var rgb = new Bgra32(1, 2, 3, 4);
var bgr = default(Bgr24);
rgb.ToBgr24(ref bgr);
Assert.Equal(new Bgr24(1, 2, 3), bgr);
}
[Fact]
public void ToBgra32()
{
var rgb = new Bgra32(1, 2, 3, 4);
var bgra = default(Bgra32);
rgb.ToBgra32(ref bgra);
Assert.Equal(new Bgra32(1, 2, 3, 4), bgra);
}
[Fact]
public void Bgra32_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(Bgra32);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra32_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgra32);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

155
tests/ImageSharp.Tests/PixelFormats/Bgra4444Tests.cs

@ -70,160 +70,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vector4.Zero, new Bgra4444(Vector4.One * -1234.0f).ToVector4());
Assert.Equal(Vector4.One, new Bgra4444(Vector4.One * 1234.0f).ToVector4());
}
[Fact]
public void Bgra4444_ToRgb24()
{
// arrange
var bgra = new Bgra4444(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Rgb24);
var expected = new Rgb24(34, 0, 136);
// act
bgra.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_ToRgba32()
{
// arrange
var bgra = new Bgra4444(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Rgba32);
var expected = new Rgba32(34, 0, 136, 0);
// act
bgra.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_ToBgr24()
{
// arrange
var bgra = new Bgra4444(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Bgr24);
var expected = new Bgr24(34, 0, 136);
// act
bgra.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_ToBgra32()
{
// arrange
var bgra = new Bgra4444(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Bgra32);
var expected = new Bgra32(34, 0, 136, 0);
// act
bgra.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_ToArgb32()
{
// arrange
var bgra = new Bgra4444(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Argb32);
var expected = new Argb32(34, 0, 136, 0);
// act
bgra.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_PackFromRgba32_ToRgba32()
{
// arrange
var bgra = default(Bgra4444);
var actual = default(Rgba32);
var expected = new Rgba32(34, 0, 136, 0);
// act
bgra.PackFromRgba32(expected);
bgra.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_PackFromBgra32_ToBgra32()
{
// arrange
var bgra = default(Bgra4444);
var actual = default(Bgra32);
var expected = new Bgra32(34, 0, 136, 0);
// act
bgra.PackFromBgra32(expected);
bgra.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_PackFromArgb32_ToArgb32()
{
// arrange
var bgra = default(Bgra4444);
var actual = default(Argb32);
var expected = new Argb32(34, 0, 136, 0);
// act
bgra.PackFromArgb32(expected);
bgra.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(Bgra4444);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra4444_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgra4444);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

155
tests/ImageSharp.Tests/PixelFormats/Bgra5551Tests.cs

@ -69,160 +69,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vector4.Zero, new Bgra5551(Vector4.One * -1234.0f).ToVector4());
Assert.Equal(Vector4.One, new Bgra5551(Vector4.One * 1234.0f).ToVector4());
}
[Fact]
public void Bgra5551_ToRgb24()
{
// arrange
var bgra = new Bgra5551(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Rgb24);
var expected = new Rgb24(24, 0, 131);
// act
bgra.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_Rgba32()
{
// arrange
var bgra = new Bgra5551(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Rgba32);
var expected = new Rgba32(24, 0, 131, 0);
// act
bgra.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_ToBgr24()
{
// arrange
var bgra = new Bgra5551(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Bgr24);
var expected = new Bgr24(24, 0, 131);
// act
bgra.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_Bgra32()
{
// arrange
var bgra = new Bgra5551(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Bgra32);
var expected = new Bgra32(24, 0, 131, 0);
// act
bgra.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_ToArgb32()
{
// arrange
var bgra = new Bgra5551(0.1f, -0.3f, 0.5f, -0.7f);
var actual = default(Argb32);
var expected = new Argb32(24, 0, 131, 0);
// act
bgra.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_PackFromRgba32_ToRgba32()
{
// arrange
var bgra = default(Bgra5551);
var expected = new Rgba32(24, 0, 131, 0);
var actual = default(Rgba32);
// act
bgra.PackFromRgba32(expected);
bgra.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_PackFromBgra32_ToBgra32()
{
// arrange
var bgra = default(Bgra5551);
var expected = new Bgra32(24, 0, 131, 0);
var actual = default(Bgra32);
// act
bgra.PackFromBgra32(expected);
bgra.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_PackFromArgb32_ToArgb32()
{
// arrange
var bgra = default(Bgra5551);
var expected = new Argb32(24, 0, 131, 0);
var actual = default(Argb32);
// act
bgra.PackFromArgb32(expected);
bgra.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(Bgra5551);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Bgra5551_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Bgra5551);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

155
tests/ImageSharp.Tests/PixelFormats/Byte4Tests.cs

@ -67,160 +67,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
Assert.Equal(Vector4.Zero, new Byte4(Vector4.One * -1234.0f).ToVector4());
Assert.Equal(Vector4.One * 255, new Byte4(Vector4.One * 1234.0f).ToVector4());
}
[Fact]
public void Byte4_ToRgb24()
{
// arrange
var byte4 = new Byte4(127.5f, -12.3f, 0.5f, -0.7f);
var actual = default(Rgb24);
var expected = new Rgb24(128, 0, 0);
// act
byte4.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_Rgba32()
{
// arrange
var byte4 = new Byte4(127.5f, -12.3f, 0.5f, -0.7f);
var actual = default(Rgba32);
var expected = new Rgba32(128, 0, 0, 0);
// act
byte4.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_ToBgr24()
{
// arrange
var byte4 = new Byte4(127.5f, -12.3f, 0.5f, -0.7f);
var actual = default(Bgr24);
var expected = new Bgr24(128, 0, 0);
// act
byte4.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_Bgra32()
{
// arrange
var byte4 = new Byte4(127.5f, -12.3f, 0.5f, -0.7f);
var actual = default(Bgra32);
var expected = new Bgra32(128, 0, 0, 0);
// act
byte4.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_Argb32()
{
// arrange
var byte4 = new Byte4(127.5f, -12.3f, 0.5f, -0.7f);
var actual = default(Argb32);
var expected = new Argb32(128, 0, 0, 0);
// act
byte4.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_PackFromRgba32_ToRgba32()
{
// arrange
var byte4 = default(Byte4);
var actual = default(Rgba32);
var expected = new Rgba32(20, 38, 0, 255);
// act
byte4.PackFromRgba32(expected);
byte4.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_PackFromBgra32_ToBgra32()
{
// arrange
var byte4 = default(Byte4);
var actual = default(Bgra32);
var expected = new Bgra32(20, 38, 0, 255);
// act
byte4.PackFromBgra32(expected);
byte4.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_PackFromArgb32_ToArgb32()
{
// arrange
var byte4 = default(Byte4);
var actual = default(Argb32);
var expected = new Argb32(20, 38, 0, 255);
// act
byte4.PackFromArgb32(expected);
byte4.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(Byte4);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 65535);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void Byte4_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(Byte4);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 65535, 0);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

151
tests/ImageSharp.Tests/PixelFormats/ColorConstructorTests.cs

@ -1,151 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colors
{
public class ColorConstructorTests
{
public static IEnumerable<object[]> Vector4Data
{
get
{
Vector4[] vector4Values = new Vector4[]
{
Vector4.Zero,
Vector4.One,
Vector4.UnitX,
Vector4.UnitY,
Vector4.UnitZ,
Vector4.UnitW,
};
foreach (Vector4 vector4 in vector4Values)
{
// using float array to work around a bug in xunit corruptint the state of any Vector4 passed as MemberData
float[] vector4Components = new float[] { vector4.X, vector4.Y, vector4.Z, vector4.W };
yield return new object[] { new Argb32(vector4), vector4Components };
yield return new object[] { new Bgra4444(vector4), vector4Components };
yield return new object[] { new Bgra5551(vector4), vector4Components };
yield return new object[] { new Byte4(vector4), vector4Components };
yield return new object[] { new HalfVector4(vector4), vector4Components };
yield return new object[] { new NormalizedByte4(vector4), vector4Components };
yield return new object[] { new NormalizedShort4(vector4), vector4Components };
yield return new object[] { new Rgba1010102(vector4), vector4Components };
yield return new object[] { new Rgba64(vector4), vector4Components };
yield return new object[] { new Short4(vector4), vector4Components };
}
}
}
public static IEnumerable<object[]> Vector3Data
{
get
{
Dictionary<Vector3, Vector4> vector3Values = new Dictionary<Vector3, Vector4>()
{
{ Vector3.One, Vector4.One },
{ Vector3.Zero, new Vector4(0, 0, 0, 1) },
{ Vector3.UnitX, new Vector4(1, 0, 0, 1) },
{ Vector3.UnitY, new Vector4(0, 1, 0, 1) },
{ Vector3.UnitZ, new Vector4(0, 0, 1, 1) },
};
foreach (Vector3 vector3 in vector3Values.Keys)
{
Vector4 vector4 = vector3Values[vector3];
// using float array to work around a bug in xunit corruptint the state of any Vector4 passed as MemberData
float[] vector4Components = new float[] { vector4.X, vector4.Y, vector4.Z, vector4.W };
yield return new object[] { new Argb32(vector3), vector4Components };
yield return new object[] { new Bgr565(vector3), vector4Components };
}
}
}
public static IEnumerable<object[]> Float4Data
{
get
{
Vector4[] vector4Values = new Vector4[]
{
Vector4.Zero,
Vector4.One,
Vector4.UnitX,
Vector4.UnitY,
Vector4.UnitZ,
Vector4.UnitW,
};
foreach (Vector4 vector4 in vector4Values)
{
// using float array to work around a bug in xunit corruptint the state of any Vector4 passed as MemberData
float[] vector4Components = new float[] { vector4.X, vector4.Y, vector4.Z, vector4.W };
yield return new object[] { new Argb32(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new Bgra4444(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new Bgra5551(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new Byte4(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new HalfVector4(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new NormalizedByte4(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new NormalizedShort4(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new Rgba1010102(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new Rgba64(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
yield return new object[] { new Short4(vector4.X, vector4.Y, vector4.Z, vector4.W), vector4Components };
}
}
}
public static IEnumerable<object[]> Float3Data
{
get
{
Dictionary<Vector3, Vector4> vector3Values = new Dictionary<Vector3, Vector4>()
{
{ Vector3.One, Vector4.One },
{ Vector3.Zero, new Vector4(0, 0, 0, 1) },
{ Vector3.UnitX, new Vector4(1, 0, 0, 1) },
{ Vector3.UnitY, new Vector4(0, 1, 0, 1) },
{ Vector3.UnitZ, new Vector4(0, 0, 1, 1) },
};
foreach (Vector3 vector3 in vector3Values.Keys)
{
Vector4 vector4 = vector3Values[vector3];
// using float array to work around a bug in xunit corruptint the state of any Vector4 passed as MemberData
float[] vector4Components = new float[] { vector4.X, vector4.Y, vector4.Z, vector4.W };
yield return new object[] { new Argb32(vector3.X, vector3.Y, vector3.Z), vector4Components };
yield return new object[] { new Bgr565(vector3.X, vector3.Y, vector3.Z), vector4Components };
}
}
}
[Theory]
[MemberData(nameof(Vector4Data))]
[MemberData(nameof(Vector3Data))]
[MemberData(nameof(Float4Data))]
[MemberData(nameof(Float3Data))]
public void ConstructorToVector4(IPixel packedVector, float[] expectedVector4Components)
{
// Arrange
int precision = 2;
// using float array to work around a bug in xunit corruptint the state of any Vector4 passed as MemberData
Vector4 expectedVector4 = new Vector4(expectedVector4Components[0], expectedVector4Components[1], expectedVector4Components[2], expectedVector4Components[3]);
// Act
Vector4 vector4 = packedVector.ToVector4();
// Assert
Assert.Equal(expectedVector4.X, vector4.X, precision);
Assert.Equal(expectedVector4.Y, vector4.Y, precision);
Assert.Equal(expectedVector4.Z, vector4.Z, precision);
Assert.Equal(expectedVector4.W, vector4.W, precision);
}
}
}

216
tests/ImageSharp.Tests/PixelFormats/ColorEqualityTests.cs

@ -1,216 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colors
{
/// <summary>
/// Test implementations of IEquatable
/// </summary>
public class ColorEqualityTests
{
public static readonly TheoryData<object, object, Type> EqualityData =
new TheoryData<object, object, Type>()
{
{ new Alpha8(.5F), new Alpha8(.5F), typeof(Alpha8) },
{ new Argb32(Vector4.One), new Argb32(Vector4.One), typeof(Argb32) },
{ new Bgr565(Vector3.One), new Bgr565(Vector3.One), typeof(Bgr565) },
{ new Bgra4444(Vector4.One), new Bgra4444(Vector4.One), typeof(Bgra4444) },
{ new Bgra5551(Vector4.One), new Bgra5551(Vector4.One), typeof(Bgra5551) },
{ new Byte4(Vector4.One * 255), new Byte4(Vector4.One * 255), typeof(Byte4) },
{ new HalfSingle(-1F), new HalfSingle(-1F), typeof(HalfSingle) },
{ new HalfVector2(0.1f, -0.3f), new HalfVector2(0.1f, -0.3f), typeof(HalfVector2) },
{ new HalfVector4(Vector4.One), new HalfVector4(Vector4.One), typeof(HalfVector4) },
{ new NormalizedByte2(-Vector2.One), new NormalizedByte2(-Vector2.One), typeof(NormalizedByte2) },
{ new NormalizedByte4(Vector4.One), new NormalizedByte4(Vector4.One), typeof(NormalizedByte4) },
{ new NormalizedShort2(Vector2.One), new NormalizedShort2(Vector2.One), typeof(NormalizedShort2) },
{ new NormalizedShort4(Vector4.One), new NormalizedShort4(Vector4.One), typeof(NormalizedShort4) },
{ new Rg32(Vector2.One), new Rg32(Vector2.One), typeof(Rg32) },
{ new Rgba1010102(Vector4.One), new Rgba1010102(Vector4.One), typeof(Rgba1010102) },
{ new Rgba32(Vector4.One), new Rgba32(Vector4.One), typeof(Rgba32) },
{ new Rgba64(Vector4.One), new Rgba64(Vector4.One), typeof(Rgba64) },
{ new Short2(Vector2.One * 0x7FFF), new Short2(Vector2.One * 0x7FFF), typeof(Short2) },
{ new Short4(Vector4.One * 0x7FFF), new Short4(Vector4.One * 0x7FFF), typeof(Short4) },
};
public static readonly TheoryData<object, object, Type> NotEqualityDataNulls =
new TheoryData<object, object, Type>()
{
// Valid object against null
{ new Alpha8(.5F), null, typeof(Alpha8) },
{ new Argb32(Vector4.One), null, typeof(Argb32) },
{ new Bgr565(Vector3.One), null, typeof(Bgr565) },
{ new Bgra4444(Vector4.One), null, typeof(Bgra4444) },
{ new Bgra5551(Vector4.One), null, typeof(Bgra5551) },
{ new Byte4(Vector4.One * 255), null, typeof(Byte4) },
{ new HalfSingle(-1F), null, typeof(HalfSingle) },
{ new HalfVector2(0.1f, -0.3f), null, typeof(HalfVector2) },
{ new HalfVector4(Vector4.One), null, typeof(HalfVector4) },
{ new NormalizedByte2(-Vector2.One), null, typeof(NormalizedByte2) },
{ new NormalizedByte4(Vector4.One), null, typeof(NormalizedByte4) },
{ new NormalizedShort2(Vector2.One), null, typeof(NormalizedShort2) },
{ new NormalizedShort4(Vector4.One), null, typeof(NormalizedShort4) },
{ new Rg32(Vector2.One), null, typeof(Rg32) },
{ new Rgba1010102(Vector4.One), null, typeof(Rgba1010102) },
{ new Rgba64(Vector4.One), null, typeof(Rgba64) },
{ new Short2(Vector2.One * 0x7FFF), null, typeof(Short2) },
{ new Short4(Vector4.One * 0x7FFF), null, typeof(Short4) },
};
public static readonly TheoryData<object, object, Type> NotEqualityDataDifferentObjects =
new TheoryData<object, object, Type>()
{
// Valid objects of different types but not equal
{ new Alpha8(.5F), new Argb32(Vector4.Zero), null },
{ new HalfSingle(-1F), new NormalizedShort2(Vector2.Zero), null },
{ new Rgba1010102(Vector4.One), new Bgra5551(Vector4.Zero), null },
};
public static readonly TheoryData<object, object, Type> NotEqualityData =
new TheoryData<object, object, Type>()
{
// Valid objects of the same type but not equal
{ new Alpha8(.5F), new Alpha8(.8F), typeof(Alpha8) },
{ new Argb32(Vector4.One), new Argb32(Vector4.Zero), typeof(Argb32) },
{ new Bgr565(Vector3.One), new Bgr565(Vector3.Zero), typeof(Bgr565) },
{ new Bgra4444(Vector4.One), new Bgra4444(Vector4.Zero), typeof(Bgra4444) },
{ new Bgra5551(Vector4.One), new Bgra5551(Vector4.Zero), typeof(Bgra5551) },
{ new Byte4(Vector4.One * 255), new Byte4(Vector4.Zero), typeof(Byte4) },
{ new HalfSingle(-1F), new HalfSingle(1F), typeof(HalfSingle) },
{ new HalfVector2(0.1f, -0.3f), new HalfVector2(0.1f, 0.3f), typeof(HalfVector2) },
{ new HalfVector4(Vector4.One), new HalfVector4(Vector4.Zero), typeof(HalfVector4) },
{ new NormalizedByte2(-Vector2.One), new NormalizedByte2(-Vector2.Zero), typeof(NormalizedByte2) },
{ new NormalizedByte4(Vector4.One), new NormalizedByte4(Vector4.Zero), typeof(NormalizedByte4) },
{ new NormalizedShort2(Vector2.One), new NormalizedShort2(Vector2.Zero), typeof(NormalizedShort2) },
{ new NormalizedShort4(Vector4.One), new NormalizedShort4(Vector4.Zero), typeof(NormalizedShort4) },
{ new Rg32(Vector2.One), new Rg32(Vector2.Zero), typeof(Rg32) },
{ new Rgba1010102(Vector4.One), new Rgba1010102(Vector4.Zero), typeof(Rgba1010102) },
{ new Rgba32(Vector4.One), new Rgba32(Vector4.Zero), typeof(Rgba32) },
{ new Rgba64(Vector4.One), new Rgba64(Vector4.Zero), typeof(Rgba64) },
{ new Short2(Vector2.One * 0x7FFF), new Short2(Vector2.Zero), typeof(Short2) },
{ new Short4(Vector4.One * 0x7FFF), new Short4(Vector4.Zero), typeof(Short4) },
};
[Theory]
[MemberData(nameof(EqualityData))]
public void Equality(object first, object second, Type type)
{
// Act
bool equal = first.Equals(second);
// Assert
Assert.True(equal);
}
[Theory]
[MemberData(nameof(NotEqualityDataNulls))]
[MemberData(nameof(NotEqualityDataDifferentObjects))]
[MemberData(nameof(NotEqualityData))]
public void NotEquality(object first, object second, Type type)
{
// Act
bool equal = first.Equals(second);
// Assert
Assert.False(equal);
}
[Theory]
[MemberData(nameof(EqualityData))]
public void HashCodeEqual(object first, object second, Type type)
{
// Act
bool equal = first.GetHashCode() == second.GetHashCode();
// Assert
Assert.True(equal);
}
[Theory]
[MemberData(nameof(NotEqualityDataDifferentObjects))]
public void HashCodeNotEqual(object first, object second, Type type)
{
// Act
bool equal = first.GetHashCode() == second.GetHashCode();
// Assert
Assert.False(equal);
}
[Theory]
[MemberData(nameof(EqualityData))]
public void EqualityObject(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the
// equality operator on the concrete type, otherwise it goes to the
// default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
// Act
dynamic equal = firstObject.Equals(secondObject);
// Assert
Assert.True(equal);
}
[Theory]
[MemberData(nameof(NotEqualityData))]
public void NotEqualityObject(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the
// equality operator on the concrete type, otherwise it goes to the
// default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
// Act
dynamic equal = firstObject.Equals(secondObject);
// Assert
Assert.False(equal);
}
[Theory]
[MemberData(nameof(EqualityData))]
public void EqualityOperator(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the
// equality operator on the concrete type, otherwise it goes to the
// default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
// Act
dynamic equal = firstObject == secondObject;
// Assert
Assert.True(equal);
}
[Theory]
[MemberData(nameof(NotEqualityData))]
public void NotEqualityOperator(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the
// equality operator on the concrete type, otherwise it goes to the
// default "object" one :)
dynamic firstObject = Convert.ChangeType(first, type);
dynamic secondObject = Convert.ChangeType(second, type);
// Act
dynamic notEqual = firstObject != secondObject;
// Assert
Assert.True(notEqual);
}
}
}

88
tests/ImageSharp.Tests/PixelFormats/ColorPackingTests.cs

@ -1,88 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Colors
{
public class ColorPackingTests
{
public static IEnumerable<object[]> Vector4PackData
{
get
{
Vector4[] vector4Values = new Vector4[]
{
Vector4.Zero,
Vector4.One,
Vector4.UnitX,
Vector4.UnitY,
Vector4.UnitZ,
Vector4.UnitW,
};
foreach (Vector4 vector4 in vector4Values)
{
float[] vector4Components = new float[] { vector4.X, vector4.Y, vector4.Z, vector4.W };
yield return new object[] { default(Argb32), vector4Components };
yield return new object[] { default(Bgra4444), vector4Components };
yield return new object[] { default(Bgra5551), vector4Components };
yield return new object[] { default(Byte4), vector4Components };
yield return new object[] { default(HalfVector4), vector4Components };
yield return new object[] { default(NormalizedByte4), vector4Components };
yield return new object[] { default(NormalizedShort4), vector4Components };
yield return new object[] { default(Rgba1010102), vector4Components };
yield return new object[] { default(Rgba64), vector4Components };
yield return new object[] { default(Short4), vector4Components };
}
}
}
public static IEnumerable<object[]> Vector3PackData
{
get
{
Vector4[] vector4Values = new Vector4[]
{
Vector4.One,
new Vector4(0, 0, 0, 1),
new Vector4(1, 0, 0, 1),
new Vector4(0, 1, 0, 1),
new Vector4(0, 0, 1, 1),
};
foreach (Vector4 vector4 in vector4Values)
{
float[] vector4Components = new float[] { vector4.X, vector4.Y, vector4.Z, vector4.W };
yield return new object[] { default(Argb32), vector4Components };
yield return new object[] { new Bgr565(), vector4Components };
}
}
}
[Theory]
[MemberData(nameof(Vector4PackData))]
[MemberData(nameof(Vector3PackData))]
public void FromVector4ToVector4(IPixel packedVector, float[] vector4ComponentsToPack)
{
// Arrange
int precision = 2;
Vector4 vector4ToPack = new Vector4(vector4ComponentsToPack[0], vector4ComponentsToPack[1], vector4ComponentsToPack[2], vector4ComponentsToPack[3]);
packedVector.PackFromVector4(vector4ToPack);
// Act
Vector4 vector4 = packedVector.ToVector4();
// Assert
Assert.Equal(vector4ToPack.X, vector4.X, precision);
Assert.Equal(vector4ToPack.Y, vector4.Y, precision);
Assert.Equal(vector4ToPack.Z, vector4.Z, precision);
Assert.Equal(vector4ToPack.W, vector4.W, precision);
}
}
}

129
tests/ImageSharp.Tests/PixelFormats/Gray16Tests.cs

@ -0,0 +1,129 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.PixelFormats
{
public class Gray16Tests
{
[Theory]
[InlineData(0)]
[InlineData(65535)]
[InlineData(32767)]
[InlineData(42)]
public void Gray16_PackedValue_EqualsInput(ushort input)
=> Assert.Equal(input, new Gray16(input).PackedValue);
[Fact]
public void Gray16_PackFromScaledVector4()
{
// Arrange
Gray16 gray = default;
const ushort expected = 32767;
Vector4 scaled = new Gray16(expected).ToScaledVector4();
// Act
gray.PackFromScaledVector4(scaled);
ushort actual = gray.PackedValue;
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0)]
[InlineData(65535)]
[InlineData(32767)]
public void Gray16_ToScaledVector4(ushort input)
{
// Arrange
var gray = new Gray16(input);
// Act
Vector4 actual = gray.ToScaledVector4();
// Assert
float vectorInput = input / 65535F;
Assert.Equal(vectorInput, actual.X);
Assert.Equal(vectorInput, actual.Y);
Assert.Equal(vectorInput, actual.Z);
Assert.Equal(1F, actual.W);
}
[Fact]
public void Gray16_PackFromVector4()
{
// Arrange
Gray16 gray = default;
const ushort expected = 32767;
var vector = new Gray16(expected).ToVector4();
// Act
gray.PackFromVector4(vector);
ushort actual = gray.PackedValue;
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0)]
[InlineData(65535)]
[InlineData(32767)]
public void Gray16_ToVector4(ushort input)
{
// Arrange
var gray = new Gray16(input);
// Act
var actual = gray.ToVector4();
// Assert
float vectorInput = input / 65535F;
Assert.Equal(vectorInput, actual.X);
Assert.Equal(vectorInput, actual.Y);
Assert.Equal(vectorInput, actual.Z);
Assert.Equal(1F, actual.W);
}
[Fact]
public void Gray16_PackFromRgba32()
{
// Arrange
Gray16 gray = default;
const byte rgb = 128;
ushort scaledRgb = ImageMaths.UpscaleFrom8BitTo16Bit(rgb);
ushort expected = ImageMaths.Get16BitBT709Luminance(scaledRgb, scaledRgb, scaledRgb);
// Act
gray.PackFromRgba32(new Rgba32(rgb, rgb, rgb));
ushort actual = gray.PackedValue;
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0)]
[InlineData(65535)]
[InlineData(8100)]
public void Gray16_ToRgba32(ushort input)
{
// Arrange
ushort expected = ImageMaths.DownScaleFrom16BitTo8Bit(input);
var gray = new Gray16(input);
// Act
var actual = gray.ToRgba32();
// Assert
Assert.Equal(expected, actual.R);
Assert.Equal(expected, actual.G);
Assert.Equal(expected, actual.B);
Assert.Equal(byte.MaxValue, actual.A);
}
}
}

127
tests/ImageSharp.Tests/PixelFormats/Gray8Tests.cs

@ -0,0 +1,127 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.PixelFormats
{
public class Gray8Tests
{
[Theory]
[InlineData(0)]
[InlineData(255)]
[InlineData(10)]
[InlineData(42)]
public void Gray8_PackedValue_EqualsInput(byte input)
=> Assert.Equal(input, new Gray8(input).PackedValue);
[Fact]
public void Gray8_PackFromScaledVector4()
{
// Arrange
Gray8 gray = default;
const byte expected = 128;
Vector4 scaled = new Gray8(expected).ToScaledVector4();
// Act
gray.PackFromScaledVector4(scaled);
byte actual = gray.PackedValue;
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0)]
[InlineData(255)]
[InlineData(30)]
public void Gray8_ToScaledVector4(byte input)
{
// Arrange
var gray = new Gray8(input);
// Act
Vector4 actual = gray.ToScaledVector4();
// Assert
float scaledInput = input / 255F;
Assert.Equal(scaledInput, actual.X);
Assert.Equal(scaledInput, actual.Y);
Assert.Equal(scaledInput, actual.Z);
Assert.Equal(1, actual.W);
}
[Fact]
public void Gray8_PackFromVector4()
{
// Arrange
Gray8 gray = default;
const int expected = 128;
var vector = new Gray8(expected).ToVector4();
// Act
gray.PackFromVector4(vector);
byte actual = gray.PackedValue;
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0)]
[InlineData(255)]
[InlineData(30)]
public void Gray8_ToVector4(byte input)
{
// Arrange
var gray = new Gray8(input);
// Act
var actual = gray.ToVector4();
// Assert
float scaledInput = input / 255F;
Assert.Equal(scaledInput, actual.X);
Assert.Equal(scaledInput, actual.Y);
Assert.Equal(scaledInput, actual.Z);
Assert.Equal(1, actual.W);
}
[Fact]
public void Gray8_PackFromRgba32()
{
// Arrange
Gray8 gray = default;
const byte rgb = 128;
byte expected = ImageMaths.Get8BitBT709Luminance(rgb, rgb, rgb);
// Act
gray.PackFromRgba32(new Rgba32(rgb, rgb, rgb));
byte actual = gray.PackedValue;
// Assert
Assert.Equal(expected, actual);
}
[Theory]
[InlineData(0)]
[InlineData(255)]
[InlineData(30)]
public void Gray8_ToRgba32(byte input)
{
// Arrange
var gray = new Gray8(input);
// Act
var actual = gray.ToRgba32();
// Assert
Assert.Equal(input, actual.R);
Assert.Equal(input, actual.G);
Assert.Equal(input, actual.B);
Assert.Equal(byte.MaxValue, actual.A);
}
}
}

107
tests/ImageSharp.Tests/PixelFormats/HalfSingleTests.cs

@ -66,112 +66,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_ToRgb24()
{
// arrange
var halfVector = new HalfSingle(.5F);
var actual = default(Rgb24);
var expected = new Rgb24(128, 0, 0);
// act
halfVector.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_Rgba32()
{
// arrange
var halfVector = new HalfSingle(.5F);
var actual = default(Rgba32);
var expected = new Rgba32(128, 0, 0, 255);
// act
halfVector.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_ToBgr24()
{
// arrange
var halfVector = new HalfSingle(.5F);
var actual = default(Bgr24);
var expected = new Bgr24(128, 0, 0);
// act
halfVector.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_Bgra32()
{
// arrange
var halfVector = new HalfSingle(.5F);
var actual = default(Bgra32);
var expected = new Bgra32(128, 0, 0, 255);
// act
halfVector.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_Argb32()
{
// arrange
var halfVector = new HalfSingle(.5F);
var actual = default(Argb32);
var expected = new Argb32(128, 0, 0, 255);
// act
halfVector.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(HalfSingle);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 0, 0);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfSingle_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(HalfSingle);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 0, 0, 65535);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

107
tests/ImageSharp.Tests/PixelFormats/HalfVector2Tests.cs

@ -71,112 +71,5 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_ToRgb24()
{
// arrange
var halfVector = new HalfVector2(.5F, .25F);
var actual = default(Rgb24);
var expected = new Rgb24(128, 64, 0);
// act
halfVector.ToRgb24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_Rgba32()
{
// arrange
var halfVector = new HalfVector2(.5F, .25F);
var actual = default(Rgba32);
var expected = new Rgba32(128, 64, 0, 255);
// act
halfVector.ToRgba32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_ToBgr24()
{
// arrange
var halfVector = new HalfVector2(.5F, .25F);
var actual = default(Bgr24);
var expected = new Bgr24(128, 64, 0);
// act
halfVector.ToBgr24(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_Bgra32()
{
// arrange
var halfVector = new HalfVector2(.5F, .25F);
var actual = default(Bgra32);
var expected = new Bgra32(128, 64, 0, 255);
// act
halfVector.ToBgra32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_Argb32()
{
// arrange
var halfVector = new HalfVector2(.5F, .25F);
var actual = default(Argb32);
var expected = new Argb32(128, 64, 0, 255);
// act
halfVector.ToArgb32(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_PackFromRgb48_ToRgb48()
{
// arrange
var input = default(HalfVector2);
var actual = default(Rgb48);
var expected = new Rgb48(65535, 65535, 0);
// act
input.PackFromRgb48(expected);
input.ToRgb48(ref actual);
// assert
Assert.Equal(expected, actual);
}
[Fact]
public void HalfVector2_PackFromRgba64_ToRgba64()
{
// arrange
var input = default(HalfVector2);
var actual = default(Rgba64);
var expected = new Rgba64(65535, 65535, 0, 65535);
// act
input.PackFromRgba64(expected);
input.ToRgba64(ref actual);
// assert
Assert.Equal(expected, actual);
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save