diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs
index 02a2e9ee55..1dc7405677 100644
--- a/src/ImageSharp/Common/Helpers/ImageMaths.cs
+++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs
@@ -14,6 +14,73 @@ namespace SixLabors.ImageSharp
///
internal static class ImageMaths
{
+ ///
+ /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static byte Get8BitBT709Luminance(byte r, byte g, byte b) => (byte)((r * .2126F) + (g * .7152F) + (b * .0722F));
+
+ ///
+ /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F));
+
+ ///
+ /// Scales a value from a 16 bit to it's 8 bit equivalent.
+ ///
+ /// The 8 bit compoonent value.
+ /// The
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static byte DownScaleFrom16BitTo8Bit(ushort component)
+ {
+ // To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
+ //
+ // (V * 255) / 65535
+ //
+ // This reduces to round(V / 257), or floor((V + 128.5)/257)
+ //
+ // Represent V as the two byte value vhi.vlo. Make a guess that the
+ // result is the top byte of V, vhi, then the correction to this value
+ // is:
+ //
+ // error = floor(((V-vhi.vhi) + 128.5) / 257)
+ // = floor(((vlo-vhi) + 128.5) / 257)
+ //
+ // This can be approximated using integer arithmetic (and a signed
+ // shift):
+ //
+ // error = (vlo-vhi+128) >> 8;
+ //
+ // The approximate differs from the exact answer only when (vlo-vhi) is
+ // 128; it then gives a correction of +1 when the exact correction is
+ // 0. This gives 128 errors. The exact answer (correct for all 16-bit
+ // input values) is:
+ //
+ // error = (vlo-vhi+128)*65535 >> 24;
+ //
+ // An alternative arithmetic calculation which also gives no errors is:
+ //
+ // (V * 255 + 32895) >> 16
+ return (byte)(((component * 255) + 32895) >> 16);
+ }
+
+ ///
+ /// Scales a value from an 8 bit to it's 16 bit equivalent.
+ ///
+ /// The 8 bit compoonent value.
+ /// The
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257);
+
///
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
///
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 71852acddd..dabab651d0 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -219,8 +219,6 @@ private void ReadRle8(Buffer2D pixels, byte[] colors, int width,
where TPixel : struct, IPixel
{
TPixel color = default;
- var rgba = new Rgba32(0, 0, 0, 255);
-
using (Buffer2D buffer = this.memoryAllocator.Allocate2D(width, height, AllocationOptions.Clean))
{
this.UncompressRle8(width, buffer.GetSpan());
@@ -233,8 +231,7 @@ private void ReadRle8(Buffer2D pixels, byte[] colors, int width,
for (int x = 0; x < width; x++)
{
- rgba.Bgr = Unsafe.As(ref colors[bufferRow[x] * 4]);
- color.PackFromRgba32(rgba);
+ color.PackFromBgr24(Unsafe.As(ref colors[bufferRow[x] * 4]));
pixelRow[x] = color;
}
}
@@ -352,8 +349,6 @@ private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int
using (IManagedByteBuffer row = this.memoryAllocator.AllocateManagedByteBuffer(arrayWidth + padding, AllocationOptions.Clean))
{
TPixel color = default;
- var rgba = new Rgba32(0, 0, 0, 255);
-
Span rowSpan = row.GetSpan();
for (int y = 0; y < height; y++)
@@ -363,7 +358,6 @@ private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int
int offset = 0;
Span pixelRow = pixels.GetRowSpan(newY);
- // TODO: Could use PixelOperations here!
for (int x = 0; x < arrayWidth; x++)
{
int colOffset = x * ppb;
@@ -371,9 +365,7 @@ private void ReadRgbPalette(Buffer2D pixels, byte[] colors, int
{
int colorIndex = ((rowSpan[offset] >> (8 - bits - (shift * bits))) & mask) * 4;
- // Stored in b-> g-> r order.
- rgba.Bgr = Unsafe.As(ref colors[colorIndex]);
- color.PackFromRgba32(rgba);
+ color.PackFromBgr24(Unsafe.As(ref colors[colorIndex]));
pixelRow[newX] = color;
}
@@ -397,7 +389,6 @@ private void ReadRgb16(Buffer2D pixels, int width, int height, b
int padding = CalculatePadding(width, 2);
int stride = (width * 2) + padding;
TPixel color = default;
- var rgba = new Rgba32(0, 0, 0, 255);
using (IManagedByteBuffer buffer = this.memoryAllocator.AllocateManagedByteBuffer(stride))
{
@@ -412,11 +403,12 @@ private void ReadRgb16(Buffer2D pixels, int width, int height, b
{
short temp = BitConverter.ToInt16(buffer.Array, offset);
- rgba.R = GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10);
- rgba.G = GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5);
- rgba.B = GetBytesFrom5BitValue(temp & Rgb16BMask);
+ var rgb = new Rgb24(
+ GetBytesFrom5BitValue((temp & Rgb16RMask) >> 10),
+ GetBytesFrom5BitValue((temp & Rgb16GMask) >> 5),
+ GetBytesFrom5BitValue(temp & Rgb16BMask));
- color.PackFromRgba32(rgba);
+ color.PackFromRgb24(rgb);
pixelRow[x] = color;
offset += 2;
}
@@ -537,7 +529,7 @@ private void ReadInfoHeader()
this.metaData = meta;
short bitsPerPixel = this.infoHeader.BitsPerPixel;
- var bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance);
+ BmpMetaData bmpMetaData = this.metaData.GetFormatMetaData(BmpFormat.Instance);
// We can only encode at these bit rates so far.
if (bitsPerPixel.Equals((short)BmpBitsPerPixel.Pixel24)
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index 44e42528cf..186ff812f7 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -101,9 +101,9 @@ public void Encode(Image image, Stream stream)
var fileHeader = new BmpFileHeader(
type: 19778, // BM
- offset: 54,
+ fileSize: 54 + infoHeader.ImageSize,
reserved: 0,
- fileSize: 54 + infoHeader.ImageSize);
+ offset: 54);
#if NETCOREAPP2_1
Span buffer = stackalloc byte[40];
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 207f126f9e..155e6484f7 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -481,22 +481,36 @@ private void ReadFrameColors(ref Image image, ref ImageFrame(QuantizedFrame quantized)
{
// Transparent pixels are much more likely to be found at the end of a palette
int index = -1;
- Rgba32 trans = default;
+ int length = quantized.Palette.Length;
- ref TPixel paletteRef = ref MemoryMarshal.GetReference(quantized.Palette.AsSpan());
- for (int i = quantized.Palette.Length - 1; i >= 0; i--)
+ using (IMemoryOwner rgbaBuffer = this.memoryAllocator.Allocate(length))
{
- ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
- entry.ToRgba32(ref trans);
- if (trans.Equals(default))
+ Span rgbaSpan = rgbaBuffer.GetSpan();
+ ref Rgba32 paletteRef = ref MemoryMarshal.GetReference(rgbaSpan);
+ PixelOperations.Instance.ToRgba32(quantized.Palette, rgbaSpan, length);
+
+ for (int i = quantized.Palette.Length - 1; i >= 0; i--)
{
- index = i;
+ if (Unsafe.Add(ref paletteRef, i).Equals(default))
+ {
+ index = i;
+ }
}
}
@@ -406,24 +411,13 @@ private void WriteImageDescriptor(ImageFrame image, bool hasColo
private void WriteColorTable(QuantizedFrame image, Stream stream)
where TPixel : struct, IPixel
{
- int pixelCount = image.Palette.Length;
-
// The maximium number of colors for the bit depth
int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * 3;
- Rgb24 rgb = default;
+ int pixelCount = image.Palette.Length;
using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength))
{
- ref TPixel paletteRef = ref MemoryMarshal.GetReference(image.Palette.AsSpan());
- ref Rgb24 rgb24Ref = ref Unsafe.As(ref MemoryMarshal.GetReference(colorTable.GetSpan()));
- for (int i = 0; i < pixelCount; i++)
- {
- ref TPixel entry = ref Unsafe.Add(ref paletteRef, i);
- entry.ToRgb24(ref rgb);
- Unsafe.Add(ref rgb24Ref, i) = rgb;
- }
-
- // Write the palette to the stream
+ PixelOperations.Instance.ToRgb24Bytes(image.Palette.AsSpan(), colorTable.GetSpan(), pixelCount);
stream.Write(colorTable.Array, 0, colorTableLength);
}
}
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index a46d83707e..1e9dbc71a1 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
@@ -312,11 +313,6 @@ public void Dispose()
private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
where TPixel : struct, IPixel
{
- // Use ITU-R recommendation 709 to match libpng.
- const float RX = .2126F;
- const float GX = .7152F;
- const float BX = .0722F;
-
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
Span rawScanlineSpan = this.rawScanline.GetSpan();
ref byte rawScanlineSpanRef = ref MemoryMarshal.GetReference(rawScanlineSpan);
@@ -327,12 +323,18 @@ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
if (this.use16Bit)
{
// 16 bit grayscale
- Rgb48 rgb = default;
- for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2)
+ using (IMemoryOwner luminanceBuffer = this.memoryAllocator.Allocate(rowSpan.Length))
{
- Unsafe.Add(ref rowSpanRef, x).ToRgb48(ref rgb);
- ushort luminance = (ushort)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B));
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
+ Span luminanceSpan = luminanceBuffer.GetSpan();
+ ref Gray16 luminanceRef = ref MemoryMarshal.GetReference(luminanceSpan);
+ PixelOperations.Instance.ToGray16(rowSpan, luminanceSpan, rowSpan.Length);
+
+ // Can't map directly to byte array as it's big endian.
+ for (int x = 0, o = 0; x < luminanceSpan.Length; x++, o += 2)
+ {
+ Gray16 luminance = Unsafe.Add(ref luminanceRef, x);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance.PackedValue);
+ }
}
}
else
@@ -340,12 +342,7 @@ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
if (this.bitDepth == 8)
{
// 8 bit grayscale
- Rgb24 rgb = default;
- for (int x = 0; x < rowSpan.Length; x++)
- {
- Unsafe.Add(ref rowSpanRef, x).ToRgb24(ref rgb);
- Unsafe.Add(ref rawScanlineSpanRef, x) = (byte)((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B));
- }
+ PixelOperations.Instance.ToGray8Bytes(rowSpan, rawScanlineSpan, rowSpan.Length);
}
else
{
@@ -356,14 +353,9 @@ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
Span tempSpan = temp.GetSpan();
ref byte tempSpanRef = ref MemoryMarshal.GetReference(tempSpan);
- Rgb24 rgb = default;
- for (int x = 0; x < rowSpan.Length; x++)
- {
- Unsafe.Add(ref rowSpanRef, x).ToRgb24(ref rgb);
- float luminance = ((RX * rgb.R) + (GX * rgb.G) + (BX * rgb.B)) / scaleFactor;
- Unsafe.Add(ref tempSpanRef, x) = (byte)luminance;
- this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth);
- }
+ // We need to first create an array of luminance bytes then scale them down to the correct bit depth.
+ PixelOperations.Instance.ToGray8Bytes(rowSpan, tempSpan, rowSpan.Length);
+ this.ScaleDownFrom8BitArray(tempSpan, rawScanlineSpan, this.bitDepth, scaleFactor);
}
}
}
@@ -373,23 +365,31 @@ private void CollectGrayscaleBytes(ReadOnlySpan rowSpan)
if (this.use16Bit)
{
// 16 bit grayscale + alpha
- Rgba64 rgba = default;
- for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 4)
+ // TODO: Should we consider in the future a GrayAlpha32 type.
+ using (IMemoryOwner rgbaBuffer = this.memoryAllocator.Allocate(rowSpan.Length))
{
- Unsafe.Add(ref rowSpanRef, x).ToRgba64(ref rgba);
- ushort luminance = (ushort)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B));
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A);
+ Span rgbaSpan = rgbaBuffer.GetSpan();
+ ref Rgba64 rgbaRef = ref MemoryMarshal.GetReference(rgbaSpan);
+ PixelOperations.Instance.ToRgba64(rowSpan, rgbaSpan, rowSpan.Length);
+
+ // Can't map directly to byte array as it's big endian.
+ for (int x = 0, o = 0; x < rgbaSpan.Length; x++, o += 4)
+ {
+ Rgba64 rgba = Unsafe.Add(ref rgbaRef, x);
+ ushort luminance = ImageMaths.Get16BitBT709Luminance(rgba.R, rgba.G, rgba.B);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A);
+ }
}
}
else
{
// 8 bit grayscale + alpha
- Rgba32 rgba = default;
+ // TODO: Should we consider in the future a GrayAlpha16 type.
for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 2)
{
- Unsafe.Add(ref rowSpanRef, x).ToRgba32(ref rgba);
- Unsafe.Add(ref rawScanlineSpanRef, o) = (byte)((RX * rgba.R) + (GX * rgba.G) + (BX * rgba.B));
+ var rgba = Unsafe.Add(ref rowSpanRef, x).ToRgba32();
+ Unsafe.Add(ref rawScanlineSpanRef, o) = ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
Unsafe.Add(ref rawScanlineSpanRef, o + 1) = rgba.A;
}
}
@@ -425,15 +425,21 @@ private void CollectTPixelBytes(ReadOnlySpan rowSpan)
case 8:
{
// 16 bit Rgba
- Rgba64 rgba = default;
- ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
- for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8)
+ using (IMemoryOwner rgbaBuffer = this.memoryAllocator.Allocate(rowSpan.Length))
{
- Unsafe.Add(ref rowSpanRef, x).ToRgba64(ref rgba);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgba.R);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.G);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgba.B);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 6, 2), rgba.A);
+ Span rgbaSpan = rgbaBuffer.GetSpan();
+ ref Rgba64 rgbaRef = ref MemoryMarshal.GetReference(rgbaSpan);
+ PixelOperations.Instance.ToRgba64(rowSpan, rgbaSpan, rowSpan.Length);
+
+ // Can't map directly to byte array as it's big endian.
+ for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 8)
+ {
+ Rgba64 rgba = Unsafe.Add(ref rgbaRef, x);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgba.R);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.G);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgba.B);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 6, 2), rgba.A);
+ }
}
break;
@@ -442,14 +448,20 @@ private void CollectTPixelBytes(ReadOnlySpan rowSpan)
default:
{
// 16 bit Rgb
- Rgb48 rgb = default;
- ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
- for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6)
+ using (IMemoryOwner rgbBuffer = this.memoryAllocator.Allocate(rowSpan.Length))
{
- Unsafe.Add(ref rowSpanRef, x).ToRgb48(ref rgb);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgb.R);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgb.G);
- BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgb.B);
+ Span rgbSpan = rgbBuffer.GetSpan();
+ ref Rgb48 rgbRef = ref MemoryMarshal.GetReference(rgbSpan);
+ PixelOperations.Instance.ToRgb48(rowSpan, rgbSpan, rowSpan.Length);
+
+ // Can't map directly to byte array as it's big endian.
+ for (int x = 0, o = 0; x < rowSpan.Length; x++, o += 6)
+ {
+ Rgb48 rgb = Unsafe.Add(ref rgbRef, x);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), rgb.R);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgb.G);
+ BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 4, 2), rgb.B);
+ }
}
break;
@@ -624,7 +636,6 @@ private void WritePaletteChunk(Stream stream, QuantizedFrame qua
TPixel[] palette = quantized.Palette;
int paletteLength = Math.Min(palette.Length, 256);
int colorTableLength = paletteLength * 3;
- Rgba32 rgba = default;
bool anyAlpha = false;
using (IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength))
@@ -639,7 +650,7 @@ private void WritePaletteChunk(Stream stream, QuantizedFrame qua
if (quantizedSpan.IndexOf((byte)i) > -1)
{
int offset = i * 3;
- palette[i].ToRgba32(ref rgba);
+ var rgba = palette[i].ToRgba32();
byte alpha = rgba.A;
@@ -851,7 +862,8 @@ private void WriteChunk(Stream stream, PngChunkType type, byte[] data, int offse
/// The source span in 8 bits.
/// The resultant span in .
/// The bit depth.
- private void ScaleDownFrom8BitArray(ReadOnlySpan source, Span result, int bits)
+ /// The scaling factor.
+ private void ScaleDownFrom8BitArray(ReadOnlySpan source, Span result, int bits, float scale = 1)
{
ref byte sourceRef = ref MemoryMarshal.GetReference(source);
ref byte resultRef = ref MemoryMarshal.GetReference(result);
@@ -864,7 +876,7 @@ private void ScaleDownFrom8BitArray(ReadOnlySpan source, Span result
for (int i = 0; i < source.Length; i++)
{
- int value = Unsafe.Add(ref sourceRef, i) & mask;
+ int value = ((int)MathF.Round(Unsafe.Add(ref sourceRef, i) / scale)) & mask;
v |= value << shift;
if (shift == 0)
diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
index 5ea25e72d4..70f2cb04b6 100644
--- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
+++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
@@ -32,30 +32,19 @@ public static void ProcessGrayscaleScanline(
{
if (header.BitDepth == 16)
{
- Rgb48 rgb48 = default;
for (int x = 0, o = 0; x < header.Width; x++, o += 2)
{
ushort luminance = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, 2));
- rgb48.R = luminance;
- rgb48.G = luminance;
- rgb48.B = luminance;
-
- pixel.PackFromRgb48(rgb48);
+ pixel.PackFromGray16(new Gray16(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
- // TODO: We should really be using Rgb24 here but IPixel does not have a PackFromRgb24 method.
- var rgba32 = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = 0; x < header.Width; x++)
{
byte luminance = (byte)(Unsafe.Add(ref scanlineSpanRef, x) * scaleFactor);
- rgba32.R = luminance;
- rgba32.G = luminance;
- rgba32.B = luminance;
-
- pixel.PackFromRgba32(rgba32);
+ pixel.PackFromGray8(new Gray8(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@@ -116,30 +105,19 @@ public static void ProcessInterlacedGrayscaleScanline(
{
if (header.BitDepth == 16)
{
- Rgb48 rgb48 = default;
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o += 2)
{
ushort luminance = BinaryPrimitives.ReadUInt16BigEndian(scanlineSpan.Slice(o, 2));
- rgb48.R = luminance;
- rgb48.G = luminance;
- rgb48.B = luminance;
-
- pixel.PackFromRgb48(rgb48);
+ pixel.PackFromGray16(new Gray16(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
else
{
- // TODO: We should really be using Rgb24 here but IPixel does not have a PackFromRgb24 method.
- var rgba32 = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o++)
{
byte luminance = (byte)(Unsafe.Add(ref scanlineSpanRef, o) * scaleFactor);
- rgba32.R = luminance;
- rgba32.G = luminance;
- rgba32.B = luminance;
-
- pixel.PackFromRgba32(rgba32);
+ pixel.PackFromGray8(new Gray8(luminance));
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@@ -311,14 +289,12 @@ public static void ProcessPaletteScanline(
}
else
{
- // TODO: We should have PackFromRgb24.
- var rgba = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = 0; x < header.Width; x++)
{
int index = Unsafe.Add(ref scanlineSpanRef, x);
- rgba.Rgb = Unsafe.Add(ref palettePixelsRef, index);
+ Rgb24 rgb = Unsafe.Add(ref palettePixelsRef, index);
- pixel.PackFromRgba32(rgba);
+ pixel.PackFromRgb24(rgb);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@@ -358,13 +334,12 @@ public static void ProcessInterlacedPaletteScanline(
}
else
{
- var rgba = new Rgba32(0, 0, 0, byte.MaxValue);
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o++)
{
int index = Unsafe.Add(ref scanlineSpanRef, o);
- rgba.Rgb = Unsafe.Add(ref palettePixelsRef, index);
+ Rgb24 rgb = Unsafe.Add(ref palettePixelsRef, index);
- pixel.PackFromRgba32(rgba);
+ pixel.PackFromRgb24(rgb);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
@@ -511,14 +486,14 @@ public static void ProcessInterlacedRgbScanline(
}
else
{
- var rgba = new Rgba32(0, 0, 0, byte.MaxValue);
+ Rgb24 rgb = default;
for (int x = pixelOffset, o = 0; x < header.Width; x += increment, o += bytesPerPixel)
{
- rgba.R = Unsafe.Add(ref scanlineSpanRef, o);
- rgba.G = Unsafe.Add(ref scanlineSpanRef, o + bytesPerSample);
- rgba.B = Unsafe.Add(ref scanlineSpanRef, o + (2 * bytesPerSample));
+ rgb.R = Unsafe.Add(ref scanlineSpanRef, o);
+ rgb.G = Unsafe.Add(ref scanlineSpanRef, o + bytesPerSample);
+ rgb.B = Unsafe.Add(ref scanlineSpanRef, o + (2 * bytesPerSample));
- pixel.PackFromRgba32(rgba);
+ pixel.PackFromRgb24(rgb);
Unsafe.Add(ref rowSpanRef, x) = pixel;
}
}
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index be1792ced1..ecf9e13ceb 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Buffers;
-using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
@@ -289,22 +287,16 @@ internal ImageFrame CloneAs(Configuration configuration)
var target = new ImageFrame(configuration, this.Width, this.Height, this.MetaData.DeepClone());
- ParallelHelper.IterateRowsWithTempBuffer(
+ ParallelHelper.IterateRows(
this.Bounds(),
configuration,
- (rows, tempRowBuffer) =>
+ (rows) =>
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span sourceRow = this.GetPixelRowSpan(y);
Span targetRow = target.GetPixelRowSpan(y);
- Span tempRowSpan = tempRowBuffer.Span;
-
- PixelOperations.Instance.ToScaledVector4(sourceRow, tempRowSpan, sourceRow.Length);
- PixelOperations.Instance.PackFromScaledVector4(
- tempRowSpan,
- targetRow,
- targetRow.Length);
+ PixelOperations.Instance.To(sourceRow, targetRow, sourceRow.Length);
}
});
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 83b2b12604..17e417dca8 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -76,10 +76,42 @@
TextTemplatingFileGenerator
PixelOperations{TPixel}.Generated.cs
+
+ TextTemplatingFileGenerator
+ Argb32.PixelOperations.Generated.cs
+
+
+ TextTemplatingFileGenerator
+ Bgr24.PixelOperations.Generated.cs
+
+
+ TextTemplatingFileGenerator
+ Bgra32.PixelOperations.Generated.cs
+
+
+ TextTemplatingFileGenerator
+ Gray8.PixelOperations.Generated.cs
+
+
+ TextTemplatingFileGenerator
+ Gray16.PixelOperations.Generated.cs
+
+
+ TextTemplatingFileGenerator
+ Rgb24.PixelOperations.Generated.cs
+
TextTemplatingFileGenerator
Rgba32.PixelOperations.Generated.cs
+
+ TextTemplatingFileGenerator
+ Rgb48.PixelOperations.Generated.cs
+
+
+ TextTemplatingFileGenerator
+ Rgba64.PixelOperations.Generated.cs
+
PorterDuffFunctions.Generated.cs
TextTemplatingFileGenerator
@@ -110,11 +142,51 @@
True
PixelOperations{TPixel}.Generated.tt
+
+ True
+ True
+ Argb32.PixelOperations.Generated.tt
+
+
+ True
+ True
+ Bgr24.PixelOperations.Generated.tt
+
+
+ True
+ True
+ Bgra32.PixelOperations.Generated.tt
+
+
+ True
+ True
+ Gray8.PixelOperations.Generated.tt
+
+
+ True
+ True
+ Gray16.PixelOperations.Generated.tt
+
+
+ True
+ True
+ Rgb24.PixelOperations.Generated.tt
+
True
True
Rgba32.PixelOperations.Generated.tt
+
+ True
+ True
+ Rgb48.PixelOperations.Generated.tt
+
+
+ True
+ True
+ Rgba64.PixelOperations.Generated.tt
+
True
True
diff --git a/src/ImageSharp/PixelFormats/Alpha8.cs b/src/ImageSharp/PixelFormats/Alpha8.cs
index a8d97d31a2..1e724768d0 100644
--- a/src/ImageSharp/PixelFormats/Alpha8.cs
+++ b/src/ImageSharp/PixelFormats/Alpha8.cs
@@ -18,11 +18,14 @@ public struct Alpha8 : IPixel, IPackedVector
///
/// Initializes a new instance of the struct.
///
- /// The alpha component
- public Alpha8(float alpha)
- {
- this.PackedValue = Pack(alpha);
- }
+ /// The alpha component.
+ public Alpha8(byte alpha) => this.PackedValue = alpha;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ /// The alpha component.
+ public Alpha8(float alpha) => this.PackedValue = Pack(alpha);
///
public byte PackedValue { get; set; }
@@ -39,11 +42,8 @@ public Alpha8(float alpha)
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Alpha8 left, Alpha8 right)
- {
- return left.PackedValue == right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Alpha8 left, Alpha8 right) => left.Equals(right);
///
/// Compares two objects for equality.
@@ -53,161 +53,91 @@ public Alpha8(float alpha)
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Alpha8 left, Alpha8 right)
- {
- return left.PackedValue != right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Alpha8 left, Alpha8 right) => !left.Equals(right);
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4();
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
- {
- this.PackedValue = Pack(vector.W);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(vector.W);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToVector4()
- {
- return new Vector4(0, 0, 0, this.PackedValue / 255F);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToVector4() => new Vector4(0, 0, 0, this.PackedValue / 255F);
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
- {
- this.PackedValue = source.A;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source) => this.PackedValue = source.A;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
- {
- this.PackedValue = source.A;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source) => this.PackedValue = byte.MaxValue;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromBgra32(Bgra32 source)
- {
- this.PackedValue = source.A;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgra32(Bgra32 source) => this.PackedValue = source.A;
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
- {
- dest = default(Rgb24);
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source) => this.PackedValue = byte.MaxValue;
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
- {
- dest.R = 0;
- dest.G = 0;
- dest.B = 0;
- dest.A = this.PackedValue;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source) => this.PackedValue = byte.MaxValue;
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
- {
- dest.R = 0;
- dest.G = 0;
- dest.B = 0;
- dest.A = this.PackedValue;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source) => this.PackedValue = byte.MaxValue;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest)
- {
- dest = default(Bgr24);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source) => this.PackedValue = source.A;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest)
- {
- dest.R = 0;
- dest.G = 0;
- dest.B = 0;
- dest.A = this.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Rgba32 ToRgba32() => new Rgba32(0, 0, 0, this.PackedValue);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackedValue = byte.MaxValue;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest)
- {
- dest.R = 0;
- dest.G = 0;
- dest.B = 0;
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
///
/// Compares an object with the packed vector.
///
/// The object to compare.
/// True if the object is equal to the packed vector.
- public override bool Equals(object obj)
- {
- return obj is Alpha8 other && this.Equals(other);
- }
+ public override bool Equals(object obj) => obj is Alpha8 other && this.Equals(other);
///
/// Compares another Alpha8 packed vector with the packed vector.
///
/// The Alpha8 packed vector to compare.
/// True if the packed vectors are equal.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Alpha8 other)
- {
- return this.PackedValue == other.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Alpha8 other) => this.PackedValue.Equals(other.PackedValue);
///
/// Gets a string representation of the packed vector.
///
/// A string representation of the packed vector.
- public override string ToString()
- {
- return (this.PackedValue / 255F).ToString();
- }
+ public override string ToString() => $"Alpha8({this.PackedValue})";
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
///
@@ -215,10 +145,7 @@ public override string ToString()
///
/// The float containing the value to pack.
/// The containing the packed values.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static byte Pack(float alpha)
- {
- return (byte)Math.Round(alpha.Clamp(0, 1) * 255F);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private static byte Pack(float alpha) => (byte)Math.Round(alpha.Clamp(0, 1F) * 255F);
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Argb32.cs b/src/ImageSharp/PixelFormats/Argb32.cs
index 51d3964ef8..1e3bd93262 100644
--- a/src/ImageSharp/PixelFormats/Argb32.cs
+++ b/src/ImageSharp/PixelFormats/Argb32.cs
@@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// as it avoids the need to create new values for modification operations.
///
[StructLayout(LayoutKind.Sequential)]
- public struct Argb32 : IPixel, IPackedVector
+ public partial struct Argb32 : IPixel, IPackedVector
{
///
/// Gets or sets the alpha component.
@@ -57,7 +57,7 @@ public struct Argb32 : IPixel, IPackedVector
/// The red component.
/// The green component.
/// The blue component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Argb32(byte r, byte g, byte b)
{
this.R = r;
@@ -73,7 +73,7 @@ public Argb32(byte r, byte g, byte b)
/// The green component.
/// The blue component.
/// The alpha component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Argb32(byte r, byte g, byte b, byte a)
{
this.R = r;
@@ -89,12 +89,9 @@ public Argb32(byte r, byte g, byte b, byte a)
/// The green component.
/// The blue component.
/// The alpha component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Argb32(float r, float g, float b, float a = 1)
- : this()
- {
- this.Pack(r, g, b, a);
- }
+ : this() => this.Pack(r, g, b, a);
///
/// Initializes a new instance of the struct.
@@ -102,12 +99,9 @@ public Argb32(float r, float g, float b, float a = 1)
///
/// The vector containing the components for the packed vector.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Argb32(Vector3 vector)
- : this()
- {
- this.Pack(ref vector);
- }
+ : this() => this.Pack(ref vector);
///
/// Initializes a new instance of the struct.
@@ -115,12 +109,9 @@ public Argb32(Vector3 vector)
///
/// The vector containing the components for the packed vector.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Argb32(Vector4 vector)
- : this()
- {
- this.Pack(ref vector);
- }
+ : this() => this.Pack(ref vector);
///
/// Initializes a new instance of the struct.
@@ -128,22 +119,19 @@ public Argb32(Vector4 vector)
///
/// The packed value.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Argb32(uint packed)
- : this()
- {
- this.Argb = packed;
- }
+ : this() => this.Argb = packed;
///
/// Gets or sets the packed representation of the Argb32 struct.
///
public uint Argb
{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As(ref this);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As(ref this) = value;
}
@@ -157,20 +145,13 @@ public uint PackedValue
///
/// Compares two objects for equality.
///
- ///
- /// The on the left side of the operand.
- ///
- ///
- /// The on the right side of the operand.
- ///
+ /// The on the left side of the operand.
+ /// The on the right side of the operand.
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Argb32 left, Argb32 right)
- {
- return left.Argb == right.Argb;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Argb32 left, Argb32 right) => left.Equals(right);
///
/// Compares two objects for equality.
@@ -180,62 +161,44 @@ public uint PackedValue
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Argb32 left, Argb32 right)
- {
- return left.Argb != right.Argb;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Argb32 left, Argb32 right) => !left.Equals(right);
+
+ ///
+ public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
- {
- this.Pack(ref vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
- ///
- public PixelOperations CreatePixelOperations() => new PixelOperations();
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4();
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToVector4()
- {
- return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source) => this.PackedValue = source.PackedValue;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source)
{
this.R = source.R;
this.G = source.G;
this.B = source.B;
- this.A = source.A;
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
- {
- this.PackedValue = source.PackedValue;
+ this.A = byte.MaxValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.R = source.R;
@@ -244,136 +207,88 @@ public void PackFromBgra32(Bgra32 source)
this.A = source.A;
}
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
+ this.R = source.PackedValue;
+ this.G = source.PackedValue;
+ this.B = source.PackedValue;
+ this.A = byte.MaxValue;
}
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = this.A;
+ byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
+ this.R = rgb;
+ this.G = rgb;
+ this.B = rgb;
+ this.A = byte.MaxValue;
}
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source)
{
- dest = this;
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = byte.MaxValue;
}
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest)
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest)
- {
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = this.A;
- }
-
- ///
- /// Converts the pixel to format.
- ///
- /// The RGBA value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
- ///
- /// Converts the pixel to format.
- ///
- /// The RGBA value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Bgra32 ToBgra32() => new Bgra32(this.R, this.G, this.B, this.A);
-
- ///
- /// Converts the pixel to format.
- ///
- /// The RGBA value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Argb32 ToArgb32() => this;
-
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
- this.R = (byte)(((source.R * 255) + 32895) >> 16);
- this.G = (byte)(((source.G * 255) + 32895) >> 16);
- this.B = (byte)(((source.B * 255) + 32895) >> 16);
+ this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
+ this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
+ this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
- this.R = (byte)(((source.R * 255) + 32895) >> 16);
- this.G = (byte)(((source.G * 255) + 32895) >> 16);
- this.B = (byte)(((source.B * 255) + 32895) >> 16);
- this.A = (byte)(((source.A * 255) + 32895) >> 16);
+ this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
+ this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
+ this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
+ this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- public override bool Equals(object obj)
- {
- return obj is Argb32 argb32 && this.Equals(argb32);
- }
+ public override bool Equals(object obj) => obj is Argb32 argb32 && this.Equals(argb32);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Argb32 other)
- {
- return this.Argb == other.Argb;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Argb32 other) => this.Argb == other.Argb;
///
/// Gets a string representation of the packed vector.
///
/// A string representation of the packed vector.
- public override string ToString()
- {
- return $"({this.R},{this.G},{this.B},{this.A})";
- }
+ public override string ToString() => $"Argb({this.A}, {this.R}, {this.G}, {this.B})";
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.Argb.GetHashCode();
- ///
- /// Gets the representation without normalizing to [0, 1]
- ///
- /// A of values in [0, 255]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Vector4 ToByteScaledVector4()
- {
- return new Vector4(this.R, this.G, this.B, this.A);
- }
-
///
/// Packs the four floats into a color.
///
@@ -381,7 +296,7 @@ internal Vector4 ToByteScaledVector4()
/// The y-component
/// The z-component
/// The w-component
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
private void Pack(float x, float y, float z, float w)
{
var value = new Vector4(x, y, z, w);
@@ -392,7 +307,7 @@ private void Pack(float x, float y, float z, float w)
/// Packs a into a uint.
///
/// The vector containing the values to pack.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector3 vector)
{
var value = new Vector4(vector, 1);
@@ -403,7 +318,7 @@ private void Pack(ref Vector3 vector)
/// Packs a into a color.
///
/// The vector containing the values to pack.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector4 vector)
{
vector *= MaxBytes;
diff --git a/src/ImageSharp/PixelFormats/Bgr24.cs b/src/ImageSharp/PixelFormats/Bgr24.cs
index 1f401f1a13..ed65bebf7f 100644
--- a/src/ImageSharp/PixelFormats/Bgr24.cs
+++ b/src/ImageSharp/PixelFormats/Bgr24.cs
@@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
///
[StructLayout(LayoutKind.Explicit)]
- public struct Bgr24 : IPixel
+ public partial struct Bgr24 : IPixel
{
///
/// The blue component.
@@ -41,7 +41,7 @@ public struct Bgr24 : IPixel
/// The red component.
/// The green component.
/// The blue component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Bgr24(byte r, byte g, byte b)
{
this.R = r;
@@ -49,39 +49,54 @@ public Bgr24(byte r, byte g, byte b)
this.B = b;
}
+ ///
+ /// Compares two objects for equality.
+ ///
+ /// The on the left side of the operand.
+ /// The on the right side of the operand.
+ ///
+ /// True if the parameter is equal to the parameter; otherwise, false.
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Bgr24 left, Bgr24 right) => left.Equals(right);
+
+ ///
+ /// Compares two objects for equality.
+ ///
+ /// The on the left side of the operand.
+ /// The on the right side of the operand.
+ ///
+ /// True if the parameter is not equal to the parameter; otherwise, false.
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Bgr24 left, Bgr24 right) => !left.Equals(right);
+
///
- public PixelOperations CreatePixelOperations() => new PixelOperations();
+ public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Bgr24 other)
- {
- return this.R == other.R && this.G == other.G && this.B == other.B;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
///
- public override bool Equals(object obj)
- {
- return obj is Bgr24 other && this.Equals(other);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public override int GetHashCode()
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector)
{
- int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
- return HashHelpers.Combine(hash, this.B.GetHashCode());
+ Rgba32 rgba = default;
+ rgba.PackFromVector4(vector);
+ this.PackFromRgba32(rgba);
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
- {
- this = source.Bgr;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToVector4() => new Rgba32(this.R, this.G, this.B, byte.MaxValue).ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromArgb32(Argb32 source)
{
this.R = source.R;
@@ -90,7 +105,11 @@ public void PackFromArgb32(Argb32 source)
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source) => this = source;
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromBgra32(Bgra32 source)
{
this.R = source.R;
@@ -99,109 +118,75 @@ public void PackFromBgra32(Bgra32 source)
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source)
{
- return this.ToVector4();
+ this.R = source.PackedValue;
+ this.G = source.PackedValue;
+ this.B = source.PackedValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source)
{
- Rgba32 rgba = default;
- rgba.PackFromVector4(vector);
- this.PackFromRgba32(rgba);
+ byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
+ this.R = rgb;
+ this.G = rgb;
+ this.B = rgb;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToVector4()
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source)
{
- return new Rgba32(this.R, this.G, this.B, 255).ToVector4();
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
- {
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
- {
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = byte.MaxValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source) => this = source.Bgr;
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
- {
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = byte.MaxValue;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, byte.MaxValue);
///
- public void ToBgr24(ref Bgr24 dest)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb48(Rgb48 source)
{
- dest = this;
+ this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
+ this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
+ this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
}
///
- public void ToBgra32(ref Bgra32 dest)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba64(Rgba64 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = byte.MaxValue;
+ this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
+ this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
+ this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgb48(Rgb48 source)
- {
- this.R = (byte)(((source.R * 255) + 32895) >> 16);
- this.G = (byte)(((source.G * 255) + 32895) >> 16);
- this.B = (byte)(((source.B * 255) + 32895) >> 16);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Bgr24 other) => this.R.Equals(other.R) && this.G.Equals(other.G) && this.B.Equals(other.B);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
+ public override bool Equals(object obj) => obj is Bgr24 other && this.Equals(other);
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba64(Rgba64 source)
- {
- this.R = (byte)(((source.R * 255) + 32895) >> 16);
- this.G = (byte)(((source.G * 255) + 32895) >> 16);
- this.B = (byte)(((source.B * 255) + 32895) >> 16);
- }
+ ///
+ public override string ToString() => $"Bgra({this.B}, {this.G}, {this.R})";
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- public override string ToString()
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public override int GetHashCode()
{
- return $"({this.B},{this.G},{this.R})";
+ int hash = HashHelpers.Combine(this.R.GetHashCode(), this.G.GetHashCode());
+ return HashHelpers.Combine(hash, this.B.GetHashCode());
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Bgr565.cs b/src/ImageSharp/PixelFormats/Bgr565.cs
index 570b975dba..04af6ef0f1 100644
--- a/src/ImageSharp/PixelFormats/Bgr565.cs
+++ b/src/ImageSharp/PixelFormats/Bgr565.cs
@@ -8,7 +8,8 @@
namespace SixLabors.ImageSharp.PixelFormats
{
///
- /// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x and z components use 5 bits, and the y component uses 6 bits.
+ /// Packed pixel type containing unsigned normalized values ranging from 0 to 1.
+ /// The x and z components use 5 bits, and the y component uses 6 bits.
///
/// Ranges from [0, 0, 0, 1] to [1, 1, 1, 1] in vector form.
///
@@ -22,8 +23,8 @@ public struct Bgr565 : IPixel, IPackedVector
/// The y-component
/// The z-component
public Bgr565(float x, float y, float z)
+ : this(new Vector3(x, y, z))
{
- this.PackedValue = Pack(x, y, z);
}
///
@@ -32,10 +33,7 @@ public Bgr565(float x, float y, float z)
///
/// The vector containing the components for the packed value.
///
- public Bgr565(Vector3 vector)
- {
- this.PackedValue = Pack(vector.X, vector.Y, vector.Z);
- }
+ public Bgr565(Vector3 vector) => this.PackedValue = Pack(ref vector);
///
public ushort PackedValue { get; set; }
@@ -48,11 +46,8 @@ public Bgr565(Vector3 vector)
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Bgr565 left, Bgr565 right)
- {
- return left.PackedValue == right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Bgr565 left, Bgr565 right) => left.Equals(right);
///
/// Compares two objects for equality.
@@ -62,183 +57,112 @@ public Bgr565(Vector3 vector)
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Bgr565 left, Bgr565 right)
- {
- return left.PackedValue != right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Bgr565 left, Bgr565 right) => !left.Equals(right);
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
- ///
- /// Expands the packed representation into a .
- /// The vector components are typically expanded in least to greatest significance order.
- ///
- /// The .
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector3 ToVector3()
- {
- return new Vector3(
- ((this.PackedValue >> 11) & 0x1F) * (1F / 31F),
- ((this.PackedValue >> 5) & 0x3F) * (1F / 63F),
- (this.PackedValue & 0x1F) * (1F / 31F));
- }
-
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4();
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromVector4(Vector4 vector)
{
- this.PackedValue = Pack(vector.X, vector.Y, vector.Z);
+ var vector3 = new Vector3(vector.X, vector.Y, vector.Z);
+ this.PackedValue = Pack(ref vector3);
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToVector4()
- {
- return new Vector4(this.ToVector3(), 1F);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToVector4() => new Vector4(this.ToVector3(), 1F);
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source) => this.PackFromVector4(source.ToVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgra32(Bgra32 source) => this.PackFromVector4(source.ToVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromBgra32(Bgra32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)MathF.Round(vector.X);
- dest.G = (byte)MathF.Round(vector.Y);
- dest.B = (byte)MathF.Round(vector.Z);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)MathF.Round(vector.X);
- dest.G = (byte)MathF.Round(vector.Y);
- dest.B = (byte)MathF.Round(vector.Z);
- dest.A = (byte)MathF.Round(vector.W);
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)MathF.Round(vector.X);
- dest.G = (byte)MathF.Round(vector.Y);
- dest.B = (byte)MathF.Round(vector.Z);
- dest.A = (byte)MathF.Round(vector.W);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)MathF.Round(vector.X);
- dest.G = (byte)MathF.Round(vector.Y);
- dest.B = (byte)MathF.Round(vector.Z);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source) => this.PackFromVector4(source.ToVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)MathF.Round(vector.X);
- dest.G = (byte)MathF.Round(vector.Y);
- dest.B = (byte)MathF.Round(vector.Z);
- dest.A = (byte)MathF.Round(vector.W);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- public override bool Equals(object obj)
+ ///
+ /// Expands the packed representation into a .
+ /// The vector components are typically expanded in least to greatest significance order.
+ ///
+ /// The .
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector3 ToVector3()
{
- return obj is Bgr565 other && this.Equals(other);
+ return new Vector3(
+ ((this.PackedValue >> 11) & 0x1F) * (1F / 31F),
+ ((this.PackedValue >> 5) & 0x3F) * (1F / 63F),
+ (this.PackedValue & 0x1F) * (1F / 31F));
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Bgr565 other)
- {
- return this.PackedValue == other.PackedValue;
- }
+ public override bool Equals(object obj) => obj is Bgr565 other && this.Equals(other);
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Bgr565 other) => this.PackedValue.Equals(other.PackedValue);
///
public override string ToString()
{
- return this.ToVector3().ToString();
+ var vector = this.ToVector3();
+ return FormattableString.Invariant($"Bgr565({vector.Z:#0.##}, {vector.Y:#0.##}, {vector.X:#0.##})");
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
- ///
- /// Packs the components into a .
- ///
- /// The x-component
- /// The y-component
- /// The z-component
- /// The containing the packed values.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static ushort Pack(float x, float y, float z)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private static ushort Pack(ref Vector3 vector)
{
- return (ushort)((((int)Math.Round(x.Clamp(0, 1) * 31F) & 0x1F) << 11)
- | (((int)Math.Round(y.Clamp(0, 1) * 63F) & 0x3F) << 5)
- | ((int)Math.Round(z.Clamp(0, 1) * 31F) & 0x1F));
+ vector = Vector3.Clamp(vector, Vector3.Zero, Vector3.One);
+
+ return (ushort)((((int)Math.Round(vector.X * 31F) & 0x1F) << 11)
+ | (((int)Math.Round(vector.Y * 63F) & 0x3F) << 5)
+ | ((int)Math.Round(vector.Z * 31F) & 0x1F));
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Bgra32.cs b/src/ImageSharp/PixelFormats/Bgra32.cs
index ff52600081..9b0ed4f96d 100644
--- a/src/ImageSharp/PixelFormats/Bgra32.cs
+++ b/src/ImageSharp/PixelFormats/Bgra32.cs
@@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.PixelFormats
///
///
[StructLayout(LayoutKind.Sequential)]
- public struct Bgra32 : IPixel, IPackedVector
+ public partial struct Bgra32 : IPixel, IPackedVector
{
///
/// Gets or sets the blue component.
@@ -54,7 +54,7 @@ public struct Bgra32 : IPixel, IPackedVector
/// The red component.
/// The green component.
/// The blue component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Bgra32(byte r, byte g, byte b)
{
this.R = r;
@@ -70,7 +70,7 @@ public Bgra32(byte r, byte g, byte b)
/// The green component.
/// The blue component.
/// The alpha component.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Bgra32(byte r, byte g, byte b, byte a)
{
this.R = r;
@@ -84,10 +84,10 @@ public Bgra32(byte r, byte g, byte b, byte a)
///
public uint Bgra
{
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
get => Unsafe.As(ref this);
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
set => Unsafe.As(ref this) = value;
}
@@ -98,62 +98,50 @@ public uint PackedValue
set => this.Bgra = value;
}
- ///
- public PixelOperations CreatePixelOperations() => new PixelOperations();
-
- ///
- public bool Equals(Bgra32 other)
- {
- return this.Bgra == other.Bgra;
- }
-
- ///
- public override bool Equals(object obj) => obj is Bgra32 other && this.Equals(other);
-
- ///
- public override int GetHashCode() => this.Bgra.GetHashCode();
+ ///
+ /// Compares two objects for equality.
+ ///
+ /// The on the left side of the operand.
+ /// The on the right side of the operand.
+ ///
+ /// True if the parameter is equal to the parameter; otherwise, false.
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Bgra32 left, Bgra32 right) => left.Equals(right);
///
- /// Gets the representation without normalizing to [0, 1]
+ /// Compares two objects for equality.
///
- /// A of values in [0, 255]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Vector4 ToByteScaledVector4()
- {
- return new Vector4(this.R, this.G, this.B, this.A);
- }
+ /// The on the left side of the operand.
+ /// The on the right side of the operand.
+ ///
+ /// True if the parameter is not equal to the parameter; otherwise, false.
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Bgra32 left, Bgra32 right) => !left.Equals(right);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
+ public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4();
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
- {
- this.Pack(ref vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToVector4()
- {
- return new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector) => this.Pack(ref vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToVector4() => new Vector4(this.R, this.G, this.B, this.A) / MaxBytes;
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source)
{
this.R = source.R;
this.G = source.G;
@@ -162,113 +150,101 @@ public void PackFromRgba32(Rgba32 source)
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source)
{
this.R = source.R;
this.G = source.G;
this.B = source.B;
- this.A = source.A;
+ this.A = byte.MaxValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromBgra32(Bgra32 source)
- {
- this.PackedValue = source.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgra32(Bgra32 source) => this = source;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
+ this.R = source.PackedValue;
+ this.G = source.PackedValue;
+ this.B = source.PackedValue;
+ this.A = byte.MaxValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = this.A;
+ byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
+ this.R = rgb;
+ this.G = rgb;
+ this.B = rgb;
+ this.A = byte.MaxValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source)
{
- dest.R = this.R;
- dest.G = this.G;
- dest.B = this.B;
- dest.A = this.A;
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = source.A;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest) => dest = Unsafe.As(ref this);
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest) => dest = this;
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source)
+ {
+ this.R = source.R;
+ this.G = source.G;
+ this.B = source.B;
+ this.A = byte.MaxValue;
+ }
- ///
- /// Converts the pixel to format.
- ///
- /// The RGBA value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A);
- ///
- /// Converts the pixel to format.
- ///
- /// The RGBA value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Argb32 ToArgb32() => new Argb32(this.R, this.G, this.B, this.A);
-
- ///
- /// Converts the pixel to format.
- ///
- /// The RGBA value
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Bgra32 ToBgra32() => this;
-
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source)
{
- this.R = (byte)(((source.R * 255) + 32895) >> 16);
- this.G = (byte)(((source.G * 255) + 32895) >> 16);
- this.B = (byte)(((source.B * 255) + 32895) >> 16);
+ this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
+ this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
+ this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source)
{
- this.R = (byte)(((source.R * 255) + 32895) >> 16);
- this.G = (byte)(((source.G * 255) + 32895) >> 16);
- this.B = (byte)(((source.B * 255) + 32895) >> 16);
- this.A = (byte)(((source.A * 255) + 32895) >> 16);
+ this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
+ this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
+ this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
+ this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
+ public override bool Equals(object obj) => obj is Bgra32 other && this.Equals(other);
+
+ ///
+ public bool Equals(Bgra32 other) => this.Bgra.Equals(other.Bgra);
+
+ ///
+ public override int GetHashCode() => this.Bgra.GetHashCode();
+
+ ///
+ public override string ToString() => $"Bgra32({this.B}, {this.G}, {this.R}, {this.A})";
///
/// Packs a into a color.
///
/// The vector containing the values to pack.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
private void Pack(ref Vector4 vector)
{
vector *= MaxBytes;
@@ -280,11 +256,5 @@ private void Pack(ref Vector4 vector)
this.B = (byte)vector.Z;
this.A = (byte)vector.W;
}
-
- ///
- public override string ToString()
- {
- return $"({this.B},{this.G},{this.R},{this.A})";
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Bgra4444.cs b/src/ImageSharp/PixelFormats/Bgra4444.cs
index 90f967f898..db1c8f865a 100644
--- a/src/ImageSharp/PixelFormats/Bgra4444.cs
+++ b/src/ImageSharp/PixelFormats/Bgra4444.cs
@@ -23,18 +23,15 @@ public struct Bgra4444 : IPixel, IPackedVector
/// The z-component
/// The w-component
public Bgra4444(float x, float y, float z, float w)
+ : this(new Vector4(x, y, z, w))
{
- this.PackedValue = Pack(x, y, z, w);
}
///
/// Initializes a new instance of the struct.
///
/// The vector containing the components for the packed vector.
- public Bgra4444(Vector4 vector)
- {
- this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
- }
+ public Bgra4444(Vector4 vector) => this.PackedValue = Pack(ref vector);
///
public ushort PackedValue { get; set; }
@@ -47,11 +44,8 @@ public Bgra4444(Vector4 vector)
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Bgra4444 left, Bgra4444 right)
- {
- return left.PackedValue == right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Bgra4444 left, Bgra4444 right) => left.Equals(right);
///
/// Compares two objects for equality.
@@ -61,177 +55,103 @@ public Bgra4444(Vector4 vector)
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Bgra4444 left, Bgra4444 right)
- {
- return left.PackedValue != right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Bgra4444 left, Bgra4444 right) => !left.Equals(right);
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4();
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
const float Max = 1 / 15F;
return new Vector4(
- ((this.PackedValue >> 8) & 0x0F) * Max,
- ((this.PackedValue >> 4) & 0x0F) * Max,
- (this.PackedValue & 0x0F) * Max,
- ((this.PackedValue >> 12) & 0x0F) * Max);
+ (this.PackedValue >> 8) & 0x0F,
+ (this.PackedValue >> 4) & 0x0F,
+ this.PackedValue & 0x0F,
+ (this.PackedValue >> 12) & 0x0F) * Max;
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
- {
- this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromBgra32(Bgra32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest)
- {
- Vector4 vector = this.ToVector4() * 255F;
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
///
- public override bool Equals(object obj)
- {
- return obj is Bgra4444 other && this.Equals(other);
- }
+ public override bool Equals(object obj) => obj is Bgra4444 other && this.Equals(other);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Bgra4444 other)
- {
- return this.PackedValue == other.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Bgra4444 other) => this.PackedValue.Equals(other.PackedValue);
///
public override string ToString()
{
- return this.ToVector4().ToString();
+ var vector = this.ToVector4();
+ return FormattableString.Invariant($"Bgra4444({vector.Z:#0.##}, {vector.Y:#0.##}, {vector.X:#0.##}, {vector.W:#0.##})");
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
- ///
- /// Packs the components into a .
- ///
- /// The x-component
- /// The y-component
- /// The z-component
- /// The w-component
- /// The containing the packed values.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static ushort Pack(float x, float y, float z, float w)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private static ushort Pack(ref Vector4 vector)
{
- return (ushort)((((int)Math.Round(w.Clamp(0, 1) * 15F) & 0x0F) << 12) |
- (((int)Math.Round(x.Clamp(0, 1) * 15F) & 0x0F) << 8) |
- (((int)Math.Round(y.Clamp(0, 1) * 15F) & 0x0F) << 4) |
- ((int)Math.Round(z.Clamp(0, 1) * 15F) & 0x0F));
+ vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
+ return (ushort)((((int)Math.Round(vector.W * 15F) & 0x0F) << 12)
+ | (((int)Math.Round(vector.X * 15F) & 0x0F) << 8)
+ | (((int)Math.Round(vector.Y * 15F) & 0x0F) << 4)
+ | ((int)Math.Round(vector.Z * 15F) & 0x0F));
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Bgra5551.cs b/src/ImageSharp/PixelFormats/Bgra5551.cs
index 3a18c03e83..5d9003cdd3 100644
--- a/src/ImageSharp/PixelFormats/Bgra5551.cs
+++ b/src/ImageSharp/PixelFormats/Bgra5551.cs
@@ -8,7 +8,8 @@
namespace SixLabors.ImageSharp.PixelFormats
{
///
- /// Packed pixel type containing unsigned normalized values ranging from 0 to 1. The x , y and z components use 5 bits, and the w component uses 1 bit.
+ /// Packed pixel type containing unsigned normalized values ranging from 0 to 1.
+ /// The x , y and z components use 5 bits, and the w component uses 1 bit.
///
/// Ranges from [0, 0, 0, 0] to [1, 1, 1, 1] in vector form.
///
@@ -23,8 +24,8 @@ public struct Bgra5551 : IPixel, IPackedVector
/// The z-component
/// The w-component
public Bgra5551(float x, float y, float z, float w)
+ : this(new Vector4(x, y, z, w))
{
- this.PackedValue = Pack(x, y, z, w);
}
///
@@ -33,10 +34,7 @@ public Bgra5551(float x, float y, float z, float w)
///
/// The vector containing the components for the packed vector.
///
- public Bgra5551(Vector4 vector)
- {
- this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
- }
+ public Bgra5551(Vector4 vector) => this.PackedValue = Pack(ref vector);
///
public ushort PackedValue { get; set; }
@@ -49,11 +47,8 @@ public Bgra5551(Vector4 vector)
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Bgra5551 left, Bgra5551 right)
- {
- return left.PackedValue == right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Bgra5551 left, Bgra5551 right) => left.Equals(right);
///
/// Compares two objects for equality.
@@ -63,31 +58,26 @@ public Bgra5551(Vector4 vector)
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Bgra5551 left, Bgra5551 right)
- {
- return left.PackedValue != right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Bgra5551 left, Bgra5551 right) => !left.Equals(right);
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4();
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4();
+
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@@ -98,150 +88,72 @@ public Vector4 ToVector4()
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
- {
- this.PackedValue = Pack(vector.X, vector.Y, vector.Z, vector.W);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromBgra32(Bgra32 source)
- {
- this.PackFromVector4(source.ToVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
- {
- Vector4 vector = this.ToByteScaledVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
- {
- Vector4 vector = this.ToByteScaledVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
- {
- Vector4 vector = this.ToByteScaledVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest)
- {
- Vector4 vector = this.ToByteScaledVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest)
- {
- Vector4 vector = this.ToByteScaledVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
///
- public override bool Equals(object obj)
- {
- return obj is Bgra5551 other && this.Equals(other);
- }
+ public override bool Equals(object obj) => obj is Bgra5551 other && this.Equals(other);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Bgra5551 other)
- {
- return this.PackedValue == other.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Bgra5551 other) => this.PackedValue.Equals(other.PackedValue);
- ///
- /// Gets a string representation of the packed vector.
- ///
- /// A string representation of the packed vector.
+ ///
public override string ToString()
{
- return this.ToVector4().ToString();
+ var vector = this.ToVector4();
+ return FormattableString.Invariant($"Bgra5551({vector.Z:#0.##}, {vector.Y:#0.##}, {vector.X:#0.##}, {vector.W:#0.##})");
}
- ///
- /// Gets a hash code of the packed vector.
- ///
- /// The hash code for the packed vector.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
- ///
- /// Packs the components into a .
- ///
- /// The x-component
- /// The y-component
- /// The z-component
- /// The w-component
- /// The containing the packed values.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static ushort Pack(float x, float y, float z, float w)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private static ushort Pack(ref Vector4 vector)
{
+ vector = Vector4.Clamp(vector, Vector4.Zero, Vector4.One);
return (ushort)(
- (((int)Math.Round(x.Clamp(0, 1) * 31F) & 0x1F) << 10)
- | (((int)Math.Round(y.Clamp(0, 1) * 31F) & 0x1F) << 5)
- | (((int)Math.Round(z.Clamp(0, 1) * 31F) & 0x1F) << 0)
- | (((int)Math.Round(w.Clamp(0, 1)) & 0x1) << 15));
+ (((int)Math.Round(vector.X * 31F) & 0x1F) << 10)
+ | (((int)Math.Round(vector.Y * 31F) & 0x1F) << 5)
+ | (((int)Math.Round(vector.Z * 31F) & 0x1F) << 0)
+ | (((int)Math.Round(vector.W) & 0x1) << 15));
}
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Vector4 ToByteScaledVector4() => this.ToVector4() * 255f;
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Byte4.cs b/src/ImageSharp/PixelFormats/Byte4.cs
index bb1b350f07..230c31c5c3 100644
--- a/src/ImageSharp/PixelFormats/Byte4.cs
+++ b/src/ImageSharp/PixelFormats/Byte4.cs
@@ -21,10 +21,7 @@ public struct Byte4 : IPixel, IPackedVector
///
/// A vector containing the initial values for the components of the Byte4 structure.
///
- public Byte4(Vector4 vector)
- {
- this.PackedValue = Pack(ref vector);
- }
+ public Byte4(Vector4 vector) => this.PackedValue = Pack(ref vector);
///
/// Initializes a new instance of the struct.
@@ -50,11 +47,8 @@ public Byte4(float x, float y, float z, float w)
///
/// True if the parameter is equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator ==(Byte4 left, Byte4 right)
- {
- return left.PackedValue == right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator ==(Byte4 left, Byte4 right) => left.Equals(right);
///
/// Compares two objects for equality.
@@ -64,38 +58,26 @@ public Byte4(float x, float y, float z, float w)
///
/// True if the parameter is not equal to the parameter; otherwise, false.
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool operator !=(Byte4 left, Byte4 right)
- {
- return left.PackedValue != right.PackedValue;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static bool operator !=(Byte4 left, Byte4 right) => !left.Equals(right);
///
public PixelOperations CreatePixelOperations() => new PixelOperations();
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromScaledVector4(Vector4 vector)
- {
- this.PackFromVector4(vector * 255F);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromScaledVector4(Vector4 vector) => this.PackFromVector4(vector * 255F);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public Vector4 ToScaledVector4()
- {
- return this.ToVector4() / 255F;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Vector4 ToScaledVector4() => this.ToVector4() / 255F;
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromVector4(Vector4 vector)
- {
- this.PackedValue = Pack(ref vector);
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromVector4(Vector4 vector) => this.PackedValue = Pack(ref vector);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public Vector4 ToVector4()
{
return new Vector4(
@@ -106,119 +88,61 @@ public Vector4 ToVector4()
}
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromRgba32(Rgba32 source)
- {
- this.PackFromVector4(source.ToByteScaledVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromArgb32(Argb32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromArgb32(Argb32 source)
- {
- this.PackFromVector4(source.ToByteScaledVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgr24(Bgr24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void PackFromBgra32(Bgra32 source)
- {
- this.PackFromVector4(source.ToByteScaledVector4());
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromBgra32(Bgra32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb24(ref Rgb24 dest)
- {
- var vector = this.ToVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray8(Gray8 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba32(ref Rgba32 dest)
- {
- var vector = this.ToVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ ///
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromGray16(Gray16 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToArgb32(ref Argb32 dest)
- {
- var vector = this.ToVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgb24(Rgb24 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgr24(ref Bgr24 dest)
- {
- var vector = this.ToVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void PackFromRgba32(Rgba32 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToBgra32(ref Bgra32 dest)
- {
- var vector = this.ToVector4();
- dest.R = (byte)vector.X;
- dest.G = (byte)vector.Y;
- dest.B = (byte)vector.Z;
- dest.A = (byte)vector.W;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public Rgba32 ToRgba32() => new Rgba32(this.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgb48(Rgb48 source) => this.PackFromScaledVector4(source.ToScaledVector4());
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgb48(ref Rgb48 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public void PackFromRgba64(Rgba64 source) => this.PackFromScaledVector4(source.ToScaledVector4());
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void ToRgba64(ref Rgba64 dest) => dest.PackFromScaledVector4(this.ToScaledVector4());
-
///
- public override bool Equals(object obj)
- {
- return obj is Byte4 byte4 && this.Equals(byte4);
- }
+ public override bool Equals(object obj) => obj is Byte4 byte4 && this.Equals(byte4);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public bool Equals(Byte4 other)
- {
- return this == other;
- }
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public bool Equals(Byte4 other) => this.PackedValue.Equals(other.PackedValue);
///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode() => this.PackedValue.GetHashCode();
- ///
- /// Returns a string representation of the current instance.
- ///
- /// String that represents the object.
+ ///
public override string ToString()
{
- return this.PackedValue.ToString("x8");
+ var vector = this.ToVector4();
+ return FormattableString.Invariant($"Bgra5551({vector.X:#0.##}, {vector.Y:#0.##}, {vector.Z:#0.##}, {vector.W:#0.##})");
}
///
@@ -226,18 +150,18 @@ public override string ToString()
///
/// The vector containing the values to pack.
/// The containing the packed values.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
const float Max = 255F;
- const float Min = 0F;
// Clamp the value between min and max values
- // TODO: Use Vector4.Clamp() here!
- uint byte4 = (uint)Math.Round(vector.X.Clamp(Min, Max)) & 0xFF;
- uint byte3 = ((uint)Math.Round(vector.Y.Clamp(Min, Max)) & 0xFF) << 0x8;
- uint byte2 = ((uint)Math.Round(vector.Z.Clamp(Min, Max)) & 0xFF) << 0x10;
- uint byte1 = ((uint)Math.Round(vector.W.Clamp(Min, Max)) & 0xFF) << 0x18;
+ vector = Vector4.Clamp(vector, Vector4.Zero, new Vector4(Max));
+
+ uint byte4 = (uint)Math.Round(vector.X) & 0xFF;
+ uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 0x8;
+ uint byte2 = ((uint)Math.Round(vector.Z) & 0xFF) << 0x10;
+ uint byte1 = ((uint)Math.Round(vector.W) & 0xFF) << 0x18;
return byte4 | byte3 | byte2 | byte1;
}
diff --git a/src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.cs
new file mode 100644
index 0000000000..0b40df8dae
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.cs
@@ -0,0 +1,177 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Argb32
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromArgb32(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+
+ ///
+ internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.tt
new file mode 100644
index 0000000000..f35adee022
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Argb32.PixelOperations.Generated.tt
@@ -0,0 +1,85 @@
+<#
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+#>
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+<#
+ void GenerateConvertToMethod(string pixelType)
+ {
+ #>
+
+ ///
+ internal override void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Argb32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Argb32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromArgb32(sp);
+ }
+ }
+ <#
+ }
+#>
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Argb32
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromArgb32(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+ <#
+ GenerateConvertToMethod("Bgr24");
+ GenerateConvertToMethod("Bgra32");
+ GenerateConvertToMethod("Gray8");
+ GenerateConvertToMethod("Gray16");
+ GenerateConvertToMethod("Rgb24");
+ GenerateConvertToMethod("Rgba32");
+ GenerateConvertToMethod("Rgb48");
+ GenerateConvertToMethod("Rgba64");
+ #>
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.cs
new file mode 100644
index 0000000000..e895254576
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.cs
@@ -0,0 +1,177 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Bgr24
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+
+ ///
+ internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.tt
new file mode 100644
index 0000000000..76163549b0
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Bgr24.PixelOperations.Generated.tt
@@ -0,0 +1,85 @@
+<#
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+#>
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+<#
+ void GenerateConvertToMethod(string pixelType)
+ {
+ #>
+
+ ///
+ internal override void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgr24 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgr24(sp);
+ }
+ }
+ <#
+ }
+#>
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Bgr24
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromBgr24(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+ <#
+ GenerateConvertToMethod("Argb32");
+ GenerateConvertToMethod("Bgra32");
+ GenerateConvertToMethod("Gray8");
+ GenerateConvertToMethod("Gray16");
+ GenerateConvertToMethod("Rgb24");
+ GenerateConvertToMethod("Rgba32");
+ GenerateConvertToMethod("Rgb48");
+ GenerateConvertToMethod("Rgba64");
+ #>
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.cs
new file mode 100644
index 0000000000..2311e0bde6
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.cs
@@ -0,0 +1,177 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Bgra32
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+
+ ///
+ internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray16 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray16 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb48(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb48 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb48 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba64(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba64 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba64 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.tt b/src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.tt
new file mode 100644
index 0000000000..4c2925d18f
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Bgra32.PixelOperations.Generated.tt
@@ -0,0 +1,85 @@
+<#
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+#>
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+<#
+ void GenerateConvertToMethod(string pixelType)
+ {
+ #>
+
+ ///
+ internal override void To<#=pixelType#>(ReadOnlySpan sourcePixels, Span<<#=pixelType#>> destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Bgra32 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref <#=pixelType#> destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromBgra32(sp);
+ }
+ }
+ <#
+ }
+#>
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Bgra32
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromBgra32(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+ <#
+ GenerateConvertToMethod("Argb32");
+ GenerateConvertToMethod("Bgr24");
+ GenerateConvertToMethod("Gray8");
+ GenerateConvertToMethod("Gray16");
+ GenerateConvertToMethod("Rgb24");
+ GenerateConvertToMethod("Rgba32");
+ GenerateConvertToMethod("Rgb48");
+ GenerateConvertToMethod("Rgba64");
+ #>
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.cs
new file mode 100644
index 0000000000..a2d9aa755f
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Generated/Gray16.PixelOperations.Generated.cs
@@ -0,0 +1,177 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+//
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ public partial struct Gray16
+ {
+
+ ///
+ /// Provides optimized overrides for bulk operations.
+ ///
+ internal class PixelOperations : PixelOperations
+ {
+ ///
+ internal override void PackFromGray16(ReadOnlySpan source, Span destPixels, int count)
+ {
+ GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count);
+
+ source.Slice(0, count).CopyTo(destPixels);
+ }
+
+ ///
+ internal override void ToGray16(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ sourcePixels.Slice(0, count).CopyTo(destPixels);
+ }
+
+
+ ///
+ internal override void ToArgb32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Argb32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Argb32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromGray16(sp);
+ }
+ }
+
+ ///
+ internal override void ToBgr24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Bgr24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Bgr24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromGray16(sp);
+ }
+ }
+
+ ///
+ internal override void ToBgra32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Bgra32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Bgra32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromGray16(sp);
+ }
+ }
+
+ ///
+ internal override void ToGray8(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Gray8 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Gray8 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromGray16(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb24(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgb24 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgb24 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromGray16(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgba32(ReadOnlySpan sourcePixels, Span destPixels, int count)
+ {
+ GuardSpans(sourcePixels, nameof(sourcePixels), destPixels, nameof(destPixels), count);
+
+ ref Gray16 sourceRef = ref MemoryMarshal.GetReference(sourcePixels);
+ ref Rgba32 destRef = ref MemoryMarshal.GetReference(destPixels);
+
+ for (int i = 0; i < count; i++)
+ {
+ ref Gray16 sp = ref Unsafe.Add(ref sourceRef, i);
+ ref Rgba32 dp = ref Unsafe.Add(ref destRef, i);
+
+ dp.PackFromGray16(sp);
+ }
+ }
+
+ ///
+ internal override void ToRgb48(ReadOnlySpan sourcePixels, Span