diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs
index bf04cb7024..3961cc6c57 100644
--- a/src/ImageSharp/Advanced/AotCompilerTools.cs
+++ b/src/ImageSharp/Advanced/AotCompilerTools.cs
@@ -7,13 +7,13 @@ using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
-using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Tiff;
+using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
diff --git a/src/ImageSharp/Formats/WebP/Lossless/BackwardReferenceEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/BackwardReferenceEncoder.cs
index f4806dd52f..ed4bfe9087 100644
--- a/src/ImageSharp/Formats/WebP/Lossless/BackwardReferenceEncoder.cs
+++ b/src/ImageSharp/Formats/WebP/Lossless/BackwardReferenceEncoder.cs
@@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
// Keep the best backward references.
var histo = new Vp8LHistogram(worst, cacheBitsTmp);
- var bitCost = histo.EstimateBits();
+ double bitCost = histo.EstimateBits();
if (lz77TypeBest == 0 || bitCost < bitCostBest)
{
diff --git a/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs
index ead8137512..f3c4ad1ca0 100644
--- a/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs
+++ b/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
/// Quality/speed trade-off (0=fast, 6=slower-better).
public Vp8LEncoder(MemoryAllocator memoryAllocator, int width, int height, int quality, int method)
{
- var pixelCount = width * height;
+ int pixelCount = width * height;
int initialSize = pixelCount * 2;
this.quality = Numerics.Clamp(quality, 0, 100);
@@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
(crunchConfig.EntropyIdx == EntropyIx.SpatialSubGreen);
this.UsePredictorTransform = (crunchConfig.EntropyIdx == EntropyIx.Spatial) ||
(crunchConfig.EntropyIdx == EntropyIx.SpatialSubGreen);
- this.UseCrossColorTransform = redAndBlueAlwaysZero ? false : this.UsePredictorTransform;
+ this.UseCrossColorTransform = !redAndBlueAlwaysZero && this.UsePredictorTransform;
this.AllocateTransformBuffer(width, height);
// Reset any parameter in the encoder that is set in the previous iteration.
@@ -335,14 +335,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
int height = image.Height;
// Check if we only deal with a small number of colors and should use a palette.
- var usePalette = this.AnalyzeAndCreatePalette(image);
+ bool usePalette = this.AnalyzeAndCreatePalette(image);
// Empirical bit sizes.
this.HistoBits = GetHistoBits(this.method, usePalette, width, height);
this.TransformBits = GetTransformBits(this.method, this.HistoBits);
// Try out multiple LZ77 on images with few colors.
- var nlz77s = (this.PaletteSize > 0 && this.PaletteSize <= 16) ? 2 : 1;
+ int nlz77s = (this.PaletteSize > 0 && this.PaletteSize <= 16) ? 2 : 1;
EntropyIx entropyIdx = this.AnalyzeEntropy(image, usePalette, this.PaletteSize, this.TransformBits, out redAndBlueAlwaysZero);
bool doNotCache = false;
@@ -382,7 +382,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
// Fill in the different LZ77s.
foreach (CrunchConfig crunchConfig in crunchConfigs)
{
- for (var j = 0; j < nlz77s; ++j)
+ for (int j = 0; j < nlz77s; ++j)
{
crunchConfig.SubConfigs.Add(new CrunchSubConfig
{
@@ -398,7 +398,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
private void EncodeImage(Span bgra, Vp8LHashChain hashChain, Vp8LBackwardRefs[] refsArray, int width, int height, bool useCache, CrunchConfig config, int cacheBits, int histogramBits)
{
int histogramImageXySize = LosslessUtils.SubSampleSize(width, histogramBits) * LosslessUtils.SubSampleSize(height, histogramBits);
- var histogramSymbols = new ushort[histogramImageXySize];
+ ushort[] histogramSymbols = new ushort[histogramImageXySize];
var huffTree = new HuffmanTree[3 * WebpConstants.CodeLengthCodes];
for (int i = 0; i < huffTree.Length; i++)
{
@@ -452,8 +452,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
HistogramEncoder.GetHistoImageSymbols(width, height, refsBest, this.quality, histogramBits, cacheBits, histogramImage, tmpHisto, histogramSymbols);
// Create Huffman bit lengths and codes for each histogram image.
- var histogramImageSize = histogramImage.Count;
- var bitArraySize = 5 * histogramImageSize;
+ int histogramImageSize = histogramImage.Count;
+ int bitArraySize = 5 * histogramImageSize;
var huffmanCodes = new HuffmanTreeCode[bitArraySize];
for (int i = 0; i < huffmanCodes.Length; i++)
{
@@ -601,7 +601,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
private void EncodeImageNoHuffman(Span bgra, Vp8LHashChain hashChain, Vp8LBackwardRefs refsTmp1, Vp8LBackwardRefs refsTmp2, int width, int height, int quality)
{
int cacheBits = 0;
- var histogramSymbols = new ushort[1]; // Only one tree, one symbol.
+ ushort[] histogramSymbols = new ushort[1]; // Only one tree, one symbol.
var huffmanCodes = new HuffmanTreeCode[5];
for (int i = 0; i < huffmanCodes.Length; i++)
@@ -728,8 +728,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
private void StoreFullHuffmanCode(HuffmanTree[] huffTree, HuffmanTreeToken[] tokens, HuffmanTreeCode tree)
{
int i;
- var codeLengthBitDepth = new byte[WebpConstants.CodeLengthCodes];
- var codeLengthBitDepthSymbols = new short[WebpConstants.CodeLengthCodes];
+ byte[] codeLengthBitDepth = new byte[WebpConstants.CodeLengthCodes];
+ short[] codeLengthBitDepthSymbols = new short[WebpConstants.CodeLengthCodes];
var huffmanCode = new HuffmanTreeCode
{
NumSymbols = WebpConstants.CodeLengthCodes,
@@ -738,9 +738,9 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
};
this.bitWriter.PutBits(0, 1);
- var numTokens = HuffmanUtils.CreateCompressedHuffmanTree(tree, tokens);
- var histogram = new uint[WebpConstants.CodeLengthCodes + 1];
- var bufRle = new bool[WebpConstants.CodeLengthCodes + 1];
+ int numTokens = HuffmanUtils.CreateCompressedHuffmanTree(tree, tokens);
+ uint[] histogram = new uint[WebpConstants.CodeLengthCodes + 1];
+ bool[] bufRle = new bool[WebpConstants.CodeLengthCodes + 1];
for (i = 0; i < numTokens; i++)
{
histogram[tokens[i].Code]++;
@@ -758,7 +758,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
int ix = tokens[i].Code;
if (ix == 0 || ix == 17 || ix == 18)
{
- trimmedLength--; // discount trailing zeros.
+ trimmedLength--; // Discount trailing zeros.
trailingZeroBits += codeLengthBitDepth[ix];
if (ix == 17)
{
@@ -775,8 +775,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
}
- var writeTrimmedLength = trimmedLength > 1 && trailingZeroBits > 12;
- var length = writeTrimmedLength ? trimmedLength : numTokens;
+ bool writeTrimmedLength = trimmedLength > 1 && trailingZeroBits > 12;
+ int length = writeTrimmedLength ? trimmedLength : numTokens;
this.bitWriter.PutBits((uint)(writeTrimmedLength ? 1 : 0), 1);
if (writeTrimmedLength)
{
@@ -976,8 +976,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
prevRow = currentRow;
}
- var entropyComp = new double[(int)HistoIx.HistoTotal];
- var entropy = new double[(int)EntropyIx.NumEntropyIx];
+ double[] entropyComp = new double[(int)HistoIx.HistoTotal];
+ double[] entropy = new double[(int)EntropyIx.NumEntropyIx];
int lastModeToAnalyze = usePalette ? (int)EntropyIx.Palette : (int)EntropyIx.SpatialSubGreen;
// Let's add one zero to the predicted histograms. The zeros are removed
@@ -1195,7 +1195,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
else
{
- var buffer = new uint[PaletteInvSize];
+ uint[] buffer = new uint[PaletteInvSize];
// Try to find a perfect hash function able to go from a color to an index
// within 1 << PaletteInvSize in order to build a hash map to go from color to index in palette.
@@ -1246,8 +1246,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
else
{
- var idxMap = new uint[paletteSize];
- var paletteSorted = new uint[paletteSize];
+ uint[] idxMap = new uint[paletteSize];
+ uint[] paletteSorted = new uint[paletteSize];
PrepareMapToPalette(palette, paletteSize, paletteSorted, idxMap);
ApplyPaletteForWithIdxMap(width, height, palette, src, srcStride, dst, dstStride, tmpRow, idxMap, xBits, paletteSorted, paletteSize);
}
@@ -1464,7 +1464,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
}
- var end = 5 * histogramImage.Count;
+ int end = 5 * histogramImage.Count;
for (int i = 0; i < end; i++)
{
int bitLength = huffmanCodes[i].NumSymbols;
@@ -1477,7 +1477,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
// Create Huffman trees.
- var bufRle = new bool[maxNumSymbols];
+ bool[] bufRle = new bool[maxNumSymbols];
var huffTree = new HuffmanTree[3 * maxNumSymbols];
for (int i = 0; i < huffTree.Length; i++)
{
diff --git a/src/ImageSharp/Formats/WebP/Lossless/Vp8LHashChain.cs b/src/ImageSharp/Formats/WebP/Lossless/Vp8LHashChain.cs
index 0e6c4aece5..f5762b6f8c 100644
--- a/src/ImageSharp/Formats/WebP/Lossless/Vp8LHashChain.cs
+++ b/src/ImageSharp/Formats/WebP/Lossless/Vp8LHashChain.cs
@@ -60,16 +60,23 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
int iterMax = GetMaxItersForQuality(quality);
int windowSize = GetWindowSizeForHashChain(quality, xSize);
int pos;
+
+ if (size <= 2)
+ {
+ this.OffsetLength[0] = 0;
+ return;
+ }
+
using IMemoryOwner hashToFirstIndexBuffer = memoryAllocator.Allocate(HashSize);
Span hashToFirstIndex = hashToFirstIndexBuffer.GetSpan();
// Initialize hashToFirstIndex array to -1.
hashToFirstIndex.Fill(-1);
- var chain = new int[size];
+ int[] chain = new int[size];
// Fill the chain linking pixels with the same hash.
- var bgraComp = bgra[0] == bgra[1];
+ bool bgraComp = bgra.Length > 1 && bgra[0] == bgra[1];
for (pos = 0; pos < size - 2;)
{
uint hashCode;
@@ -78,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
{
// Consecutive pixels with the same color will share the same hash.
// We therefore use a different hash: the color and its repetition length.
- var tmp = new uint[2];
+ uint[] tmp = new uint[2];
uint len = 1;
tmp[0] = bgra[pos];
@@ -168,7 +175,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
pos = minPos - 1;
}
- var bestBgra = bgra.Slice(bgraStart)[bestLength];
+ uint bestBgra = bgra.Slice(bgraStart)[bestLength];
for (; pos >= minPos && (--iter > 0); pos = chain[pos])
{
@@ -194,7 +201,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
// We have the best match but in case the two intervals continue matching
// to the left, we have the best matches for the left-extended pixels.
- var maxBasePosition = (uint)basePosition;
+ uint maxBasePosition = (uint)basePosition;
while (true)
{
this.OffsetLength[basePosition] = (bestDistance << BackwardReferenceEncoder.MaxLengthBits) | (uint)bestLength;
@@ -231,16 +238,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
}
[MethodImpl(InliningOptions.ShortMethod)]
- public int FindLength(int basePosition)
- {
- return (int)(this.OffsetLength[basePosition] & ((1U << BackwardReferenceEncoder.MaxLengthBits) - 1));
- }
+ public int FindLength(int basePosition) => (int)(this.OffsetLength[basePosition] & ((1U << BackwardReferenceEncoder.MaxLengthBits) - 1));
[MethodImpl(InliningOptions.ShortMethod)]
- public int FindOffset(int basePosition)
- {
- return (int)(this.OffsetLength[basePosition] >> BackwardReferenceEncoder.MaxLengthBits);
- }
+ public int FindOffset(int basePosition) => (int)(this.OffsetLength[basePosition] >> BackwardReferenceEncoder.MaxLengthBits);
///
/// Calculates the hash for a pixel pair.
@@ -252,7 +253,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
{
uint key = bgra[1] * HashMultiplierHi;
key += bgra[0] * HashMultiplierLo;
- key = key >> (32 - HashBits);
+ key >>= 32 - HashBits;
return key;
}
@@ -263,10 +264,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
/// The quality.
/// Number of hash chain lookups.
[MethodImpl(InliningOptions.ShortMethod)]
- private static int GetMaxItersForQuality(int quality)
- {
- return 8 + (quality * quality / 128);
- }
+ private static int GetMaxItersForQuality(int quality) => 8 + (quality * quality / 128);
[MethodImpl(InliningOptions.ShortMethod)]
private static int GetWindowSizeForHashChain(int quality, int xSize)
diff --git a/src/ImageSharp/Formats/WebP/WebpEncoderCore.cs b/src/ImageSharp/Formats/WebP/WebpEncoderCore.cs
index b785345ee3..ecc940782b 100644
--- a/src/ImageSharp/Formats/WebP/WebpEncoderCore.cs
+++ b/src/ImageSharp/Formats/WebP/WebpEncoderCore.cs
@@ -3,7 +3,6 @@
using System.IO;
using System.Threading;
-using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats.Webp.Lossless;
using SixLabors.ImageSharp.Formats.Webp.Lossy;
diff --git a/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs b/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs
index 39055faf50..0056a187b3 100644
--- a/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs
+++ b/tests/ImageSharp.Benchmarks/Codecs/EncodeTiff.cs
@@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
ImageCodecInfo codec = FindCodecForType("image/tiff");
using var parameters = new EncoderParameters(1)
{
- Param = {[0] = new EncoderParameter(Encoder.Compression, (long)Cast(this.Compression))}
+ Param = { [0] = new EncoderParameter(Encoder.Compression, (long)Cast(this.Compression)) }
};
using var memoryStream = new MemoryStream();
@@ -73,12 +73,6 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
{
TiffPhotometricInterpretation photometricInterpretation = TiffPhotometricInterpretation.Rgb;
- // Workaround for 1-bit bug
- if (this.Compression == TiffCompression.CcittGroup3Fax || this.Compression == TiffCompression.Ccitt1D)
- {
- photometricInterpretation = TiffPhotometricInterpretation.WhiteIsZero;
- }
-
var encoder = new TiffEncoder() { Compression = this.Compression, PhotometricInterpretation = photometricInterpretation };
using var memoryStream = new MemoryStream();
this.core.SaveAsTiff(memoryStream, encoder);
diff --git a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
index 11964f2535..828fc0dcd3 100644
--- a/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/WebP/WebpEncoderTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
+using System.IO;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
@@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
};
using Image image = provider.GetImage();
- var testOutputDetails = string.Concat("lossless", "_q", quality);
+ string testOutputDetails = string.Concat("lossless", "_q", quality);
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder);
}
@@ -49,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
};
using Image image = provider.GetImage();
- var testOutputDetails = string.Concat("lossless", "_m", method);
+ string testOutputDetails = string.Concat("lossless", "_m", method);
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder);
}
@@ -67,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
};
using Image image = provider.GetImage();
- var testOutputDetails = string.Concat("lossy", "_q", quality);
+ string testOutputDetails = string.Concat("lossy", "_q", quality);
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder, customComparer: GetComparer(quality));
}
@@ -91,10 +92,22 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
};
using Image image = provider.GetImage();
- var testOutputDetails = string.Concat("lossy", "_m", method);
+ string testOutputDetails = string.Concat("lossy", "_m", method);
image.VerifyEncoder(provider, "webp", testOutputDetails, encoder, customComparer: GetComparer(quality));
}
+ [Fact]
+ public void Encode_Lossless_OneByOnePixel_Works()
+ {
+ // Just make sure, encoding 1 pixel by 1 pixel does not throw an exception.
+ using var image = new Image(1, 1);
+ var encoder = new WebpEncoder() { Lossy = false };
+ using (var memStream = new MemoryStream())
+ {
+ image.SaveAsWebp(memStream, encoder);
+ }
+ }
+
private static ImageComparer GetComparer(int quality)
{
float tolerance = 0.01f; // ~1.0%
diff --git a/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs b/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs
index a82ea70179..2456246b67 100644
--- a/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/ImageMetadataTests.cs
@@ -98,8 +98,8 @@ namespace SixLabors.ImageSharp.Tests.Metadata
image.Metadata.SyncProfiles();
- Assert.Equal(400, ((Rational)image.Metadata.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble());
- Assert.Equal(500, ((Rational)image.Metadata.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble());
+ Assert.Equal(400, image.Metadata.ExifProfile.GetValue(ExifTag.XResolution).Value.ToDouble());
+ Assert.Equal(500, image.Metadata.ExifProfile.GetValue(ExifTag.YResolution).Value.ToDouble());
}
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
index 2bcee62bd2..4b374b21f6 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
@@ -5,12 +5,12 @@ using System;
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
-using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.Formats.Tiff;
+using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
namespace SixLabors.ImageSharp.Tests
diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
index 4ad32a3798..c836bda350 100644
--- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs
@@ -5,9 +5,9 @@ using System;
using System.IO;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
-using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.Formats.Jpeg;
+using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs;
using Xunit;
using Xunit.Abstractions;