Browse Source

Remove more allocations and add tasks.

pull/2546/head
James Jackson-South 3 years ago
parent
commit
63829e8437
  1. 23
      src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs
  2. 23
      src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs
  3. 7
      src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs

23
src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs

@ -52,6 +52,8 @@ internal static class BackwardReferenceEncoder
Vp8LHashChain? hashChainBox = null;
Vp8LStreaks stats = new();
Vp8LBitEntropy bitsEntropy = new();
ColorCache[] colorCache = new ColorCache[WebpConstants.MaxColorCacheBits + 1];
for (int lz77Type = 1; lz77TypesToTry > 0; lz77TypesToTry &= ~lz77Type, lz77Type <<= 1)
{
int cacheBitsTmp = cacheBitsInitial;
@ -76,7 +78,7 @@ internal static class BackwardReferenceEncoder
}
// Next, try with a color cache and update the references.
cacheBitsTmp = CalculateBestCacheSize(memoryAllocator, bgra, quality, worst, cacheBitsTmp);
cacheBitsTmp = CalculateBestCacheSize(memoryAllocator, colorCache, bgra, quality, worst, cacheBitsTmp);
if (cacheBitsTmp > 0)
{
BackwardRefsWithLocalCache(bgra, cacheBitsTmp, worst);
@ -123,6 +125,7 @@ internal static class BackwardReferenceEncoder
/// <returns>Best cache size.</returns>
private static int CalculateBestCacheSize(
MemoryAllocator memoryAllocator,
Span<ColorCache> colorCache,
ReadOnlySpan<uint> bgra,
uint quality,
Vp8LBackwardRefs refs,
@ -138,12 +141,8 @@ internal static class BackwardReferenceEncoder
double entropyMin = MaxEntropy;
int pos = 0;
// TODO: Pass from outer loop and clear.
ColorCache[] colorCache = new ColorCache[WebpConstants.MaxColorCacheBits + 1];
// TODO: Use fixed size.
using Vp8LHistogramSet histos = new(memoryAllocator, WebpConstants.MaxColorCacheBits + 1, 0);
for (int i = 0; i <= WebpConstants.MaxColorCacheBits; i++)
using Vp8LHistogramSet histos = new(memoryAllocator, colorCache.Length, 0);
for (int i = 0; i < colorCache.Length; i++)
{
histos[i].PaletteCodeBits = i;
colorCache[i] = new ColorCache(i);
@ -448,12 +447,12 @@ internal static class BackwardReferenceEncoder
int ix = useColorCache ? colorCache!.Contains(color) : -1;
if (ix >= 0)
{
double mul0 = 0.68;
const double mul0 = 0.68;
costVal += costModel.GetCacheCost((uint)ix) * mul0;
}
else
{
double mul1 = 0.82;
const double mul1 = 0.82;
if (useColorCache)
{
colorCache!.Insert(color);
@ -700,10 +699,8 @@ internal static class BackwardReferenceEncoder
bestLength = MaxLength;
break;
}
else
{
bestLength = currLength;
}
bestLength = currLength;
}
}
}

23
src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Six Labors Split License.
#nullable disable
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
@ -45,9 +46,9 @@ internal static class HistogramEncoder
int imageHistoRawSize = histoXSize * histoYSize;
const int entropyCombineNumBins = BinSize;
// TODO: Allocations!
ushort[] mapTmp = new ushort[imageHistoRawSize];
ushort[] clusterMappings = new ushort[imageHistoRawSize];
using IMemoryOwner<ushort> tmp = memoryAllocator.Allocate<ushort>(imageHistoRawSize * 2, AllocationOptions.Clean);
Span<ushort> mapTmp = tmp.Slice(0, imageHistoRawSize);
Span<ushort> clusterMappings = tmp.Slice(imageHistoRawSize, imageHistoRawSize);
using Vp8LHistogramSet origHisto = new(memoryAllocator, imageHistoRawSize, cacheBits);
@ -60,13 +61,12 @@ internal static class HistogramEncoder
bool entropyCombine = numUsed > entropyCombineNumBins * 2 && quality < 100;
if (entropyCombine)
{
ushort[] binMap = mapTmp;
int numClusters = numUsed;
double combineCostFactor = GetCombineCostFactor(imageHistoRawSize, quality);
HistogramAnalyzeEntropyBin(imageHisto, binMap);
HistogramAnalyzeEntropyBin(imageHisto, mapTmp);
// Collapse histograms with similar entropy.
HistogramCombineEntropyBin(imageHisto, histogramSymbols, clusterMappings, tmpHisto, binMap, entropyCombineNumBins, combineCostFactor);
HistogramCombineEntropyBin(imageHisto, histogramSymbols, clusterMappings, tmpHisto, mapTmp, entropyCombineNumBins, combineCostFactor);
OptimizeHistogramSymbols(clusterMappings, numClusters, mapTmp, histogramSymbols);
}
@ -128,7 +128,7 @@ internal static class HistogramEncoder
/// Partition histograms to different entropy bins for three dominant (literal,
/// red and blue) symbol costs and compute the histogram aggregate bitCost.
/// </summary>
private static void HistogramAnalyzeEntropyBin(Vp8LHistogramSet histograms, ushort[] binMap)
private static void HistogramAnalyzeEntropyBin(Vp8LHistogramSet histograms, Span<ushort> binMap)
{
int histoSize = histograms.Count;
DominantCostRange costRange = new();
@ -198,9 +198,9 @@ internal static class HistogramEncoder
private static void HistogramCombineEntropyBin(
Vp8LHistogramSet histograms,
Span<ushort> clusters,
ushort[] clusterMappings,
Span<ushort> clusterMappings,
Vp8LHistogram curCombo,
ushort[] binMap,
ReadOnlySpan<ushort> binMap,
int numBins,
double combineCostFactor)
{
@ -276,7 +276,7 @@ internal static class HistogramEncoder
/// Given a Histogram set, the mapping of clusters 'clusterMapping' and the
/// current assignment of the cells in 'symbols', merge the clusters and assign the smallest possible clusters values.
/// </summary>
private static void OptimizeHistogramSymbols(ushort[] clusterMappings, int numClusters, ushort[] clusterMappingsTmp, Span<ushort> symbols)
private static void OptimizeHistogramSymbols(Span<ushort> clusterMappings, int numClusters, Span<ushort> clusterMappingsTmp, Span<ushort> symbols)
{
bool doContinue = true;
@ -303,7 +303,7 @@ internal static class HistogramEncoder
// Create a mapping from a cluster id to its minimal version.
int clusterMax = 0;
clusterMappingsTmp.AsSpan().Clear();
clusterMappingsTmp.Clear();
// Re-map the ids.
for (int i = 0; i < symbols.Length; i++)
@ -515,7 +515,6 @@ internal static class HistogramEncoder
histograms.DisposeAt(idx2);
// Remove pairs intersecting the just combined best pair.
// TODO: Reversing this will avoid the need to remove from the end of the list.
for (int i = 0; i < histoPriorityList.Count;)
{
HistogramPair p = histoPriorityList[i];

7
src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs

@ -885,7 +885,7 @@ internal class Vp8LEncoder : IDisposable
private void StoreFullHuffmanCode(Span<HuffmanTree> huffTree, HuffmanTreeToken[] tokens, HuffmanTreeCode tree)
{
// TODO: Allocations.
// TODO: Allocations. This method is called in a loop.
int i;
byte[] codeLengthBitDepth = new byte[WebpConstants.CodeLengthCodes];
short[] codeLengthBitDepthSymbols = new short[WebpConstants.CodeLengthCodes];
@ -1628,6 +1628,7 @@ internal class Vp8LEncoder : IDisposable
}
}
// TODO: Allocations.
int end = 5 * histogramImage.Count;
for (int i = 0; i < end; i++)
{
@ -1641,9 +1642,9 @@ internal class Vp8LEncoder : IDisposable
}
// Create Huffman trees.
// TODO: Allocations. Size here has a max and can be sliced.
// TODO: Allocations.
bool[] bufRle = new bool[maxNumSymbols];
Span<HuffmanTree> huffTree = stackalloc HuffmanTree[3 * maxNumSymbols];
HuffmanTree[] huffTree = new HuffmanTree[3 * maxNumSymbols];
for (int i = 0; i < histogramImage.Count; i++)
{

Loading…
Cancel
Save