diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index b729f30e90..d5b0fccd6c 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -9,7 +9,6 @@ namespace ImageSharp.Formats
using System.Buffers;
using System.IO;
using System.Linq;
- using System.Numerics;
using IO;
using Quantizers;
@@ -22,7 +21,7 @@ namespace ImageSharp.Formats
///
/// The pixel buffer, used to reduce allocations.
///
- private readonly byte[] pixelBuffer = new byte[3];
+ private readonly byte[] buffer = new byte[16];
///
/// The number of bits requires to store the image palette.
@@ -77,7 +76,7 @@ namespace ImageSharp.Formats
// Quantize the image returning a palette.
QuantizedImage quantized = ((IQuantizer)this.Quantizer).Quantize(image, this.Quality);
- int index = GetTransparentIndex(quantized);
+ int index = this.GetTransparentIndex(quantized);
// Write the header.
this.WriteHeader(writer);
@@ -95,11 +94,14 @@ namespace ImageSharp.Formats
if (image.Frames.Any())
{
this.WriteApplicationExtension(writer, image.RepeatCount, image.Frames.Count);
- foreach (ImageFrame frame in image.Frames)
+
+ // ReSharper disable once ForCanBeConvertedToForeach
+ for (int i = 0; i < image.Frames.Count; i++)
{
+ ImageFrame frame = image.Frames[i];
QuantizedImage quantizedFrame = ((IQuantizer)this.Quantizer).Quantize(frame, this.Quality);
- this.WriteGraphicalControlExtension(frame, writer, GetTransparentIndex(quantizedFrame));
+ this.WriteGraphicalControlExtension(frame, writer, this.GetTransparentIndex(quantizedFrame));
this.WriteImageDescriptor(frame, writer);
this.WriteColorTable(quantizedFrame, writer);
this.WriteImageData(quantizedFrame, writer);
@@ -121,25 +123,35 @@ namespace ImageSharp.Formats
///
/// The .
///
- private static int GetTransparentIndex(QuantizedImage quantized)
+ private int GetTransparentIndex(QuantizedImage quantized)
where TColor : struct, IPackedPixel
where TPacked : struct, IEquatable
{
// Find the lowest alpha value and make it the transparent index.
- int index = -1;
- float alpha = 1;
+ int index = 255;
+ byte alpha = 255;
+ bool hasEmpty = false;
+
+ // Some images may have more than one quantized pixel returned with an alpha value of zero
+ // (No idea why?!) so we should always ignore if we have empty pixels present.
for (int i = 0; i < quantized.Palette.Length; i++)
{
- Vector4 vector = quantized.Palette[i].ToVector4();
- if (vector == Vector4.Zero)
- {
- return i;
- }
+ quantized.Palette[i].ToBytes(this.buffer, 0, ComponentOrder.XYZW);
- if (vector.W < alpha)
+ if (!hasEmpty)
{
- alpha = vector.W;
- index = i;
+ if (this.buffer[0] == 0 && this.buffer[1] == 0 && this.buffer[2] == 0 && this.buffer[3] == 0)
+ {
+ alpha = this.buffer[3];
+ index = i;
+ hasEmpty = true;
+ }
+
+ if (this.buffer[3] < alpha)
+ {
+ alpha = this.buffer[3];
+ index = i;
+ }
}
}
@@ -173,7 +185,7 @@ namespace ImageSharp.Formats
Height = (short)image.Height,
GlobalColorTableFlag = false, // Always false for now.
GlobalColorTableSize = this.bitDepth - 1,
- BackgroundColorIndex = (byte)(tranparencyIndex > -1 ? tranparencyIndex : 255)
+ BackgroundColorIndex = (byte)tranparencyIndex
};
writer.Write((ushort)descriptor.Width);
@@ -186,13 +198,11 @@ namespace ImageSharp.Formats
field.SetBits(5, 3, descriptor.GlobalColorTableSize); // 6-8 : GCT size. 2^(N+1)
// Reduce the number of writes
- byte[] arr =
- {
- field.Byte, descriptor.BackgroundColorIndex, // Background Color Index
- descriptor.PixelAspectRatio // Pixel aspect ratio. Assume 1:1
- };
+ this.buffer[0] = field.Byte;
+ this.buffer[1] = descriptor.BackgroundColorIndex; // Background Color Index
+ this.buffer[2] = descriptor.PixelAspectRatio; // Pixel aspect ratio. Assume 1:1
- writer.Write(arr);
+ writer.Write(this.buffer, 0, 3);
}
///
@@ -206,13 +216,11 @@ namespace ImageSharp.Formats
// Application Extension Header
if (repeatCount != 1 && frames > 0)
{
- byte[] ext =
- {
- GifConstants.ExtensionIntroducer, GifConstants.ApplicationExtensionLabel,
- GifConstants.ApplicationBlockSize
- };
+ this.buffer[0] = GifConstants.ExtensionIntroducer;
+ this.buffer[1] = GifConstants.ApplicationExtensionLabel;
+ this.buffer[2] = GifConstants.ApplicationBlockSize;
- writer.Write(ext);
+ writer.Write(this.buffer, 0, 3);
writer.Write(GifConstants.ApplicationIdentification.ToCharArray()); // NETSCAPE2.0
writer.Write((byte)3); // Application block length
@@ -243,7 +251,7 @@ namespace ImageSharp.Formats
where TPacked : struct, IEquatable
{
// TODO: Check transparency logic.
- bool hasTransparent = transparencyIndex > -1;
+ bool hasTransparent = transparencyIndex < 255;
DisposalMethod disposalMethod = hasTransparent
? DisposalMethod.RestoreToBackground
: DisposalMethod.Unspecified;
@@ -256,13 +264,11 @@ namespace ImageSharp.Formats
DelayTime = image.FrameDelay
};
- // Reduce the number of writes.
- byte[] intro =
- {
- GifConstants.ExtensionIntroducer, GifConstants.GraphicControlLabel, 4 // Size
- };
-
- writer.Write(intro);
+ // Write the intro.
+ this.buffer[0] = GifConstants.ExtensionIntroducer;
+ this.buffer[1] = GifConstants.GraphicControlLabel;
+ this.buffer[2] = 4;
+ writer.Write(this.buffer, 0, 3);
PackedField field = default(PackedField);
field.SetBits(3, 3, (int)extension.DisposalMethod); // 1-3 : Reserved, 4-6 : Disposal
@@ -273,7 +279,7 @@ namespace ImageSharp.Formats
writer.Write(field.Byte);
writer.Write((ushort)extension.DelayTime);
- writer.Write((byte)(extension.TransparencyIndex == -1 ? 255 : extension.TransparencyIndex));
+ writer.Write((byte)extension.TransparencyIndex);
writer.Write(GifConstants.Terminator);
}
@@ -327,10 +333,10 @@ namespace ImageSharp.Formats
for (int i = 0; i < pixelCount; i++)
{
int offset = i * 3;
- image.Palette[i].ToBytes(this.pixelBuffer, 0, ComponentOrder.XYZ);
- colorTable[offset] = this.pixelBuffer[0];
- colorTable[offset + 1] = this.pixelBuffer[1];
- colorTable[offset + 2] = this.pixelBuffer[2];
+ image.Palette[i].ToBytes(this.buffer, 0, ComponentOrder.XYZ);
+ colorTable[offset] = this.buffer[0];
+ colorTable[offset + 1] = this.buffer[1];
+ colorTable[offset + 2] = this.buffer[2];
}
writer.Write(colorTable, 0, colorTableLength);