// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // // // Utility methods for working with supported image formats. // // -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Imaging.Formats { using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Reflection; using ImageProcessor.Configuration; /// /// Utility methods for working with supported image formats. /// public static class FormatUtilities { /// /// Gets the correct from the given stream. /// /// /// /// The to read from. /// /// /// The . /// public static ISupportedImageFormat GetFormat(Stream stream) { // Reset the position of the stream to ensure we're reading the correct part. stream.Position = 0; IEnumerable supportedImageFormats = ImageProcessorBootstrapper.Instance.SupportedImageFormats; byte[] buffer = new byte[4]; stream.Read(buffer, 0, buffer.Length); foreach (ISupportedImageFormat supportedImageFormat in supportedImageFormats) { byte[][] headers = supportedImageFormat.FileHeaders; // ReSharper disable once LoopCanBeConvertedToQuery foreach (byte[] header in headers) { if (header.SequenceEqual(buffer.Take(header.Length))) { stream.Position = 0; // Return a new instance as we want to use instance properties. return Activator.CreateInstance(supportedImageFormat.GetType()) as ISupportedImageFormat; } } } stream.Position = 0; return null; } /// /// Returns a value indicating whether the given image is indexed. /// /// /// The to test. /// /// /// The true if the image is indexed; otherwise, false. /// public static bool IsIndexed(Image image) { // Test value of flags using bitwise AND. // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags return (image.PixelFormat & PixelFormat.Indexed) != 0; } /// /// Returns a value indicating whether the given image is indexed. /// /// /// The to test. /// /// /// The true if the image is animated; otherwise, false. /// public static bool IsAnimated(Image image) { return ImageAnimator.CanAnimate(image); } /// /// Returns information about the given . /// /// /// The image to extend. /// /// /// The image format. /// /// /// Whether to fetch the images frames. /// /// /// The . /// public static GifInfo GetGifInfo(Image image, ImageFormat format, bool fetchFrames = true) { if (image.RawFormat.Guid != ImageFormat.Gif.Guid && format.Guid != ImageFormat.Gif.Guid) { throw new ArgumentException("Image is not a gif."); } GifInfo info = new GifInfo { Height = image.Height, Width = image.Width }; if (IsAnimated(image)) { info.IsAnimated = true; if (fetchFrames) { FrameDimension frameDimension = new FrameDimension(image.FrameDimensionsList[0]); int frameCount = image.GetFrameCount(frameDimension); int last = frameCount - 1; int delay = 0; int index = 0; List gifFrames = new List(); for (int f = 0; f < frameCount; f++) { int thisDelay = BitConverter.ToInt32(image.GetPropertyItem(20736).Value, index); int toAddDelay = thisDelay * 10 < 20 ? 20 : thisDelay * 10; // Minimum delay is 20 ms // Find the frame image.SelectActiveFrame(frameDimension, f); // TODO: Get positions. gifFrames.Add(new GifFrame { Delay = toAddDelay, Image = (Image)image.Clone() }); // Reset the position. if (f == last) { image.SelectActiveFrame(frameDimension, 0); } delay += toAddDelay; index += 4; } info.GifFrames = gifFrames; info.AnimationLength = delay; // Loop info is stored at byte 20737. info.LoopCount = BitConverter.ToInt16(image.GetPropertyItem(20737).Value, 0); info.IsLooped = info.LoopCount != 1; } } return info; } /// /// Returns an instance of EncodingParameters for jpeg compression. /// /// The quality to return the image at. /// The encodingParameters for jpeg compression. public static EncoderParameters GetEncodingParameters(int quality) { EncoderParameters encoderParameters = null; try { // Create a series of encoder parameters. encoderParameters = new EncoderParameters(1); // Set the quality. encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality); } catch { if (encoderParameters != null) { encoderParameters.Dispose(); } } return encoderParameters; } /// /// Uses reflection to allow the creation of an instance of . /// /// /// The . /// public static PropertyItem CreatePropertyItem() { Type type = typeof(PropertyItem); ConstructorInfo constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null); return (PropertyItem)constructor.Invoke(null); } } }