/// <summary> /// Applies the given processor the current image. /// </summary> /// <param name="processor">The processor delegate.</param> /// <param name="factory">The <see cref="ImageFactory" />.</param> public override void ApplyProcessor(Func <ImageFactory, Image> processor, ImageFactory factory) { GifDecoder decoder = new GifDecoder(factory.Image, factory.AnimationProcessMode); if (decoder.IsAnimated) { Image factoryImage = factory.Image; GifEncoder encoder = new GifEncoder(null, null, decoder.LoopCount); for (int i = 0; i < decoder.FrameCount; i++) { GifFrame frame = decoder.GetFrame(factoryImage, i); factory.Image = frame.Image; frame.Image = this.Quantizer.Quantize(processor.Invoke(factory)); encoder.AddFrame(frame); } factoryImage.Dispose(); factory.Image = encoder.Save(); } else { base.ApplyProcessor(processor, factory); } }
/// <inheritdoc /> public override Image Save(Stream stream, Image image, long bitDepth) { // Never use default save for gifs. It's terrible. var decoder = new GifDecoder(image, AnimationProcessMode.All); var encoder = new GifEncoder(null, null, decoder.LoopCount); for (int i = 0; i < decoder.FrameCount; i++) { GifFrame frame = decoder.GetFrame(image, i); frame.Image = this.Quantizer.Quantize(frame.Image); encoder.AddFrame(frame); } encoder.Save(stream); return(encoder.Save()); }
/// <summary> /// Applies the given processor the current image. /// </summary> /// <param name="processor">The processor delegate.</param> /// <param name="factory">The <see cref="ImageFactory" />.</param> public override void ApplyProcessor(Func <ImageFactory, Image> processor, ImageFactory factory) { GifDecoder decoder = new GifDecoder(factory.Image); if (decoder.IsAnimated) { GifEncoder encoder = new GifEncoder(null, null, decoder.LoopCount); foreach (GifFrame frame in decoder.GifFrames) { factory.Image = frame.Image; frame.Image = this.Quantizer.Quantize(processor.Invoke(factory)); encoder.AddFrame(frame); } factory.Image = encoder.Save(); } else { base.ApplyProcessor(processor, factory); } }
/// <summary> /// Creates a copy of an image allowing you to set the pixel format. /// Disposing of the original is the responsibility of the user. /// <remarks> /// Unlike the native <see cref="Image.Clone"/> method this also copies animation frames. /// </remarks> /// </summary> /// <param name="source">The source image to copy.</param> /// <param name="format">The <see cref="PixelFormat"/> to set the copied image to.</param> /// <returns> /// The <see cref="Image"/>. /// </returns> public static Image Copy(this Image source, PixelFormat format = PixelFormat.Format32bppPArgb) { if (FormatUtilities.IsAnimated(source)) { // TODO: Ensure that we handle other animated types. GifDecoder decoder = new GifDecoder(source); GifEncoder encoder = new GifEncoder(null, null, decoder.LoopCount); foreach (GifFrame frame in decoder.GifFrames) { frame.Image = ((Bitmap)frame.Image).Clone(new Rectangle(0, 0, frame.Image.Width, frame.Image.Height), format); ((Bitmap)frame.Image).SetResolution(source.HorizontalResolution, source.VerticalResolution); encoder.AddFrame(frame); } return encoder.Save(); } Bitmap copy = ((Bitmap)source).Clone(new Rectangle(0, 0, source.Width, source.Height), format); copy.SetResolution(source.HorizontalResolution, source.VerticalResolution); return copy; }
/// <summary> /// Creates a deep copy of an image allowing you to set the pixel format. /// Disposing of the original is the responsibility of the user. /// <remarks> /// Unlike the native <see cref="Image.Clone"/> method this also copies animation frames. /// </remarks> /// </summary> /// <param name="source">The source image to copy.</param> /// <param name="animationProcessMode">The process mode for frames in animated images.</param> /// <param name="format">The <see cref="PixelFormat"/> to set the copied image to.</param> /// <param name="preserveExifData">Whether to preserve exif metadata. Defaults to false.</param> /// <returns> /// The <see cref="Image"/>. /// </returns> public static Image Copy(this Image source, AnimationProcessMode animationProcessMode, PixelFormat format = PixelFormat.Format32bppPArgb, bool preserveExifData = false) { if (source.RawFormat.Equals(ImageFormat.Gif)) { // Read from the correct first frame when performing additional processing source.SelectActiveFrame(FrameDimension.Time, 0); GifDecoder decoder = new GifDecoder(source, animationProcessMode); GifEncoder encoder = new GifEncoder(null, null, decoder.LoopCount); // Have to use Octree here, there's no way to inject it. OctreeQuantizer quantizer = new OctreeQuantizer(); for (int i = 0; i < decoder.FrameCount; i++) { GifFrame frame = decoder.GetFrame(source, i); frame.Image = quantizer.Quantize(((Bitmap)frame.Image).Clone(new Rectangle(0, 0, frame.Image.Width, frame.Image.Height), format)); ((Bitmap)frame.Image).SetResolution(source.HorizontalResolution, source.VerticalResolution); encoder.AddFrame(frame); } return encoder.Save(); } // Create a new image and copy it's pixels. Bitmap copy = new Bitmap(source.Width, source.Height, format); copy.SetResolution(source.HorizontalResolution, source.VerticalResolution); using (Graphics graphics = Graphics.FromImage(copy)) { graphics.DrawImageUnscaled(source, 0, 0); } if (preserveExifData) { foreach (PropertyItem item in source.PropertyItems) { copy.SetPropertyItem(item); } } return copy; }
/// <summary> /// Applies the given processor the current image. /// </summary> /// <param name="processor">The processor delegate.</param> /// <param name="factory">The <see cref="ImageFactory" />.</param> public override void ApplyProcessor(Func<ImageFactory, Image> processor, ImageFactory factory) { GifDecoder decoder = new GifDecoder(factory.Image, factory.AnimationProcessMode); if (decoder.IsAnimated) { Image factoryImage = factory.Image; GifEncoder encoder = new GifEncoder(null, null, decoder.LoopCount); for (int i = 0; i < decoder.FrameCount; i++) { GifFrame frame = decoder.GetFrame(factoryImage, i); factory.Image = frame.Image; frame.Image = this.Quantizer.Quantize(processor.Invoke(factory)); encoder.AddFrame(frame); } factoryImage.Dispose(); factory.Image = encoder.Save(); } else { base.ApplyProcessor(processor, factory); } }
/// <summary> /// Applies the given processor the current image. /// </summary> /// <param name="processor">The processor delegate.</param> /// <param name="factory">The <see cref="ImageFactory" />.</param> public override void ApplyProcessor(Func<ImageFactory, Image> processor, ImageFactory factory) { GifDecoder decoder = new GifDecoder(factory.Image); if (decoder.IsAnimated) { GifEncoder encoder = new GifEncoder(null, null, decoder.LoopCount); foreach (GifFrame frame in decoder.GifFrames) { factory.Image = frame.Image; frame.Image = this.Quantizer.Quantize(processor.Invoke(factory)); encoder.AddFrame(frame); } factory.Image = encoder.Save(); } else { base.ApplyProcessor(processor, factory); } }