📷 A modern, cross-platform, 2D Graphics library for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

139 lines
4.7 KiB

namespace ImageProcessor.Formats
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
public class GifEncoder : IImageEncoder
{
/// <summary>
/// The quality.
/// </summary>
private int quality = 256;
/// <summary>
/// Gets or sets the quality of output for images.
/// </summary>
/// <remarks>For gifs the value ranges from 1 to 256.</remarks>
public int Quality
{
get
{
return this.quality;
}
set
{
this.quality = value.Clamp(1, 256);
}
}
/// <summary>
/// Gets the default file extension for this encoder.
/// </summary>
public string Extension
{
get { return "GIF"; }
}
/// <summary>
/// Returns a value indicating whether the <see cref="IImageDecoder"/> supports the specified
/// file header.
/// </summary>
/// <param name="extension">The <see cref="string"/> containing the file extension.</param>
/// <returns>
/// True if the decoder supports the file extension; otherwise, false.
/// </returns>
public bool IsSupportedFileExtension(string extension)
{
Guard.NotNullOrEmpty(extension, "extension");
extension = extension.StartsWith(".") ? extension.Substring(1) : extension;
return extension.Equals("GIF", StringComparison.OrdinalIgnoreCase);
}
public void Encode(ImageBase image, Stream stream)
{
Guard.NotNull(image, "image");
Guard.NotNull(stream, "stream");
// Write the header.
// File Header signature and version.
this.WriteString(stream, "GIF");
this.WriteString(stream, "89a");
GifLogicalScreenDescriptor descriptor = new GifLogicalScreenDescriptor
{
Width = (short)image.Width,
Height = (short)image.Height,
GlobalColorTableFlag = true,
GlobalColorTableSize = this.Quality
};
this.WriteGlobalLogicalScreenDescriptor(stream, descriptor);
throw new System.NotImplementedException();
}
private void WriteGlobalLogicalScreenDescriptor(Stream stream, GifLogicalScreenDescriptor descriptor)
{
this.WriteShort(stream, descriptor.Width);
this.WriteShort(stream, descriptor.Width);
int bitdepth = this.GetBitsNeededForColorDepth(descriptor.GlobalColorTableSize) - 1;
int packed = 0x80 | // 1 : global color table flag = 1 (gct used)
0x70 | // 2-4 : color resolution
0x00 | // 5 : gct sort flag = 0
bitdepth; // 6-8 : gct size`
this.WriteByte(stream, packed);
this.WriteByte(stream, descriptor.BackgroundColorIndex); // Background Color Index
this.WriteByte(stream, descriptor.PixelAspectRatio); // Pixel aspect ratio
}
/// <summary>
/// Writes a short to the given stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="value">The value to write.</param>
private void WriteShort(Stream stream, int value)
{
// Leave only one significant byte.
stream.WriteByte(Convert.ToByte(value & 0xff));
stream.WriteByte(Convert.ToByte((value >> 8) & 0xff));
}
/// <summary>
/// Writes a short to the given stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="value">The value to write.</param>
private void WriteByte(Stream stream, int value)
{
stream.WriteByte(Convert.ToByte(value));
}
/// <summary>
/// Writes a string to the given stream.
/// </summary>
/// <param name="stream">The <see cref="Stream"/> containing image data.</param>
/// <param name="value">The value to write.</param>
private void WriteString(Stream stream, string value)
{
char[] chars = value.ToCharArray();
foreach (char c in chars)
{
stream.WriteByte((byte)c);
}
}
/// <summary>
/// Returns how many bits are required to store the specified number of colors.
/// Performs a Log2() on the value.
/// </summary>
private int GetBitsNeededForColorDepth(int colors)
{
return (int)Math.Ceiling(Math.Log(colors, 2));
}
}
}