예제 #1
0
        private void EncodeGlobal <TPixel>(Image <TPixel> image, IndexedImageFrame <TPixel> quantized, int transparencyIndex, Stream stream)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            // The palette quantizer can reuse the same pixel map across multiple frames
            // since the palette is unchanging. This allows a reduction of memory usage across
            // multi frame gifs using a global palette.
            EuclideanPixelMap <TPixel> pixelMap = default;
            bool pixelMapSet = false;

            for (int i = 0; i < image.Frames.Count; i++)
            {
                ImageFrame <TPixel> frame         = image.Frames[i];
                ImageFrameMetadata  metadata      = frame.Metadata;
                GifFrameMetadata    frameMetadata = metadata.GetGifMetadata();
                this.WriteGraphicalControlExtension(frameMetadata, transparencyIndex, stream);
                this.WriteImageDescriptor(frame, false, stream);

                if (i == 0)
                {
                    this.WriteImageData(quantized, stream);
                }
                else
                {
                    if (!pixelMapSet)
                    {
                        pixelMapSet = true;
                        pixelMap    = new EuclideanPixelMap <TPixel>(this.configuration, quantized.Palette);
                    }

                    using var paletteFrameQuantizer = new PaletteQuantizer <TPixel>(this.configuration, this.quantizer.Options, pixelMap);
                    using IndexedImageFrame <TPixel> paletteQuantized = paletteFrameQuantizer.QuantizeFrame(frame, frame.Bounds());
                    this.WriteImageData(paletteQuantized, stream);
                }
            }
        }
예제 #2
0
        private void EncodeGlobal <TPixel>(Image <TPixel> image, IQuantizedFrame <TPixel> quantized, int transparencyIndex, Stream stream)
            where TPixel : struct, IPixel <TPixel>
        {
            for (int i = 0; i < image.Frames.Count; i++)
            {
                ImageFrame <TPixel> frame         = image.Frames[i];
                ImageFrameMetadata  metadata      = frame.Metadata;
                GifFrameMetadata    frameMetadata = metadata.GetGifMetadata();
                this.WriteGraphicalControlExtension(frameMetadata, transparencyIndex, stream);
                this.WriteImageDescriptor(frame, false, stream);

                if (i == 0)
                {
                    this.WriteImageData(quantized, stream);
                }
                else
                {
                    using (IFrameQuantizer <TPixel> paletteFrameQuantizer =
                               new PaletteFrameQuantizer <TPixel>(this.configuration, this.quantizer.Diffuser, quantized.Palette))
                    {
                        using (IQuantizedFrame <TPixel> paletteQuantized = paletteFrameQuantizer.QuantizeFrame(frame))
                        {
                            this.WriteImageData(paletteQuantized, stream);
                        }
                    }
                }
            }
        }
예제 #3
0
        private void EncodeLocal <TPixel>(Image <TPixel> image, QuantizedFrame <TPixel> quantized, Stream stream)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            ImageFrame <TPixel> previousFrame = null;
            GifFrameMetadata    previousMeta  = null;

            foreach (ImageFrame <TPixel> frame in image.Frames)
            {
                ImageFrameMetadata metadata      = frame.Metadata;
                GifFrameMetadata   frameMetadata = metadata.GetGifMetadata();
                if (quantized is null)
                {
                    // Allow each frame to be encoded at whatever color depth the frame designates if set.
                    if (previousFrame != null && previousMeta.ColorTableLength != frameMetadata.ColorTableLength &&
                        frameMetadata.ColorTableLength > 0)
                    {
                        var options = new QuantizerOptions
                        {
                            Dither      = this.quantizer.Options.Dither,
                            DitherScale = this.quantizer.Options.DitherScale,
                            MaxColors   = frameMetadata.ColorTableLength
                        };

                        using (IFrameQuantizer <TPixel> frameQuantizer = this.quantizer.CreateFrameQuantizer <TPixel>(this.configuration, options))
                        {
                            quantized = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
                        }
                    }
                    else
                    {
                        using (IFrameQuantizer <TPixel> frameQuantizer = this.quantizer.CreateFrameQuantizer <TPixel>(this.configuration))
                        {
                            quantized = frameQuantizer.QuantizeFrame(frame, frame.Bounds());
                        }
                    }
                }

                this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length).Clamp(1, 8);
                this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream);
                this.WriteImageDescriptor(frame, true, stream);
                this.WriteColorTable(quantized, stream);
                this.WriteImageData(quantized, stream);

                quantized?.Dispose();
                quantized     = null; // So next frame can regenerate it
                previousFrame = frame;
                previousMeta  = frameMetadata;
            }
        }
예제 #4
0
        public void ConstructorImageFrameMetadata()
        {
            const int frameDelay                   = 42;
            const int colorTableLength             = 128;
            const GifDisposalMethod disposalMethod = GifDisposalMethod.RestoreToBackground;

            var metaData = new ImageFrameMetadata();
            GifFrameMetadata gifFrameMetadata = metaData.GetGifMetadata();

            gifFrameMetadata.FrameDelay       = frameDelay;
            gifFrameMetadata.ColorTableLength = colorTableLength;
            gifFrameMetadata.DisposalMethod   = disposalMethod;

            var clone = new ImageFrameMetadata(metaData);
            GifFrameMetadata cloneGifFrameMetadata = clone.GetGifMetadata();

            Assert.Equal(frameDelay, cloneGifFrameMetadata.FrameDelay);
            Assert.Equal(colorTableLength, cloneGifFrameMetadata.ColorTableLength);
            Assert.Equal(disposalMethod, cloneGifFrameMetadata.DisposalMethod);
        }
        public void CloneIsDeep()
        {
            // arrange
            var exifProfile = new ExifProfile();

            exifProfile.SetValue(ExifTag.Software, "UnitTest");
            exifProfile.SetValue(ExifTag.Artist, "UnitTest");
            var xmpProfile = new XmpProfile(new byte[0]);
            var iccProfile = new IccProfile()
            {
                Header = new IccProfileHeader()
                {
                    CmmType = "Unittest"
                }
            };
            var iptcProfile = new ImageSharp.Metadata.Profiles.Iptc.IptcProfile();
            var metaData    = new ImageFrameMetadata()
            {
                XmpProfile  = xmpProfile,
                ExifProfile = exifProfile,
                IccProfile  = iccProfile,
                IptcProfile = iptcProfile
            };

            // act
            ImageFrameMetadata clone = metaData.DeepClone();

            // assert
            Assert.NotNull(clone);
            Assert.NotNull(clone.ExifProfile);
            Assert.NotNull(clone.XmpProfile);
            Assert.NotNull(clone.IccProfile);
            Assert.NotNull(clone.IptcProfile);
            Assert.False(metaData.ExifProfile.Equals(clone.ExifProfile));
            Assert.True(metaData.ExifProfile.Values.Count == clone.ExifProfile.Values.Count);
            Assert.False(ReferenceEquals(metaData.XmpProfile, clone.XmpProfile));
            Assert.True(metaData.XmpProfile.Data.Equals(clone.XmpProfile.Data));
            Assert.False(metaData.GetGifMetadata().Equals(clone.GetGifMetadata()));
            Assert.False(metaData.IccProfile.Equals(clone.IccProfile));
            Assert.False(metaData.IptcProfile.Equals(clone.IptcProfile));
        }