// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // namespace ImageProcessorCore { using System; using System.IO; using Formats; using Processors; /// /// Extension methods for the type. /// public static partial class ImageExtensions { /// /// Saves the image to the given stream with the bmp format. /// /// The pixel format. /// The packed format. uint, long, float. /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. public static void SaveAsBmp(this Image source, Stream stream) where TColor : IPackedVector where TPacked : struct => new BmpEncoder().Encode(source, stream); /// /// Saves the image to the given stream with the png format. /// /// The pixel format. /// The packed format. uint, long, float. /// The image this method extends. /// The stream to save the image to. /// The quality to save the image to representing the number of colors. /// Anything equal to 256 and below will cause the encoder to save the image in an indexed format. /// /// Thrown if the stream is null. public static void SaveAsPng(this Image source, Stream stream, int quality = int.MaxValue) where TColor : IPackedVector where TPacked : struct => new PngEncoder { Quality = quality }.Encode(source, stream); /// /// Saves the image to the given stream with the jpeg format. /// /// The pixel format. /// The packed format. uint, long, float. /// The image this method extends. /// The stream to save the image to. /// The quality to save the image to. Between 1 and 100. /// Thrown if the stream is null. public static void SaveAsJpeg(this Image source, Stream stream, int quality = 75) where TColor : IPackedVector where TPacked : struct => new JpegEncoder { Quality = quality }.Encode(source, stream); /// /// Saves the image to the given stream with the gif format. /// /// The pixel format. /// The packed format. uint, long, float. /// The image this method extends. /// The stream to save the image to. /// The quality to save the image to representing the number of colors. Between 1 and 256. /// Thrown if the stream is null. internal static void SaveAsGif(this Image source, Stream stream, int quality = 256) where TColor : IPackedVector where TPacked : struct => new GifEncoder { Quality = quality }.Encode(source, stream); /// /// Applies the collection of processors to the image. /// This method does not resize the target image. /// /// The pixel format. /// The packed format. uint, long, float. /// The image this method extends. /// The processor to apply to the image. /// The . internal static Image Process(this Image source, IImageProcessor processor) where TColor : IPackedVector where TPacked : struct { return Process(source, source.Bounds, processor); } /// /// Applies the collection of processors to the image. /// This method does not resize the target image. /// /// The pixel format. /// The packed format. uint, long, float. /// The image this method extends. /// /// The structure that specifies the portion of the image object to draw. /// /// The processors to apply to the image. /// The . internal static Image Process(this Image source, Rectangle sourceRectangle, IImageProcessor processor) where TColor : IPackedVector where TPacked : struct { return PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle)); } /// /// Applies the collection of processors to the image. /// /// This method is not chainable. /// /// /// The pixel format. /// The packed format. long, float. /// The source image. Cannot be null. /// The target image width. /// The target image height. /// The processor to apply to the image. /// The . internal static Image Process(this Image source, int width, int height, IImageSampler sampler) where TColor : IPackedVector where TPacked : struct { return Process(source, width, height, source.Bounds, default(Rectangle), sampler); } /// /// Applies the collection of processors to the image. /// /// This method does will resize the target image if the source and target rectangles are different. /// /// /// The pixel format. /// The packed format. long, float. /// The source image. Cannot be null. /// The target image width. /// The target image height. /// /// The structure that specifies the portion of the image object to draw. /// /// /// The structure that specifies the location and size of the drawn image. /// The image is scaled to fit the rectangle. /// /// The processor to apply to the image. /// The . internal static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSampler sampler) where TColor : IPackedVector where TPacked : struct { return PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle)); } /// /// Performs the given action on the source image. /// /// The pixel format. /// The packed format. long, float. /// The image to perform the action against. /// Whether to clone the image. /// The to perform against the image. /// The . private static Image PerformAction(Image source, bool clone, Action, ImageBase> action) where TColor : IPackedVector where TPacked : struct { Image transformedImage = clone ? new Image(source) : new Image(); // Several properties still require copying if (!clone) transformedImage.CopyProperties(source); action(source, transformedImage); for (int i = 0; i < source.Frames.Count; i++) { ImageFrame sourceFrame = source.Frames[i]; ImageFrame tranformedFrame = clone ? new ImageFrame(sourceFrame) : new ImageFrame { FrameDelay = sourceFrame.FrameDelay }; action(sourceFrame, tranformedFrame); if (!clone) { transformedImage.Frames.Add(tranformedFrame); } else { transformedImage.Frames[i] = tranformedFrame; } } source = transformedImage; return source; } } }