diff --git a/src/ImageSharp/Formats/WebP/AlphaDecoder.cs b/src/ImageSharp/Formats/WebP/AlphaDecoder.cs
index 8a276cebc3..f386c42da5 100644
--- a/src/ImageSharp/Formats/WebP/AlphaDecoder.cs
+++ b/src/ImageSharp/Formats/WebP/AlphaDecoder.cs
@@ -22,7 +22,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
/// The (maybe compressed) alpha data.
/// The first byte of the alpha image stream contains information on ow to decode the stream.
/// Used for allocating memory during decoding.
- public AlphaDecoder(int width, int height, byte[] data, byte alphaChunkHeader, MemoryAllocator memoryAllocator)
+ /// The configuration.
+ public AlphaDecoder(int width, int height, byte[] data, byte alphaChunkHeader, MemoryAllocator memoryAllocator, Configuration configuration)
{
this.Width = width;
this.Height = height;
@@ -59,7 +60,7 @@ namespace SixLabors.ImageSharp.Formats.WebP
if (this.Compressed)
{
var bitReader = new Vp8LBitReader(data);
- this.LosslessDecoder = new WebPLosslessDecoder(bitReader, memoryAllocator);
+ this.LosslessDecoder = new WebPLosslessDecoder(bitReader, memoryAllocator, configuration);
this.LosslessDecoder.DecodeImageStream(this.Vp8LDec, width, height, true);
}
}
diff --git a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
index a9312f19c7..f188d7d7b7 100644
--- a/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
+++ b/src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
@@ -89,12 +89,12 @@ namespace SixLabors.ImageSharp.Formats.WebP
Buffer2D pixels = image.GetRootFramePixelBuffer();
if (imageInfo.IsLossLess)
{
- var losslessDecoder = new WebPLosslessDecoder(imageInfo.Vp8LBitReader, this.memoryAllocator);
+ var losslessDecoder = new WebPLosslessDecoder(imageInfo.Vp8LBitReader, this.memoryAllocator, this.configuration);
losslessDecoder.Decode(pixels, image.Width, image.Height);
}
else
{
- var lossyDecoder = new WebPLossyDecoder(imageInfo.Vp8BitReader, this.memoryAllocator);
+ var lossyDecoder = new WebPLossyDecoder(imageInfo.Vp8BitReader, this.memoryAllocator, this.configuration);
lossyDecoder.Decode(pixels, image.Width, image.Height, imageInfo);
}
diff --git a/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs b/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs
index 6ca54690fc..5bb7befaf4 100644
--- a/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs
+++ b/src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs
@@ -27,6 +27,16 @@ namespace SixLabors.ImageSharp.Formats.WebP
///
private readonly Vp8LBitReader bitReader;
+ ///
+ /// The global configuration.
+ ///
+ private readonly Configuration configuration;
+
+ ///
+ /// Used for allocating memory during processing operations.
+ ///
+ private readonly MemoryAllocator memoryAllocator;
+
private static readonly int BitsSpecialMarker = 0x100;
private static readonly int NumArgbCacheRows = 16;
@@ -62,20 +72,17 @@ namespace SixLabors.ImageSharp.Formats.WebP
0, 1, 1, 1, 0
};
- ///
- /// Used for allocating memory during processing operations.
- ///
- private readonly MemoryAllocator memoryAllocator;
-
///
/// Initializes a new instance of the class.
///
/// Bitreader to read from the stream.
/// Used for allocating memory during processing operations.
- public WebPLosslessDecoder(Vp8LBitReader bitReader, MemoryAllocator memoryAllocator)
+ /// The configuration.
+ public WebPLosslessDecoder(Vp8LBitReader bitReader, MemoryAllocator memoryAllocator, Configuration configuration)
{
this.bitReader = bitReader;
this.memoryAllocator = memoryAllocator;
+ this.configuration = configuration;
}
///
@@ -181,25 +188,21 @@ namespace SixLabors.ImageSharp.Formats.WebP
where TPixel : struct, IPixel
{
Span pixelData = decoder.Pixels.GetSpan();
+ int width = decoder.Width;
// Apply reverse transformations, if any are present.
this.ApplyInverseTransforms(decoder, pixelData);
- TPixel color = default;
+ Span pixelDataAsBytes = MemoryMarshal.Cast(pixelData);
for (int y = 0; y < decoder.Height; y++)
{
- Span pixelRow = pixels.GetRowSpan(y);
- for (int x = 0; x < decoder.Width; x++)
- {
- int idx = (y * decoder.Width) + x;
- uint pixel = pixelData[idx];
- byte a = (byte)((pixel & 0xFF000000) >> 24);
- byte r = (byte)((pixel & 0xFF0000) >> 16);
- byte g = (byte)((pixel & 0xFF00) >> 8);
- byte b = (byte)(pixel & 0xFF);
- color.FromRgba32(new Rgba32(r, g, b, a));
- pixelRow[x] = color;
- }
+ Span row = pixelDataAsBytes.Slice(y * width * 4, width * 4);
+ Span pixelSpan = pixels.GetRowSpan(y);
+ PixelOperations.Instance.FromBgra32Bytes(
+ this.configuration,
+ row,
+ pixelSpan,
+ width);
}
}
diff --git a/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs b/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs
index 03faaaa7ca..4e06b441fe 100644
--- a/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs
+++ b/src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs
@@ -24,15 +24,22 @@ namespace SixLabors.ImageSharp.Formats.WebP
///
private readonly MemoryAllocator memoryAllocator;
+ ///
+ /// The global configuration.
+ ///
+ private readonly Configuration configuration;
+
///
/// Initializes a new instance of the class.
///
/// Bitreader to read from the stream.
/// Used for allocating memory during processing operations.
- public WebPLossyDecoder(Vp8BitReader bitReader, MemoryAllocator memoryAllocator)
+ /// The configuration.
+ public WebPLossyDecoder(Vp8BitReader bitReader, MemoryAllocator memoryAllocator, Configuration configuration)
{
- this.memoryAllocator = memoryAllocator;
this.bitReader = bitReader;
+ this.memoryAllocator = memoryAllocator;
+ this.configuration = configuration;
}
public void Decode(Buffer2D pixels, int width, int height, WebPImageInfo info)
@@ -85,7 +92,8 @@ namespace SixLabors.ImageSharp.Formats.WebP
height,
info.Features.AlphaData,
info.Features.AlphaChunkHeader,
- this.memoryAllocator))
+ this.memoryAllocator,
+ this.configuration))
{
alphaDecoder.Decode();
this.DecodePixelValues(width, height, decoder.Pixels.Memory.Span, pixels, alphaDecoder.Alpha);
@@ -101,39 +109,38 @@ namespace SixLabors.ImageSharp.Formats.WebP
private void DecodePixelValues(int width, int height, Span pixelData, Buffer2D pixels, IMemoryOwner alpha = null)
where TPixel : struct, IPixel
{
- TPixel color = default;
- bool hasAlpha = false;
- Span alphaSpan = null;
if (alpha != null)
{
- hasAlpha = true;
- alphaSpan = alpha.Memory.Span;
- }
-
- for (int y = 0; y < height; y++)
- {
- Span pixelRow = pixels.GetRowSpan(y);
- for (int x = 0; x < width; x++)
+ TPixel color = default;
+ Span alphaSpan = alpha.Memory.Span;
+ for (int y = 0; y < height; y++)
{
- int offset = (y * width) + x;
- int idxBgr = offset * 3;
- byte b = pixelData[idxBgr];
- byte g = pixelData[idxBgr + 1];
- byte r = pixelData[idxBgr + 2];
-
- // TODO: use bulk conversion here.
- if (hasAlpha)
+ Span pixelRow = pixels.GetRowSpan(y);
+ for (int x = 0; x < width; x++)
{
+ int offset = (y * width) + x;
+ int idxBgr = offset * 3;
+ byte b = pixelData[idxBgr];
+ byte g = pixelData[idxBgr + 1];
+ byte r = pixelData[idxBgr + 2];
byte a = alphaSpan[offset];
color.FromBgra32(new Bgra32(r, g, b, a));
+ pixelRow[x] = color;
}
- else
- {
- color.FromBgr24(new Bgr24(r, g, b));
- }
-
- pixelRow[x] = color;
}
+
+ return;
+ }
+
+ for (int y = 0; y < height; y++)
+ {
+ Span row = pixelData.Slice(y * width * 3, width * 3);
+ Span pixelSpan = pixels.GetRowSpan(y);
+ PixelOperations.Instance.FromBgr24Bytes(
+ this.configuration,
+ row,
+ pixelSpan,
+ width);
}
}