/// <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>
        /// Processes the image.
        /// </summary>
        /// <param name="processor">
        /// The processor.
        /// </param>
        /// <param name="factory">
        /// The factory.
        /// </param>
        private static void ApplyProcessor(Func<ImageFactory, Image> processor, ImageFactory factory)
        {
            ImageInfo imageInfo = factory.Image.GetImageInfo(factory.ImageFormat);

            if (imageInfo.IsAnimated)
            {
                OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);

                // We don't dispose of the memory stream as that is disposed when a new image is created and doing so
                // beforehand will cause an exception.
                MemoryStream stream = new MemoryStream();
                using (GifEncoder encoder = new GifEncoder(stream, null, null, imageInfo.LoopCount))
                {
                    foreach (GifFrame frame in imageInfo.GifFrames)
                    {
                        factory.Update(frame.Image);
                        frame.Image = quantizer.Quantize(processor.Invoke(factory));
                        encoder.AddFrame(frame);
                    }
                }

                stream.Position = 0;
                factory.Update(Image.FromStream(stream));
            }
            else
            {
                factory.Update(processor.Invoke(factory));
            }

            // Set the property item information from any Exif metadata.
            // We do this here so that they can be changed between processor methods.
            if (factory.PreserveExifData)
            {
                foreach (KeyValuePair<int, PropertyItem> propertItem in factory.ExifPropertyItems)
                {
                    try
                    {
                        factory.Image.SetPropertyItem(propertItem.Value);
                    }
                    // ReSharper disable once EmptyGeneralCatchClause
                    catch
                    {
                        // Do nothing. The image format does not handle EXIF data.
                        // TODO: empty catch is fierce code smell.
                    }
                }
            }
        }
Пример #3
0
 /// <summary>
 /// Uses the <see cref="T:ImageProcessor.Imaging.OctreeQuantizer"/>
 /// to fix the color palette of gif images.
 /// </summary>
 private void FixGifs()
 {
     // Fix the colour palette of gif images.
     // TODO: Why does the palette not get fixed when resized to the same dimensions.
     if (object.Equals(this.ImageFormat, ImageFormat.Gif))
     {
         OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);
         this.Image = quantizer.Quantize(this.Image);
     }
 }
Пример #4
0
        /// <summary>
        /// Applies the given processor the current image.
        /// </summary>
        /// <param name="processor">
        /// The processor delegate.
        /// </param>
        private void ApplyProcessor(Func<ImageFactory, Image> processor)
        {
            ImageInfo imageInfo = this.Image.GetImageInfo(this.ImageFormat);

            if (imageInfo.IsAnimated)
            {
                OctreeQuantizer quantizer = new OctreeQuantizer(255, 8);

                // We don't dispose of the memory stream as that is disposed when a new image is created and doing so
                // beforehand will cause an exception.
                MemoryStream stream = new MemoryStream();
                using (GifEncoder encoder = new GifEncoder(stream, null, null, imageInfo.LoopCount))
                {
                    foreach (GifFrame frame in imageInfo.GifFrames)
                    {
                        this.Image = frame.Image;
                        frame.Image = quantizer.Quantize(processor.Invoke(this));
                        encoder.AddFrame(frame);
                    }
                }

                stream.Position = 0;
                this.Image = Image.FromStream(stream);
            }
            else
            {
                this.Image = processor.Invoke(this);
            }
        }