diff --git a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
index e0e11ad9ee..689c9a85b4 100644
--- a/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
+++ b/src/ImageSharp/Dithering/Ordered/IOrderedDither.cs
@@ -17,12 +17,12 @@ namespace SixLabors.ImageSharp.Dithering
/// The source pixel
/// The color to apply to the pixels above the threshold.
/// The color to apply to the pixels below the threshold.
- /// The byte array to pack/unpack to. Must have a length of 4. Bytes are unpacked to Xyzw order.
+ /// The to pack/unpack to.
/// The component index to test the threshold against. Must range from 0 to 3.
/// The column index.
/// The row index.
/// The pixel format.
- void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y)
+ void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, ref Rgba32 rgba, int index, int x, int y)
where TPixel : struct, IPixel;
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs b/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs
index 09c30eb272..b29de4cf23 100644
--- a/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs
+++ b/src/ImageSharp/Dithering/Ordered/OrderedDitherBase.cs
@@ -26,14 +26,11 @@ namespace SixLabors.ImageSharp.Dithering.Base
}
///
- public void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, byte[] bytes, int index, int x, int y)
+ public void Dither(ImageFrame image, TPixel source, TPixel upper, TPixel lower, ref Rgba32 rgba, int index, int x, int y)
where TPixel : struct, IPixel
{
- // TODO: This doesn't really cut it for me.
- // I'd rather be using float but we need to add some sort of normalization vector methods to all IPixel implementations
- // before we can do that as the vectors all cover different ranges.
- source.ToXyzwBytes(bytes, 0);
- image[x, y] = this.matrix[y % 3, x % 3] >= bytes[index] ? lower : upper;
+ source.ToRgba32(ref rgba);
+ image[x, y] = this.matrix[y % 3, x % 3] >= rgba[index] ? lower : upper;
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 1b145a79eb..41c8e944d8 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -351,16 +351,16 @@ namespace SixLabors.ImageSharp.Formats.Gif
// Get max colors for bit depth.
int colorTableLength = (int)Math.Pow(2, this.bitDepth) * 3;
byte[] colorTable = ArrayPool.Shared.Rent(colorTableLength);
-
+ var rgb = default(Rgb24);
try
{
for (int i = 0; i < pixelCount; i++)
{
int offset = i * 3;
- image.Palette[i].ToXyzBytes(this.buffer, 0);
- colorTable[offset] = this.buffer[0];
- colorTable[offset + 1] = this.buffer[1];
- colorTable[offset + 2] = this.buffer[2];
+ image.Palette[i].ToRgb24(ref rgb);
+ colorTable[offset] = rgb.R;
+ colorTable[offset + 1] = rgb.G;
+ colorTable[offset + 2] = rgb.B;
}
writer.Write(colorTable, 0, colorTableLength);
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 86a63f5b47..0efd46ec74 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -318,6 +318,7 @@ namespace SixLabors.ImageSharp.Formats.Png
where TPixel : struct, IPixel
{
byte[] rawScanlineArray = this.rawScanline.Array;
+ var rgba = default(Rgba32);
// Copy the pixels across from the image.
// Reuse the chunk type buffer.
@@ -326,8 +327,8 @@ namespace SixLabors.ImageSharp.Formats.Png
// Convert the color to YCbCr and store the luminance
// Optionally store the original color alpha.
int offset = x * this.bytesPerPixel;
- rowSpan[x].ToXyzwBytes(this.chunkTypeBuffer, 0);
- byte luminance = (byte)((0.299F * this.chunkTypeBuffer[0]) + (0.587F * this.chunkTypeBuffer[1]) + (0.114F * this.chunkTypeBuffer[2]));
+ rowSpan[x].ToRgba32(ref rgba);
+ byte luminance = (byte)((0.299F * rgba.R) + (0.587F * rgba.G) + (0.114F * rgba.B));
for (int i = 0; i < this.bytesPerPixel; i++)
{
@@ -337,7 +338,7 @@ namespace SixLabors.ImageSharp.Formats.Png
}
else
{
- rawScanlineArray[offset + i] = this.chunkTypeBuffer[3];
+ rawScanlineArray[offset + i] = rgba.A;
}
}
}
@@ -518,7 +519,7 @@ namespace SixLabors.ImageSharp.Formats.Png
int colorTableLength = (int)Math.Pow(2, header.BitDepth) * 3;
byte[] colorTable = ArrayPool.Shared.Rent(colorTableLength);
byte[] alphaTable = ArrayPool.Shared.Rent(pixelCount);
- byte[] bytes = ArrayPool.Shared.Rent(4);
+ var rgba = default(Rgba32);
bool anyAlpha = false;
try
{
@@ -527,13 +528,13 @@ namespace SixLabors.ImageSharp.Formats.Png
if (quantized.Pixels.Contains(i))
{
int offset = i * 3;
- palette[i].ToXyzwBytes(bytes, 0);
+ palette[i].ToRgba32(ref rgba);
- byte alpha = bytes[3];
+ byte alpha = rgba.A;
- colorTable[offset] = bytes[0];
- colorTable[offset + 1] = bytes[1];
- colorTable[offset + 2] = bytes[2];
+ colorTable[offset] = rgba.R;
+ colorTable[offset + 1] = rgba.G;
+ colorTable[offset + 2] = rgba.B;
if (alpha > this.threshold)
{
@@ -557,7 +558,6 @@ namespace SixLabors.ImageSharp.Formats.Png
{
ArrayPool.Shared.Return(colorTable);
ArrayPool.Shared.Return(alphaTable);
- ArrayPool.Shared.Return(bytes);
}
return quantized;
diff --git a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs
deleted file mode 100644
index 37b225d2e0..0000000000
--- a/src/ImageSharp/PixelFormats/PixelConversionExtensions.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp.PixelFormats
-{
- ///
- /// Extension methods for copying single pixel data into byte Spans.
- /// TODO: This utility class exists for legacy reasons. Need to do a lot of chore work to remove it (mostly in test classes).
- ///
- internal static class PixelConversionExtensions
- {
- ///
- /// Expands the packed representation into a given byte array.
- /// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in
- ///
- /// The pixel type.
- /// The pixel to copy the data from.
- /// The bytes to set the color in.
- /// The starting index of the .
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ToXyzBytes(this TPixel pixel, Span bytes, int startIndex)
- where TPixel : struct, IPixel
- {
- ref Rgb24 dest = ref bytes.GetRgb24(startIndex);
- pixel.ToRgb24(ref dest);
- }
-
- ///
- /// Expands the packed representation into a given byte array.
- /// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in
- ///
- /// The pixel type.
- /// The pixel to copy the data from.
- /// The bytes to set the color in.
- /// The starting index of the .
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ToXyzwBytes(this TPixel pixel, Span bytes, int startIndex)
- where TPixel : struct, IPixel
- {
- ref Rgba32 dest = ref Unsafe.As(ref bytes[startIndex]);
- pixel.ToRgba32(ref dest);
- }
-
- ///
- /// Expands the packed representation into a given byte array.
- /// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in
- ///
- /// The pixel type.
- /// The pixel to copy the data from.
- /// The bytes to set the color in.
- /// The starting index of the .
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ToZyxBytes(this TPixel pixel, Span bytes, int startIndex)
- where TPixel : struct, IPixel
- {
- ref Bgr24 dest = ref Unsafe.As(ref bytes[startIndex]);
- pixel.ToBgr24(ref dest);
- }
-
- ///
- /// Expands the packed representation into a given byte array.
- /// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in
- ///
- /// The pixel type.
- /// The pixel to copy the data from.
- /// The bytes to set the color in.
- /// The starting index of the .
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void ToZyxwBytes(this TPixel pixel, Span bytes, int startIndex)
- where TPixel : struct, IPixel
- {
- ref Bgra32 dest = ref Unsafe.As(ref bytes[startIndex]);
- pixel.ToBgra32(ref dest);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/Rgba32.cs b/src/ImageSharp/PixelFormats/Rgba32.cs
index 51647fc1f9..b213de019e 100644
--- a/src/ImageSharp/PixelFormats/Rgba32.cs
+++ b/src/ImageSharp/PixelFormats/Rgba32.cs
@@ -220,6 +220,32 @@ namespace SixLabors.ImageSharp
set => this.Rgba = value;
}
+ ///
+ /// Gets the component value at the given index
+ ///
+ /// The component index
+ /// The
+ public byte this[int index]
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ DebugGuard.MustBeGreaterThanOrEqualTo(index, 0, nameof(index));
+ DebugGuard.MustBeLessThanOrEqualTo(index, 3, nameof(index));
+ switch (index)
+ {
+ case 0:
+ return this.R;
+ case 1:
+ return this.G;
+ case 2:
+ return this.B;
+ default:
+ return this.A;
+ }
+ }
+ }
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
index 203a64cf16..a2fd17c94b 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
int startX = interest.X;
int endX = interest.Right;
- byte[] bytes = new byte[4];
+ var rgba = default(Rgba32);
for (int y = startY; y < endY; y++)
{
Span row = source.GetPixelRowSpan(y);
@@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
for (int x = startX; x < endX; x++)
{
TPixel sourceColor = row[x];
- this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, bytes, this.Index, x, y);
+ this.Dither.Dither(source, sourceColor, this.UpperColor, this.LowerColor, ref rgba, this.Index, x, y);
}
}
}
diff --git a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
index 8ab390f4e7..44311e080b 100644
--- a/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
+++ b/src/ImageSharp/Quantizers/WuQuantizer{TPixel}.cs
@@ -60,11 +60,6 @@ namespace SixLabors.ImageSharp.Quantizers
///
private const int TableLength = IndexCount * IndexCount * IndexCount * IndexAlphaCount;
- ///
- /// A buffer for storing pixels
- ///
- private readonly byte[] rgbaBuffer = new byte[4];
-
///
/// A lookup table for colors
///
@@ -199,19 +194,15 @@ namespace SixLabors.ImageSharp.Quantizers
{
// Add the color to a 3-D color histogram.
// Colors are expected in r->g->b->a format
- pixel.ToXyzwBytes(this.rgbaBuffer, 0);
-
- byte r = this.rgbaBuffer[0];
- byte g = this.rgbaBuffer[1];
- byte b = this.rgbaBuffer[2];
- byte a = this.rgbaBuffer[3];
+ var rgba = default(Rgba32);
+ pixel.ToRgba32(ref rgba);
- int inr = r >> (8 - IndexBits);
- int ing = g >> (8 - IndexBits);
- int inb = b >> (8 - IndexBits);
- int ina = a >> (8 - IndexAlphaBits);
+ int r = rgba.R >> 2; // 8 - IndexBits
+ int g = rgba.G >> 2;
+ int b = rgba.B >> 2;
+ int a = rgba.A >> 5; // 8 - IndexAlphaBits
- int ind = GetPaletteIndex(inr + 1, ing + 1, inb + 1, ina + 1);
+ int ind = GetPaletteIndex(r + 1, g + 1, b + 1, a + 1);
this.vwt[ind]++;
this.vmr[ind] += r;
@@ -840,12 +831,13 @@ namespace SixLabors.ImageSharp.Quantizers
}
// Expected order r->g->b->a
- pixel.ToXyzwBytes(this.rgbaBuffer, 0);
+ var rgba = default(Rgba32);
+ pixel.ToRgba32(ref rgba);
- int r = this.rgbaBuffer[0] >> (8 - IndexBits);
- int g = this.rgbaBuffer[1] >> (8 - IndexBits);
- int b = this.rgbaBuffer[2] >> (8 - IndexBits);
- int a = this.rgbaBuffer[3] >> (8 - IndexAlphaBits);
+ int r = rgba.R >> (8 - IndexBits);
+ int g = rgba.G >> (8 - IndexBits);
+ int b = rgba.B >> (8 - IndexBits);
+ int a = rgba.A >> (8 - IndexAlphaBits);
return this.tag[GetPaletteIndex(r + 1, g + 1, b + 1, a + 1)];
}