Browse Source

Faster decoding

pull/527/head
James Jackson-South 8 years ago
parent
commit
c43957951b
  1. 14
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  2. 36
      src/ImageSharp/Formats/Gif/LzwDecoder.cs

14
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers; using System.Buffers;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
@ -410,13 +411,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> previousFrame, Span<byte> indices, Span<byte> colorTable, GifImageDescriptor descriptor) private void ReadFrameColors<TPixel>(ref Image<TPixel> image, ref ImageFrame<TPixel> previousFrame, Span<byte> indices, Span<byte> colorTable, GifImageDescriptor descriptor)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
ref byte indicesRef = ref MemoryMarshal.GetReference(indices);
int imageWidth = this.logicalScreenDescriptor.Width; int imageWidth = this.logicalScreenDescriptor.Width;
int imageHeight = this.logicalScreenDescriptor.Height; int imageHeight = this.logicalScreenDescriptor.Height;
ImageFrame<TPixel> prevFrame = null; ImageFrame<TPixel> prevFrame = null;
ImageFrame<TPixel> currentFrame = null; ImageFrame<TPixel> currentFrame = null;
ImageFrame<TPixel> imageFrame; ImageFrame<TPixel> imageFrame;
if (previousFrame == null) if (previousFrame == null)
@ -479,7 +479,6 @@ namespace SixLabors.ImageSharp.Formats.Gif
} }
writeY = interlaceY + descriptor.Top; writeY = interlaceY + descriptor.Top;
interlaceY += interlaceIncrement; interlaceY += interlaceIncrement;
} }
else else
@ -487,14 +486,13 @@ namespace SixLabors.ImageSharp.Formats.Gif
writeY = y; writeY = y;
} }
Span<TPixel> rowSpan = imageFrame.GetPixelRowSpan(writeY); ref TPixel rowRef = ref MemoryMarshal.GetReference(imageFrame.GetPixelRowSpan(writeY));
var rgba = new Rgba32(0, 0, 0, 255); var rgba = new Rgba32(0, 0, 0, 255);
// #403 The left + width value can be larger than the image width // #403 The left + width value can be larger than the image width
for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < rowSpan.Length; x++) for (int x = descriptor.Left; x < descriptor.Left + descriptor.Width && x < imageWidth; x++)
{ {
int index = indices[i]; int index = Unsafe.Add(ref indicesRef, i);
if (this.graphicsControlExtension == null || if (this.graphicsControlExtension == null ||
this.graphicsControlExtension.TransparencyFlag == false || this.graphicsControlExtension.TransparencyFlag == false ||
@ -502,7 +500,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{ {
int indexOffset = index * 3; int indexOffset = index * 3;
ref TPixel pixel = ref rowSpan[x]; ref TPixel pixel = ref Unsafe.Add(ref rowRef, x);
rgba.Rgb = colorTable.GetRgb24(indexOffset); rgba.Rgb = colorTable.GetRgb24(indexOffset);
pixel.PackFromRgba32(rgba); pixel.PackFromRgba32(rgba);

36
src/ImageSharp/Formats/Gif/LzwDecoder.cs

@ -4,7 +4,8 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Gif namespace SixLabors.ImageSharp.Formats.Gif
@ -115,14 +116,14 @@ namespace SixLabors.ImageSharp.Formats.Gif
int data = 0; int data = 0;
int first = 0; int first = 0;
Span<int> prefixSpan = this.prefix.Span; ref int prefixRef = ref MemoryMarshal.GetReference(this.prefix.Span);
Span<int> suffixSpan = this.suffix.Span; ref int suffixRef = ref MemoryMarshal.GetReference(this.suffix.Span);
Span<int> pixelStackSpan = this.pixelStack.Span; ref int pixelStackRef = ref MemoryMarshal.GetReference(this.pixelStack.Span);
ref byte pixelsRef = ref MemoryMarshal.GetReference(pixels);
for (code = 0; code < clearCode; code++) for (code = 0; code < clearCode; code++)
{ {
prefixSpan[code] = 0; Unsafe.Add(ref suffixRef, code) = (byte)code;
suffixSpan[code] = (byte)code;
} }
byte[] buffer = new byte[255]; byte[] buffer = new byte[255];
@ -176,7 +177,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
if (oldCode == NullCode) if (oldCode == NullCode)
{ {
pixelStackSpan[top++] = suffixSpan[code]; Unsafe.Add(ref pixelStackRef, top++) = Unsafe.Add(ref suffixRef, code);
oldCode = code; oldCode = code;
first = code; first = code;
continue; continue;
@ -185,27 +186,27 @@ namespace SixLabors.ImageSharp.Formats.Gif
int inCode = code; int inCode = code;
if (code == availableCode) if (code == availableCode)
{ {
pixelStackSpan[top++] = (byte)first; Unsafe.Add(ref pixelStackRef, top++) = (byte)first;
code = oldCode; code = oldCode;
} }
while (code > clearCode) while (code > clearCode)
{ {
pixelStackSpan[top++] = suffixSpan[code]; Unsafe.Add(ref pixelStackRef, top++) = Unsafe.Add(ref suffixRef, code);
code = prefixSpan[code]; code = Unsafe.Add(ref prefixRef, code);
} }
first = suffixSpan[code]; int suffixCode = Unsafe.Add(ref suffixRef, code);
first = suffixCode;
pixelStackSpan[top++] = suffixSpan[code]; Unsafe.Add(ref pixelStackRef, top++) = suffixCode;
// Fix for Gifs that have "deferred clear code" as per here : // Fix for Gifs that have "deferred clear code" as per here :
// https://bugzilla.mozilla.org/show_bug.cgi?id=55918 // https://bugzilla.mozilla.org/show_bug.cgi?id=55918
if (availableCode < MaxStackSize) if (availableCode < MaxStackSize)
{ {
prefixSpan[availableCode] = oldCode; Unsafe.Add(ref prefixRef, availableCode) = oldCode;
suffixSpan[availableCode] = first; Unsafe.Add(ref suffixRef, availableCode) = first;
availableCode++; availableCode++;
if (availableCode == codeMask + 1 && availableCode < MaxStackSize) if (availableCode == codeMask + 1 && availableCode < MaxStackSize)
{ {
@ -221,7 +222,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
top--; top--;
// Clear missing pixels // Clear missing pixels
pixels[xyz++] = (byte)pixelStackSpan[top]; Unsafe.Add(ref pixelsRef, xyz++) = (byte)Unsafe.Add(ref pixelStackRef, top);
} }
} }
@ -238,8 +239,9 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary> /// </summary>
/// <param name="buffer">The buffer to store the block in.</param> /// <param name="buffer">The buffer to store the block in.</param>
/// <returns> /// <returns>
/// The <see cref="T:byte[]"/>. /// The <see cref="int"/>.
/// </returns> /// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int ReadBlock(byte[] buffer) private int ReadBlock(byte[] buffer)
{ {
int bufferSize = this.stream.ReadByte(); int bufferSize = this.stream.ReadByte();

Loading…
Cancel
Save