diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index fb1d33277..175a9f777 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -34,7 +34,7 @@ internal sealed class PngEncoderCore : IImageEncoderInternals, IDisposable
private readonly MemoryAllocator memoryAllocator;
///
- /// The configuration instance for the decoding operation.
+ /// The configuration instance for the encoding operation.
///
private readonly Configuration configuration;
diff --git a/src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs b/src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs
index ed09c9966..deb0a37f0 100644
--- a/src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs
+++ b/src/ImageSharp/Formats/Qoi/QoiDecoderCore.cs
@@ -202,9 +202,9 @@ internal class QoiDecoderCore : IImageDecoderInternals
// Get one pixel from the difference (-2..1) of the previous pixel
case QoiChunk.QoiOpDiff:
- byte redDifference = (byte)((operationByte & 0b00110000) >> 4);
- byte greenDifference = (byte)((operationByte & 0b00001100) >> 2);
- byte blueDifference = (byte)(operationByte & 0b00000011);
+ int redDifference = (operationByte & 0b00110000) >> 4;
+ int greenDifference = (operationByte & 0b00001100) >> 2;
+ int blueDifference = operationByte & 0b00000011;
readPixel = previousPixel with
{
R = (byte)Numerics.Modulo256(previousPixel.R + (redDifference - 2)),
@@ -219,14 +219,14 @@ internal class QoiDecoderCore : IImageDecoderInternals
// Get green difference in 6 bits and red and blue differences
// depending on the green one
case QoiChunk.QoiOpLuma:
- byte diffGreen = (byte)(operationByte & 0b00111111);
- byte currentGreen = (byte)Numerics.Modulo256(previousPixel.G + (diffGreen - 32));
- byte nextByte = (byte)stream.ReadByte();
- byte diffRedDG = (byte)(nextByte >> 4);
- byte diffBlueDG = (byte)(nextByte & 0b00001111);
- byte currentRed = (byte)Numerics.Modulo256(diffRedDG - 8 + (diffGreen - 32) + previousPixel.R);
- byte currentBlue = (byte)Numerics.Modulo256(diffBlueDG - 8 + (diffGreen - 32) + previousPixel.B);
- readPixel = previousPixel with { R = currentRed, B = currentBlue, G = currentGreen };
+ int diffGreen = operationByte & 0b00111111;
+ int currentGreen = Numerics.Modulo256(previousPixel.G + (diffGreen - 32));
+ int nextByte = stream.ReadByte();
+ int diffRedDG = nextByte >> 4;
+ int diffBlueDG = nextByte & 0b00001111;
+ int currentRed = Numerics.Modulo256(diffRedDG - 8 + (diffGreen - 32) + previousPixel.R);
+ int currentBlue = Numerics.Modulo256(diffBlueDG - 8 + (diffGreen - 32) + previousPixel.B);
+ readPixel = previousPixel with { R = (byte)currentRed, B = (byte)currentBlue, G = (byte)currentGreen };
pixel.FromRgba32(readPixel);
pixelArrayPosition = GetArrayPosition(readPixel);
previouslySeenPixels[pixelArrayPosition] = readPixel;
diff --git a/src/ImageSharp/Formats/Qoi/QoiEncoder.cs b/src/ImageSharp/Formats/Qoi/QoiEncoder.cs
index 85763a89e..b3769d45c 100644
--- a/src/ImageSharp/Formats/Qoi/QoiEncoder.cs
+++ b/src/ImageSharp/Formats/Qoi/QoiEncoder.cs
@@ -27,7 +27,7 @@ public class QoiEncoder : ImageEncoder
///
protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken)
{
- QoiEncoderCore encoder = new(this, image.GetMemoryAllocator());
+ QoiEncoderCore encoder = new(this, image.GetMemoryAllocator(), image.GetConfiguration());
encoder.Encode(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Qoi/QoiEncoderCore.cs b/src/ImageSharp/Formats/Qoi/QoiEncoderCore.cs
index 75a08d7a4..251b7436e 100644
--- a/src/ImageSharp/Formats/Qoi/QoiEncoderCore.cs
+++ b/src/ImageSharp/Formats/Qoi/QoiEncoderCore.cs
@@ -24,15 +24,21 @@ public class QoiEncoderCore : IImageEncoderInternals
///
private readonly MemoryAllocator memoryAllocator;
+ ///
+ /// The configuration instance for the encoding operation.
+ ///
+ private readonly Configuration configuration;
+
///
/// Initializes a new instance of the class.
///
/// The encoder with options.
/// The to use for buffer allocations.
- public QoiEncoderCore(QoiEncoder encoder, MemoryAllocator memoryAllocator)
+ public QoiEncoderCore(QoiEncoder encoder, MemoryAllocator memoryAllocator, Configuration configuration)
{
this.encoder = encoder;
this.memoryAllocator = memoryAllocator;
+ this.configuration = configuration;
}
///
@@ -75,15 +81,17 @@ public class QoiEncoderCore : IImageEncoderInternals
Rgba32 previousPixel = new(0, 0, 0, 255);
Rgba32 currentRgba32 = default;
Buffer2D pixels = image.Frames[0].PixelBuffer;
+ using IMemoryOwner rgbaRowBuffer = this.memoryAllocator.Allocate(pixels.Width);
+ Span rgbaRow = rgbaRowBuffer.GetSpan();
for (int i = 0; i < pixels.Height; i++)
{
Span row = pixels.DangerousGetRowSpan(i);
+ PixelOperations.Instance.ToRgba32(this.configuration, row, rgbaRow);
for (int j = 0; j < row.Length && i < pixels.Height; j++)
{
// We get the RGBA value from pixels
- TPixel currentPixel = row[j];
- currentPixel.ToRgba32(ref currentRgba32);
+ currentRgba32 = rgbaRow[j];
// First, we check if the current pixel is equal to the previous one
// If so, we do a QOI_OP_RUN
@@ -97,7 +105,7 @@ public class QoiEncoderCore : IImageEncoderInternals
* and we should discuss what to do about this approach and
* if it's correct
*/
- byte repetitions = 0;
+ int repetitions = 0;
do
{
repetitions++;
@@ -112,15 +120,15 @@ public class QoiEncoderCore : IImageEncoderInternals
}
row = pixels.DangerousGetRowSpan(i);
+ PixelOperations.Instance.ToRgba32(this.configuration, row, rgbaRow);
}
- currentPixel = row[j];
- currentPixel.ToRgba32(ref currentRgba32);
+ currentRgba32 = rgbaRow[j];
}
while (currentRgba32.Equals(previousPixel) && repetitions < 62);
j--;
- stream.WriteByte((byte)((byte)QoiChunk.QoiOpRun | (repetitions - 1)));
+ stream.WriteByte((byte)((int)QoiChunk.QoiOpRun | (repetitions - 1)));
/* If it's a QOI_OP_RUN, we don't overwrite the previous pixel since
* it will be taken and compared on the next iteration
@@ -131,7 +139,7 @@ public class QoiEncoderCore : IImageEncoderInternals
// else, we check if it exists in the previously seen pixels
// If so, we do a QOI_OP_INDEX
int pixelArrayPosition = GetArrayPosition(currentRgba32);
- if (previouslySeenPixels[pixelArrayPosition].Equals(currentPixel))
+ if (previouslySeenPixels[pixelArrayPosition].Equals(currentRgba32))
{
stream.WriteByte((byte)pixelArrayPosition);
}
@@ -141,9 +149,9 @@ public class QoiEncoderCore : IImageEncoderInternals
// Since it wasn't found on the previously seen pixels, we save it
previouslySeenPixels[pixelArrayPosition] = currentRgba32;
- sbyte diffRed = (sbyte)(currentRgba32.R - previousPixel.R);
- sbyte diffGreen = (sbyte)(currentRgba32.G - previousPixel.G);
- sbyte diffBlue = (sbyte)(currentRgba32.B - previousPixel.B);
+ int diffRed = currentRgba32.R - previousPixel.R;
+ int diffGreen = currentRgba32.G - previousPixel.G;
+ int diffBlue = currentRgba32.B - previousPixel.B;
// If so, we do a QOI_OP_DIFF
if (diffRed is >= -2 and <= 1 &&
@@ -152,26 +160,26 @@ public class QoiEncoderCore : IImageEncoderInternals
currentRgba32.A == previousPixel.A)
{
// Bottom limit is -2, so we add 2 to make it equal to 0
- byte dr = (byte)(diffRed + 2);
- byte dg = (byte)(diffGreen + 2);
- byte db = (byte)(diffBlue + 2);
- byte valueToWrite = (byte)((byte)QoiChunk.QoiOpDiff | (dr << 4) | (dg << 2) | db);
+ int dr = diffRed + 2;
+ int dg = diffGreen + 2;
+ int db = diffBlue + 2;
+ byte valueToWrite = (byte)((int)QoiChunk.QoiOpDiff | (dr << 4) | (dg << 2) | db);
stream.WriteByte(valueToWrite);
}
else
{
// else, we check if the green difference is less than -32..31 and the rest -8..7
// If so, we do a QOI_OP_LUMA
- sbyte diffRedGreen = (sbyte)(diffRed - diffGreen);
- sbyte diffBlueGreen = (sbyte)(diffBlue - diffGreen);
+ int diffRedGreen = diffRed - diffGreen;
+ int diffBlueGreen = diffBlue - diffGreen;
if (diffGreen is >= -32 and <= 31 &&
diffRedGreen is >= -8 and <= 7 &&
diffBlueGreen is >= -8 and <= 7 &&
currentRgba32.A == previousPixel.A)
{
- byte dr_dg = (byte)(diffRedGreen + 8);
- byte db_dg = (byte)(diffBlueGreen + 8);
- byte byteToWrite1 = (byte)((byte)QoiChunk.QoiOpLuma | (diffGreen + 32));
+ int dr_dg = diffRedGreen + 8;
+ int db_dg = diffBlueGreen + 8;
+ byte byteToWrite1 = (byte)((int)QoiChunk.QoiOpLuma | (diffGreen + 32));
byte byteToWrite2 = (byte)((dr_dg << 4) | db_dg);
stream.WriteByte(byteToWrite1);
stream.WriteByte(byteToWrite2);
diff --git a/tests/ImageSharp.Benchmarks/Codecs/Qoi/IdentifyQoi.cs b/tests/ImageSharp.Benchmarks/Codecs/Qoi/IdentifyQoi.cs
deleted file mode 100644
index 9631d80cb..000000000
--- a/tests/ImageSharp.Benchmarks/Codecs/Qoi/IdentifyQoi.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-using BenchmarkDotNet.Attributes;
-using SixLabors.ImageSharp.Formats;
-using SixLabors.ImageSharp.Formats.Qoi;
-using SixLabors.ImageSharp.Tests;
-
-namespace SixLabors.ImageSharp.Benchmarks.Codecs.Qoi;
-
-[Config(typeof(Config.ShortMultiFramework))]
-public class IdentifyQoi
-{
- private byte[] qoiBytes;
-
- private string TestImageFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImage);
-
- [Params(TestImages.Qoi.TestCardRGBA, TestImages.Qoi.TestCard, TestImages.Qoi.QoiLogo, TestImages.Qoi.EdgeCase, TestImages.Png.Bike)]
- public string TestImage { get; set; }
-
- [GlobalSetup]
- public void ReadImages() => this.qoiBytes ??= File.ReadAllBytes(this.TestImageFullPath);
-
- [Benchmark]
- public ImageInfo Identify()
- {
- using MemoryStream memoryStream = new(this.qoiBytes);
- return QoiDecoder.Instance.Identify(DecoderOptions.Default, memoryStream);
- }
-}
diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
index 217e3165c..0ba2f4b94 100644
--- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
+++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
@@ -69,8 +69,5 @@
-
-
-