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> /// <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> /// </summary>
/// <param name="stream">The stream to write to.</param> /// <param name="stream">The stream to write to.</param>
public void WriteToStream(Stream stream) 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 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) 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: // Cubic ramp between 1 and MaxHistoGreedy:
int thresholdSize = (int)(1 + (x * x * x * (MaxHistoGreedy - 1))); int thresholdSize = (int)(1 + (x * x * x * (MaxHistoGreedy - 1)));
bool doGreedy = HistogramCombineStochastic(imageHisto, ref numUsed, thresholdSize); bool doGreedy = HistogramCombineStochastic(imageHisto, thresholdSize);
if (doGreedy) if (doGreedy)
{ {
HistogramCombineGreedy(imageHisto); HistogramCombineGreedy(imageHisto);
@ -303,14 +303,15 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
/// Perform histogram aggregation using a stochastic approach. /// Perform histogram aggregation using a stochastic approach.
/// </summary> /// </summary>
/// <returns>true if a greedy approach needs to be performed afterwards, false otherwise.</returns> /// <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(); var rand = new Random();
int triesWithNoSuccess = 0; int triesWithNoSuccess = 0;
var numUsed = histograms.Count(h => h != null);
int outerIters = numUsed; int outerIters = numUsed;
int numTriesNoSuccess = outerIters / 2; int numTriesNoSuccess = outerIters / 2;
if (histograms.Count < minClusterSize) if (numUsed < minClusterSize)
{ {
return true; return true;
} }
@ -333,7 +334,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
double bestCost = (histoPriorityList.Count == 0) ? 0.0d : histoPriorityList[0].CostDiff; double bestCost = (histoPriorityList.Count == 0) ? 0.0d : histoPriorityList[0].CostDiff;
int bestIdx1 = -1; int bestIdx1 = -1;
int bestIdx2 = 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); uint randRange = (uint)((numUsed - 1) * numUsed);
// Pick random samples. // Pick random samples.
@ -454,16 +455,26 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private static void HistogramCombineGreedy(List<Vp8LHistogram> histograms) private static void HistogramCombineGreedy(List<Vp8LHistogram> histograms)
{ {
int histoSize = histograms.Count; int histoSize = histograms.Count(h => h != null);
// Priority list of histogram pairs. // Priority list of histogram pairs.
var histoPriorityList = new List<HistogramPair>(); var histoPriorityList = new List<HistogramPair>();
int maxSize = histoSize * histoSize; 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); 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. // 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) 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.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats.WebP.BitWriter; using SixLabors.ImageSharp.Formats.WebP.BitWriter;
@ -34,13 +33,13 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
/// <summary> /// <summary>
/// The <see cref="MemoryAllocator"/> to use for buffer allocations. /// The <see cref="MemoryAllocator"/> to use for buffer allocations.
/// </summary> /// </summary>
private MemoryAllocator memoryAllocator; private readonly MemoryAllocator memoryAllocator;
/// <summary> /// <summary>
/// A bit writer for writing lossless webp streams. /// A bit writer for writing lossless webp streams.
/// </summary> /// </summary>
private Vp8LBitWriter bitWriter; private Vp8LBitWriter bitWriter;
private const int ApplyPaletteGreedyMax = 4; private const int ApplyPaletteGreedyMax = 4;
private const int PaletteInvSizeBits = 11; private const int PaletteInvSizeBits = 11;
@ -309,9 +308,20 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
this.bitWriter.PutBits(0, 1); // No more transforms. this.bitWriter.PutBits(0, 1); // No more transforms.
// Encode and write the transformed image. // Encode and write the transformed image.
this.EncodeImage(bgra, this.HashChain, this.Refs, this.CurrentWidth, height, quality, useCache, crunchConfig, this.EncodeImage(
this.CacheBits, this.HistoBits, bytePosition); bgra,
this.HashChain,
this.Refs,
this.CurrentWidth,
height,
quality,
useCache,
crunchConfig,
this.CacheBits,
this.HistoBits,
bytePosition);
} }
// TODO: Comparison and picking of best (smallest) encoding // 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. // Try out multiple LZ77 on images with few colors.
var nlz77s = (this.PaletteSize > 0 && this.PaletteSize <= 16) ? 2 : 1; var nlz77s = (this.PaletteSize > 0 && this.PaletteSize <= 16) ? 2 : 1;
EntropyIx entropyIdx = this.AnalyzeEntropy(image, usePalette, this.PaletteSize, this.TransformBits, out redAndBlueAlwaysZero); EntropyIx entropyIdx = this.AnalyzeEntropy(image, usePalette, this.PaletteSize, this.TransformBits, out redAndBlueAlwaysZero);
bool doNotCache = false; bool doNotCache = false;
var crunchConfigs = new List<CrunchConfig>(); var crunchConfigs = new List<CrunchConfig>();
@ -358,7 +368,7 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
else else
{ {
// Only choose the guessed best transform. // Only choose the guessed best transform.
crunchConfigs.Add(new CrunchConfig {EntropyIdx = entropyIdx}); crunchConfigs.Add(new CrunchConfig { EntropyIdx = entropyIdx });
if (configQuality >= 75 && method == 5) if (configQuality >= 75 && method == 5)
{ {
// Test with and without color cache. // 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 we have a palette, also check in combination with spatial.
if (entropyIdx == EntropyIx.Palette) 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) public void AllocateTransformBuffer(int width, int height)
{ {
int imageSize = width * height;
// VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra // VP8LResidualImage needs room for 2 scanlines of uint32 pixels with an extra
// pixel in each, plus 2 regular scanlines of bytes. // pixel in each, plus 2 regular scanlines of bytes.
int argbScratchSize = this.UsePredictorTransform ? ((width + 1) * 2) + (((width * 2) + 4 - 1) / 4) : 0; 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 private class CrunchConfig
{ {
public EntropyIx EntropyIdx { get; set; } public EntropyIx EntropyIdx { get; set; }
public List<CrunchSubConfig> SubConfigs { get; } = new List<CrunchSubConfig>(); public List<CrunchSubConfig> SubConfigs { get; } = new List<CrunchSubConfig>();
} }
@ -1627,9 +1636,8 @@ namespace SixLabors.ImageSharp.Formats.WebP.Lossless
private class CrunchSubConfig private class CrunchSubConfig
{ {
public int Lz77 { get; set; } public int Lz77 { get; set; }
public bool DoNotCache { get; set; } public bool DoNotCache { get; set; }
} }
} }
} }

Loading…
Cancel
Save