// // 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 ImageProcessorCore.Samplers; /// /// Exstension methods for the type. /// public static class ImageExtensions { /// /// Saves the image to the given stream with the bmp format. /// /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. public static void SaveAsBmp(this ImageBase source, Stream stream) => new BmpEncoder().Encode(source, stream); /// /// Saves the image to the given stream with the png format. /// /// The image this method extends. /// The stream to save the image to. /// Thrown if the stream is null. public static void SaveAsPng(this ImageBase source, Stream stream) => new PngEncoder().Encode(source, stream); /// /// Saves the image to the given stream with the jpeg format. /// /// 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 ImageBase source, Stream stream, int quality = 80) => new JpegEncoder { Quality = quality }.Encode(source, stream); /// /// Saves the image to the given stream with the gif format. /// /// 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 100. /// Thrown if the stream is null. public static void SaveAsGif(this ImageBase source, Stream stream, int quality = 256) => new GifEncoder() { Quality = quality }.Encode(source, stream); /// /// Applies the collection of processors to the image. /// /// The image this method extends. /// Any processors to apply to the image. /// The . public static Image Process(this Image source, params IImageProcessor[] processors) { return Process(source, source.Bounds, processors); } /// /// Applies the collection of processors to the image. /// This method does not resize the target image. /// /// The image this method extends. /// /// The structure that specifies the portion of the image object to draw. /// /// Any processors to apply to the image. /// The . public static Image Process(this Image source, Rectangle sourceRectangle, params IImageProcessor[] processors) { // ReSharper disable once LoopCanBeConvertedToQuery foreach (IImageProcessor filter in processors) { source = PerformAction(source, true, (sourceImage, targetImage) => filter.Apply(targetImage, sourceImage, sourceRectangle)); } return source; } /// /// Applies the collection of processors to the image. /// /// The source image. Cannot be null. /// The target image width. /// The target image height. /// Any processors to apply to the image. /// The . public static Image Process(this Image source, int width, int height, params IImageSampler[] processors) { return Process(source, width, height, source.Bounds, default(Rectangle), processors); } /// /// 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 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. /// /// Any processors to apply to the image. /// The . public static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, params IImageSampler[] processors) { // ReSharper disable once LoopCanBeConvertedToQuery foreach (IImageSampler sampler in processors) { source = PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle)); } return source; } /// /// Performs the given action on the source image. /// /// 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 action) { Image transformedImage = clone ? new Image(source) : new Image { // Several properties require copying HorizontalResolution = source.HorizontalResolution, VerticalResolution = source.VerticalResolution, CurrentImageFormat = source.CurrentImageFormat, RepeatCount = source.RepeatCount }; 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; } } return transformedImage; } } }