Browse Source

Merge pull request #242 from JimBobSquarePants/pixel-conversion-refactor

Refactor pixel conversion methods
pull/249/head
James Jackson-South 9 years ago
committed by GitHub
parent
commit
ee1896c99e
  1. 45
      src/ImageSharp/Common/Extensions/ByteExtensions.cs
  2. 1
      src/ImageSharp/Common/Helpers/Guard.cs
  3. 29
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  4. 6
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  5. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/YCbCrToRgbTables.cs
  6. 70
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  7. 75
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  8. 4
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  9. 16
      src/ImageSharp/Image/PixelAccessor{TPixel}.cs
  10. 29
      src/ImageSharp/ImageSharp.csproj
  11. 38
      src/ImageSharp/PixelFormats/Alpha8.cs
  12. 57
      src/ImageSharp/PixelFormats/Argb32.cs
  13. 135
      src/ImageSharp/PixelFormats/Bgr24.cs
  14. 42
      src/ImageSharp/PixelFormats/Bgr565.cs
  15. 187
      src/ImageSharp/PixelFormats/Bgra32.cs
  16. 56
      src/ImageSharp/PixelFormats/Bgra4444.cs
  17. 53
      src/ImageSharp/PixelFormats/Bgra5551.cs
  18. 42
      src/ImageSharp/PixelFormats/Byte4.cs
  19. 14
      src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
  20. 302
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.cs
  21. 130
      src/ImageSharp/PixelFormats/Generated/PixelOperations{TPixel}.Generated.tt
  22. 130
      src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.cs
  23. 99
      src/ImageSharp/PixelFormats/Generated/Rgba32.PixelOperations.Generated.tt
  24. 76
      src/ImageSharp/PixelFormats/HalfSingle.cs
  25. 76
      src/ImageSharp/PixelFormats/HalfVector2.cs
  26. 76
      src/ImageSharp/PixelFormats/HalfVector4.cs
  27. 43
      src/ImageSharp/PixelFormats/IPixel.cs
  28. 86
      src/ImageSharp/PixelFormats/NormalizedByte2.cs
  29. 86
      src/ImageSharp/PixelFormats/NormalizedByte4.cs
  30. 86
      src/ImageSharp/PixelFormats/NormalizedShort2.cs
  31. 86
      src/ImageSharp/PixelFormats/NormalizedShort4.cs
  32. 76
      src/ImageSharp/PixelFormats/PixelConversionExtensions.cs
  33. 204
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
  34. 57
      src/ImageSharp/PixelFormats/Rg32.cs
  35. 132
      src/ImageSharp/PixelFormats/Rgb24.cs
  36. 46
      src/ImageSharp/PixelFormats/Rgba1010102.cs
  37. 159
      src/ImageSharp/PixelFormats/Rgba32.PixelOperations.cs
  38. 169
      src/ImageSharp/PixelFormats/Rgba32.cs
  39. 46
      src/ImageSharp/PixelFormats/Rgba64.cs
  40. 5
      src/ImageSharp/PixelFormats/RgbaVector.PixelOperations.cs
  41. 65
      src/ImageSharp/PixelFormats/RgbaVector.cs
  42. 86
      src/ImageSharp/PixelFormats/Short2.cs
  43. 86
      src/ImageSharp/PixelFormats/Short4.cs
  44. 2
      src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs
  45. 14
      src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs
  46. 6
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs
  47. 4
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
  48. 4
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
  49. 206
      tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs
  50. 156
      tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs
  51. 156
      tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertToRgba32.cs
  52. 2
      tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj
  53. 1
      tests/ImageSharp.Sandbox46/Program.cs
  54. 4
      tests/ImageSharp.Sandbox46/Tests/PixelFormats/PixelBlenderTests.cs
  55. 2
      tests/ImageSharp.Tests/Common/BufferTests.cs
  56. 2
      tests/ImageSharp.Tests/Common/ConstantsTests.cs
  57. 4
      tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs
  58. 10
      tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs
  59. 20
      tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs
  60. 12
      tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs
  61. 8
      tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs
  62. 4
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  63. 6
      tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs
  64. 2
      tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs
  65. 202
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs
  66. 1
      tests/ImageSharp.Tests/Numerics/RectangleFTests.cs
  67. 143
      tests/ImageSharp.Tests/PixelFormats/Bgr24Tests.cs
  68. 150
      tests/ImageSharp.Tests/PixelFormats/Bgra32Tests.cs
  69. 0
      tests/ImageSharp.Tests/PixelFormats/ColorConstructorTests.cs
  70. 0
      tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs
  71. 0
      tests/ImageSharp.Tests/PixelFormats/ColorEqualityTests.cs
  72. 0
      tests/ImageSharp.Tests/PixelFormats/ColorPackingTests.cs
  73. 28
      tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs
  74. 50
      tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs
  75. 32
      tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
  76. 143
      tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs
  77. 0
      tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs
  78. 0
      tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs
  79. 0
      tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs
  80. 2
      tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs
  81. 4
      tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs
  82. 4
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs
  83. 6
      tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs
  84. 14
      tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs
  85. 2
      tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs

45
src/ImageSharp/Common/Extensions/ByteExtensions.cs

@ -5,10 +5,13 @@
namespace ImageSharp
{
using System;
using System.Runtime.CompilerServices;
using ImageSharp.PixelFormats;
/// <summary>
/// Extension methods for the <see cref="byte"/> struct.
/// Extension methods for the <see cref="byte"/> struct buffers.
/// </summary>
internal static class ByteExtensions
{
@ -44,5 +47,45 @@ namespace ImageSharp
j--;
}
}
/// <summary>
/// Returns a reference to the given position of the array unsafe casted to <see cref="ImageSharp.PixelFormats.Rgb24"/>.
/// </summary>
/// <param name="bytes">The byte array.</param>
/// <param name="offset">The offset in bytes.</param>
/// <returns>The <see cref="ImageSharp.PixelFormats.Rgb24"/> reference at the given offset.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Rgb24 GetRgb24(this byte[] bytes, int offset)
{
DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset));
return ref Unsafe.As<byte, Rgb24>(ref bytes[offset]);
}
/// <summary>
/// Returns a reference to the given position of the span unsafe casted to <see cref="ImageSharp.PixelFormats.Rgb24"/>.
/// </summary>
/// <param name="bytes">The byte span.</param>
/// <param name="offset">The offset in bytes.</param>
/// <returns>The <see cref="ImageSharp.PixelFormats.Rgb24"/> reference at the given offset.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Rgb24 GetRgb24(this Span<byte> bytes, int offset)
{
DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset));
return ref Unsafe.As<byte, Rgb24>(ref bytes[offset]);
}
/// <summary>
/// Returns a reference to the given position of the buffer pointed by `baseRef` unsafe casted to <see cref="ImageSharp.PixelFormats.Rgb24"/>.
/// </summary>
/// <param name="baseRef">A reference to the beginning of the buffer</param>
/// <param name="offset">The offset in bytes.</param>
/// <returns>The <see cref="ImageSharp.PixelFormats.Rgb24"/> reference at the given offset.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Rgb24 GetRgb24(ref byte baseRef, int offset)
{
return ref Unsafe.As<byte, Rgb24>(ref Unsafe.Add(ref baseRef, offset));
}
}
}

1
src/ImageSharp/Common/Helpers/Guard.cs

@ -242,7 +242,6 @@ namespace ImageSharp
/// <paramref name="target"/> is true
/// </exception>
public static void MustBeSizedAtLeast<T>(Span<T> target, int minLength, string parameterName)
where T : struct
{
if (target.Length < minLength)
{

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

@ -6,7 +6,8 @@ namespace ImageSharp.Formats
{
using System;
using System.IO;
using System.Runtime.CompilerServices;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
/// <summary>
@ -243,13 +244,16 @@ namespace ImageSharp.Formats
byte[] row = new byte[arrayWidth + padding];
TPixel color = default(TPixel);
Rgba32 rgba = default(Rgba32);
for (int y = 0; y < height; y++)
{
int newY = Invert(y, height, inverted);
this.currentStream.Read(row, 0, row.Length);
int offset = 0;
Span<TPixel> pixelRow = pixels.GetRowSpan(y);
// TODO: Could use PixelOperations here!
for (int x = 0; x < arrayWidth; x++)
{
int colOffset = x * ppb;
@ -260,8 +264,9 @@ namespace ImageSharp.Formats
int newX = colOffset + shift;
// Stored in b-> g-> r order.
color.PackFromBytes(colors[colorIndex + 2], colors[colorIndex + 1], colors[colorIndex], 255);
pixels[newX, newY] = color;
rgba.Bgr = Unsafe.As<byte, Bgr24>(ref colors[colorIndex]);
color.PackFromRgba32(rgba);
pixelRow[newX] = color;
}
offset++;
@ -286,6 +291,8 @@ namespace ImageSharp.Formats
const int ComponentCount = 2;
TPixel color = default(TPixel);
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
using (PixelArea<TPixel> row = new PixelArea<TPixel>(width, ComponentOrder.Xyz))
{
for (int y = 0; y < height; y++)
@ -294,17 +301,19 @@ namespace ImageSharp.Formats
int newY = Invert(y, height, inverted);
Span<TPixel> pixelRow = pixels.GetRowSpan(newY);
int offset = 0;
for (int x = 0; x < width; x++)
{
short temp = BitConverter.ToInt16(row.Bytes, offset);
byte r = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR);
byte g = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG);
byte b = (byte)((temp & Rgb16BMask) * ScaleR);
rgba.R = (byte)(((temp & Rgb16RMask) >> 11) * ScaleR);
rgba.G = (byte)(((temp & Rgb16GMask) >> 5) * ScaleG);
rgba.B = (byte)((temp & Rgb16BMask) * ScaleR);
color.PackFromBytes(r, g, b, 255);
pixels[x, newY] = color;
color.PackFromRgba32(rgba);
pixelRow[x] = color;
offset += ComponentCount;
}
}

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

@ -435,6 +435,8 @@ namespace ImageSharp.Formats
Span<TPixel> rowSpan = image.GetRowSpan(writeY);
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width; x++)
{
int index = indices[i];
@ -446,7 +448,9 @@ namespace ImageSharp.Formats
int indexOffset = index * 3;
ref TPixel pixel = ref rowSpan[x];
pixel.PackFromBytes(colorTable[indexOffset], colorTable[indexOffset + 1], colorTable[indexOffset + 2], 255);
rgba.Rgb = colorTable.GetRgb24(indexOffset);
pixel.PackFromRgba32(rgba);
}
i++;

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/YCbCrToRgbTables.cs

@ -91,7 +91,7 @@ namespace ImageSharp.Formats.Jpg
// float b = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero);
byte b = (byte)(y + tables->CbBTable[cb]).Clamp(0, 255);
packed.PackFromBytes(r, g, b, byte.MaxValue);
packed.PackFromRgba32(new Rgba32(r, g, b, 255));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

70
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -613,25 +613,23 @@ namespace ImageSharp.Formats
private void ConvertFromGrayScale<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
using (PixelAccessor<TPixel> pixels = image.Lock())
{
Parallel.For(
0,
image.Height,
image.Configuration.ParallelOptions,
y =>
Parallel.For(
0,
image.Height,
image.Configuration.ParallelOptions,
y =>
{
ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y);
int yoff = this.grayImage.GetRowOffset(y);
for (int x = 0; x < image.Width; x++)
{
byte rgb = this.grayImage.Pixels[yoff + x];
TPixel packed = default(TPixel);
packed.PackFromBytes(rgb, rgb, rgb, 255);
pixels[x, y] = packed;
ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x);
pixel.PackFromRgba32(new Rgba32(rgb, rgb, rgb, 255));
}
});
}
this.AssignResolution(image);
}
@ -646,30 +644,29 @@ namespace ImageSharp.Formats
{
int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor;
using (PixelAccessor<TPixel> pixels = image.Lock())
{
Parallel.For(
0,
image.Height,
image.Configuration.ParallelOptions,
y =>
Parallel.For(
0,
image.Height,
image.Configuration.ParallelOptions,
y =>
{
// TODO: Simplify + optimize + share duplicate code across converter methods
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y);
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int x = 0; x < image.Width; x++)
{
byte red = this.ycbcrImage.YChannel[yo + x];
byte green = this.ycbcrImage.CbChannel[co + (x / scale)];
byte blue = this.ycbcrImage.CrChannel[co + (x / scale)];
rgba.R = this.ycbcrImage.YChannel[yo + x];
rgba.G = this.ycbcrImage.CbChannel[co + (x / scale)];
rgba.B = this.ycbcrImage.CrChannel[co + (x / scale)];
TPixel packed = default(TPixel);
packed.PackFromBytes(red, green, blue, 255);
pixels[x, y] = packed;
ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x);
pixel.PackFromRgba32(rgba);
}
});
}
this.AssignResolution(image);
}
@ -729,16 +726,15 @@ namespace ImageSharp.Formats
{
int scale = this.ComponentArray[0].HorizontalFactor / this.ComponentArray[1].HorizontalFactor;
using (PixelAccessor<TPixel> pixels = image.Lock())
{
Parallel.For(
0,
image.Height,
y =>
Parallel.For(
0,
image.Height,
y =>
{
// TODO: Simplify + optimize + share duplicate code across converter methods
int yo = this.ycbcrImage.GetRowYOffset(y);
int co = this.ycbcrImage.GetRowCOffset(y);
ref TPixel pixelRowBaseRef = ref image.GetPixelReference(0, y);
for (int x = 0; x < image.Width; x++)
{
@ -746,12 +742,10 @@ namespace ImageSharp.Formats
byte cb = this.ycbcrImage.CbChannel[co + (x / scale)];
byte cr = this.ycbcrImage.CrChannel[co + (x / scale)];
TPixel packed = default(TPixel);
this.PackYcck(ref packed, yy, cb, cr, x, y);
pixels[x, y] = packed;
ref TPixel pixel = ref Unsafe.Add(ref pixelRowBaseRef, x);
this.PackYcck(ref pixel, yy, cb, cr, x, y);
}
});
}
this.AssignResolution(image);
}
@ -860,7 +854,7 @@ namespace ImageSharp.Formats
byte g = (byte)(((m / 255F) * (1F - keyline)).Clamp(0, 1) * 255);
byte b = (byte)(((y / 255F) * (1F - keyline)).Clamp(0, 1) * 255);
packed.PackFromBytes(r, g, b, 255);
packed.PackFromRgba32(new Rgba32(r, g, b));
}
/// <summary>
@ -904,7 +898,7 @@ namespace ImageSharp.Formats
byte g = (byte)(((1 - magenta) * (1 - keyline)).Clamp(0, 1) * 255);
byte b = (byte)(((1 - yellow) * (1 - keyline)).Clamp(0, 1) * 255);
packed.PackFromBytes(r, g, b, 255);
packed.PackFromRgba32(new Rgba32(r, g, b));
}
/// <summary>

75
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -574,7 +574,7 @@ namespace ImageSharp.Formats
for (int x = 0; x < this.header.Width; x++)
{
byte intensity = (byte)(newScanline1[x] * factor);
color.PackFromBytes(intensity, intensity, intensity, 255);
color.PackFromRgba32(new Rgba32(intensity, intensity, intensity));
rowSpan[x] = color;
}
@ -589,7 +589,7 @@ namespace ImageSharp.Formats
byte intensity = defilteredScanline[offset];
byte alpha = defilteredScanline[offset + this.bytesPerSample];
color.PackFromBytes(intensity, intensity, intensity, alpha);
color.PackFromRgba32(new Rgba32(intensity, intensity, intensity));
rowSpan[x] = color;
}
@ -603,13 +603,13 @@ namespace ImageSharp.Formats
case PngColorType.Rgb:
PixelOperations<TPixel>.Instance.PackFromXyzBytes(scanlineBuffer, rowSpan, this.header.Width);
PixelOperations<TPixel>.Instance.PackFromRgb24Bytes(scanlineBuffer, rowSpan, this.header.Width);
break;
case PngColorType.RgbWithAlpha:
PixelOperations<TPixel>.Instance.PackFromXyzwBytes(scanlineBuffer, rowSpan, this.header.Width);
PixelOperations<TPixel>.Instance.PackFromRgba32Bytes(scanlineBuffer, rowSpan, this.header.Width);
break;
}
@ -628,6 +628,8 @@ namespace ImageSharp.Formats
byte[] palette = this.palette;
var color = default(TPixel);
Rgba32 rgba = default(Rgba32);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
{
// If the alpha palette is not null and has one or more entries, this means, that the image contains an alpha
@ -637,35 +639,33 @@ namespace ImageSharp.Formats
int index = newScanline[x + 1];
int pixelOffset = index * 3;
byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
rgba.A = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
if (a > 0)
if (rgba.A > 0)
{
byte r = palette[pixelOffset];
byte g = palette[pixelOffset + 1];
byte b = palette[pixelOffset + 2];
color.PackFromBytes(r, g, b, a);
rgba.Rgb = palette.GetRgb24(pixelOffset);
}
else
{
color.PackFromBytes(0, 0, 0, 0);
rgba = default(Rgba32);
}
color.PackFromRgba32(rgba);
row[x] = color;
}
}
else
{
rgba.A = 255;
for (int x = 0; x < this.header.Width; x++)
{
int index = newScanline[x + 1];
int pixelOffset = index * 3;
byte r = palette[pixelOffset];
byte g = palette[pixelOffset + 1];
byte b = palette[pixelOffset + 2];
rgba.Rgb = palette.GetRgb24(pixelOffset);
color.PackFromBytes(r, g, b, 255);
color.PackFromRgba32(rgba);
row[x] = color;
}
}
@ -692,7 +692,7 @@ namespace ImageSharp.Formats
for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++)
{
byte intensity = (byte)(newScanline1[o] * factor);
color.PackFromBytes(intensity, intensity, intensity, 255);
color.PackFromRgba32(new Rgba32(intensity, intensity, intensity));
rowSpan[x] = color;
}
@ -704,8 +704,7 @@ namespace ImageSharp.Formats
{
byte intensity = defilteredScanline[o];
byte alpha = defilteredScanline[o + this.bytesPerSample];
color.PackFromBytes(intensity, intensity, intensity, alpha);
color.PackFromRgba32(new Rgba32(intensity, intensity, intensity, alpha));
rowSpan[x] = color;
}
@ -714,6 +713,7 @@ namespace ImageSharp.Formats
case PngColorType.Palette:
byte[] newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
Rgba32 rgba = default(Rgba32);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
{
@ -724,35 +724,33 @@ namespace ImageSharp.Formats
int index = newScanline[o];
int offset = index * 3;
byte a = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
rgba.A = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
if (a > 0)
if (rgba.A > 0)
{
byte r = this.palette[offset];
byte g = this.palette[offset + 1];
byte b = this.palette[offset + 2];
color.PackFromBytes(r, g, b, a);
rgba.Rgb = this.palette.GetRgb24(offset);
}
else
{
color.PackFromBytes(0, 0, 0, 0);
rgba = default(Rgba32);
}
color.PackFromRgba32(rgba);
rowSpan[x] = color;
}
}
else
{
rgba.A = 255;
for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o++)
{
int index = newScanline[o];
int offset = index * 3;
byte r = this.palette[offset];
byte g = this.palette[offset + 1];
byte b = this.palette[offset + 2];
rgba.Rgb = this.palette.GetRgb24(offset);
color.PackFromBytes(r, g, b, 255);
color.PackFromRgba32(rgba);
rowSpan[x] = color;
}
}
@ -761,13 +759,14 @@ namespace ImageSharp.Formats
case PngColorType.Rgb:
rgba.A = 255;
for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel)
{
byte r = defilteredScanline[o];
byte g = defilteredScanline[o + this.bytesPerSample];
byte b = defilteredScanline[o + (2 * this.bytesPerSample)];
rgba.R = defilteredScanline[o];
rgba.G = defilteredScanline[o + this.bytesPerSample];
rgba.B = defilteredScanline[o + (2 * this.bytesPerSample)];
color.PackFromBytes(r, g, b, 255);
color.PackFromRgba32(rgba);
rowSpan[x] = color;
}
@ -777,12 +776,12 @@ namespace ImageSharp.Formats
for (int x = pixelOffset, o = 1; x < this.header.Width; x += increment, o += this.bytesPerPixel)
{
byte r = defilteredScanline[o];
byte g = defilteredScanline[o + this.bytesPerSample];
byte b = defilteredScanline[o + (2 * this.bytesPerSample)];
byte a = defilteredScanline[o + (3 * this.bytesPerSample)];
rgba.R = defilteredScanline[o];
rgba.G = defilteredScanline[o + this.bytesPerSample];
rgba.B = defilteredScanline[o + (2 * this.bytesPerSample)];
rgba.A = defilteredScanline[o + (3 * this.bytesPerSample)];
color.PackFromBytes(r, g, b, a);
color.PackFromRgba32(rgba);
rowSpan[x] = color;
}

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

@ -338,11 +338,11 @@ namespace ImageSharp.Formats
{
if (this.bytesPerPixel == 4)
{
PixelOperations<TPixel>.Instance.ToXyzwBytes(rowSpan, this.rawScanline, this.width);
PixelOperations<TPixel>.Instance.ToRgba32Bytes(rowSpan, this.rawScanline, this.width);
}
else
{
PixelOperations<TPixel>.Instance.ToXyzBytes(rowSpan, this.rawScanline, this.width);
PixelOperations<TPixel>.Instance.ToRgb24Bytes(rowSpan, this.rawScanline, this.width);
}
}

16
src/ImageSharp/Image/PixelAccessor{TPixel}.cs

@ -275,7 +275,7 @@ namespace ImageSharp
Span<byte> source = area.GetRowSpan(y);
Span<TPixel> destination = this.GetRowSpan(targetX, targetY + y);
Operations.PackFromZyxBytes(source, destination, width);
Operations.PackFromBgr24Bytes(source, destination, width);
}
}
@ -295,7 +295,7 @@ namespace ImageSharp
Span<byte> source = area.GetRowSpan(y);
Span<TPixel> destination = this.GetRowSpan(targetX, targetY + y);
Operations.PackFromZyxwBytes(source, destination, width);
Operations.PackFromBgra32Bytes(source, destination, width);
}
}
@ -315,7 +315,7 @@ namespace ImageSharp
Span<byte> source = area.GetRowSpan(y);
Span<TPixel> destination = this.GetRowSpan(targetX, targetY + y);
Operations.PackFromXyzBytes(source, destination, width);
Operations.PackFromRgb24Bytes(source, destination, width);
}
}
@ -334,7 +334,7 @@ namespace ImageSharp
{
Span<byte> source = area.GetRowSpan(y);
Span<TPixel> destination = this.GetRowSpan(targetX, targetY + y);
Operations.PackFromXyzwBytes(source, destination, width);
Operations.PackFromRgba32Bytes(source, destination, width);
}
}
@ -353,7 +353,7 @@ namespace ImageSharp
{
Span<TPixel> source = this.GetRowSpan(sourceX, sourceY + y);
Span<byte> destination = area.GetRowSpan(y);
Operations.ToZyxBytes(source, destination, width);
Operations.ToBgr24Bytes(source, destination, width);
}
}
@ -372,7 +372,7 @@ namespace ImageSharp
{
Span<TPixel> source = this.GetRowSpan(sourceX, sourceY + y);
Span<byte> destination = area.GetRowSpan(y);
Operations.ToZyxwBytes(source, destination, width);
Operations.ToBgra32Bytes(source, destination, width);
}
}
@ -391,7 +391,7 @@ namespace ImageSharp
{
Span<TPixel> source = this.GetRowSpan(sourceX, sourceY + y);
Span<byte> destination = area.GetRowSpan(y);
Operations.ToXyzBytes(source, destination, width);
Operations.ToRgb24Bytes(source, destination, width);
}
}
@ -410,7 +410,7 @@ namespace ImageSharp
{
Span<TPixel> source = this.GetRowSpan(sourceX, sourceY + y);
Span<byte> destination = area.GetRowSpan(y);
Operations.ToXyzwBytes(source, destination, width);
Operations.ToRgba32Bytes(source, destination, width);
}
}

29
src/ImageSharp/ImageSharp.csproj

@ -53,6 +53,35 @@
<ItemGroup>
<None Update="Formats\Jpeg\Components\Block8x8F.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Block8x8F.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\PixelOperations{TPixel}.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PixelOperations{TPixel}.Generated.cs</LastGenOutput>
</None>
<None Update="PixelFormats\Generated\Rgba32.PixelOperations.Generated.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Rgba32.PixelOperations.Generated.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Formats\Jpeg\Components\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Block8x8F.Generated.tt</DependentUpon>
</Compile>
<Compile Update="PixelFormats\Generated\PixelOperations{TPixel}.Generated.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PixelOperations{TPixel}.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>
</ItemGroup>
</Project>

38
src/ImageSharp/PixelFormats/Alpha8.cs

@ -62,7 +62,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Alpha8> CreateBulkOperations() => new PixelOperations<Alpha8>();
public PixelOperations<Alpha8> CreatePixelOperations() => new PixelOperations<Alpha8>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -80,47 +80,43 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackedValue = w;
this.PackedValue = source.A;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
dest = default(Rgb24);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = this.PackedValue;
dest.R = 0;
dest.G = 0;
dest.B = 0;
dest.A = this.PackedValue;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
dest = default(Bgr24);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
bytes[startIndex] = 0;
bytes[startIndex + 1] = 0;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = this.PackedValue;
dest.R = 0;
dest.G = 0;
dest.B = 0;
dest.A = this.PackedValue;
}
/// <summary>

57
src/ImageSharp/PixelFormats/Argb32.cs

@ -59,11 +59,24 @@ namespace ImageSharp.PixelFormats
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
public Argb32(byte r, byte g, byte b, byte a = 255)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Argb32(byte r, byte g, byte b, byte a)
{
this.PackedValue = Pack(r, g, b, a);
}
/// <summary>
/// Initializes a new instance of the <see cref="Argb32"/> 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)]
public Argb32(byte r, byte g, byte b)
{
this.PackedValue = Pack(r, g, b, 255);
}
/// <summary>
/// Initializes a new instance of the <see cref="Argb32"/> struct.
/// </summary>
@ -224,7 +237,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Argb32> CreateBulkOperations() => new PixelOperations<Argb32>();
public PixelOperations<Argb32> CreatePixelOperations() => new PixelOperations<Argb32>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -235,47 +248,47 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackedValue = Pack(x, y, z, w);
this.PackedValue = Pack(source.R, source.G, source.B, source.A);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
}
/// <inheritdoc/>

135
src/ImageSharp/PixelFormats/Bgr24.cs

@ -0,0 +1,135 @@
// <copyright file="Bgr24.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.PixelFormats
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in blue, green, red order.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Bgr24 : IPixel<Bgr24>
{
/// <summary>
/// The blue component.
/// </summary>
public byte B;
/// <summary>
/// The green component.
/// </summary>
public byte G;
/// <summary>
/// The red component.
/// </summary>
public byte R;
/// <summary>
/// Initializes a new instance of the <see cref="Bgr24"/> 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)]
public Bgr24(byte r, byte g, byte b)
{
this.R = r;
this.G = g;
this.B = b;
}
/// <inheritdoc/>
public PixelOperations<Bgr24> CreatePixelOperations() => new PixelOperations<Bgr24>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Bgr24 other)
{
return this.R == other.R && this.G == other.G && this.B == other.B;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj?.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
unchecked
{
int hashCode = this.B;
hashCode = (hashCode * 397) ^ this.G;
hashCode = (hashCode * 397) ^ this.R;
return hashCode;
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this = source.Bgr;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
var rgba = default(Rgba32);
rgba.PackFromVector4(vector);
this.PackFromRgba32(rgba);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
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;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgba32(ref Rgba32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = 255;
}
/// <inheritdoc/>
public void ToBgr24(ref Bgr24 dest)
{
dest = this;
}
/// <inheritdoc/>
public void ToBgra32(ref Bgra32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = 255;
}
}
}

42
src/ImageSharp/PixelFormats/Bgr565.cs

@ -71,7 +71,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Bgr565> CreateBulkOperations() => new PixelOperations<Bgr565>();
public PixelOperations<Bgr565> CreatePixelOperations() => new PixelOperations<Bgr565>();
/// <summary>
/// Expands the packed representation into a <see cref="Vector3"/>.
@ -103,51 +103,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / 255F);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
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 ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
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 />

187
src/ImageSharp/PixelFormats/Bgra32.cs

@ -0,0 +1,187 @@
// <copyright file="Bgra32.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.PixelFormats
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in blue, green, red, and alpha order.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Bgra32 : IPixel<Bgra32>, IPackedVector<uint>
{
/// <summary>
/// Gets or sets the blue component.
/// </summary>
public byte B;
/// <summary>
/// Gets or sets the green component.
/// </summary>
public byte G;
/// <summary>
/// Gets or sets the red component.
/// </summary>
public byte R;
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
public byte A;
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> 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)]
public Bgra32(byte r, byte g, byte b)
{
this.R = r;
this.G = g;
this.B = b;
this.A = 255;
}
/// <summary>
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Bgra32(byte r, byte g, byte b, byte a)
{
this.R = r;
this.G = g;
this.B = b;
this.A = a;
}
/// <summary>
/// Gets or sets the packed representation of the Bgra32 struct.
/// </summary>
public uint Bgra
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return Unsafe.As<Bgra32, uint>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
Unsafe.As<Bgra32, uint>(ref this) = value;
}
}
/// <inheritdoc/>
public uint PackedValue
{
get => this.Bgra;
set => this.Bgra = value;
}
/// <inheritdoc/>
public PixelOperations<Bgra32> CreatePixelOperations() => new PixelOperations<Bgra32>();
/// <inheritdoc/>
public bool Equals(Bgra32 other)
{
return this.R == other.R && this.G == other.G && this.B == other.B && this.A == other.A;
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj?.GetType() == typeof(Bgra32) && this.Equals((Bgra32)obj);
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
int hashCode = this.B;
hashCode = (hashCode * 397) ^ this.G;
hashCode = (hashCode * 397) ^ this.R;
hashCode = (hashCode * 397) ^ this.A;
return hashCode;
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
var rgba = default(Rgba32);
rgba.PackFromVector4(vector);
this.PackFromRgba32(rgba);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return this.ToRgba32().ToVector4();
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this.R = source.R;
this.G = source.G;
this.B = source.B;
this.A = source.A;
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.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 = this.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;
}
/// <summary>
/// Converts the pixel to <see cref="Rgba32"/> format.
/// </summary>
/// <returns>The RGBA value</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
}
}

56
src/ImageSharp/PixelFormats/Bgra4444.cs

@ -70,7 +70,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Bgra4444> CreateBulkOperations() => new PixelOperations<Bgra4444>();
public PixelOperations<Bgra4444> CreatePixelOperations() => new PixelOperations<Bgra4444>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -79,10 +79,10 @@ namespace ImageSharp.PixelFormats
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) * Max,
((this.PackedValue >> 4) & 0x0F) * Max,
(this.PackedValue & 0x0F) * Max,
((this.PackedValue >> 12) & 0x0F) * Max);
}
/// <inheritdoc />
@ -94,51 +94,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / 255F);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
@ -179,9 +179,9 @@ namespace ImageSharp.PixelFormats
private static ushort Pack(float x, float y, float z, float w)
{
return (ushort)((((int)Math.Round(w.Clamp(0, 1) * 15F) & 0x0F) << 12) |
(((int)Math.Round(x.Clamp(0, 1) * 15F) & 0x0F) << 8) |
(((int)Math.Round(y.Clamp(0, 1) * 15F) & 0x0F) << 4) |
((int)Math.Round(z.Clamp(0, 1) * 15F) & 0x0F));
(((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));
}
}
}

53
src/ImageSharp/PixelFormats/Bgra5551.cs

@ -72,7 +72,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Bgra5551> CreateBulkOperations() => new PixelOperations<Bgra5551>();
public PixelOperations<Bgra5551> CreatePixelOperations() => new PixelOperations<Bgra5551>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -94,51 +94,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / 255F);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
@ -190,5 +190,8 @@ namespace ImageSharp.PixelFormats
(((int)Math.Round(z.Clamp(0, 1) * 31F) & 0x1F) << 0) |
(((int)Math.Round(w.Clamp(0, 1)) & 0x1) << 15));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4() => this.ToVector4() * 255f;
}
}

42
src/ImageSharp/PixelFormats/Byte4.cs

@ -73,7 +73,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Byte4> CreateBulkOperations() => new PixelOperations<Byte4>();
public PixelOperations<Byte4> CreatePixelOperations() => new PixelOperations<Byte4>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -95,51 +95,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w));
this.PackFromVector4(source.ToUnscaledVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />

14
src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs

@ -35,12 +35,13 @@ namespace ImageSharp.PixelFormats
}
TPixel result = default(TPixel);
result.PackFromBytes(
Rgba32 rgba = new Rgba32(
(byte)(packedValue >> 24),
(byte)(packedValue >> 16),
(byte)(packedValue >> 8),
(byte)(packedValue >> 0));
result.PackFromRgba32(rgba);
return result;
}
@ -51,12 +52,7 @@ namespace ImageSharp.PixelFormats
/// <param name="green">The green intensity.</param>
/// <param name="blue">The blue intensity.</param>
/// <returns>Returns a <typeparamref name="TPixel"/> that represents the color defined by the provided RGB values with 100% opacity.</returns>
public static TPixel FromRGB(byte red, byte green, byte blue)
{
TPixel color = default(TPixel);
color.PackFromBytes(red, green, blue, 255);
return color;
}
public static TPixel FromRGB(byte red, byte green, byte blue) => FromRGBA(red, green, blue, 255);
/// <summary>
/// Creates a new <typeparamref name="TPixel"/> representation from standard RGBA bytes.
@ -69,7 +65,7 @@ namespace ImageSharp.PixelFormats
public static TPixel FromRGBA(byte red, byte green, byte blue, byte alpha)
{
TPixel color = default(TPixel);
color.PackFromBytes(red, green, blue, alpha);
color.PackFromRgba32(new Rgba32(red, green, blue, alpha));
return color;
}

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

@ -0,0 +1,302 @@
// <auto-generated />
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.PixelFormats
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
public partial class PixelOperations<TPixel>
{
/// <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="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 PackFromRgba32(Span<Rgba32> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference();
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference();
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
rgba = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba32(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgba32(Span{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="Span{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(Span<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgba32(sourceBytes.NonPortableCast<byte, Rgba32>(), 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>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Rgba32"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToRgba32(Span<TPixel> sourcePixels, Span<Rgba32> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference();
ref Rgba32 destBaseRef = ref dest.DangerousGetPinnableReference();
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);
}
}
/// <summary>
/// A helper for <see cref="ToRgba32(Span{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="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(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
this.ToRgba32(sourceColors, destBytes.NonPortableCast<byte, Rgba32>(), count);
}
/// <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="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 PackFromBgra32(Span<Bgra32> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference();
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference();
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();
dp.PackFromRgba32(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFromBgra32(Span{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="Span{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(Span<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromBgra32(sourceBytes.NonPortableCast<byte, Bgra32>(), 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>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Bgra32"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToBgra32(Span<TPixel> sourcePixels, Span<Bgra32> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference();
ref Bgra32 destBaseRef = ref dest.DangerousGetPinnableReference();
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);
}
}
/// <summary>
/// A helper for <see cref="ToBgra32(Span{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="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(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
this.ToBgra32(sourceColors, destBytes.NonPortableCast<byte, Bgra32>(), count);
}
/// <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>
/// <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 PackFromRgb24(Span<Rgb24> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference();
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference();
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
rgba.Rgb = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba32(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFromRgb24(Span{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>
/// <param name="sourceBytes">The <see cref="Span{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 PackFromRgb24Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromRgb24(sourceBytes.NonPortableCast<byte, Rgb24>(), destPixels, count);
}
/// <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="count">The number of pixels to convert.</param>
internal virtual void ToRgb24(Span<TPixel> sourcePixels, Span<Rgb24> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference();
ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference();
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);
}
}
/// <summary>
/// A helper for <see cref="ToRgb24(Span{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="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(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
this.ToRgb24(sourceColors, destBytes.NonPortableCast<byte, Rgb24>(), count);
}
/// <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="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 PackFromBgr24(Span<Bgr24> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference();
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference();
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
rgba.Bgr = Unsafe.Add(ref sourceRef, i);
dp.PackFromRgba32(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFromBgr24(Span{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="Span{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(Span<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFromBgr24(sourceBytes.NonPortableCast<byte, Bgr24>(), 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>
/// <param name="sourcePixels">The span of source pixels</param>
/// <param name="dest">The destination span of <see cref="Bgr24"/> data.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToBgr24(Span<TPixel> sourcePixels, Span<Bgr24> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference();
ref Bgr24 destBaseRef = ref dest.DangerousGetPinnableReference();
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);
}
}
/// <summary>
/// A helper for <see cref="ToBgr24(Span{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="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(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
this.ToBgr24(sourceColors, destBytes.NonPortableCast<byte, Bgr24>(), count);
}
}
}

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

@ -0,0 +1,130 @@
<#
// <copyright file="PixelOperations{TPixel}.Generated.tt" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
#>
<#@ 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 GenerateToDestFormatMethods(string pixelType)
{
#>
/// <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="count">The number of pixels to convert.</param>
internal virtual void To<#=pixelType#>(Span<TPixel> sourcePixels, Span<<#=pixelType#>> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference();
ref <#=pixelType#> destBaseRef = ref dest.DangerousGetPinnableReference();
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);
}
}
/// <summary>
/// A helper for <see cref="To<#=pixelType#>(Span{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="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(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast<byte, <#=pixelType#>>(), count);
}
<#
}
void GeneratePackFromMethodUsingPackFromRgba32(string pixelType, string rgbaOperationCode)
{
#>
/// <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>
/// <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 PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span<TPixel> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference();
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference();
Rgba32 rgba = new Rgba32(0, 0, 0, 255);
for (int i = 0; i < count; i++)
{
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
<#=rgbaOperationCode#>
dp.PackFromRgba32(rgba);
}
}
/// <summary>
/// A helper for <see cref="PackFrom<#=pixelType#>(Span{<#=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>
/// <param name="sourceBytes">The <see cref="Span{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 PackFrom<#=pixelType#>Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count)
{
this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast<byte, <#=pixelType#>>(), destPixels, count);
}
<#
}
#>
// <auto-generated />
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.PixelFormats
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
public partial class PixelOperations<TPixel>
{
<#
GeneratePackFromMethodUsingPackFromRgba32("Rgba32", "rgba = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgba32");
GeneratePackFromMethodUsingPackFromRgba32("Bgra32", "rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();");
GenerateToDestFormatMethods("Bgra32");
GeneratePackFromMethodUsingPackFromRgba32("Rgb24", "rgba.Rgb = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Rgb24");
GeneratePackFromMethodUsingPackFromRgba32("Bgr24", "rgba.Bgr = Unsafe.Add(ref sourceRef, i);");
GenerateToDestFormatMethods("Bgr24");
#>
}
}

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

@ -0,0 +1,130 @@
// <auto-generated />
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgba32
{
internal partial class PixelOperations : PixelOperations<Rgba32>
{
/// <inheritdoc />
internal override void PackFromRgb24(Span<Rgb24> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference();
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference();
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;
}
}
/// <inheritdoc />
internal override void ToRgb24(Span<Rgba32> sourcePixels, Span<Rgb24> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference();
ref Rgb24 destRef = ref dest.DangerousGetPinnableReference();
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);
}
}
/// <inheritdoc />
internal override void PackFromBgr24(Span<Bgr24> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference();
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference();
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;
}
}
/// <inheritdoc />
internal override void ToBgr24(Span<Rgba32> sourcePixels, Span<Bgr24> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference();
ref Bgr24 destRef = ref dest.DangerousGetPinnableReference();
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;
}
}
/// <inheritdoc />
internal override void PackFromBgra32(Span<Bgra32> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference();
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference();
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();
}
}
/// <inheritdoc />
internal override void ToBgra32(Span<Rgba32> sourcePixels, Span<Bgra32> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference();
ref Bgra32 destRef = ref dest.DangerousGetPinnableReference();
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();
}
}
}
}
}

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

@ -0,0 +1,99 @@
<#
// <copyright file="Rgba32.PixelOperations.Generated.tt" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
#>
<#@ 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 GeneratePackFromMethod(string pixelType, string converterCode)
{
#>
/// <inheritdoc />
internal override void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span<Rgba32> destPixels, int count)
{
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference();
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference();
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#>(Span<Rgba32> sourcePixels, Span<<#=pixelType#>> dest, int count)
{
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference();
ref <#=pixelType#> destRef = ref dest.DangerousGetPinnableReference();
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#>
}
}
<#
}
#>
// <auto-generated />
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ImageSharp.Memory;
using ImageSharp.PixelFormats;
/// <content>
/// Provides optimized overrides for bulk operations.
/// </content>
public partial struct Rgba32
{
internal partial class PixelOperations : PixelOperations<Rgba32>
{
<#
GeneratePackFromMethod("Rgb24", "Unsafe.As<Rgba32, Rgb24>(ref dp) = sp; dp.A = 255;");
GenerateConvertToMethod("Rgb24", "dp = Unsafe.As<Rgba32, Rgb24>(ref sp);");
GeneratePackFromMethod("Bgr24", "dp.Bgr = sp; dp.A = 255;");
GenerateConvertToMethod("Bgr24", "dp = sp.Bgr;");
GeneratePackFromMethod("Bgra32", "dp = sp.ToRgba32();");
GenerateConvertToMethod("Bgra32", "dp = sp.ToBgra32();");
#>
}
}
}

76
src/ImageSharp/PixelFormats/HalfSingle.cs

@ -76,7 +76,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<HalfSingle> CreateBulkOperations() => new PixelOperations<HalfSingle>();
public PixelOperations<HalfSingle> CreatePixelOperations() => new PixelOperations<HalfSingle>();
/// <summary>
/// Expands the packed representation into a <see cref="float"/>.
@ -104,67 +104,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
@ -192,5 +176,15 @@ namespace ImageSharp.PixelFormats
{
return this.PackedValue.GetHashCode();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

76
src/ImageSharp/PixelFormats/HalfVector2.cs

@ -86,7 +86,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<HalfVector2> CreateBulkOperations() => new PixelOperations<HalfVector2>();
public PixelOperations<HalfVector2> CreatePixelOperations() => new PixelOperations<HalfVector2>();
/// <summary>
/// Expands the packed representation into a <see cref="Vector2"/>.
@ -118,67 +118,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc />
@ -220,5 +204,15 @@ namespace ImageSharp.PixelFormats
uint num = (uint)(HalfTypeHelper.Pack(y) << 0x10);
return num2 | num;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

76
src/ImageSharp/PixelFormats/HalfVector4.cs

@ -89,7 +89,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<HalfVector4> CreateBulkOperations() => new PixelOperations<HalfVector4>();
public PixelOperations<HalfVector4> CreatePixelOperations() => new PixelOperations<HalfVector4>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -111,67 +111,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / MaxBytes);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
@ -214,5 +198,15 @@ namespace ImageSharp.PixelFormats
ulong num1 = (ulong)HalfTypeHelper.Pack(vector.W) << 0x30;
return num4 | num3 | num2 | num1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= MaxBytes;
vector += Half;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

43
src/ImageSharp/PixelFormats/IPixel.cs

@ -20,7 +20,7 @@ namespace ImageSharp.PixelFormats
/// This method is not intended to be consumed directly. Use <see cref="PixelOperations{TPixel}.Instance"/> instead.
/// </summary>
/// <returns>The <see cref="PixelOperations{TPixel}"/> instance.</returns>
PixelOperations<TSelf> CreateBulkOperations();
PixelOperations<TSelf> CreatePixelOperations();
}
/// <summary>
@ -42,44 +42,33 @@ namespace ImageSharp.PixelFormats
Vector4 ToVector4();
/// <summary>
/// Sets the packed representation from the given byte array.
/// Packs the pixel from an <see cref="Rgba32"/> value.
/// </summary>
/// <param name="x">The x-component.</param>
/// <param name="y">The y-component.</param>
/// <param name="z">The z-component.</param>
/// <param name="w">The w-component.</param>
void PackFromBytes(byte x, byte y, byte z, byte w);
/// <param name="source">The <see cref="Rgba32"/> value.</param>
void PackFromRgba32(Rgba32 source);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in <see cref="Rgba32"/>
/// Converts the pixel to <see cref="Rgb24"/> format.
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToXyzBytes(Span<byte> bytes, int startIndex);
/// <param name="dest">The destination pixel to write to</param>
void ToRgb24(ref Rgb24 dest);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in <see cref="Rgba32"/>
/// Converts the pixel to <see cref="Rgba32"/> format.
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToXyzwBytes(Span<byte> bytes, int startIndex);
/// <param name="dest">The destination pixel to write to</param>
void ToRgba32(ref Rgba32 dest);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in <see cref="Rgba32"/>
/// Converts the pixel to <see cref="Bgr24"/> format.
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToZyxBytes(Span<byte> bytes, int startIndex);
/// <param name="dest">The destination pixel to write to</param>
void ToBgr24(ref Bgr24 dest);
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in <see cref="Rgba32"/>
/// Converts the pixel to <see cref="Bgra32"/> format.
/// </summary>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
void ToZyxwBytes(Span<byte> bytes, int startIndex);
/// <param name="dest">The destination pixel to write to</param>
void ToBgra32(ref Bgra32 dest);
}
}

86
src/ImageSharp/PixelFormats/NormalizedByte2.cs

@ -91,7 +91,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<NormalizedByte2> CreateBulkOperations() => new PixelOperations<NormalizedByte2>();
public PixelOperations<NormalizedByte2> CreatePixelOperations() => new PixelOperations<NormalizedByte2>();
/// <summary>
/// Expands the packed representation into a <see cref="Vector2"/>.
@ -122,9 +122,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = new Vector4(x, y, z, w);
Vector4 vector = source.ToUnscaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@ -134,68 +134,44 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = 0;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = 255;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc />
@ -238,5 +214,17 @@ namespace ImageSharp.PixelFormats
return (ushort)(byte2 | byte1);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

86
src/ImageSharp/PixelFormats/NormalizedByte4.cs

@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<NormalizedByte4> CreateBulkOperations() => new PixelOperations<NormalizedByte4>();
public PixelOperations<NormalizedByte4> CreatePixelOperations() => new PixelOperations<NormalizedByte4>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -115,9 +115,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = new Vector4(x, y, z, w);
Vector4 vector = source.ToUnscaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@ -127,68 +127,44 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
@ -235,5 +211,17 @@ namespace ImageSharp.PixelFormats
return byte4 | byte3 | byte2 | byte1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

86
src/ImageSharp/PixelFormats/NormalizedShort2.cs

@ -91,7 +91,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<NormalizedShort2> CreateBulkOperations() => new PixelOperations<NormalizedShort2>();
public PixelOperations<NormalizedShort2> CreatePixelOperations() => new PixelOperations<NormalizedShort2>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -109,9 +109,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = new Vector4(x, y, z, w);
Vector4 vector = source.ToUnscaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@ -121,68 +121,44 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = 255;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
/// <summary>
@ -245,5 +221,17 @@ namespace ImageSharp.PixelFormats
return word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

86
src/ImageSharp/PixelFormats/NormalizedShort4.cs

@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<NormalizedShort4> CreateBulkOperations() => new PixelOperations<NormalizedShort4>();
public PixelOperations<NormalizedShort4> CreatePixelOperations() => new PixelOperations<NormalizedShort4>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -117,9 +117,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = new Vector4(x, y, z, w);
Vector4 vector = source.ToUnscaledVector4();
vector -= Round;
vector -= Half;
vector -= Round;
@ -129,68 +129,44 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
Vector4 vector = this.ToScaledVector4();
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 ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
Vector4 vector = this.ToScaledVector4();
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 />
@ -241,5 +217,17 @@ namespace ImageSharp.PixelFormats
return word4 | word3 | word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector *= Half;
vector += Round;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

76
src/ImageSharp/PixelFormats/PixelConversionExtensions.cs

@ -0,0 +1,76 @@
namespace ImageSharp.PixelFormats
{
using System;
using System.Runtime.CompilerServices;
/// <summary>
/// Extension methods for copying single pixel data into byte Spans.
/// TODO: This utility class exists for legacy reasons. Need to do a lot of chore work to remove it (mostly in test classes).
/// </summary>
internal static class PixelConversionExtensions
{
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in <see cref="Rgb24"/>
/// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="pixel">The pixel to copy the data from.</param>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToXyzBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex)
where TPixel : struct, IPixel<TPixel>
{
ref Rgb24 dest = ref bytes.GetRgb24(startIndex);
pixel.ToRgb24(ref dest);
}
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in <see cref="Rgba32"/>
/// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="pixel">The pixel to copy the data from.</param>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToXyzwBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex)
where TPixel : struct, IPixel<TPixel>
{
ref Rgba32 dest = ref Unsafe.As<byte, Rgba32>(ref bytes[startIndex]);
pixel.ToRgba32(ref dest);
}
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in <see cref="Bgr24"/>
/// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="pixel">The pixel to copy the data from.</param>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToZyxBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex)
where TPixel : struct, IPixel<TPixel>
{
ref Bgr24 dest = ref Unsafe.As<byte, Bgr24>(ref bytes[startIndex]);
pixel.ToBgr24(ref dest);
}
/// <summary>
/// Expands the packed representation into a given byte array.
/// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in <see cref="Bgra32"/>
/// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="pixel">The pixel to copy the data from.</param>
/// <param name="bytes">The bytes to set the color in.</param>
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToZyxwBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex)
where TPixel : struct, IPixel<TPixel>
{
ref Bgra32 dest = ref Unsafe.As<byte, Bgra32>(ref bytes[startIndex]);
pixel.ToBgra32(ref dest);
}
}
}

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

@ -20,7 +20,7 @@ namespace ImageSharp.PixelFormats
/// <summary>
/// Gets the global <see cref="PixelOperations{TPixel}"/> instance for the pixel type <typeparamref name="TPixel"/>
/// </summary>
public static PixelOperations<TPixel> Instance { get; } = default(TPixel).CreateBulkOperations();
public static PixelOperations<TPixel> Instance { get; } = default(TPixel).CreatePixelOperations();
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromVector4(Vector4)"/>
@ -30,8 +30,7 @@ namespace ImageSharp.PixelFormats
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromVector4(Span<Vector4> sourceVectors, Span<TPixel> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceVectors, count, nameof(sourceVectors));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
GuardSpans(sourceVectors, nameof(sourceVectors), destColors, nameof(destColors), count);
ref Vector4 sourceRef = ref sourceVectors.DangerousGetPinnableReference();
ref TPixel destRef = ref destColors.DangerousGetPinnableReference();
@ -52,8 +51,7 @@ namespace ImageSharp.PixelFormats
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToVector4(Span<TPixel> sourceColors, Span<Vector4> destVectors, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors));
GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count);
ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference();
ref Vector4 destRef = ref destVectors.DangerousGetPinnableReference();
@ -67,187 +65,25 @@ namespace ImageSharp.PixelFormats
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyz"/>.
/// Verifies that the given 'source' and 'dest' spans are at least of 'minLength' size.
/// Throwing an <see cref="ArgumentException"/> if the condition is not met.
/// </summary>
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromXyzBytes(Span<byte> sourceBytes, Span<TPixel> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference();
ref TPixel destRef = ref destColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
int i3 = i * 3;
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBytes(
Unsafe.Add(ref sourceRef, i3),
Unsafe.Add(ref sourceRef, i3 + 1),
Unsafe.Add(ref sourceRef, i3 + 2),
255);
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToXyzBytes(Span{byte}, int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToXyzBytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes));
ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
sp.ToXyzBytes(destBytes, i * 3);
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyzw"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromXyzwBytes(Span<byte> sourceBytes, Span<TPixel> destColors, int count)
/// <typeparam name="TSource">The source element type</typeparam>
/// <typeparam name="TDest">The destination element type</typeparam>
/// <param name="source">The source span</param>
/// <param name="sourceParamName">The source parameter name</param>
/// <param name="dest">The destination span</param>
/// <param name="destParamName">The destination parameter name</param>
/// <param name="minLength">The minimum length</param>
protected internal static void GuardSpans<TSource, TDest>(
Span<TSource> source,
string sourceParamName,
Span<TDest> dest,
string destParamName,
int minLength)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference();
ref TPixel destRef = ref destColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
int i4 = i * 4;
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBytes(
Unsafe.Add(ref sourceRef, i4),
Unsafe.Add(ref sourceRef, i4 + 1),
Unsafe.Add(ref sourceRef, i4 + 2),
Unsafe.Add(ref sourceRef, i4 + 3));
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToXyzwBytes(Span{byte}, int)"/>
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToXyzwBytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes));
ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
sp.ToXyzwBytes(destBytes, i * 4);
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Zyx"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromZyxBytes(Span<byte> sourceBytes, Span<TPixel> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference();
ref TPixel destRef = ref destColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
int i3 = i * 3;
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBytes(
Unsafe.Add(ref sourceRef, i3 + 2),
Unsafe.Add(ref sourceRef, i3 + 1),
Unsafe.Add(ref sourceRef, i3),
255);
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToZyxBytes(Span{byte}, int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToZyxBytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes));
ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
sp.ToZyxBytes(destBytes, i * 3);
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Zyxw"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="Span{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromZyxwBytes(Span<byte> sourceBytes, Span<TPixel> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
ref byte sourceRef = ref sourceBytes.DangerousGetPinnableReference();
ref TPixel destRef = ref destColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
int i4 = i * 4;
ref TPixel dp = ref Unsafe.Add(ref destRef, i);
dp.PackFromBytes(
Unsafe.Add(ref sourceRef, i4 + 2),
Unsafe.Add(ref sourceRef, i4 + 1),
Unsafe.Add(ref sourceRef, i4),
Unsafe.Add(ref sourceRef, i4 + 3));
}
}
/// <summary>
/// Bulk version of <see cref="IPixel.ToZyxwBytes(Span{byte}, int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void ToZyxwBytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes));
ref TPixel sourceRef = ref sourceColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
ref TPixel sp = ref Unsafe.Add(ref sourceRef, i);
sp.ToZyxwBytes(destBytes, i * 4);
}
Guard.MustBeSizedAtLeast(source, minLength, sourceParamName);
Guard.MustBeSizedAtLeast(dest, minLength, destParamName);
}
}
}

57
src/ImageSharp/PixelFormats/Rg32.cs

@ -76,7 +76,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Rg32> CreateBulkOperations() => new PixelOperations<Rg32>();
public PixelOperations<Rg32> CreatePixelOperations() => new PixelOperations<Rg32>();
/// <summary>
/// Expands the packed representation into a <see cref="Vector2"/>.
@ -107,55 +107,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / 255F);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)vector.X;
dest.G = (byte)vector.Y;
dest.B = (byte)vector.Z;
dest.A = (byte)vector.W;
}
/// <inheritdoc />
@ -197,5 +193,8 @@ namespace ImageSharp.PixelFormats
((int)Math.Round(x.Clamp(0, 1) * 65535F) & 0xFFFF) |
(((int)Math.Round(y.Clamp(0, 1) * 65535F) & 0xFFFF) << 16));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4() => this.ToVector4() * 255f;
}
}

132
src/ImageSharp/PixelFormats/Rgb24.cs

@ -0,0 +1,132 @@
// <copyright file="Rgb24.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.PixelFormats
{
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/// <summary>
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
/// The color components are stored in red, green, blue order.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct Rgb24 : IPixel<Rgb24>
{
/// <summary>
/// The red component.
/// </summary>
public byte R;
/// <summary>
/// The green component.
/// </summary>
public byte G;
/// <summary>
/// The blue component.
/// </summary>
public byte B;
/// <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)]
public Rgb24(byte r, byte g, byte b)
{
this.R = r;
this.G = g;
this.B = b;
}
/// <inheritdoc/>
public PixelOperations<Rgb24> CreatePixelOperations() => new PixelOperations<Rgb24>();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Rgb24 other)
{
return this.R == other.R && this.G == other.G && this.B == other.B;
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj?.GetType() == typeof(Rgb24) && this.Equals((Rgb24)obj);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode()
{
unchecked
{
int hashCode = this.R;
hashCode = (hashCode * 397) ^ this.G;
hashCode = (hashCode * 397) ^ this.B;
return hashCode;
}
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromRgba32(Rgba32 source)
{
this = Unsafe.As<Rgba32, Rgb24>(ref source);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromVector4(Vector4 vector)
{
var rgba = default(Rgba32);
rgba.PackFromVector4(vector);
this.PackFromRgba32(rgba);
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Rgba32(this.R, this.G, this.B, 255).ToVector4();
}
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToRgb24(ref Rgb24 dest)
{
dest = this;
}
/// <inheritdoc/>
public void ToRgba32(ref Rgba32 dest)
{
dest.Rgb = this;
dest.A = 255;
}
/// <inheritdoc/>
public void ToBgr24(ref Bgr24 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
}
/// <inheritdoc/>
public void ToBgra32(ref Bgra32 dest)
{
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = 255;
}
}
}

46
src/ImageSharp/PixelFormats/Rgba1010102.cs

@ -79,7 +79,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Rgba1010102> CreateBulkOperations() => new PixelOperations<Rgba1010102>();
public PixelOperations<Rgba1010102> CreatePixelOperations() => new PixelOperations<Rgba1010102>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -101,55 +101,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / 255F);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
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 ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
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 />

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

@ -21,7 +21,7 @@ namespace ImageSharp
/// <summary>
/// <see cref="PixelOperations{TPixel}"/> implementation optimized for <see cref="Rgba32"/>.
/// </summary>
internal class PixelOperations : PixelOperations<Rgba32>
internal partial class PixelOperations : PixelOperations<Rgba32>
{
/// <summary>
/// SIMD optimized bulk implementation of <see cref="IPixel.PackFromVector4(Vector4)"/>
@ -121,164 +121,19 @@ namespace ImageSharp
}
/// <inheritdoc />
internal override void PackFromXyzBytes(Span<byte> sourceBytes, Span<Rgba32> destColors, int count)
internal override void PackFromRgba32(Span<Rgba32> source, Span<Rgba32> destPixels, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
ref RGB24 sourceRef = ref Unsafe.As<byte, RGB24>(ref sourceBytes.DangerousGetPinnableReference());
ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference();
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;
}
}
/// <inheritdoc />
internal override void ToXyzBytes(Span<Rgba32> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes));
ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference();
ref RGB24 destRef = ref Unsafe.As<byte, RGB24>(ref destBytes.DangerousGetPinnableReference());
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);
}
}
/// <inheritdoc />
internal override unsafe void PackFromXyzwBytes(Span<byte> sourceBytes, Span<Rgba32> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
SpanHelper.Copy(sourceBytes, destColors.AsBytes(), count * sizeof(Rgba32));
SpanHelper.Copy(source, destPixels, count);
}
/// <inheritdoc />
internal override unsafe void ToXyzwBytes(Span<Rgba32> sourceColors, Span<byte> destBytes, int count)
internal override void ToRgba32(Span<Rgba32> sourcePixels, Span<Rgba32> dest, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes));
SpanHelper.Copy(sourceColors.AsBytes(), destBytes, count * sizeof(Rgba32));
}
/// <inheritdoc />
internal override void PackFromZyxBytes(Span<byte> sourceBytes, Span<Rgba32> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 3, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
ref RGB24 sourceRef = ref Unsafe.As<byte, RGB24>(ref sourceBytes.DangerousGetPinnableReference());
ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference();
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.ToZyx();
dp.A = 255;
}
}
/// <inheritdoc />
internal override void ToZyxBytes(Span<Rgba32> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 3, nameof(destBytes));
ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference();
ref RGB24 destRef = ref Unsafe.As<byte, RGB24>(ref destBytes.DangerousGetPinnableReference());
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);
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count);
dp = Unsafe.As<Rgba32, RGB24>(ref sp).ToZyx();
}
}
/// <inheritdoc />
internal override void PackFromZyxwBytes(Span<byte> sourceBytes, Span<Rgba32> destColors, int count)
{
Guard.MustBeSizedAtLeast(sourceBytes, count * 4, nameof(sourceBytes));
Guard.MustBeSizedAtLeast(destColors, count, nameof(destColors));
ref RGBA32 sourceRef = ref Unsafe.As<byte, RGBA32>(ref sourceBytes.DangerousGetPinnableReference());
ref Rgba32 destRef = ref destColors.DangerousGetPinnableReference();
for (int i = 0; i < count; i++)
{
ref RGBA32 sp = ref Unsafe.Add(ref sourceRef, i);
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
RGBA32 zyxw = sp.ToZyxw();
dp = Unsafe.As<RGBA32, Rgba32>(ref zyxw);
}
}
/// <inheritdoc />
internal override void ToZyxwBytes(Span<Rgba32> sourceColors, Span<byte> destBytes, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destBytes, count * 4, nameof(destBytes));
ref Rgba32 sourceRef = ref sourceColors.DangerousGetPinnableReference();
ref RGBA32 destRef = ref Unsafe.As<byte, RGBA32>(ref destBytes.DangerousGetPinnableReference());
for (int i = 0; i < count; i++)
{
ref RGBA32 sp = ref Unsafe.As<Rgba32, RGBA32>(ref Unsafe.Add(ref sourceRef, i));
ref RGBA32 dp = ref Unsafe.Add(ref destRef, i);
dp = sp.ToZyxw();
}
}
/// <summary>
/// Helper struct to manipulate 3-byte RGB data.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct RGB24
{
private byte x;
private byte y;
private byte z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public RGB24 ToZyx() => new RGB24 { x = this.z, y = this.y, z = this.x };
}
/// <summary>
/// Helper struct to manipulate 4-byte RGBA data.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct RGBA32
{
private byte x;
private byte y;
private byte z;
private byte w;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public RGBA32 ToZyxw() => new RGBA32 { x = this.z, y = this.y, z = this.x, w = this.w };
SpanHelper.Copy(sourcePixels, dest, count);
}
/// <summary>

169
src/ImageSharp/PixelFormats/Rgba32.cs

@ -23,39 +23,29 @@ namespace ImageSharp
/// 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.Explicit)]
[StructLayout(LayoutKind.Sequential)]
public partial struct Rgba32 : IPixel<Rgba32>, IPackedVector<uint>
{
/// <summary>
/// Gets or sets the red component.
/// </summary>
[FieldOffset(0)]
public byte R;
/// <summary>
/// Gets or sets the green component.
/// </summary>
[FieldOffset(1)]
public byte G;
/// <summary>
/// Gets or sets the blue component.
/// </summary>
[FieldOffset(2)]
public byte B;
/// <summary>
/// Gets or sets the alpha component.
/// </summary>
[FieldOffset(3)]
public byte A;
/// <summary>
/// The packed representation of the value.
/// </summary>
[FieldOffset(0)]
public uint Rgba;
/// <summary>
/// The shift count for the red component
/// </summary>
@ -86,6 +76,21 @@ namespace ImageSharp
/// </summary>
private static readonly Vector4 Half = new Vector4(0.5F);
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> 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)]
public Rgba32(byte r, byte g, byte b)
{
this.R = r;
this.G = g;
this.B = b;
this.A = 255;
}
/// <summary>
/// Initializes a new instance of the <see cref="Rgba32"/> struct.
/// </summary>
@ -94,8 +99,7 @@ namespace ImageSharp
/// <param name="b">The blue component.</param>
/// <param name="a">The alpha component.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Rgba32(byte r, byte g, byte b, byte a = 255)
: this()
public Rgba32(byte r, byte g, byte b, byte a)
{
this.R = r;
this.G = g;
@ -156,8 +160,68 @@ namespace ImageSharp
this.Rgba = packed;
}
/// <summary>
/// Gets or sets the packed representation of the Rgba32 struct.
/// </summary>
public uint Rgba
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return Unsafe.As<Rgba32, uint>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
Unsafe.As<Rgba32, uint>(ref this) = value;
}
}
/// <summary>
/// Gets or sets the RGB components of this struct as <see cref="Rgb24"/>
/// </summary>
public Rgb24 Rgb
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return Unsafe.As<Rgba32, Rgb24>(ref this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
Unsafe.As<Rgba32, Rgb24>(ref this) = value;
}
}
/// <summary>
/// Gets or sets the RGB components of this struct as <see cref="Bgr24"/> reverting the component order.
/// </summary>
public Bgr24 Bgr
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return new Bgr24(this.R, this.G, this.B);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
this.R = value.R;
this.G = value.G;
this.B = value.B;
}
}
/// <inheritdoc/>
public uint PackedValue { get => this.Rgba; set => this.Rgba = value; }
public uint PackedValue
{
get => this.Rgba;
set => this.Rgba = value;
}
/// <summary>
/// Compares two <see cref="Rgba32"/> objects for equality.
@ -207,16 +271,13 @@ namespace ImageSharp
}
/// <inheritdoc />
public PixelOperations<Rgba32> CreateBulkOperations() => new PixelOperations();
public PixelOperations<Rgba32> CreatePixelOperations() => new PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.R = x;
this.G = y;
this.B = z;
this.A = w;
this = source;
}
/// <summary>
@ -229,42 +290,37 @@ namespace ImageSharp
return hexOrder.ToString("X8");
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
dest = Unsafe.As<Rgba32, Rgb24>(ref this);
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
bytes[startIndex] = this.R;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.B;
bytes[startIndex + 3] = this.A;
dest = this;
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
bytes[startIndex] = this.B;
bytes[startIndex + 1] = this.G;
bytes[startIndex + 2] = this.R;
bytes[startIndex + 3] = this.A;
dest.R = this.R;
dest.G = this.G;
dest.B = this.B;
dest.A = this.A;
}
/// <inheritdoc/>
@ -281,6 +337,17 @@ namespace ImageSharp
return 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()
{
return new Bgra32(this.R, this.G, this.B, this.A);
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
@ -308,14 +375,24 @@ namespace ImageSharp
{
unchecked
{
int hashCode = this.R.GetHashCode();
hashCode = (hashCode * 397) ^ this.G.GetHashCode();
hashCode = (hashCode * 397) ^ this.B.GetHashCode();
hashCode = (hashCode * 397) ^ this.A.GetHashCode();
int hashCode = this.R;
hashCode = (hashCode * 397) ^ this.G;
hashCode = (hashCode * 397) ^ this.B;
hashCode = (hashCode * 397) ^ this.A;
return hashCode;
}
}
/// <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 ToUnscaledVector4()
{
return new Vector4(this.R, this.G, this.B, this.A);
}
/// <summary>
/// Packs the four floats into a <see cref="uint"/>.
/// </summary>

46
src/ImageSharp/PixelFormats/Rgba64.cs

@ -78,7 +78,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Rgba64> CreateBulkOperations() => new PixelOperations<Rgba64>();
public PixelOperations<Rgba64> CreatePixelOperations() => new PixelOperations<Rgba64>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -100,55 +100,51 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.PackFromVector4(new Vector4(x, y, z, w) / 255F);
this.PackFromVector4(source.ToVector4());
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
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 ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4() * 255F;
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
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 />

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

@ -23,10 +23,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
internal override unsafe void ToVector4(Span<RgbaVector> sourceColors, Span<Vector4> destVectors, int count)
{
Guard.MustBeSizedAtLeast(sourceColors, count, nameof(sourceColors));
Guard.MustBeSizedAtLeast(destVectors, count, nameof(destVectors));
GuardSpans(sourceColors, nameof(sourceColors), destVectors, nameof(destVectors), count);
SpanHelper.Copy(sourceColors.AsBytes(), destVectors.AsBytes(), count * sizeof(Vector4));
SpanHelper.Copy(sourceColors.NonPortableCast<RgbaVector, Vector4>(), destVectors, count);
}
}
}

65
src/ImageSharp/PixelFormats/RgbaVector.cs

@ -211,13 +211,13 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<RgbaVector> CreateBulkOperations() => new RgbaVector.PixelOperations();
public PixelOperations<RgbaVector> CreatePixelOperations() => new RgbaVector.PixelOperations();
/// <inheritdoc/>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
this.backingVector = new Vector4(x, y, z, w) / MaxBytes;
this.backingVector = source.ToVector4();
}
/// <summary>
@ -233,50 +233,46 @@ namespace ImageSharp.PixelFormats
return hexOrder.ToString("X8");
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes;
vector += Half;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes;
vector += Half;
bytes[startIndex] = (byte)vector.X;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.Z;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
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/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes;
vector += Half;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc/>
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes;
vector += Half;
bytes[startIndex] = (byte)vector.Z;
bytes[startIndex + 1] = (byte)vector.Y;
bytes[startIndex + 2] = (byte)vector.X;
bytes[startIndex + 3] = (byte)vector.W;
Vector4 vector = this.ToScaledVector4();
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/>
@ -320,5 +316,8 @@ namespace ImageSharp.PixelFormats
{
return this.backingVector.GetHashCode();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4() => Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One) * MaxBytes;
}
}

86
src/ImageSharp/PixelFormats/Short2.cs

@ -91,7 +91,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Short2> CreateBulkOperations() => new PixelOperations<Short2>();
public PixelOperations<Short2> CreatePixelOperations() => new PixelOperations<Short2>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -109,9 +109,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
Vector2 vector = new Vector2(x, y) / 255;
Vector2 vector = new Vector2(source.R, source.G) / 255;
vector *= 65534;
vector -= new Vector2(32767);
this.PackedValue = Pack(vector.X, vector.Y);
@ -119,68 +119,44 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
Vector2 vector = this.ToScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = 0;
bytes[startIndex + 3] = 255;
Vector2 vector = this.ToScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
Vector2 vector = this.ToScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
bytes[startIndex] = 0;
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = 255;
Vector2 vector = this.ToScaledVector2();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = 0;
dest.A = 255;
}
/// <summary>
@ -239,5 +215,17 @@ namespace ImageSharp.PixelFormats
return word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector2 ToScaledVector2()
{
Vector2 vector = this.ToVector2();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector2.Clamp(vector, Vector2.Zero, MaxBytes);
return vector;
}
}
}

86
src/ImageSharp/PixelFormats/Short4.cs

@ -93,7 +93,7 @@ namespace ImageSharp.PixelFormats
}
/// <inheritdoc />
public PixelOperations<Short4> CreateBulkOperations() => new PixelOperations<Short4>();
public PixelOperations<Short4> CreatePixelOperations() => new PixelOperations<Short4>();
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -115,9 +115,9 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void PackFromBytes(byte x, byte y, byte z, byte w)
public void PackFromRgba32(Rgba32 source)
{
Vector4 vector = new Vector4(x, y, z, w) / 255;
Vector4 vector = source.ToVector4();
vector *= 65534;
vector -= new Vector4(32767);
this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
@ -125,68 +125,44 @@ namespace ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzBytes(Span<byte> bytes, int startIndex)
public void ToRgb24(ref Rgb24 dest)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToXyzwBytes(Span<byte> bytes, int startIndex)
public void ToRgba32(ref Rgba32 dest)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.X);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
Vector4 vector = this.ToScaledVector4();
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 ToZyxBytes(Span<byte> bytes, int startIndex)
public void ToBgr24(ref Bgr24 dest)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
Vector4 vector = this.ToScaledVector4();
dest.R = (byte)MathF.Round(vector.X);
dest.G = (byte)MathF.Round(vector.Y);
dest.B = (byte)MathF.Round(vector.Z);
}
/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ToZyxwBytes(Span<byte> bytes, int startIndex)
public void ToBgra32(ref Bgra32 dest)
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
bytes[startIndex] = (byte)MathF.Round(vector.Z);
bytes[startIndex + 1] = (byte)MathF.Round(vector.Y);
bytes[startIndex + 2] = (byte)MathF.Round(vector.X);
bytes[startIndex + 3] = (byte)MathF.Round(vector.W);
Vector4 vector = this.ToScaledVector4();
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 />
@ -246,5 +222,17 @@ namespace ImageSharp.PixelFormats
return word4 | word3 | word2 | word1;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Vector4 ToScaledVector4()
{
Vector4 vector = this.ToVector4();
vector /= 65534;
vector *= 255;
vector += Half;
vector += Round;
vector = Vector4.Clamp(vector, Vector4.Zero, MaxBytes);
return vector;
}
}
}

2
src/ImageSharp/Quantizers/OctreeQuantizer{TPixel}.cs

@ -499,7 +499,7 @@ namespace ImageSharp.Quantizers
// And set the color of the palette entry
var pixel = default(TPixel);
pixel.PackFromBytes(r, g, b, 255);
pixel.PackFromRgba32(new Rgba32(r, g, b, 255));
palette[index] = pixel;
// Consume the next palette index

14
src/ImageSharp/Quantizers/PaletteQuantizer{TPixel}.cs

@ -18,11 +18,6 @@ namespace ImageSharp.Quantizers
public sealed class PaletteQuantizer<TPixel> : Quantizer<TPixel>
where TPixel : struct, IPixel<TPixel>
{
/// <summary>
/// The pixel buffer, used to reduce allocations.
/// </summary>
private readonly byte[] pixelBuffer = new byte[4];
/// <summary>
/// A lookup table for colors
/// </summary>
@ -48,14 +43,9 @@ namespace ImageSharp.Quantizers
Rgba32[] constants = ColorConstants.WebSafeColors;
TPixel[] safe = new TPixel[constants.Length + 1];
for (int i = 0; i < constants.Length; i++)
{
constants[i].ToXyzwBytes(this.pixelBuffer, 0);
var packed = default(TPixel);
packed.PackFromBytes(this.pixelBuffer[0], this.pixelBuffer[1], this.pixelBuffer[2], this.pixelBuffer[3]);
safe[i] = packed;
}
Span<byte> constantsBytes = constants.AsSpan().NonPortableCast<Rgba32, byte>();
PixelOperations<TPixel>.Instance.PackFromRgba32Bytes(constantsBytes, safe, constants.Length);
this.colors = safe;
}
else

6
tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs

@ -40,7 +40,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk
{
int i4 = i * 4;
TPixel c = default(TPixel);
c.PackFromBytes(s[i4], s[i4 + 1], s[i4 + 2], s[i4 + 3]);
c.PackFromRgba32(new Rgba32(s[i4], s[i4 + 1], s[i4 + 2], s[i4 + 3]));
d[i] = c;
}
}
@ -48,13 +48,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk
[Benchmark]
public void CommonBulk()
{
new PixelOperations<TPixel>().PackFromXyzwBytes(this.source, this.destination, this.Count);
new PixelOperations<TPixel>().PackFromRgba32Bytes(this.source, this.destination, this.Count);
}
[Benchmark]
public void OptimizedBulk()
{
PixelOperations<TPixel>.Instance.PackFromXyzwBytes(this.source, this.destination, this.Count);
PixelOperations<TPixel>.Instance.PackFromRgba32Bytes(this.source, this.destination, this.Count);
}
}

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

@ -46,13 +46,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk
[Benchmark]
public void CommonBulk()
{
new PixelOperations<TPixel>().ToXyzBytes(this.source, this.destination, this.Count);
new PixelOperations<TPixel>().ToRgb24Bytes(this.source, this.destination, this.Count);
}
[Benchmark]
public void OptimizedBulk()
{
PixelOperations<TPixel>.Instance.ToXyzBytes(this.source, this.destination, this.Count);
PixelOperations<TPixel>.Instance.ToRgb24Bytes(this.source, this.destination, this.Count);
}
}

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

@ -51,13 +51,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk
[Benchmark]
public void CommonBulk()
{
new PixelOperations<TPixel>().ToXyzwBytes(this.source, this.destination, this.Count);
new PixelOperations<TPixel>().ToRgba32Bytes(this.source, this.destination, this.Count);
}
[Benchmark]
public void OptimizedBulk()
{
PixelOperations<TPixel>.Instance.ToXyzwBytes(this.source, this.destination, this.Count);
PixelOperations<TPixel>.Instance.ToRgba32Bytes(this.source, this.destination, this.Count);
}
}

206
tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromRgba32.cs

@ -0,0 +1,206 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Benchmarks.General
{
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
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>
{
private T[] dest;
private Rgba32[] source;
public ConversionRunner(int count)
{
this.dest = new T[count];
this.source = new Rgba32[count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunByRefConversion()
{
int count = this.dest.Length;
ref T destBaseRef = ref this.dest[0];
ref Rgba32 sourceBaseRef = ref this.source[0];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref destBaseRef, i).FromRgba32(ref Unsafe.Add(ref sourceBaseRef, i));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunByValConversion()
{
int count = this.dest.Length;
ref T destBaseRef = ref this.dest[0];
ref Rgba32 sourceBaseRef = ref this.source[0];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref destBaseRef, i).FromRgba32(Unsafe.Add(ref sourceBaseRef, i));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunFromBytesConversion()
{
int count = this.dest.Length;
ref T destBaseRef = ref this.dest[0];
ref Rgba32 sourceBaseRef = ref this.source[0];
for (int i = 0; i < count; i++)
{
ref Rgba32 s = ref Unsafe.Add(ref sourceBaseRef, i);
Unsafe.Add(ref destBaseRef, i).FromBytes(s.R, s.G, s.B, s.A);
}
}
}
private ConversionRunner<TestRgba> compatibleMemLayoutRunner;
private ConversionRunner<TestArgb> permutedRunner;
[Params(32)]
public int Count { get; set; }
[Setup]
public void Setup()
{
this.compatibleMemLayoutRunner = new ConversionRunner<TestRgba>(this.Count);
this.permutedRunner = new ConversionRunner<TestArgb>(this.Count);
}
[Benchmark(Baseline = true)]
public void CompatibleByRef()
{
this.compatibleMemLayoutRunner.RunByRefConversion();
}
[Benchmark]
public void CompatibleByVal()
{
this.compatibleMemLayoutRunner.RunByValConversion();
}
[Benchmark]
public void CompatibleFromBytes()
{
this.compatibleMemLayoutRunner.RunFromBytesConversion();
}
[Benchmark]
public void PermutedByRef()
{
this.permutedRunner.RunByRefConversion();
}
[Benchmark]
public void PermutedByVal()
{
this.permutedRunner.RunByValConversion();
}
[Benchmark]
public void PermutedFromBytes()
{
this.permutedRunner.RunFromBytesConversion();
}
}
/*
* Results:
* Method | Count | Mean | StdDev | Scaled | Scaled-StdDev |
* ------------------ |------ |----------- |---------- |------- |-------------- |
* CompatibleByRef | 32 | 20.6339 ns | 0.0742 ns | 1.00 | 0.00 |
* CompatibleByVal | 32 | 23.7425 ns | 0.0997 ns | 1.15 | 0.01 |
* CompatibleFromBytes | 32 | 38.7017 ns | 0.1103 ns | 1.88 | 0.01 |
* PermutedByRef | 32 | 39.2892 ns | 0.1366 ns | 1.90 | 0.01 |
* PermutedByVal | 32 | 38.5178 ns | 0.1946 ns | 1.87 | 0.01 |
* PermutedFromBytes | 32 | 38.6683 ns | 0.0801 ns | 1.87 | 0.01 |
*
* !!! Conclusion !!!
* All memory-incompatible (permuted) variants are equivalent with the the "FromBytes" solution.
* In memory compatible cases we should use the optimized Bulk-copying variant anyways,
* so there is no benefit introducing non-bulk API-s other than PackFromBytes() OR PackFromRgba32().
*/
}

156
tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertFromVector4.cs

@ -0,0 +1,156 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Benchmarks.General
{
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
public class PixelConversion_ConvertFromVector4
{
interface ITestPixel<T>
where T : struct, ITestPixel<T>
{
void FromVector4(Vector4 source);
void FromVector4(ref Vector4 source);
}
[StructLayout(LayoutKind.Sequential)]
struct TestArgb : ITestPixel<TestArgb>
{
private byte a, r, g, b;
[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;
}
}
[StructLayout(LayoutKind.Sequential)]
struct TestRgbaVector : ITestPixel<TestRgbaVector>
{
private Vector4 v;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(Vector4 p)
{
this.v = p;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FromVector4(ref Vector4 p)
{
this.v = p;
}
}
struct ConversionRunner<T>
where T : struct, ITestPixel<T>
{
private T[] dest;
private Vector4[] source;
public ConversionRunner(int count)
{
this.dest = new T[count];
this.source = new Vector4[count];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunByRefConversion()
{
int count = this.dest.Length;
ref T destBaseRef = ref this.dest[0];
ref Vector4 sourceBaseRef = ref this.source[0];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref destBaseRef, i).FromVector4(ref Unsafe.Add(ref sourceBaseRef, i));
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RunByValConversion()
{
int count = this.dest.Length;
ref T destBaseRef = ref this.dest[0];
ref Vector4 sourceBaseRef = ref this.source[0];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref destBaseRef, i).FromVector4(Unsafe.Add(ref sourceBaseRef, i));
}
}
}
private ConversionRunner<TestArgb> nonVectorRunner;
private ConversionRunner<TestRgbaVector> vectorRunner;
[Params(32)]
public int Count { get; set; }
[Setup]
public void Setup()
{
this.nonVectorRunner = new ConversionRunner<TestArgb>(this.Count);
this.vectorRunner = new ConversionRunner<TestRgbaVector>(this.Count);
}
[Benchmark(Baseline = true)]
public void VectorByRef()
{
this.vectorRunner.RunByRefConversion();
}
[Benchmark]
public void VectorByVal()
{
this.vectorRunner.RunByValConversion();
}
[Benchmark]
public void NonVectorByRef()
{
this.nonVectorRunner.RunByRefConversion();
}
[Benchmark]
public void NonVectorByVal()
{
this.nonVectorRunner.RunByValConversion();
}
}
/*
* Results:
* Method | Count | Mean | StdDev | Scaled | Scaled-StdDev |
* --------------- |------ |----------- |---------- |------- |-------------- |
* VectorByRef | 32 | 23.6678 ns | 0.1141 ns | 1.00 | 0.00 |
* VectorByVal | 32 | 24.5347 ns | 0.0771 ns | 1.04 | 0.01 |
* NonVectorByRef | 32 | 59.0187 ns | 0.2114 ns | 2.49 | 0.01 |
* NonVectorByVal | 32 | 58.7529 ns | 0.2545 ns | 2.48 | 0.02 |
*
* !!! Conclusion !!!
* We do not need by-ref version of ConvertFromVector4() stuff
*/
}

156
tests/ImageSharp.Benchmarks/General/PixelConversion_ConvertToRgba32.cs

@ -0,0 +1,156 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Benchmarks.General
{
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
/// <summary>
/// When implementing TPixel --> Rgba32 style conversions on IPixel, should which API should we prefer?
/// 1. Rgba32 ToRgba32();
/// OR
/// 2. void CopyToRgba32(ref Rgba32 dest);
/// ?
/// </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>
{
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];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref destBaseRef, i) = Unsafe.Add(ref sourceBaseRef, i).ToRgba32();
}
}
[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];
for (int i = 0; i < count; i++)
{
Unsafe.Add(ref sourceBaseRef, i).CopyToRgba32(ref Unsafe.Add(ref destBaseRef, i));
}
}
}
private ConversionRunner<TestRgba> compatibleMemoryLayoutRunner;
private ConversionRunner<TestArgb> permutedRunner;
[Params(128)]
public int Count { get; set; }
[Setup]
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 | StdDev | Scaled | Scaled-StdDev |
* --------------- |------ |------------ |---------- |------- |-------------- |
* CompatibleRetval | 128 | 89.7358 ns | 2.2389 ns | 1.00 | 0.00 |
* CompatibleCopyTo | 128 | 89.4112 ns | 2.2901 ns | 1.00 | 0.03 |
* PermutedRetval | 128 | 845.4038 ns | 5.6154 ns | 9.43 | 0.23 |
* PermutedCopyTo | 128 | 155.6004 ns | 3.8870 ns | 1.73 | 0.06 |
*/
}

2
tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj

@ -17,8 +17,8 @@
</ItemGroup>
<ItemGroup>
<!--<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />-->
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="Moq" Version="4.7.1" />
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
<!--<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />-->
</ItemGroup>
<ItemGroup>

1
tests/ImageSharp.Sandbox46/Program.cs

@ -10,6 +10,7 @@ namespace ImageSharp.Sandbox46
using ImageSharp.Tests;
using ImageSharp.Tests.Colors;
using ImageSharp.Tests.PixelFormats;
using ImageSharp.Tests.Processing.Transforms;
using Xunit.Abstractions;

4
tests/ImageSharp.Tests/PixelFormats/PixelOperations.cs → tests/ImageSharp.Sandbox46/Tests/PixelFormats/PixelBlenderTests.cs

@ -15,7 +15,7 @@ namespace ImageSharp.Tests.PixelFormats
public class PixelOperations
{
public static TheoryData<object, Type, PixelBlenderMode> blenderMappings = new TheoryData<object, Type, PixelBlenderMode>()
public static TheoryData<object, Type, PixelBlenderMode> BlenderMappings = new TheoryData<object, Type, PixelBlenderMode>()
{
{ new TestPixel<Rgba32>(), typeof(DefaultNormalPixelBlender<Rgba32>), PixelBlenderMode.Normal },
{ new TestPixel<Rgba32>(), typeof(DefaultScreenPixelBlender<Rgba32>), PixelBlenderMode.Screen },
@ -39,7 +39,7 @@ namespace ImageSharp.Tests.PixelFormats
};
[Theory]
[MemberData(nameof(blenderMappings))]
[MemberData(nameof(BlenderMappings))]
public void ReturnsCorrectBlender<TPixel>(TestPixel<TPixel> pixel, Type type, PixelBlenderMode mode)
where TPixel : struct, IPixel<TPixel>
{

2
tests/ImageSharp.Tests/Common/BufferTests.cs

@ -163,7 +163,7 @@ namespace ImageSharp.Tests.Common
// Assert.Equal(buffer.Array, span.ToArray());
// Assert.Equal(0, span.Start);
Assert.SpanPointsTo(span, buffer);
Assert.Equal(span.Length, 42);
Assert.Equal(42, span.Length);
}
}

2
tests/ImageSharp.Tests/Common/ConstantsTests.cs

@ -12,7 +12,7 @@ namespace ImageSharp.Tests.Common
[Fact]
public void Epsilon()
{
Assert.Equal(Constants.Epsilon, 0.001f);
Assert.Equal(0.001f, Constants.Epsilon);
}
}
}

4
tests/ImageSharp.Tests/Drawing/Text/TextGraphicsOptionsTests.cs

@ -22,7 +22,7 @@ namespace ImageSharp.Tests.Drawing.Text
TextGraphicsOptions textOptions = opt;
Assert.Equal(false, textOptions.Antialias);
Assert.False(textOptions.Antialias);
Assert.Equal(99, textOptions.AntialiasSubpixelDepth);
}
@ -36,7 +36,7 @@ namespace ImageSharp.Tests.Drawing.Text
GraphicsOptions opt = (GraphicsOptions)textOptions;
Assert.Equal(false, opt.Antialias);
Assert.False(opt.Antialias);
Assert.Equal(99, opt.AntialiasSubpixelDepth);
}
}

10
tests/ImageSharp.Tests/Formats/Jpg/JpegProfilingBenchmarks.cs

@ -34,7 +34,7 @@ namespace ImageSharp.Tests
};
// [Theory] // Benchmark, enable manually
[MemberData(nameof(DecodeJpegData))]
// [MemberData(nameof(DecodeJpegData))]
public void DecodeJpeg(string fileName)
{
const int ExecutionCount = 30;
@ -60,10 +60,10 @@ namespace ImageSharp.Tests
// Benchmark, enable manually!
// [Theory]
[InlineData(1, 75, JpegSubsample.Ratio420)]
[InlineData(30, 75, JpegSubsample.Ratio420)]
[InlineData(30, 75, JpegSubsample.Ratio444)]
[InlineData(30, 100, JpegSubsample.Ratio444)]
// [InlineData(1, 75, JpegSubsample.Ratio420)]
// [InlineData(30, 75, JpegSubsample.Ratio420)]
// [InlineData(30, 75, JpegSubsample.Ratio444)]
// [InlineData(30, 100, JpegSubsample.Ratio444)]
public void EncodeJpeg(int executionCount, int quality, JpegSubsample subsample)
{
string[] testFiles = TestImages.Bmp.All

20
tests/ImageSharp.Tests/Formats/Jpg/YCbCrImageTests.cs

@ -19,11 +19,6 @@ namespace ImageSharp.Tests
private ITestOutputHelper Output { get; }
private void PrintChannel(string name, JpegPixelArea channel)
{
this.Output.WriteLine($"{name}: Stride={channel.Stride}");
}
[Theory]
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio410, 4, 2)]
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio411, 4, 1)]
@ -31,7 +26,10 @@ namespace ImageSharp.Tests
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio422, 2, 1)]
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio440, 1, 2)]
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444, 1, 1)]
public void CalculateChrominanceSize(int ratioValue, int expectedDivX, int expectedDivY)
internal void CalculateChrominanceSize(
YCbCrImage.YCbCrSubsampleRatio ratioValue,
int expectedDivX,
int expectedDivY)
{
YCbCrImage.YCbCrSubsampleRatio ratio = (YCbCrImage.YCbCrSubsampleRatio)ratioValue;
@ -39,7 +37,7 @@ namespace ImageSharp.Tests
Size size = YCbCrImage.CalculateChrominanceSize(400, 400, ratio);
//this.Output.WriteLine($"Ch Size: {size}");
Assert.Equal(new Size(400/expectedDivX, 400/expectedDivY), size);
Assert.Equal(new Size(400 / expectedDivX, 400 / expectedDivY), size);
}
[Theory]
@ -49,7 +47,7 @@ namespace ImageSharp.Tests
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio422, 2)]
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio440, 1)]
[InlineData(YCbCrImage.YCbCrSubsampleRatio.YCbCrSubsampleRatio444, 1)]
public void Create(int ratioValue, int expectedCStrideDiv)
internal void Create(YCbCrImage.YCbCrSubsampleRatio ratioValue, int expectedCStrideDiv)
{
YCbCrImage.YCbCrSubsampleRatio ratio = (YCbCrImage.YCbCrSubsampleRatio)ratioValue;
@ -61,10 +59,14 @@ namespace ImageSharp.Tests
//this.PrintChannel("Cb", img.CbChannel);
//this.PrintChannel("Cr", img.CrChannel);
Assert.Equal(img.YChannel.Width, 400);
Assert.Equal(400, img.YChannel.Width);
Assert.Equal(img.CbChannel.Width, 400 / expectedCStrideDiv);
Assert.Equal(img.CrChannel.Width, 400 / expectedCStrideDiv);
}
private void PrintChannel(string name, JpegPixelArea channel)
{
this.Output.WriteLine($"{name}: Stride={channel.Stride}");
}
}
}

12
tests/ImageSharp.Tests/IO/BigEndianBitConverter.ToTypeTests.cs

@ -56,13 +56,13 @@ namespace ImageSharp.Tests.IO
[Fact]
public void ToBoolean()
{
Assert.Equal(false, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0));
Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0));
Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0));
Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0 }, 0));
Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1 }, 0));
Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 42 }, 0));
Assert.Equal(false, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1));
Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1));
Assert.Equal(true, EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1));
Assert.False(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1));
Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1));
Assert.True(EndianBitConverter.BigEndianConverter.ToBoolean(new byte[] { 0, 42 }, 1));
}
/// <summary>

8
tests/ImageSharp.Tests/IO/LittleEndianBitConverter.ToTypeTests.cs

@ -56,11 +56,11 @@ namespace ImageSharp.Tests.IO
[Fact]
public void ToBoolean()
{
Assert.Equal(false, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0));
Assert.Equal(true, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0));
Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0 }, 0));
Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1 }, 0));
Assert.Equal(false, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1));
Assert.Equal(true, EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1));
Assert.False(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 1, 0 }, 1));
Assert.True(EndianBitConverter.LittleEndianConverter.ToBoolean(new byte[] { 0, 1 }, 1));
}
/// <summary>

4
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -7,12 +7,12 @@
<DebugSymbols>True</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<None Include="PixelFormats\PixelOperations.cs" />
<None Include="PixelFormats\PixelOperationsTests.Blender.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="Moq" Version="4.7.1" />
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
</ItemGroup>
<ItemGroup>

6
tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs

@ -25,7 +25,7 @@ namespace ImageSharp.Tests
Assert.Equal(property1, property2);
Assert.True(property1 == property2);
Assert.Equal(property3, null);
Assert.Null(property3);
}
/// <summary>
@ -41,7 +41,7 @@ namespace ImageSharp.Tests
Assert.False(property1.Equals("Foo"));
Assert.NotEqual(property1, null);
Assert.NotNull(property1);
Assert.NotEqual(property1, property2);
Assert.True(property1 != property2);
@ -69,7 +69,7 @@ namespace ImageSharp.Tests
{
ImageProperty property = new ImageProperty("Foo", null);
Assert.Equal("Foo", property.Name);
Assert.Equal(null, property.Value);
Assert.Null(property.Value);
property = new ImageProperty("Foo", string.Empty);
Assert.Equal(string.Empty, property.Value);

2
tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs

@ -44,7 +44,7 @@ namespace ImageSharp.Tests
Assert.Equal(ExifDataType.Ascii, value.DataType);
Assert.Equal(ExifTag.GPSDOP, value.Tag);
Assert.Equal(false, value.IsArray);
Assert.False(value.IsArray);
Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.ToString());
Assert.Equal("Windows Photo Editor 10.0.10011.16384", value.Value);
}

202
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs

@ -10,10 +10,12 @@ namespace ImageSharp.Tests.Icc
public class IccDataReaderTagDataEntryTests
{
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UnknownTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UnknownTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUnknownTagDataEntry(byte[] data, IccUnknownTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUnknownTagDataEntry output = reader.ReadUnknownTagDataEntry(size);
@ -21,10 +23,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ChromaticityTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ChromaticityTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadChromaticityTagDataEntry(byte[] data, IccChromaticityTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccChromaticityTagDataEntry output = reader.ReadChromaticityTagDataEntry();
@ -32,10 +36,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ColorantOrderTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ColorantOrderTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadColorantOrderTagDataEntry(byte[] data, IccColorantOrderTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccColorantOrderTagDataEntry output = reader.ReadColorantOrderTagDataEntry();
@ -43,10 +49,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ColorantTableTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ColorantTableTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadColorantTableTagDataEntry(byte[] data, IccColorantTableTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccColorantTableTagDataEntry output = reader.ReadColorantTableTagDataEntry();
@ -54,10 +62,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.CurveTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.CurveTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadCurveTagDataEntry(byte[] data, IccCurveTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccCurveTagDataEntry output = reader.ReadCurveTagDataEntry();
@ -65,10 +75,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.DataTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.DataTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadDataTagDataEntry(byte[] data, IccDataTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccDataTagDataEntry output = reader.ReadDataTagDataEntry(size);
@ -76,10 +88,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.DateTimeTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.DateTimeTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadDateTimeTagDataEntry(byte[] data, IccDateTimeTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccDateTimeTagDataEntry output = reader.ReadDateTimeTagDataEntry();
@ -87,10 +101,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.Lut16TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.Lut16TagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadLut16TagDataEntry(byte[] data, IccLut16TagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccLut16TagDataEntry output = reader.ReadLut16TagDataEntry();
@ -98,10 +114,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.Lut8TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.Lut8TagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadLut8TagDataEntry(byte[] data, IccLut8TagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccLut8TagDataEntry output = reader.ReadLut8TagDataEntry();
@ -109,10 +127,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.LutAToBTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.LutAToBTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadLutAToBTagDataEntry(byte[] data, IccLutAToBTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccLutAToBTagDataEntry output = reader.ReadLutAtoBTagDataEntry();
@ -120,10 +140,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.LutBToATagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.LutBToATagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadLutBToATagDataEntry(byte[] data, IccLutBToATagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccLutBToATagDataEntry output = reader.ReadLutBtoATagDataEntry();
@ -131,10 +153,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.MeasurementTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.MeasurementTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadMeasurementTagDataEntry(byte[] data, IccMeasurementTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccMeasurementTagDataEntry output = reader.ReadMeasurementTagDataEntry();
@ -142,10 +166,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadMultiLocalizedUnicodeTagDataEntry(byte[] data, IccMultiLocalizedUnicodeTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccMultiLocalizedUnicodeTagDataEntry output = reader.ReadMultiLocalizedUnicodeTagDataEntry();
@ -153,10 +179,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.MultiProcessElementsTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.MultiProcessElementsTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadMultiProcessElementsTagDataEntry(byte[] data, IccMultiProcessElementsTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccMultiProcessElementsTagDataEntry output = reader.ReadMultiProcessElementsTagDataEntry();
@ -164,10 +192,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.NamedColor2TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.NamedColor2TagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadNamedColor2TagDataEntry(byte[] data, IccNamedColor2TagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccNamedColor2TagDataEntry output = reader.ReadNamedColor2TagDataEntry();
@ -175,10 +205,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ParametricCurveTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ParametricCurveTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadParametricCurveTagDataEntry(byte[] data, IccParametricCurveTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccParametricCurveTagDataEntry output = reader.ReadParametricCurveTagDataEntry();
@ -186,10 +218,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ProfileSequenceDescTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ProfileSequenceDescTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadProfileSequenceDescTagDataEntry(byte[] data, IccProfileSequenceDescTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccProfileSequenceDescTagDataEntry output = reader.ReadProfileSequenceDescTagDataEntry();
@ -197,10 +231,14 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ProfileSequenceIdentifierTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadProfileSequenceIdentifierTagDataEntry(byte[] data, IccProfileSequenceIdentifierTagDataEntry expected)
[MemberData(
nameof(IccTestDataTagDataEntry.ProfileSequenceIdentifierTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadProfileSequenceIdentifierTagDataEntry(
byte[] data,
IccProfileSequenceIdentifierTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccProfileSequenceIdentifierTagDataEntry output = reader.ReadProfileSequenceIdentifierTagDataEntry();
@ -208,10 +246,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ResponseCurveSet16TagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ResponseCurveSet16TagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadResponseCurveSet16TagDataEntry(byte[] data, IccResponseCurveSet16TagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccResponseCurveSet16TagDataEntry output = reader.ReadResponseCurveSet16TagDataEntry();
@ -219,10 +259,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.Fix16ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.Fix16ArrayTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadFix16ArrayTagDataEntry(byte[] data, IccFix16ArrayTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccFix16ArrayTagDataEntry output = reader.ReadFix16ArrayTagDataEntry(size);
@ -230,10 +272,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.SignatureTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.SignatureTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadSignatureTagDataEntry(byte[] data, IccSignatureTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccSignatureTagDataEntry output = reader.ReadSignatureTagDataEntry();
@ -241,10 +285,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.TextTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.TextTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadTextTagDataEntry(byte[] data, IccTextTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccTextTagDataEntry output = reader.ReadTextTagDataEntry(size);
@ -252,10 +298,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UFix16ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UFix16ArrayTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUFix16ArrayTagDataEntry(byte[] data, IccUFix16ArrayTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUFix16ArrayTagDataEntry output = reader.ReadUFix16ArrayTagDataEntry(size);
@ -263,10 +311,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UInt16ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UInt16ArrayTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUInt16ArrayTagDataEntry(byte[] data, IccUInt16ArrayTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUInt16ArrayTagDataEntry output = reader.ReadUInt16ArrayTagDataEntry(size);
@ -274,10 +324,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UInt32ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UInt32ArrayTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUInt32ArrayTagDataEntry(byte[] data, IccUInt32ArrayTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUInt32ArrayTagDataEntry output = reader.ReadUInt32ArrayTagDataEntry(size);
@ -285,10 +337,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UInt64ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UInt64ArrayTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUInt64ArrayTagDataEntry(byte[] data, IccUInt64ArrayTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUInt64ArrayTagDataEntry output = reader.ReadUInt64ArrayTagDataEntry(size);
@ -296,10 +350,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UInt8ArrayTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UInt8ArrayTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUInt8ArrayTagDataEntry(byte[] data, IccUInt8ArrayTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUInt8ArrayTagDataEntry output = reader.ReadUInt8ArrayTagDataEntry(size);
@ -307,10 +363,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ViewingConditionsTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ViewingConditionsTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadViewingConditionsTagDataEntry(byte[] data, IccViewingConditionsTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccViewingConditionsTagDataEntry output = reader.ReadViewingConditionsTagDataEntry();
@ -318,10 +376,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.XYZTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.XYZTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadXyzTagDataEntry(byte[] data, IccXyzTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccXyzTagDataEntry output = reader.ReadXyzTagDataEntry(size);
@ -329,10 +389,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.TextDescriptionTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.TextDescriptionTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadTextDescriptionTagDataEntry(byte[] data, IccTextDescriptionTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccTextDescriptionTagDataEntry output = reader.ReadTextDescriptionTagDataEntry();
@ -340,10 +402,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.CrdInfoTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.CrdInfoTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadCrdInfoTagDataEntry(byte[] data, IccCrdInfoTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccCrdInfoTagDataEntry output = reader.ReadCrdInfoTagDataEntry();
@ -351,10 +415,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.ScreeningTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.ScreeningTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadScreeningTagDataEntry(byte[] data, IccScreeningTagDataEntry expected)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccScreeningTagDataEntry output = reader.ReadScreeningTagDataEntry();
@ -362,10 +428,12 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
[MemberData(nameof(IccTestDataTagDataEntry.UcrBgTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
[MemberData(
nameof(IccTestDataTagDataEntry.UcrBgTagDataEntryTestData),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadUcrBgTagDataEntry(byte[] data, IccUcrBgTagDataEntry expected, uint size)
{
IccDataReader reader = CreateReader(data);
IccDataReader reader = this.CreateReader(data);
IccUcrBgTagDataEntry output = reader.ReadUcrBgTagDataEntry(size);

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

@ -256,6 +256,7 @@ namespace ImageSharp.Tests
Assert.Equal(string.Format(CultureInfo.CurrentCulture, "RectangleF [ X={0}, Y={1}, Width={2}, Height={3} ]", r.X, r.Y, r.Width, r.Height), r.ToString());
}
[Theory]
[InlineData(0, 0, 0, 0)]
[InlineData(5, -5, 0.2, -1.3)]
public void ToStringTestEmpty(float x, float y, float width, float height)

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

@ -0,0 +1,143 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests
{
using System.Numerics;
using ImageSharp.PixelFormats;
using Xunit;
public class Bgr24Tests
{
public static readonly TheoryData<byte, byte, byte> ColorData =
new TheoryData<byte, byte, byte>() { { 1, 2, 3 }, { 4, 5, 6 }, { 0, 255, 42 } };
[Theory]
[MemberData(nameof(ColorData))]
public void Constructor(byte r, byte g, byte b)
{
var p = new Rgb24(r, g, b);
Assert.Equal(r, p.R);
Assert.Equal(g, p.G);
Assert.Equal(b, p.B);
}
[Fact]
public unsafe void ByteLayoutIsSequentialBgr()
{
var color = new Bgr24(1, 2, 3);
byte* ptr = (byte*)&color;
Assert.Equal(3, ptr[0]);
Assert.Equal(2, ptr[1]);
Assert.Equal(1, ptr[2]);
}
[Theory]
[MemberData(nameof(ColorData))]
public void Equals_WhenTrue(byte r, byte g, byte b)
{
var x = new Bgr24(r, g, b);
var y = new Bgr24(r, g, b);
Assert.True(x.Equals(y));
Assert.True(x.Equals((object)y));
Assert.Equal(x.GetHashCode(), y.GetHashCode());
}
[Theory]
[InlineData(1, 2, 3, 1, 2, 4)]
[InlineData(0, 255, 0, 0, 244, 0)]
[InlineData(1, 255, 0, 0, 255, 0)]
public void Equals_WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2)
{
var a = new Bgr24(r1, g1, b1);
var b = new Bgr24(r2, g2, b2);
Assert.False(a.Equals(b));
Assert.False(a.Equals((object)b));
}
[Fact]
public void PackFromRgba32()
{
var rgb = default(Bgr24);
rgb.PackFromRgba32(new Rgba32(1, 2, 3, 4));
Assert.Equal(1, rgb.R);
Assert.Equal(2, rgb.G);
Assert.Equal(3, rgb.B);
}
private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4(
r / 255f,
g / 255f,
b / 255f,
a / 255f);
[Fact]
public void PackFromVector4()
{
var rgb = default(Bgr24);
rgb.PackFromVector4(Vec(1, 2, 3, 4));
Assert.Equal(1, rgb.R);
Assert.Equal(2, rgb.G);
Assert.Equal(3, rgb.B);
}
[Fact]
public void ToVector4()
{
var rgb = new Bgr24(1, 2, 3);
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);
}
}
}

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

@ -0,0 +1,150 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests
{
using System.Numerics;
using ImageSharp.PixelFormats;
using Xunit;
public class Bgra32Tests
{
public static readonly TheoryData<byte, byte, byte, byte> ColorData =
new TheoryData<byte, byte, byte, byte>()
{
{ 1, 2, 3, 4 }, { 4, 5, 6, 7 }, { 0, 255, 42, 0 }, { 1, 2, 3, 255 }
};
[Theory]
[MemberData(nameof(ColorData))]
public void Constructor(byte b, byte g, byte r, byte a)
{
var p = new Bgra32(r, g, b, a);
Assert.Equal(r, p.R);
Assert.Equal(g, p.G);
Assert.Equal(b, p.B);
Assert.Equal(a, p.A);
}
[Fact]
public unsafe void ByteLayoutIsSequentialBgra()
{
var color = new Bgra32(1, 2, 3, 4);
byte* ptr = (byte*)&color;
Assert.Equal(3, ptr[0]);
Assert.Equal(2, ptr[1]);
Assert.Equal(1, ptr[2]);
Assert.Equal(4, ptr[3]);
}
[Theory]
[MemberData(nameof(ColorData))]
public void Equality_WhenTrue(byte b, byte g, byte r, byte a)
{
var x = new Bgra32(r, g, b, a);
var y = new Bgra32(r, g, b, a);
Assert.True(x.Equals(y));
Assert.True(x.Equals((object)y));
Assert.Equal(x.GetHashCode(), y.GetHashCode());
}
[Theory]
[InlineData(1, 2, 3, 4, 1, 2, 3, 5)]
[InlineData(0, 0, 255, 0, 0, 0, 244, 0)]
[InlineData(0, 255, 0, 0, 0, 244, 0, 0)]
[InlineData(1, 255, 0, 0, 0, 255, 0, 0)]
public void Equality_WhenFalse(byte b1, byte g1, byte r1, byte a1, byte b2, byte g2, byte r2, byte a2)
{
var x = new Bgra32(r1, g1, b1, a1);
var y = new Bgra32(r2, g2, b2, a2);
Assert.False(x.Equals(y));
Assert.False(x.Equals((object)y));
}
[Fact]
public void PackFromRgba32()
{
var rgb = default(Rgb24);
rgb.PackFromRgba32(new Rgba32(1, 2, 3, 4));
Assert.Equal(1, rgb.R);
Assert.Equal(2, rgb.G);
Assert.Equal(3, rgb.B);
}
private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4(
r / 255f,
g / 255f,
b / 255f,
a / 255f);
[Fact]
public void PackFromVector4()
{
var c = default(Bgra32);
c.PackFromVector4(Vec(1, 2, 3, 4));
Assert.Equal(1, c.R);
Assert.Equal(2, c.G);
Assert.Equal(3, c.B);
Assert.Equal(4, c.A);
}
[Fact]
public void ToVector4()
{
var rgb = new Bgra32(1, 2, 3, 4);
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);
}
}
}

0
tests/ImageSharp.Tests/Colors/ColorConstructorTests.cs → tests/ImageSharp.Tests/PixelFormats/ColorConstructorTests.cs

0
tests/ImageSharp.Tests/Colors/ColorDefinitionTests.cs → tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs

0
tests/ImageSharp.Tests/Colors/ColorEqualityTests.cs → tests/ImageSharp.Tests/PixelFormats/ColorEqualityTests.cs

0
tests/ImageSharp.Tests/Colors/ColorPackingTests.cs → tests/ImageSharp.Tests/PixelFormats/ColorPackingTests.cs

28
tests/ImageSharp.Tests/Colors/PackedPixelTests.cs → tests/ImageSharp.Tests/PixelFormats/PackedPixelTests.cs

@ -40,10 +40,10 @@ namespace ImageSharp.Tests.Colors
// Test ordering
Vector4 vector = new Alpha8(.5F).ToVector4();
Assert.Equal(vector.X, 0);
Assert.Equal(vector.Y, 0);
Assert.Equal(vector.Z, 0);
Assert.Equal(vector.W, .5F, 2);
Assert.Equal(0, vector.X);
Assert.Equal(0, vector.Y);
Assert.Equal(0, vector.Z);
Assert.Equal(.5F, vector.W, 2);
byte[] rgb = new byte[3];
byte[] rgba = new byte[4];
@ -302,7 +302,7 @@ namespace ImageSharp.Tests.Colors
Assert.Equal(bgra, new byte[] { 0, 0, 128, 0 });
Byte4 r = new Byte4();
r.PackFromBytes(20, 38, 0, 255);
r.PackFromRgba32(new Rgba32(20, 38, 0, 255));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 });
}
@ -448,7 +448,7 @@ namespace ImageSharp.Tests.Colors
float y = -0.3f;
Assert.Equal(0xda0d, new NormalizedByte2(x, y).PackedValue);
NormalizedByte2 n = new NormalizedByte2();
n.PackFromBytes(141, 90, 0, 0);
n.PackFromRgba32(new Rgba32(141, 90, 0, 0));
Assert.Equal(0xda0d, n.PackedValue);
byte[] rgb = new byte[3];
@ -491,7 +491,7 @@ namespace ImageSharp.Tests.Colors
float w = -0.7f;
Assert.Equal(0xA740DA0D, new NormalizedByte4(x, y, z, w).PackedValue);
NormalizedByte4 n = new NormalizedByte4();
n.PackFromBytes(141, 90, 192, 39);
n.PackFromRgba32(new Rgba32(141, 90, 192, 39));
Assert.Equal(0xA740DA0D, n.PackedValue);
Assert.Equal((uint)958796544, new NormalizedByte4(0.0008f, 0.15f, 0.30f, 0.45f).PackedValue);
@ -515,7 +515,7 @@ namespace ImageSharp.Tests.Colors
// http://community.monogame.net/t/normalizedbyte4-texture2d-gives-different-results-from-xna/8012/8
NormalizedByte4 r = new NormalizedByte4();
r.PackFromBytes(9, 115, 202, 127);
r.PackFromRgba32(new Rgba32(9, 115, 202, 127));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 });
@ -554,7 +554,7 @@ namespace ImageSharp.Tests.Colors
byte[] bgra = new byte[4];
NormalizedShort2 n = new NormalizedShort2();
n.PackFromBytes(141, 90, 0, 0);
n.PackFromRgba32(new Rgba32(141, 90, 0, 0));
n.ToXyzBytes(rgb, 0);
Assert.Equal(rgb, new byte[] { 141, 90, 0 });
@ -615,7 +615,7 @@ namespace ImageSharp.Tests.Colors
Assert.Equal(bgra, new byte[] { 192, 90, 141, 39 });
NormalizedShort4 r = new NormalizedShort4();
r.PackFromBytes(9, 115, 202, 127);
r.PackFromRgba32(new Rgba32(9, 115, 202, 127));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 9, 115, 202, 127 });
}
@ -708,7 +708,7 @@ namespace ImageSharp.Tests.Colors
// Alpha component accuracy will be awful.
Rgba1010102 r = new Rgba1010102();
r.PackFromBytes(25, 0, 128, 0);
r.PackFromRgba32(new Rgba32(25, 0, 128, 0));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 25, 0, 128, 0 });
}
@ -801,7 +801,7 @@ namespace ImageSharp.Tests.Colors
Assert.Equal(bgra, new byte[] { 76, 38, 20, 115 });
Rgba64 r = new Rgba64();
r.PackFromBytes(20, 38, 76, 115);
r.PackFromRgba32(new Rgba32(20, 38, 76, 115));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 76, 115 });
}
@ -856,7 +856,7 @@ namespace ImageSharp.Tests.Colors
Assert.Equal(bgra, new byte[] { 0, 127, 128, 255 });
Short2 r = new Short2();
r.PackFromBytes(20, 38, 0, 255);
r.PackFromRgba32(new Rgba32(20, 38, 0, 255));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 });
}
@ -913,7 +913,7 @@ namespace ImageSharp.Tests.Colors
Assert.Equal(bgra, new byte[] { 243, 177, 172, 128 });
Short4 r = new Short4();
r.PackFromBytes(20, 38, 0, 255);
r.PackFromRgba32(new Rgba32(20, 38, 0, 255));
r.ToXyzwBytes(rgba, 0);
Assert.Equal(rgba, new byte[] { 20, 38, 0, 255 });
}

50
tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.Blender.cs

@ -0,0 +1,50 @@
// <copyright file="PixelBlenderTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests.PixelFormats
{
using System;
using System.Collections.Generic;
using System.Text;
using ImageSharp.PixelFormats;
using ImageSharp.PixelFormats.PixelBlenders;
using ImageSharp.Tests.TestUtilities;
using Xunit;
public partial class PixelOperationsTests
{
public static TheoryData<object, Type, PixelBlenderMode> BlenderMappings = new TheoryData<object, Type, PixelBlenderMode>()
{
{ new TestPixel<Rgba32>(), typeof(DefaultNormalPixelBlender<Rgba32>), PixelBlenderMode.Normal },
{ new TestPixel<Rgba32>(), typeof(DefaultScreenPixelBlender<Rgba32>), PixelBlenderMode.Screen },
{ new TestPixel<Rgba32>(), typeof(DefaultHardLightPixelBlender<Rgba32>), PixelBlenderMode.HardLight },
{ new TestPixel<Rgba32>(), typeof(DefaultOverlayPixelBlender<Rgba32>), PixelBlenderMode.Overlay },
{ new TestPixel<Rgba32>(), typeof(DefaultDarkenPixelBlender<Rgba32>), PixelBlenderMode.Darken },
{ new TestPixel<Rgba32>(), typeof(DefaultLightenPixelBlender<Rgba32>), PixelBlenderMode.Lighten },
{ new TestPixel<Rgba32>(), typeof(DefaultAddPixelBlender<Rgba32>), PixelBlenderMode.Add },
{ new TestPixel<Rgba32>(), typeof(DefaultSubstractPixelBlender<Rgba32>), PixelBlenderMode.Substract },
{ new TestPixel<Rgba32>(), typeof(DefaultMultiplyPixelBlender<Rgba32>), PixelBlenderMode.Multiply },
{ new TestPixel<RgbaVector>(), typeof(DefaultNormalPixelBlender<RgbaVector>), PixelBlenderMode.Normal },
{ new TestPixel<RgbaVector>(), typeof(DefaultScreenPixelBlender<RgbaVector>), PixelBlenderMode.Screen },
{ new TestPixel<RgbaVector>(), typeof(DefaultHardLightPixelBlender<RgbaVector>), PixelBlenderMode.HardLight },
{ new TestPixel<RgbaVector>(), typeof(DefaultOverlayPixelBlender<RgbaVector>), PixelBlenderMode.Overlay },
{ new TestPixel<RgbaVector>(), typeof(DefaultDarkenPixelBlender<RgbaVector>), PixelBlenderMode.Darken },
{ new TestPixel<RgbaVector>(), typeof(DefaultLightenPixelBlender<RgbaVector>), PixelBlenderMode.Lighten },
{ new TestPixel<RgbaVector>(), typeof(DefaultAddPixelBlender<RgbaVector>), PixelBlenderMode.Add },
{ new TestPixel<RgbaVector>(), typeof(DefaultSubstractPixelBlender<RgbaVector>), PixelBlenderMode.Substract },
{ new TestPixel<RgbaVector>(), typeof(DefaultMultiplyPixelBlender<RgbaVector>), PixelBlenderMode.Multiply },
};
[Theory]
[MemberData(nameof(BlenderMappings))]
public void ReturnsCorrectBlender<TPixel>(TestPixel<TPixel> pixel, Type type, PixelBlenderMode mode)
where TPixel : struct, IPixel<TPixel>
{
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(mode);
Assert.IsType(type, blender);
}
}
}

32
tests/ImageSharp.Tests/Colors/PixelOperationsTests.cs → tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs

@ -1,6 +1,6 @@
// ReSharper disable InconsistentNaming
// ReSharper disable AccessToDisposedClosure
namespace ImageSharp.Tests.Colors
namespace ImageSharp.Tests.PixelFormats
{
using System;
using System.Numerics;
@ -11,8 +11,9 @@ namespace ImageSharp.Tests.Colors
using Xunit;
using Xunit.Abstractions;
public class PixelOperationsTests
public partial class PixelOperationsTests
{
public class Color32 : PixelOperationsTests<Rgba32>
{
public Color32(ITestOutputHelper output)
@ -42,8 +43,11 @@ namespace ImageSharp.Tests.Colors
);
}
// [Fact] // Profiling benchmark - enable manually!
#pragma warning disable xUnit1013 // Public method should be marked as test
public void Benchmark_ToVector4()
#pragma warning restore xUnit1013 // Public method should be marked as test
{
int times = 200000;
int count = 1024;
@ -155,13 +159,13 @@ namespace ImageSharp.Tests.Colors
{
int i3 = i * 3;
expected[i].PackFromBytes(source[i3 + 0], source[i3 + 1], source[i3 + 2], 255);
expected[i].PackFromRgba32(new Rgba32(source[i3 + 0], source[i3 + 1], source[i3 + 2], 255));
}
TestOperation(
source,
expected,
(s, d) => Operations.PackFromXyzBytes(s, d, count)
(s, d) => Operations.PackFromRgb24Bytes(s, d, count)
);
}
@ -181,7 +185,7 @@ namespace ImageSharp.Tests.Colors
TestOperation(
source,
expected,
(s, d) => Operations.ToXyzBytes(s, d, count)
(s, d) => Operations.ToRgb24Bytes(s, d, count)
);
}
@ -196,13 +200,13 @@ namespace ImageSharp.Tests.Colors
{
int i4 = i * 4;
expected[i].PackFromBytes(source[i4 + 0], source[i4 + 1], source[i4 + 2], source[i4 + 3]);
expected[i].PackFromRgba32(new Rgba32(source[i4 + 0], source[i4 + 1], source[i4 + 2], source[i4 + 3]));
}
TestOperation(
source,
expected,
(s, d) => Operations.PackFromXyzwBytes(s, d, count)
(s, d) => Operations.PackFromRgba32Bytes(s, d, count)
);
}
@ -222,7 +226,7 @@ namespace ImageSharp.Tests.Colors
TestOperation(
source,
expected,
(s, d) => Operations.ToXyzwBytes(s, d, count)
(s, d) => Operations.ToRgba32Bytes(s, d, count)
);
}
@ -237,13 +241,13 @@ namespace ImageSharp.Tests.Colors
{
int i3 = i * 3;
expected[i].PackFromBytes(source[i3 + 2], source[i3 + 1], source[i3 + 0], 255);
expected[i].PackFromRgba32(new Rgba32(source[i3 + 2], source[i3 + 1], source[i3 + 0], 255));
}
TestOperation(
source,
expected,
(s, d) => Operations.PackFromZyxBytes(s, d, count)
(s, d) => Operations.PackFromBgr24Bytes(s, d, count)
);
}
@ -263,7 +267,7 @@ namespace ImageSharp.Tests.Colors
TestOperation(
source,
expected,
(s, d) => Operations.ToZyxBytes(s, d, count)
(s, d) => Operations.ToBgr24Bytes(s, d, count)
);
}
@ -278,13 +282,13 @@ namespace ImageSharp.Tests.Colors
{
int i4 = i * 4;
expected[i].PackFromBytes(source[i4 + 2], source[i4 + 1], source[i4 + 0], source[i4 + 3]);
expected[i].PackFromRgba32(new Rgba32(source[i4 + 2], source[i4 + 1], source[i4 + 0], source[i4 + 3]));
}
TestOperation(
source,
expected,
(s, d) => Operations.PackFromZyxwBytes(s, d, count)
(s, d) => Operations.PackFromBgra32Bytes(s, d, count)
);
}
@ -304,7 +308,7 @@ namespace ImageSharp.Tests.Colors
TestOperation(
source,
expected,
(s, d) => Operations.ToZyxwBytes(s, d, count)
(s, d) => Operations.ToBgra32Bytes(s, d, count)
);
}

143
tests/ImageSharp.Tests/PixelFormats/Rgb24Tests.cs

@ -0,0 +1,143 @@
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests
{
using System;
using System.Numerics;
using ImageSharp.PixelFormats;
using Xunit;
public class Rgb24Tests
{
public static readonly TheoryData<byte, byte, byte> ColorData =
new TheoryData<byte, byte, byte>() { { 1, 2, 3 }, { 4, 5, 6 }, { 0, 255, 42 } };
[Theory]
[MemberData(nameof(ColorData))]
public void Constructor(byte r, byte g, byte b)
{
var p = new Rgb24(r, g, b);
Assert.Equal(r, p.R);
Assert.Equal(g, p.G);
Assert.Equal(b, p.B);
}
[Fact]
public unsafe void ByteLayoutIsSequentialRgb()
{
var color = new Rgb24(1, 2, 3);
byte* ptr = (byte*)&color;
Assert.Equal(1, ptr[0]);
Assert.Equal(2, ptr[1]);
Assert.Equal(3, ptr[2]);
}
[Theory]
[MemberData(nameof(ColorData))]
public void Equals_WhenTrue(byte r, byte g, byte b)
{
var x = new Rgb24(r, g, b);
var y = new Rgb24(r, g, b);
Assert.True(x.Equals(y));
Assert.True(x.Equals((object)y));
Assert.Equal(x.GetHashCode(), y.GetHashCode());
}
[Theory]
[InlineData(1, 2, 3, 1, 2, 4)]
[InlineData(0, 255, 0, 0, 244, 0)]
[InlineData(1, 255, 0, 0, 255, 0)]
public void Equals_WhenFalse(byte r1, byte g1, byte b1, byte r2, byte g2, byte b2)
{
var a = new Rgb24(r1, g1, b1);
var b = new Rgb24(r2, g2, b2);
Assert.False(a.Equals(b));
Assert.False(a.Equals((object)b));
}
[Fact]
public void PackFromRgba32()
{
var rgb = default(Rgb24);
rgb.PackFromRgba32(new Rgba32(1, 2, 3, 4));
Assert.Equal(1, rgb.R);
Assert.Equal(2, rgb.G);
Assert.Equal(3, rgb.B);
}
private static Vector4 Vec(byte r, byte g, byte b, byte a = 255) => new Vector4(
r / 255f,
g / 255f,
b / 255f,
a / 255f);
[Fact]
public void PackFromVector4()
{
var rgb = default(Rgb24);
rgb.PackFromVector4(Vec(1, 2, 3, 4));
Assert.Equal(1, rgb.R);
Assert.Equal(2, rgb.G);
Assert.Equal(3, rgb.B);
}
[Fact]
public void ToVector4()
{
var rgb = new Rgb24(1, 2, 3);
Assert.Equal(Vec(1, 2, 3), rgb.ToVector4());
}
[Fact]
public void ToRgb24()
{
var rgb = new Rgb24(1, 2, 3);
var dest = default(Rgb24);
rgb.ToRgb24(ref dest);
Assert.Equal(rgb, dest);
}
[Fact]
public void ToRgba32()
{
var rgb = new Rgb24(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 Rgb24(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 Rgb24(1, 2, 3);
var bgra = default(Bgra32);
rgb.ToBgra32(ref bgra);
Assert.Equal(new Bgra32(1, 2, 3, 255), bgra);
}
}
}

0
tests/ImageSharp.Tests/Colors/Rgba32Tests.cs → tests/ImageSharp.Tests/PixelFormats/Rgba32Tests.cs

0
tests/ImageSharp.Tests/Colors/RgbaVectorTests.cs → tests/ImageSharp.Tests/PixelFormats/RgbaVectorTests.cs

0
tests/ImageSharp.Tests/Colors/UnPackedPixelTests.cs → tests/ImageSharp.Tests/PixelFormats/UnPackedPixelTests.cs

2
tests/ImageSharp.Tests/Processing/Transforms/PadTest.cs

@ -26,7 +26,7 @@ namespace ImageSharp.Tests.Processing.Transforms
{
for (int x = 0; x < 25; x++)
{
Assert.Equal(image[x, y], default(TPixel));
Assert.Equal(default(TPixel), image[x, y]);
}
}
}

4
tests/ImageSharp.Tests/Processing/Transforms/ResizeProfilingBenchmarks.cs

@ -25,8 +25,8 @@ namespace ImageSharp.Tests.Processing.Transforms
public int ExecutionCount { get; set; } = 50;
// [Theory] // Benchmark, enable manually!
[InlineData(100, 100)]
[InlineData(2000, 2000)]
// [InlineData(100, 100)]
// [InlineData(2000, 2000)]
public void ResizeBicubic(int width, int height)
{
this.Measure(this.ExecutionCount,

4
tests/ImageSharp.Tests/TestUtilities/ImageProviders/SolidProvider.cs

@ -53,11 +53,11 @@ namespace ImageSharp.Tests
{
Image<TPixel> image = base.GetImage();
TPixel color = default(TPixel);
color.PackFromBytes(this.r, this.g, this.b, this.a);
color.PackFromRgba32(new Rgba32(this.r, this.g, this.b, this.a));
return image.Fill(color);
}
public override void Serialize(IXunitSerializationInfo info)
{
info.AddValue("red", this.r);

6
tests/ImageSharp.Tests/TestUtilities/PixelTypes.cs

@ -52,6 +52,12 @@ namespace ImageSharp.Tests
Short4 = 1 << 17,
Rgb24 = 18,
Bgr24 = 19,
Bgra32 = 20,
// TODO: Add multi-flag entries by rules defined in PackedPixelConverterHelper
// "All" is handled as a separate, individual case instead of using bitwise OR

14
tests/ImageSharp.Tests/TestUtilities/Tests/TestImageProviderTests.cs

@ -103,8 +103,8 @@ namespace ImageSharp.Tests
where TPixel : struct, IPixel<TPixel>
{
Image<TPixel> img = provider.GetImage();
Assert.Equal(img.Width, 10);
Assert.Equal(img.Height, 20);
Assert.Equal(10, img.Width);
Assert.Equal(20, img.Height);
byte[] colors = new byte[4];
@ -116,10 +116,10 @@ namespace ImageSharp.Tests
{
pixels[x, y].ToXyzwBytes(colors, 0);
Assert.Equal(colors[0], 255);
Assert.Equal(colors[1], 100);
Assert.Equal(colors[2], 50);
Assert.Equal(colors[3], 200);
Assert.Equal(255, colors[0]);
Assert.Equal(100, colors[1]);
Assert.Equal(50, colors[2]);
Assert.Equal(200, colors[3]);
}
}
}
@ -143,7 +143,7 @@ namespace ImageSharp.Tests
where TPixel : struct, IPixel<TPixel>
{
Image<TPixel> img = provider.GetImage();
Assert.Equal(img.Width, 3);
Assert.Equal(3, img.Width);
if (provider.PixelType == PixelTypes.Rgba32)
{
Assert.IsType<Image<Rgba32>>(img);

2
tests/ImageSharp.Tests/TestUtilities/Tests/TestUtilityExtensionsTests.cs

@ -118,7 +118,7 @@ namespace ImageSharp.Tests
IEnumerable<KeyValuePair<PixelTypes, Type>> expanded = pixelTypes.ExpandAllTypes();
Assert.Equal(expanded.Count(), 4);
Assert.Equal(4, expanded.Count());
AssertContainsPixelType<Alpha8>(PixelTypes.Alpha8, expanded);
AssertContainsPixelType<Bgr565>(PixelTypes.Bgr565, expanded);

Loading…
Cancel
Save