Browse Source

Merge branch 'master' into bp/ColorBlueTransformAvx

pull/1824/head
Brian Popow 5 years ago
committed by GitHub
parent
commit
37189bfa78
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  2. 4
      src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffLzwEncoder.cs
  3. 12
      src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6TiffCompression.cs
  4. 2
      src/ImageSharp/Formats/Webp/Lossless/CostModel.cs
  5. 2
      src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs
  6. 2
      src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs
  7. 10
      src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs
  8. 8
      src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs
  9. 2
      src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs
  10. 47
      src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs
  11. 2
      tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs

4
src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

@ -288,8 +288,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <param name="componentCount">The number of components to write.</param> /// <param name="componentCount">The number of components to write.</param>
private void WriteDefineHuffmanTables(int componentCount) private void WriteDefineHuffmanTables(int componentCount)
{ {
// This uses a C#'s compiler optimization that refers to the static data segment of the assembly,
// and doesn't incur any allocation at all.
// Table identifiers. // Table identifiers.
ReadOnlySpan<byte> headers = stackalloc byte[] ReadOnlySpan<byte> headers = new byte[]
{ {
0x00, 0x00,
0x10, 0x10,

4
src/ImageSharp/Formats/Tiff/Compression/Compressors/TiffLzwEncoder.cs

@ -256,8 +256,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Compressors
private void ResetTables() private void ResetTables()
{ {
this.children.GetSpan().Fill(0); this.children.GetSpan().Clear();
this.siblings.GetSpan().Fill(0); this.siblings.GetSpan().Clear();
this.bitsPerCode = MinBits; this.bitsPerCode = MinBits;
this.maxCode = MaxValue(this.bitsPerCode); this.maxCode = MaxValue(this.bitsPerCode);
this.nextValidCode = EoiCode + 1; this.nextValidCode = EoiCode + 1;

12
src/ImageSharp/Formats/Tiff/Compression/Decompressors/T6TiffCompression.cs

@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
uint bitsWritten = 0; uint bitsWritten = 0;
for (int y = 0; y < height; y++) for (int y = 0; y < height; y++)
{ {
scanLine.Fill(0); scanLine.Clear();
Decode2DScanline(bitReader, this.isWhiteZero, referenceScanLine, scanLine); Decode2DScanline(bitReader, this.isWhiteZero, referenceScanLine, scanLine);
bitsWritten = this.WriteScanLine(buffer, scanLine, bitsWritten); bitsWritten = this.WriteScanLine(buffer, scanLine, bitsWritten);
@ -116,7 +116,15 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
{ {
// If a TIFF reader encounters EOFB before the expected number of lines has been extracted, // If a TIFF reader encounters EOFB before the expected number of lines has been extracted,
// it is appropriate to assume that the missing rows consist entirely of white pixels. // it is appropriate to assume that the missing rows consist entirely of white pixels.
scanline.Fill(whiteIsZero ? (byte)0 : (byte)255); if (whiteIsZero)
{
scanline.Clear();
}
else
{
scanline.Fill((byte)255);
}
break; break;
} }

2
src/ImageSharp/Formats/Webp/Lossless/CostModel.cs

@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
if (nonzeros <= 1) if (nonzeros <= 1)
{ {
output.AsSpan(0, numSymbols).Fill(0); output.AsSpan(0, numSymbols).Clear();
} }
else else
{ {

2
src/ImageSharp/Formats/Webp/Lossless/HistogramEncoder.cs

@ -287,7 +287,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
// Create a mapping from a cluster id to its minimal version. // Create a mapping from a cluster id to its minimal version.
int clusterMax = 0; int clusterMax = 0;
clusterMappingsTmp.AsSpan().Fill(0); clusterMappingsTmp.AsSpan().Clear();
// Re-map the ids. // Re-map the ids.
for (int i = 0; i < symbols.Length; i++) for (int i = 0; i < symbols.Length; i++)

2
src/ImageSharp/Formats/Webp/Lossless/HuffmanUtils.cs

@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
public static void CreateHuffmanTree(uint[] histogram, int treeDepthLimit, bool[] bufRle, HuffmanTree[] huffTree, HuffmanTreeCode huffCode) public static void CreateHuffmanTree(uint[] histogram, int treeDepthLimit, bool[] bufRle, HuffmanTree[] huffTree, HuffmanTreeCode huffCode)
{ {
int numSymbols = huffCode.NumSymbols; int numSymbols = huffCode.NumSymbols;
bufRle.AsSpan().Fill(false); bufRle.AsSpan().Clear();
OptimizeHuffmanForRle(numSymbols, bufRle, histogram); OptimizeHuffmanForRle(numSymbols, bufRle, histogram);
GenerateOptimalTree(huffTree, histogram, numSymbols, treeDepthLimit, huffCode.CodeLengths); GenerateOptimalTree(huffTree, histogram, numSymbols, treeDepthLimit, huffCode.CodeLengths);

10
src/ImageSharp/Formats/Webp/Lossless/Vp8LHistogram.cs

@ -320,7 +320,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
} }
else else
{ {
output.Literal.AsSpan(0, literalSize).Fill(0); output.Literal.AsSpan(0, literalSize).Clear();
} }
} }
@ -343,7 +343,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
} }
else else
{ {
output.Red.AsSpan(0, size).Fill(0); output.Red.AsSpan(0, size).Clear();
} }
} }
@ -366,7 +366,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
} }
else else
{ {
output.Blue.AsSpan(0, size).Fill(0); output.Blue.AsSpan(0, size).Clear();
} }
} }
@ -389,7 +389,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
} }
else else
{ {
output.Alpha.AsSpan(0, size).Fill(0); output.Alpha.AsSpan(0, size).Clear();
} }
} }
@ -412,7 +412,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossless
} }
else else
{ {
output.Distance.AsSpan(0, size).Fill(0); output.Distance.AsSpan(0, size).Clear();
} }
} }

8
src/ImageSharp/Formats/Webp/Lossy/Vp8EncIterator.cs

@ -911,7 +911,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
this.LeftNz[8] = 0; this.LeftNz[8] = 0;
this.LeftDerr.AsSpan().Fill(0); this.LeftDerr.AsSpan().Clear();
} }
private void InitTop() private void InitTop()
@ -919,14 +919,14 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
int topSize = this.mbw * 16; int topSize = this.mbw * 16;
this.YTop.AsSpan(0, topSize).Fill(127); this.YTop.AsSpan(0, topSize).Fill(127);
this.UvTop.AsSpan().Fill(127); this.UvTop.AsSpan().Fill(127);
this.Nz.AsSpan().Fill(0); this.Nz.AsSpan().Clear();
int predsW = (4 * this.mbw) + 1; int predsW = (4 * this.mbw) + 1;
int predsH = (4 * this.mbh) + 1; int predsH = (4 * this.mbh) + 1;
int predsSize = predsW * predsH; int predsSize = predsW * predsH;
this.Preds.AsSpan(predsSize + this.predsWidth, this.mbw).Fill(0); this.Preds.AsSpan(predsSize + this.predsWidth, this.mbw).Clear();
this.TopDerr.AsSpan().Fill(0); this.TopDerr.AsSpan().Clear();
} }
private int Bit(uint nz, int n) => (nz & (1 << n)) != 0 ? 1 : 0; private int Bit(uint nz, int n) => (nz & (1 << n)) != 0 ? 1 : 0;

2
src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs

@ -546,7 +546,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
int predsW = (4 * this.Mbw) + 1; int predsW = (4 * this.Mbw) + 1;
int predsH = (4 * this.Mbh) + 1; int predsH = (4 * this.Mbh) + 1;
int predsSize = predsW * predsH; int predsSize = predsW * predsH;
this.Preds.AsSpan(predsSize + this.PredsWidth - 4, 4).Fill(0); this.Preds.AsSpan(predsSize + this.PredsWidth - 4, 4).Clear();
this.Nz[0] = 0; // constant this.Nz[0] = 0; // constant
} }

47
src/ImageSharp/Processing/Processors/Quantization/WuQuantizer{TPixel}.cs

@ -417,19 +417,40 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
for (int r = 1; r < IndexCount; r++) for (int r = 1; r < IndexCount; r++)
{ {
// Currently, RyuJIT hoists the invariants of multi-level nested loop only to the
// immediate outer loop. See https://github.com/dotnet/runtime/issues/61420
// To ensure the calculation doesn't happen repeatedly, hoist some of the calculations
// in the form of ind1* manually.
int ind1R = (r << ((IndexBits * 2) + IndexAlphaBits)) +
(r << (IndexBits + IndexAlphaBits + 1)) +
(r << (IndexBits * 2)) +
(r << (IndexBits + 1)) +
r;
volumeSpan.Clear(); volumeSpan.Clear();
for (int g = 1; g < IndexCount; g++) for (int g = 1; g < IndexCount; g++)
{ {
int ind1G = ind1R +
(g << (IndexBits + IndexAlphaBits)) +
(g << IndexBits) +
g;
int r_g = r + g;
areaSpan.Clear(); areaSpan.Clear();
for (int b = 1; b < IndexCount; b++) for (int b = 1; b < IndexCount; b++)
{ {
int ind1B = ind1G +
((r_g + b) << IndexAlphaBits) +
b;
Moment line = default; Moment line = default;
for (int a = 1; a < IndexAlphaCount; a++) for (int a = 1; a < IndexAlphaCount; a++)
{ {
int ind1 = GetPaletteIndex(r, g, b, a); int ind1 = ind1B + a;
line += momentSpan[ind1]; line += momentSpan[ind1];
areaSpan[a] += line; areaSpan[a] += line;
@ -628,13 +649,35 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
for (int r = cube.RMin + 1; r <= cube.RMax; r++) for (int r = cube.RMin + 1; r <= cube.RMax; r++)
{ {
// Currently, RyuJIT hoists the invariants of multi-level nested loop only to the
// immediate outer loop. See https://github.com/dotnet/runtime/issues/61420
// To ensure the calculation doesn't happen repeatedly, hoist some of the calculations
// in the form of ind1* manually.
int ind1R = (r << ((IndexBits * 2) + IndexAlphaBits)) +
(r << (IndexBits + IndexAlphaBits + 1)) +
(r << (IndexBits * 2)) +
(r << (IndexBits + 1)) +
r;
for (int g = cube.GMin + 1; g <= cube.GMax; g++) for (int g = cube.GMin + 1; g <= cube.GMax; g++)
{ {
int ind1G = ind1R +
(g << (IndexBits + IndexAlphaBits)) +
(g << IndexBits) +
g;
int r_g = r + g;
for (int b = cube.BMin + 1; b <= cube.BMax; b++) for (int b = cube.BMin + 1; b <= cube.BMax; b++)
{ {
int ind1B = ind1G +
((r_g + b) << IndexAlphaBits) +
b;
for (int a = cube.AMin + 1; a <= cube.AMax; a++) for (int a = cube.AMin + 1; a <= cube.AMax; a++)
{ {
tagSpan[GetPaletteIndex(r, g, b, a)] = label; int index = ind1B + a;
tagSpan[index] = label;
} }
} }
} }

2
tests/ImageSharp.Benchmarks/Codecs/EncodeIndexedPng.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public void PngCoreWuNoDither() public void PngCoreWuNoDither()
{ {
using var memoryStream = new MemoryStream(); using var memoryStream = new MemoryStream();
var options = new PngEncoder { Quantizer = new WuQuantizer(new QuantizerOptions { Dither = null }) }; var options = new PngEncoder { Quantizer = new WuQuantizer(new QuantizerOptions { Dither = null }), ColorType = PngColorType.Palette };
this.bmpCore.SaveAsPng(memoryStream, options); this.bmpCore.SaveAsPng(memoryStream, options);
} }
} }

Loading…
Cancel
Save