diff --git a/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs index 83c4bda1f8..b1159fc6cc 100644 --- a/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs +++ b/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs @@ -798,7 +798,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless { int maxIters = 4 + ((7 * quality) >> 8); // in range [4..6] int greenToRedBest = 0; - float bestDiff = GetPredictionCostCrossColorRed(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToRedBest, accumulatedRedHisto); + double bestDiff = GetPredictionCostCrossColorRed(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToRedBest, accumulatedRedHisto); for (int iter = 0; iter < maxIters; iter++) { // ColorTransformDelta is a 3.5 bit fixed point, so 32 is equal to @@ -810,7 +810,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless for (int offset = -delta; offset <= delta; offset += 2 * delta) { int greenToRedCur = offset + greenToRedBest; - float curDiff = GetPredictionCostCrossColorRed(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToRedCur, accumulatedRedHisto); + double curDiff = GetPredictionCostCrossColorRed(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToRedCur, accumulatedRedHisto); if (curDiff < bestDiff) { bestDiff = curDiff; @@ -831,7 +831,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless sbyte[] deltaLut = { 16, 16, 8, 4, 2, 2, 2 }; // Initial value at origin: - float bestDiff = GetPredictionCostCrossColorBlue(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToBlueBest, redToBlueBest, accumulatedBlueHisto); + double bestDiff = GetPredictionCostCrossColorBlue(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToBlueBest, redToBlueBest, accumulatedBlueHisto); for (int iter = 0; iter < iters; iter++) { int delta = deltaLut[iter]; @@ -839,7 +839,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless { int greenToBlueCur = (offset[axis][0] * delta) + greenToBlueBest; int redToBlueCur = (offset[axis][1] * delta) + redToBlueBest; - float curDiff = GetPredictionCostCrossColorBlue(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToBlueCur, redToBlueCur, accumulatedBlueHisto); + double curDiff = GetPredictionCostCrossColorBlue(argb, stride, tileWidth, tileHeight, prevX, prevY, greenToBlueCur, redToBlueCur, accumulatedBlueHisto); if (curDiff < bestDiff) { bestDiff = curDiff; @@ -865,12 +865,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless bestTx.RedToBlue = (byte)(redToBlueBest & 0xff); } - private static float GetPredictionCostCrossColorRed(Span argb, int stride, int tileWidth, int tileHeight, Vp8LMultipliers prevX, Vp8LMultipliers prevY, int greenToRed, int[] accumulatedRedHisto) + private static double GetPredictionCostCrossColorRed(Span argb, int stride, int tileWidth, int tileHeight, Vp8LMultipliers prevX, Vp8LMultipliers prevY, int greenToRed, int[] accumulatedRedHisto) { int[] histo = new int[256]; CollectColorRedTransforms(argb, stride, tileWidth, tileHeight, greenToRed, histo); - float curDiff = PredictionCostCrossColor(accumulatedRedHisto, histo); + double curDiff = PredictionCostCrossColor(accumulatedRedHisto, histo); if ((byte)greenToRed == prevX.GreenToRed) { @@ -890,12 +890,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless return curDiff; } - private static float GetPredictionCostCrossColorBlue(Span argb, int stride, int tileWidth, int tileHeight, Vp8LMultipliers prevX, Vp8LMultipliers prevY, int greenToBlue, int redToBlue, int[] accumulatedBlueHisto) + private static double GetPredictionCostCrossColorBlue(Span argb, int stride, int tileWidth, int tileHeight, Vp8LMultipliers prevX, Vp8LMultipliers prevY, int greenToBlue, int redToBlue, int[] accumulatedBlueHisto) { int[] histo = new int[256]; CollectColorBlueTransforms(argb, stride, tileWidth, tileHeight, greenToBlue, redToBlue, histo); - float curDiff = PredictionCostCrossColor(accumulatedBlueHisto, histo); + double curDiff = PredictionCostCrossColor(accumulatedBlueHisto, histo); if ((byte)greenToBlue == prevX.GreenToBlue) { curDiff -= 3; // Favor keeping the areas locally similar. @@ -1088,7 +1088,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless } [MethodImpl(InliningOptions.ShortMethod)] - private static float PredictionCostCrossColor(int[] accumulated, int[] counts) + private static double PredictionCostCrossColor(int[] accumulated, int[] counts) { // Favor low entropy, locally and globally. // Favor small absolute values for PredictionCostSpatial. diff --git a/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs index fd4404d91c..58d91951c4 100644 --- a/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/WebP/PredictorEncoderTests.cs @@ -6,7 +6,9 @@ using System.IO; using SixLabors.ImageSharp.Formats.Experimental.Webp; using SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless; using SixLabors.ImageSharp.PixelFormats; +#if SUPPORTS_RUNTIME_INTRINSICS using SixLabors.ImageSharp.Tests.TestUtilities; +#endif using Xunit; namespace SixLabors.ImageSharp.Tests.Formats.WebP @@ -16,18 +18,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.WebP { [Fact] public static void ColorSpaceTransform_WithBikeImage_ProducesExpectedData() - { - RunColorSpaceTransformTestWithBikeImage(); - } + => RunColorSpaceTransformTestWithBikeImage(); - // Note: only run with netcoreapp, because the test fails with net472 in Release mode (not in Debug mode) for unknown reason. -#if NETCOREAPP [Fact] public static void ColorSpaceTransform_WithPeakImage_ProducesExpectedData() - { - RunColorSpaceTransformTestWithPeakImage(); - } -#endif + => RunColorSpaceTransformTestWithPeakImage(); #if SUPPORTS_RUNTIME_INTRINSICS [Fact]