Browse Source

Replace indexed span iteration with foreach (+performance)

pull/2940/head
Maxim Shipko 12 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. // 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()) if (v.IsLiteral())
{ {
uint pix = bgra[pos++]; uint pix = bgra[pos++];
@ -780,9 +779,8 @@ internal static class BackwardReferenceEncoder
{ {
int pixelIndex = 0; int pixelIndex = 0;
ColorCache colorCache = new(cacheBits); 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()) if (v.IsLiteral())
{ {
uint bgraLiteral = v.BgraOrDistance; uint bgraLiteral = v.BgraOrDistance;
@ -790,7 +788,7 @@ internal static class BackwardReferenceEncoder
if (ix >= 0) if (ix >= 0)
{ {
// Color cache contains bgraLiteral // Color cache contains bgraLiteral
refs[idx] = PixOrCopy.CreateCacheIdx(ix); v = PixOrCopy.CreateCacheIdx(ix);
} }
else else
{ {
@ -812,15 +810,13 @@ internal static class BackwardReferenceEncoder
private static void BackwardReferences2DLocality(int xSize, Vp8LBackwardRefs refs) 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()) if (v.IsCopy())
{ {
int dist = (int)v.BgraOrDistance; int dist = (int)v.BgraOrDistance;
int transformedDist = DistanceToPlaneCode(xSize, dist); 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); using OwnedVp8LHistogram histogram = OwnedVp8LHistogram.Create(this.memoryAllocator, cacheBits);
// The following code is similar to HistogramCreate but converts the distance to plane code. // 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); 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 x = 0, y = 0;
int histoXSize = LosslessUtils.SubSampleSize(xSize, histoBits); 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); int ix = ((y >> histoBits) * histoXSize) + (x >> histoBits);
histograms[ix].AddSinglePixOrCopy(v, false); histograms[ix].AddSinglePixOrCopy(v, false);
x += v.Len; x += v.Len;
@ -217,7 +216,7 @@ internal static class HistogramEncoder
clusterMappings[idx] = (ushort)idx; clusterMappings[idx] = (ushort)idx;
} }
List<int> indicesToRemove = new(); List<int> indicesToRemove = [];
Vp8LStreaks stats = new(); Vp8LStreaks stats = new();
Vp8LBitEntropy bitsEntropy = new(); Vp8LBitEntropy bitsEntropy = new();
for (int idx = 0; idx < histograms.Count; idx++) 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: // 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. // the smaller the faster but the worse for the compression.
List<HistogramPair> histoPriorityList = new(); List<HistogramPair> histoPriorityList = [];
const int maxSize = 9; const int maxSize = 9;
// Fill the initial mapping. // Fill the initial mapping.
@ -480,7 +479,7 @@ internal static class HistogramEncoder
int histoSize = histograms.Count(h => h != null); int histoSize = histograms.Count(h => h != null);
// Priority list of histogram pairs. // Priority list of histogram pairs.
List<HistogramPair> histoPriorityList = new(); List<HistogramPair> histoPriorityList = [];
int maxSize = histoSize * histoSize; int maxSize = histoSize * histoSize;
Vp8LStreaks stats = new(); Vp8LStreaks stats = new();
Vp8LBitEntropy bitsEntropy = 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 internal class Vp8LBackwardRefs : IDisposable
{ {
private readonly IMemoryOwner<PixOrCopy> refs; private readonly IMemoryOwner<PixOrCopy> refs;
private int count;
public Vp8LBackwardRefs(MemoryAllocator memoryAllocator, int pixels) public Vp8LBackwardRefs(MemoryAllocator memoryAllocator, int pixels)
{ {
this.refs = memoryAllocator.Allocate<PixOrCopy>(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 Span<PixOrCopy>.Enumerator GetEnumerator() => this.refs.Slice(0, this.count).GetEnumerator();
public void Clear() => this.Count = 0;
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() => this.refs.Dispose(); 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]; int histogramIx = histogramSymbols[0];
Span<HuffmanTreeCode> codes = huffmanCodes.AsSpan(5 * histogramIx); 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)) if (tileX != (x & tileMask) || tileY != (y & tileMask))
{ {
tileX = x & 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> /// <param name="refs">The backward references.</param>
public void StoreRefs(Vp8LBackwardRefs refs) 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