Browse Source

Adding skeleton

Former-commit-id: 341e5a0d6f29347ebe35e4c113aafbc4d6c8bb73
pull/17/head
James South 12 years ago
parent
commit
684345f7eb
  1. 108
      src/ImageProcessor/Extensions/ImageExtensions.cs
  2. 2
      src/ImageProcessor/ImageProcessor.csproj
  3. 102
      src/ImageProcessor/Imaging/GifEncoder.cs

108
src/ImageProcessor/Extensions/ImageExtensions.cs

@ -0,0 +1,108 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ImageExtensions.cs" company="James South">
// Copyright (c) James South.
// Licensed under the Apache License, Version 2.0.
// </copyright>
// <summary>
// Encapsulates a series of time saving extension methods to the <see cref="T:System.Drawing.Imaging.Image" /> class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace ImageProcessor.Extensions
{
using System;
using System.Drawing;
using System.Drawing.Imaging;
/// <summary>
/// Encapsulates a series of time saving extension methods to the <see cref="T:System.Drawing.Imaging.Image" /> class.
/// </summary>
public static class ImageExtensions
{
/// <summary>
/// Returns information about the given <see cref="System.Drawing.Image"/>.
/// </summary>
/// <param name="image">
/// The image.
/// </param>
/// <returns>
/// The <see cref="ImageInfo"/>.
/// </returns>
public static ImageInfo GetImageInfo(this Image image)
{
ImageInfo info = new ImageInfo
{
Height = image.Height,
Width = image.Width,
// Test value of flags using bitwise AND.
// ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
IsIndexed = (image.PixelFormat & PixelFormat.Indexed) != 0
};
if (image.RawFormat.Equals(ImageFormat.Gif))
{
if (ImageAnimator.CanAnimate(image))
{
FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]);
int frameCount = image.GetFrameCount(frameDimension);
int delay = 0;
int index = 0;
for (int f = 0; f < frameCount; f++)
{
int thisDelay = BitConverter.ToInt32(image.GetPropertyItem(20736).Value, index) * 10;
delay += thisDelay < 100 ? 100 : thisDelay; // Minimum delay is 100 ms
index += 4;
}
info.AnimationLength = delay;
info.IsAnimated = true;
// Loop info is stored at byte 20737.
info.IsLooped = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0) != 1;
}
}
return info;
}
/// <summary>
/// Provides information about an image.
/// <see cref="http://madskristensen.net/post/examine-animated-gife28099s-in-c"/>
/// </summary>
public struct ImageInfo
{
/// <summary>
/// The image width.
/// </summary>
public int Width;
/// <summary>
/// The image height.
/// </summary>
public int Height;
/// <summary>
/// Whether the is indexed.
/// </summary>
public bool IsIndexed;
/// <summary>
/// Whether the is animated.
/// </summary>
public bool IsAnimated;
/// <summary>
/// The is looped.
/// </summary>
public bool IsLooped;
/// <summary>
/// The animation length in milliseconds.
/// </summary>
public int AnimationLength;
}
}
}

2
src/ImageProcessor/ImageProcessor.csproj

@ -60,6 +60,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Extensions\DoubleExtensions.cs" />
<Compile Include="Extensions\ImageExtensions.cs" />
<Compile Include="Extensions\ImageFormatExtensions.cs" />
<Compile Include="Extensions\IntegerExtensions.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
@ -70,6 +71,7 @@
<Compile Include="Imaging\CropMode.cs" />
<Compile Include="Imaging\GaussianLayer.cs" />
<Compile Include="Imaging\ColorQuantizer.cs" />
<Compile Include="Imaging\GifEncoder.cs" />
<Compile Include="Imaging\ResizeLayer.cs" />
<Compile Include="Imaging\Filters\BlackWhiteMatrixFilter.cs" />
<Compile Include="Imaging\Filters\ColorMatrixes.cs" />

102
src/ImageProcessor/Imaging/GifEncoder.cs

@ -0,0 +1,102 @@

namespace ImageProcessor.Imaging
{
using System;
/// <summary>
/// Encodes multiple images as an animated gif to a stream.
/// <remarks>
/// Always wire this up in a using block.
/// Disposing the encoder will complete the file.
/// Uses default .NET GIF encoding and adds animation headers.
/// </remarks>
/// </summary>
public class GifEncoder : IDisposable
{
#region Fields
private const string FileType = "GIF";
private const string FileVersion = "89a";
private const byte FileTrailer = 0x3b;
private const int ApplicationExtensionBlockIdentifier = 0xff21;
private const byte ApplicationBlockSize = 0x0b;
private const string ApplicationIdentification = "NETSCAPE2.0";
private const int GraphicControlExtensionBlockIdentifier = 0xf921;
private const byte GraphicControlExtensionBlockSize = 0x04;
private const long SourceGlobalColorInfoPosition = 10;
private const long SourceGraphicControlExtensionPosition = 781;
private const long SourceGraphicControlExtensionLength = 8;
private const long SourceImageBlockPosition = 789;
private const long SourceImageBlockHeaderLength = 11;
private const long SourceColorBlockPosition = 13;
private const long SourceColorBlockLength = 768;
/// <summary>
/// A value indicating whether this instance of the given entity has been disposed.
/// </summary>
/// <value><see langword="true"/> if this instance has been disposed; otherwise, <see langword="false"/>.</value>
/// <remarks>
/// If the entity is disposed, it must not be disposed a second
/// time. The isDisposed field is set the first time the entity
/// is disposed. If the isDisposed field is true, then the Dispose()
/// method will not dispose again. This help not to prolong the entity's
/// life in the Garbage Collector.
/// </remarks>
private bool isDisposed;
#endregion
#region IDisposable Members
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
public void Dispose()
{
this.Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes the object and frees resources for the Garbage Collector.
/// </summary>
/// <param name="disposing">If true, the object gets disposed.</param>
protected virtual void Dispose(bool disposing)
{
if (this.isDisposed)
{
return;
}
if (disposing)
{
// Dispose of any managed resources here.
//if (this.Image != null)
//{
// // Dispose of the memory stream from Load and the image.
// if (this.inputStream != null)
// {
// this.inputStream.Dispose();
// this.inputStream = null;
// }
// this.Image.Dispose();
// this.Image = null;
//}
}
// Call the appropriate methods to clean up
// unmanaged resources here.
// Note disposing is done.
this.isDisposed = true;
}
#endregion
}
}
Loading…
Cancel
Save