From eb7a9089f884c4a943418a6744270fbc12f34f5f Mon Sep 17 00:00:00 2001 From: Brian Popow Date: Mon, 27 Jul 2020 12:36:44 +0200 Subject: [PATCH] Add missing null checks --- .../Formats/WebP/BitWriter/Vp8LBitWriter.cs | 2 +- .../Formats/WebP/Lossless/HistogramEncoder.cs | 29 +++++++++++------ .../Formats/WebP/Lossless/Vp8LEncoder.cs | 32 ++++++++++++------- 3 files changed, 41 insertions(+), 22 deletions(-) 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; } } } - - }