Browse Source

Review changes

pull/1552/head
Brian Popow 6 years ago
parent
commit
62d475506f
  1. 4
      src/ImageSharp/Formats/WebP/AlphaDecoder.cs
  2. 6
      src/ImageSharp/Formats/WebP/LosslessUtils.cs
  3. 11
      src/ImageSharp/Formats/WebP/WebPDecoderCore.cs
  4. 23
      src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs
  5. 8
      src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs
  6. 44
      tests/ImageSharp.Benchmarks/Codecs/DecodeWebp.cs

4
src/ImageSharp/Formats/WebP/AlphaDecoder.cs

@ -273,10 +273,10 @@ namespace SixLabors.ImageSharp.Formats.WebP
int bitsPerPixel = 8 >> transform.Bits;
int width = transform.XSize;
Span<uint> colorMap = transform.Data.Memory.Span;
int srcOffset = 0;
int dstOffset = 0;
if (bitsPerPixel < 8)
{
int srcOffset = 0;
int dstOffset = 0;
int pixelsPerByte = 1 << transform.Bits;
int countMask = pixelsPerByte - 1;
int bitMask = (1 << bitsPerPixel) - 1;

6
src/ImageSharp/Formats/WebP/LosslessUtils.cs

@ -279,14 +279,16 @@ namespace SixLabors.ImageSharp.Formats.WebP
newColorMap[0] = transformData[0];
Span<byte> data = MemoryMarshal.Cast<uint, byte>(transformData);
Span<byte> newData = MemoryMarshal.Cast<uint, byte>(newColorMap);
int numColorsX4 = 4 * numColors;
int i;
for (i = 4; i < 4 * numColors; ++i)
for (i = 4; i < numColorsX4; i++)
{
// Equivalent to AddPixelEq(), on a byte-basis.
newData[i] = (byte)((data[i] + newData[i - 4]) & 0xff);
}
for (; i < 4 * newColorMap.Length; ++i)
int colorMapLength4 = 4 * newColorMap.Length;
for (; i < colorMapLength4; i++)
{
newData[i] = 0; // black tail.
}

11
src/ImageSharp/Formats/WebP/WebPDecoderCore.cs

@ -235,7 +235,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
return new WebPImageInfo() { Width = width, Height = height, Features = features };
}
// TODO: check if VP8 or VP8L info about the dimensions match VP8X info
switch (chunkType)
{
case WebPChunkType.Vp8:
@ -415,7 +414,11 @@ namespace SixLabors.ImageSharp.Formats.WebP
{
case WebPChunkType.Iccp:
uint iccpChunkSize = this.ReadChunkSize();
if (!this.IgnoreMetadata)
if (this.IgnoreMetadata)
{
this.currentStream.Skip((int)iccpChunkSize);
}
else
{
var iccpData = new byte[iccpChunkSize];
this.currentStream.Read(iccpData, 0, (int)iccpChunkSize);
@ -425,10 +428,6 @@ namespace SixLabors.ImageSharp.Formats.WebP
this.Metadata.IccProfile = profile;
}
}
else
{
this.currentStream.Skip((int)iccpChunkSize);
}
break;

23
src/ImageSharp/Formats/WebP/WebPLosslessDecoder.cs

@ -929,9 +929,17 @@ namespace SixLabors.ImageSharp.Formats.WebP
return (dist >= 1) ? dist : 1;
}
/// <summary>
/// Copies pixels when a backward reference is used.
/// Copy 'length' number of pixels (in scan-line order) from the sequence of pixels prior to them by 'dist' pixels.
/// </summary>
/// <param name="pixelData">The pixel data.</param>
/// <param name="decodedPixels">The number of so far decoded pixels.</param>
/// <param name="dist">The backward reference distance prior to the current decoded pixel.</param>
/// <param name="length">The number of pixels to copy.</param>
private static void CopyBlock(Span<uint> pixelData, int decodedPixels, int dist, int length)
{
if (dist >= length)
if (dist >= length) // no overlap.
{
Span<uint> src = pixelData.Slice(decodedPixels - dist, length);
Span<uint> dest = pixelData.Slice(decodedPixels);
@ -939,18 +947,27 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
else
{
// There is overlap between the backward reference distance and the pixels to copy.
Span<uint> src = pixelData.Slice(decodedPixels - dist);
Span<uint> dest = pixelData.Slice(decodedPixels);
for (int i = 0; i < length; ++i)
for (int i = 0; i < length; i++)
{
dest[i] = src[i];
}
}
}
/// <summary>
/// Copies alpha values when a backward reference is used.
/// Copy 'length' number of alpha values from the sequence of alpha values prior to them by 'dist'.
/// </summary>
/// <param name="data">The alpha values.</param>
/// <param name="pos">The position of the so far decoded pixels.</param>
/// <param name="dist">The backward reference distance prior to the current decoded pixel.</param>
/// <param name="length">The number of pixels to copy.</param>
private static void CopyBlock8B(Span<byte> data, int pos, int dist, int length)
{
if (dist >= length)
if (dist >= length) // no overlap.
{
data.Slice(pos - dist, length).CopyTo(data.Slice(pos));
}

8
src/ImageSharp/Formats/WebP/WebPLossyDecoder.cs

@ -699,15 +699,17 @@ namespace SixLabors.ImageSharp.Formats.WebP
}
// Loop over each output pairs of row.
var bufferStride2 = 2 * bufferStride;
var ioStride2 = 2 * io.YStride;
for (; y + 2 < yEnd; y += 2)
{
topU = curU;
topV = curV;
curU = curU.Slice(io.UvStride);
curV = curV.Slice(io.UvStride);
this.UpSample(curY.Slice(io.YStride), curY.Slice(2 * io.YStride), topU, topV, curU, curV, dst.Slice(bufferStride), dst.Slice(2 * bufferStride), mbw);
curY = curY.Slice(2 * io.YStride);
dst = dst.Slice(2 * bufferStride);
this.UpSample(curY.Slice(io.YStride), curY.Slice(ioStride2), topU, topV, curU, curV, dst.Slice(bufferStride), dst.Slice(bufferStride2), mbw);
curY = curY.Slice(ioStride2);
dst = dst.Slice(bufferStride2);
}
// Move to last row.

44
tests/ImageSharp.Benchmarks/Codecs/DecodeWebp.cs

@ -15,6 +15,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
public class DecodeWebp : BenchmarkBase
{
private byte[] webpLossyBytes;
private byte[] webpLosslessBytes;
private string TestImageLossyFullPath => Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, this.TestImageLossy);
@ -30,59 +31,40 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs
[GlobalSetup]
public void ReadImages()
{
if (this.webpLossyBytes is null)
{
this.webpLossyBytes = File.ReadAllBytes(this.TestImageLossyFullPath);
}
if (this.webpLosslessBytes is null)
{
this.webpLosslessBytes = File.ReadAllBytes(this.TestImageLosslessFullPath);
}
this.webpLossyBytes ??= File.ReadAllBytes(this.TestImageLossyFullPath);
this.webpLosslessBytes ??= File.ReadAllBytes(this.TestImageLosslessFullPath);
}
[Benchmark(Description = "Magick Lossy WebP")]
public int WebpLossyMagick()
{
var settings = new MagickReadSettings { Format = MagickFormat.WebP };
using (var image = new MagickImage(new MemoryStream(this.webpLossyBytes), settings))
{
return image.Width;
}
using var image = new MagickImage(new MemoryStream(this.webpLossyBytes), settings);
return image.Width;
}
[Benchmark(Description = "ImageSharp Lossy Webp")]
public int WebpLossy()
{
using (var memoryStream = new MemoryStream(this.webpLossyBytes))
{
using (var image = Image.Load<Rgba32>(memoryStream))
{
return image.Height;
}
}
using var memoryStream = new MemoryStream(this.webpLossyBytes);
using var image = Image.Load<Rgba32>(memoryStream);
return image.Height;
}
[Benchmark(Description = "Magick Lossless WebP")]
public int WebpLosslessMagick()
{
var settings = new MagickReadSettings { Format = MagickFormat.WebP };
using (var image = new MagickImage(new MemoryStream(this.webpLosslessBytes), settings))
{
return image.Width;
}
using var image = new MagickImage(new MemoryStream(this.webpLosslessBytes), settings);
return image.Width;
}
[Benchmark(Description = "ImageSharp Lossless Webp")]
public int WebpLossless()
{
using (var memoryStream = new MemoryStream(this.webpLosslessBytes))
{
using (var image = Image.Load<Rgba32>(memoryStream))
{
return image.Height;
}
}
using var memoryStream = new MemoryStream(this.webpLosslessBytes);
using var image = Image.Load<Rgba32>(memoryStream);
return image.Height;
}
/* Results 18.03.2020

Loading…
Cancel
Save