Browse Source

Faster Gif transparency lookup.

pull/1138/head
James Jackson-South 6 years ago
parent
commit
fb26d0ebd1
  1. 29
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs

29
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Buffers;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -86,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
} }
// Get the number of bits. // Get the number of bits.
this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length);
// Write the header. // Write the header.
this.WriteHeader(stream); this.WriteHeader(stream);
@ -193,7 +192,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
} }
} }
this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8); this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length);
this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream); this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream);
this.WriteImageDescriptor(frame, true, stream); this.WriteImageDescriptor(frame, true, stream);
this.WriteColorTable(quantized, stream); this.WriteColorTable(quantized, stream);
@ -218,21 +217,18 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// Transparent pixels are much more likely to be found at the end of a palette. // Transparent pixels are much more likely to be found at the end of a palette.
// Palette length maxes out at 256 so safe to stackalloc.
int index = -1; int index = -1;
int length = quantized.Palette.Length; ReadOnlySpan<TPixel> paletteSpan = quantized.Palette.Span;
Span<Rgba32> rgbaSpan = stackalloc Rgba32[paletteSpan.Length];
PixelOperations<TPixel>.Instance.ToRgba32(quantized.Configuration, paletteSpan, rgbaSpan);
ref Rgba32 rgbaSpanRef = ref MemoryMarshal.GetReference(rgbaSpan);
using (IMemoryOwner<Rgba32> rgbaBuffer = this.memoryAllocator.Allocate<Rgba32>(length)) for (int i = rgbaSpan.Length - 1; i >= 0; i--)
{ {
Span<Rgba32> rgbaSpan = rgbaBuffer.GetSpan(); if (Unsafe.Add(ref rgbaSpanRef, i).Equals(default))
ref Rgba32 paletteRef = ref MemoryMarshal.GetReference(rgbaSpan);
PixelOperations<TPixel>.Instance.ToRgba32(this.configuration, quantized.Palette.Span, rgbaSpan);
for (int i = quantized.Palette.Length - 1; i >= 0; i--)
{ {
if (Unsafe.Add(ref paletteRef, i).Equals(default)) index = i;
{
index = i;
}
} }
} }
@ -451,15 +447,14 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// The maximum number of colors for the bit depth // The maximum number of colors for the bit depth
int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * 3; int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf<Rgb24>();
int pixelCount = image.Palette.Length;
using IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength, AllocationOptions.Clean); using IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength, AllocationOptions.Clean);
PixelOperations<TPixel>.Instance.ToRgb24Bytes( PixelOperations<TPixel>.Instance.ToRgb24Bytes(
this.configuration, this.configuration,
image.Palette.Span, image.Palette.Span,
colorTable.GetSpan(), colorTable.GetSpan(),
pixelCount); image.Palette.Length);
stream.Write(colorTable.Array, 0, colorTableLength); stream.Write(colorTable.Array, 0, colorTableLength);
} }

Loading…
Cancel
Save