Browse Source

Replace indexed span iteration with foreach (+performance)

pull/2940/head
Maxim Shipko 11 months ago
parent
commit
ff9d3a6223
  1. 14
      src/ImageSharp/Formats/Webp/Lossless/BackwardReferenceEncoder.cs
  2. 4
      src/ImageSharp/Formats/Webp/Lossless/CostModel.cs
  3. 9
      src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs
  4. 11
      src/ImageSharp/Formats/Webp/Lossless/Vp8LBackwardRefs.cs
  5. 3
      src/ImageSharp/Formats/Webp/Lossless/Vp8LEncoder.cs
  6. 4
      src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs

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

@ -149,9 +149,8 @@ internal static class BackwardReferenceEncoder
}
// Find the cacheBits giving the lowest entropy.
for (int idx = 0; idx < refs.Count; idx++)
foreach (PixOrCopy v in refs)
{
PixOrCopy v = refs[idx];
if (v.IsLiteral())
{
uint pix = bgra[pos++];
@ -780,9 +779,8 @@ internal static class BackwardReferenceEncoder
{
int pixelIndex = 0;
ColorCache colorCache = new(cacheBits);
for (int idx = 0; idx < refs.Count; idx++)
foreach (ref PixOrCopy v in refs)
{
PixOrCopy v = refs[idx];
if (v.IsLiteral())
{
uint bgraLiteral = v.BgraOrDistance;
@ -790,7 +788,7 @@ internal static class BackwardReferenceEncoder
if (ix >= 0)
{
// Color cache contains bgraLiteral
refs[idx] = PixOrCopy.CreateCacheIdx(ix);
v = PixOrCopy.CreateCacheIdx(ix);
}
else
{
@ -812,15 +810,13 @@ internal static class BackwardReferenceEncoder
private static void BackwardReferences2DLocality(int xSize, Vp8LBackwardRefs refs)
{
for (int idx = 0; idx < refs.Count; idx++)
foreach (ref PixOrCopy v in refs)
{
PixOrCopy v = refs[idx];
if (v.IsCopy())
{
int dist = (int)v.BgraOrDistance;
int transformedDist = DistanceToPlaneCode(xSize, dist);
refs[idx] = PixOrCopy.CreateCopy((uint)transformedDist, v.Len);
v = PixOrCopy.CreateCopy((uint)transformedDist, v.Len);
}
}
}

4
src/ImageSharp/Formats/Webp/Lossless/CostModel.cs

@ -40,9 +40,9 @@ internal class CostModel
using OwnedVp8LHistogram histogram = OwnedVp8LHistogram.Create(this.memoryAllocator, cacheBits);
// The following code is similar to HistogramCreate but converts the distance to plane code.
for (int i = 0; i < backwardRefs.Count; i++)
foreach (PixOrCopy v in backwardRefs)
{
histogram.AddSinglePixOrCopy(backwardRefs[i], true, xSize);
histogram.AddSinglePixOrCopy(v, true, xSize);
}
ConvertPopulationCountTableToBitEstimates(histogram.NumCodes(), histogram.Literal, this.Literal);

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

@ -110,9 +110,8 @@ internal static class HistogramEncoder
int x = 0, y = 0;
int histoXSize = LosslessUtils.SubSampleSize(xSize, histoBits);
for (int i = 0; i < backwardRefs.Count; i++)
foreach (PixOrCopy v in backwardRefs)
{
PixOrCopy v = backwardRefs[i];
int ix = ((y >> histoBits) * histoXSize) + (x >> histoBits);
histograms[ix].AddSinglePixOrCopy(v, false);
x += v.Len;
@ -217,7 +216,7 @@ internal static class HistogramEncoder
clusterMappings[idx] = (ushort)idx;
}
List<int> indicesToRemove = new();
List<int> indicesToRemove = [];
Vp8LStreaks stats = new();
Vp8LBitEntropy bitsEntropy = new();
for (int idx = 0; idx < histograms.Count; idx++)
@ -345,7 +344,7 @@ internal static class HistogramEncoder
// Priority list of histogram pairs. Its size impacts the quality of the compression and the speed:
// the smaller the faster but the worse for the compression.
List<HistogramPair> histoPriorityList = new();
List<HistogramPair> histoPriorityList = [];
const int maxSize = 9;
// Fill the initial mapping.
@ -480,7 +479,7 @@ internal static class HistogramEncoder
int histoSize = histograms.Count(h => h != null);
// Priority list of histogram pairs.
List<HistogramPair> histoPriorityList = new();
List<HistogramPair> histoPriorityList = [];
int maxSize = histoSize * histoSize;
Vp8LStreaks stats = new();
Vp8LBitEntropy bitsEntropy = new();

11
src/ImageSharp/Formats/Webp/Lossless/Vp8LBackwardRefs.cs

@ -9,20 +9,19 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless;
internal class Vp8LBackwardRefs : IDisposable
{
private readonly IMemoryOwner<PixOrCopy> refs;
private int count;
public Vp8LBackwardRefs(MemoryAllocator memoryAllocator, int pixels)
{
this.refs = memoryAllocator.Allocate<PixOrCopy>(pixels);
this.Count = 0;
this.count = 0;
}
public int Count { get; private set; }
public void Add(PixOrCopy pixOrCopy) => this.refs.Memory.Span[this.count++] = pixOrCopy;
public ref PixOrCopy this[int index] => ref this.refs.Memory.Span[index];
public void Clear() => this.count = 0;
public void Add(PixOrCopy pixOrCopy) => this.refs.Memory.Span[this.Count++] = pixOrCopy;
public void Clear() => this.Count = 0;
public Span<PixOrCopy>.Enumerator GetEnumerator() => this.refs.Slice(0, this.count).GetEnumerator();
/// <inheritdoc/>
public void Dispose() => this.refs.Dispose();

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

@ -1058,9 +1058,8 @@ internal class Vp8LEncoder : IDisposable
int histogramIx = histogramSymbols[0];
Span<HuffmanTreeCode> codes = huffmanCodes.AsSpan(5 * histogramIx);
for (int i = 0; i < backwardRefs.Count; i++)
foreach (PixOrCopy v in backwardRefs)
{
PixOrCopy v = backwardRefs[i];
if (tileX != (x & tileMask) || tileY != (y & tileMask))
{
tileX = x & tileMask;

4
src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs

@ -138,9 +138,9 @@ internal abstract unsafe class Vp8LHistogram
/// <param name="refs">The backward references.</param>
public void StoreRefs(Vp8LBackwardRefs refs)
{
for (int i = 0; i < refs.Count; i++)
foreach (PixOrCopy v in refs)
{
this.AddSinglePixOrCopy(refs[i], false);
this.AddSinglePixOrCopy(v, false);
}
}

Loading…
Cancel
Save