Browse Source

Write missing padding byte

pull/1552/head
Brian Popow 6 years ago
parent
commit
bc4d4ccc34
  1. 25
      src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs
  2. 4
      src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs

25
src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs

@ -67,7 +67,6 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// Cubic ramp between 1 and MaxHistoGreedy: // Cubic ramp between 1 and MaxHistoGreedy:
int thresholdSize = (int)(1 + (x * x * x * (MaxHistoGreedy - 1))); int thresholdSize = (int)(1 + (x * x * x * (MaxHistoGreedy - 1)));
RemoveEmptyHistograms(imageHisto);
bool doGreedy = HistogramCombineStochastic(imageHisto, thresholdSize); bool doGreedy = HistogramCombineStochastic(imageHisto, thresholdSize);
if (doGreedy) if (doGreedy)
{ {
@ -83,22 +82,17 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private static void RemoveEmptyHistograms(List<Vp8LHistogram> histograms) private static void RemoveEmptyHistograms(List<Vp8LHistogram> histograms)
{ {
int size = 0; int size = 0;
var indicesToRemove = new List<int>();
for (int i = 0; i < histograms.Count; i++) for (int i = 0; i < histograms.Count; i++)
{ {
if (histograms[i] == null) if (histograms[i] == null)
{ {
indicesToRemove.Add(i);
continue; continue;
} }
histograms[size++] = histograms[i]; histograms[size++] = histograms[i];
} }
foreach (int index in indicesToRemove.OrderByDescending(i => i)) histograms.RemoveRange(size, histograms.Count - size);
{
histograms.RemoveAt(index);
}
} }
/// <summary> /// <summary>
@ -321,7 +315,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
return true; return true;
} }
// Priority queue 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.
var histoPriorityList = new List<HistogramPair>(); var histoPriorityList = new List<HistogramPair>();
int maxSize = 9; int maxSize = 9;
@ -338,7 +332,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
mappings[j++] = iter; mappings[j++] = iter;
} }
// Collapse similar histograms // Collapse similar histograms.
for (int iter = 0; iter < outerIters && numUsed >= minClusterSize && ++triesWithNoSuccess < numTriesNoSuccess; iter++) for (int iter = 0; iter < outerIters && numUsed >= minClusterSize && ++triesWithNoSuccess < numTriesNoSuccess; iter++)
{ {
double bestCost = (histoPriorityList.Count == 0) ? 0.0d : histoPriorityList[0].CostDiff; double bestCost = (histoPriorityList.Count == 0) ? 0.0d : histoPriorityList[0].CostDiff;
@ -391,15 +385,15 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
Span<int> dst = mappings.AsSpan(mappingIndex); Span<int> dst = mappings.AsSpan(mappingIndex);
src.CopyTo(dst); src.CopyTo(dst);
// Merge the histograms and remove bestIdx2 from the queue. // Merge the histograms and remove bestIdx2 from the list.
HistogramAdd(histograms[bestIdx2], histograms[bestIdx1], histograms[bestIdx1]); HistogramAdd(histograms[bestIdx2], histograms[bestIdx1], histograms[bestIdx1]);
histograms.ElementAt(bestIdx1).BitCost = histoPriorityList[0].CostCombo; histograms.ElementAt(bestIdx1).BitCost = histoPriorityList[0].CostCombo;
histograms.RemoveAt(bestIdx2); histograms[bestIdx2] = null;
numUsed--; numUsed--;
for (int j = 0; j < histoPriorityList.Count;) for (int j = 0; j < histoPriorityList.Count;)
{ {
HistogramPair p = histoPriorityList.ElementAt(j); HistogramPair p = histoPriorityList[j];
bool isIdx1Best = p.Idx1 == bestIdx1 || p.Idx1 == bestIdx2; bool isIdx1Best = p.Idx1 == bestIdx1 || p.Idx1 == bestIdx2;
bool isIdx2Best = p.Idx2 == bestIdx1 || p.Idx2 == bestIdx2; bool isIdx2Best = p.Idx2 == bestIdx1 || p.Idx2 == bestIdx2;
bool doEval = false; bool doEval = false;
@ -408,13 +402,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
// check for it all the time nevertheless. // check for it all the time nevertheless.
if (isIdx1Best && isIdx2Best) if (isIdx1Best && isIdx2Best)
{ {
histoPriorityList[j] = histoPriorityList[histoPriorityList.Count - 1];
histoPriorityList.RemoveAt(histoPriorityList.Count - 1); histoPriorityList.RemoveAt(histoPriorityList.Count - 1);
numUsed--;
continue; continue;
} }
// Any pair containing one of the two best indices should only refer to // Any pair containing one of the two best indices should only refer to
// best_idx1. Its cost should also be updated. // bestIdx1. Its cost should also be updated.
if (isIdx1Best) if (isIdx1Best)
{ {
p.Idx1 = bestIdx1; p.Idx1 = bestIdx1;
@ -440,8 +434,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
HistoListUpdatePair(histograms[p.Idx1], histograms[p.Idx2], 0.0d, p); HistoListUpdatePair(histograms[p.Idx1], histograms[p.Idx2], 0.0d, p);
if (p.CostDiff >= 0.0d) if (p.CostDiff >= 0.0d)
{ {
histoPriorityList[j] = histoPriorityList[histoPriorityList.Count - 1];
histoPriorityList.RemoveAt(histoPriorityList.Count - 1); histoPriorityList.RemoveAt(histoPriorityList.Count - 1);
numUsed--;
continue; continue;
} }
} }
@ -628,6 +622,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private static void HistoListUpdatePair(Vp8LHistogram h1, Vp8LHistogram h2, double threshold, HistogramPair pair) private static void HistoListUpdatePair(Vp8LHistogram h1, Vp8LHistogram h2, double threshold, HistogramPair pair)
{ {
double sumCost = h1.BitCost + h2.BitCost; double sumCost = h1.BitCost + h2.BitCost;
pair.CostCombo = 0.0d;
h1.GetCombinedHistogramEntropy(h2, sumCost + threshold, costInitial: pair.CostCombo, out var cost); h1.GetCombinedHistogramEntropy(h2, sumCost + threshold, costInitial: pair.CostCombo, out var cost);
pair.CostCombo = cost; pair.CostCombo = cost;
pair.CostDiff = pair.CostCombo - sumCost; pair.CostDiff = pair.CostCombo - sumCost;

4
src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs

@ -193,6 +193,10 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
var riffSize = WebPConstants.TagSize + WebPConstants.ChunkHeaderSize + vp8LSize + pad; var riffSize = WebPConstants.TagSize + WebPConstants.ChunkHeaderSize + vp8LSize + pad;
this.WriteRiffHeader(riffSize, vp8LSize, stream); this.WriteRiffHeader(riffSize, vp8LSize, stream);
this.bitWriter.WriteToStream(stream); this.bitWriter.WriteToStream(stream);
if (pad == 1)
{
stream.WriteByte(0);
}
} }
/// <summary> /// <summary>

Loading…
Cancel
Save