Browse Source

Add missing null checks

pull/1552/head
Brian Popow 6 years ago
parent
commit
eb7a9089f8
  1. 2
      src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs
  2. 29
      src/ImageSharp/Formats/WebP/Lossless/HistogramEncoder.cs
  3. 32
      src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs

2
src/ImageSharp/Formats/WebP/BitWriter/Vp8LBitWriter.cs

@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.BitWriter
}
/// <summary>
/// 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.
/// </summary>
/// <param name="stream">The stream to write to.</param>
public void WriteToStream(Stream stream)

29
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<Vp8LHistogram> 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.
/// </summary>
/// <returns>true if a greedy approach needs to be performed afterwards, false otherwise.</returns>
private static bool HistogramCombineStochastic(List<Vp8LHistogram> histograms, ref int numUsed, int minClusterSize)
private static bool HistogramCombineStochastic(List<Vp8LHistogram> 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<Vp8LHistogram> histograms)
{
int histoSize = histograms.Count;
int histoSize = histograms.Count(h => h != null);
// Priority list of histogram pairs.
var histoPriorityList = new List<HistogramPair>();
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)
{

32
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
/// <summary>
/// The <see cref="MemoryAllocator"/> to use for buffer allocations.
/// </summary>
private MemoryAllocator memoryAllocator;
private readonly MemoryAllocator memoryAllocator;
/// <summary>
/// A bit writer for writing lossless webp streams.
/// </summary>
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<CrunchConfig>();
@ -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<CrunchSubConfig> SubConfigs { get; } = new List<CrunchSubConfig>();
}
@ -1627,9 +1636,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private class CrunchSubConfig
{
public int Lz77 { get; set; }
public bool DoNotCache { get; set; }
}
}
}

Loading…
Cancel
Save