diff --git a/src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs b/src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs
index cd6249632e..73f808b630 100644
--- a/src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs
+++ b/src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs
@@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.BitWriter
}
///
- /// Writes the encoded bytes of the image to the stream. Call BitWriterFinish() before this.
+ /// Writes the encoded bytes of the image to the stream. Call BitWriterFinish() before this.
///
/// The stream to write to.
public void WriteToStream(Stream stream)
diff --git a/src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs
index 6366beadc7..1893e6015c 100644
--- a/src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs
+++ b/src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private const uint NonTrivialSym = 0xffffffff;
- private const short InvalidHistogramSymbol = Int16.MaxValue;
+ private const short InvalidHistogramSymbol = short.MaxValue;
public static void GetHistoImageSymbols(int xSize, int ySize, Vp8LBackwardRefs refs, int quality, int histoBits, int cacheBits, List imageHisto, Vp8LHistogram tmpHisto, short[] histogramSymbols)
{
@@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// Cubic ramp between 1 and MaxHistoGreedy:
int thresholdSize = (int)(1 + (x * x * x * (MaxHistoGreedy - 1)));
- bool doGreedy = HistogramCombineStochastic(imageHisto, ref numUsed, thresholdSize);
+ bool doGreedy = HistogramCombineStochastic(imageHisto, thresholdSize);
if (doGreedy)
{
HistogramCombineGreedy(imageHisto);
@@ -303,14 +303,15 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
/// Perform histogram aggregation using a stochastic approach.
///
/// true if a greedy approach needs to be performed afterwards, false otherwise.
- private static bool HistogramCombineStochastic(List histograms, ref int numUsed, int minClusterSize)
+ private static bool HistogramCombineStochastic(List histograms, int minClusterSize)
{
var rand = new Random();
int triesWithNoSuccess = 0;
+ var numUsed = histograms.Count(h => h != null);
int outerIters = numUsed;
int numTriesNoSuccess = outerIters / 2;
- if (histograms.Count < minClusterSize)
+ if (numUsed < minClusterSize)
{
return true;
}
@@ -333,7 +334,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
double bestCost = (histoPriorityList.Count == 0) ? 0.0d : histoPriorityList[0].CostDiff;
int bestIdx1 = -1;
int bestIdx2 = 1;
- int numTries = numUsed / 2; // TODO: should that be histogram.Count/2?
+ int numTries = numUsed / 2;
uint randRange = (uint)((numUsed - 1) * numUsed);
// Pick random samples.
@@ -454,16 +455,26 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private static void HistogramCombineGreedy(List histograms)
{
- int histoSize = histograms.Count;
+ int histoSize = histograms.Count(h => h != null);
// Priority list of histogram pairs.
var histoPriorityList = new List();
int maxSize = histoSize * histoSize;
- for (int i = 0; i < histograms.Count; i++)
+ for (int i = 0; i < histoSize; i++)
{
- for (int j = i + 1; j < histograms.Count; j++)
+ if (histograms[i] == null)
+ {
+ continue;
+ }
+
+ for (int j = i + 1; j < histoSize; j++)
{
+ if (histograms[j] == null)
+ {
+ continue;
+ }
+
HistoPriorityListPush(histoPriorityList, maxSize, histograms, i, j, 0.0d);
}
}
@@ -496,7 +507,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
}
// Push new pairs formed with combined histogram to the list.
- for (int i = 0; i < histograms.Count; i++)
+ for (int i = 0; i < histoSize; i++)
{
if (i == idx1 || histograms[i] == null)
{
diff --git a/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs
index 2e48bf7dce..f2f1175897 100644
--- a/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs
+++ b/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs
@@ -7,7 +7,6 @@ using System.Buffers.Binary;
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.WebP.BitWriter;
@@ -34,13 +33,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
///
/// The to use for buffer allocations.
///
- private MemoryAllocator memoryAllocator;
+ private readonly MemoryAllocator memoryAllocator;
///
/// A bit writer for writing lossless webp streams.
///
private Vp8LBitWriter bitWriter;
-
+
private const int ApplyPaletteGreedyMax = 4;
private const int PaletteInvSizeBits = 11;
@@ -309,9 +308,20 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
this.bitWriter.PutBits(0, 1); // No more transforms.
// Encode and write the transformed image.
- this.EncodeImage(bgra, this.HashChain, this.Refs, this.CurrentWidth, height, quality, useCache, crunchConfig,
- this.CacheBits, this.HistoBits, bytePosition);
+ this.EncodeImage(
+ bgra,
+ this.HashChain,
+ this.Refs,
+ this.CurrentWidth,
+ height,
+ quality,
+ useCache,
+ crunchConfig,
+ this.CacheBits,
+ this.HistoBits,
+ bytePosition);
}
+
// TODO: Comparison and picking of best (smallest) encoding
}
@@ -336,7 +346,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// Try out multiple LZ77 on images with few colors.
var nlz77s = (this.PaletteSize > 0 && this.PaletteSize <= 16) ? 2 : 1;
EntropyIx entropyIdx = this.AnalyzeEntropy(image, usePalette, this.PaletteSize, this.TransformBits, out redAndBlueAlwaysZero);
-
+
bool doNotCache = false;
var crunchConfigs = new List();
@@ -358,7 +368,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
else
{
// Only choose the guessed best transform.
- crunchConfigs.Add(new CrunchConfig {EntropyIdx = entropyIdx});
+ crunchConfigs.Add(new CrunchConfig { EntropyIdx = entropyIdx });
if (configQuality >= 75 && method == 5)
{
// Test with and without color cache.
@@ -367,7 +377,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// If we have a palette, also check in combination with spatial.
if (entropyIdx == EntropyIx.Palette)
{
- crunchConfigs.Add(new CrunchConfig { EntropyIdx = EntropyIx.PaletteAndSpatial});
+ crunchConfigs.Add(new CrunchConfig { EntropyIdx = EntropyIx.PaletteAndSpatial });
}
}
}
@@ -1584,8 +1594,6 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
public void AllocateTransformBuffer(int width, int height)
{
- int imageSize = width * height;
-
// VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra
// pixel in each, plus 2 regular scanlines of bytes.
int argbScratchSize = this.UsePredictorTransform ? ((width + 1) * 2) + (((width * 2) + 4 - 1) / 4) : 0;
@@ -1620,6 +1628,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private class CrunchConfig
{
public EntropyIx EntropyIdx { get; set; }
+
public List SubConfigs { get; } = new List();
}
@@ -1627,9 +1636,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private class CrunchSubConfig
{
public int Lz77 { get; set; }
+
public bool DoNotCache { get; set; }
}
}
-
-
}