/// <summary> /// Writes the graphics control extension to the stream. /// </summary> /// <param name="metaData">The metadata of the image or frame.</param> /// <param name="writer">The stream to write to.</param> /// <param name="transparencyIndex">The index of the color in the color palette to make transparent.</param> private void WriteGraphicalControlExtension(ImageFrameMetaData metaData, EndianBinaryWriter writer, int transparencyIndex) { var extension = new GifGraphicsControlExtension { DisposalMethod = metaData.DisposalMethod, TransparencyFlag = transparencyIndex > -1, TransparencyIndex = unchecked ((byte)transparencyIndex), DelayTime = metaData.FrameDelay }; // Write the intro. this.buffer[0] = GifConstants.ExtensionIntroducer; this.buffer[1] = GifConstants.GraphicControlLabel; this.buffer[2] = 4; writer.Write(this.buffer, 0, 3); var field = default(PackedField); field.SetBits(3, 3, (int)extension.DisposalMethod); // 1-3 : Reserved, 4-6 : Disposal // TODO: Allow this as an option. field.SetBit(6, false); // 7 : User input - 0 = none field.SetBit(7, extension.TransparencyFlag); // 8: Has transparent. writer.Write(field.Byte); writer.Write((ushort)extension.DelayTime); writer.Write(extension.TransparencyIndex); writer.Write(GifConstants.Terminator); }
private void EncodeGlobal <TPixel>(Image <TPixel> image, QuantizedFrame <TPixel> quantized, int transparencyIndex, Stream stream) where TPixel : struct, IPixel <TPixel> { var palleteQuantizer = new PaletteQuantizer(this.quantizer.Diffuser); for (int i = 0; i < image.Frames.Count; i++) { ImageFrame <TPixel> frame = image.Frames[i]; ImageFrameMetaData metaData = frame.MetaData; GifFrameMetaData frameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); this.WriteGraphicalControlExtension(frameMetaData, transparencyIndex, stream); this.WriteImageDescriptor(frame, false, stream); if (i == 0) { this.WriteImageData(quantized, stream); } else { using (QuantizedFrame <TPixel> paletteQuantized = palleteQuantizer.CreateFrameQuantizer(image.GetConfiguration(), () => quantized.Palette).QuantizeFrame(frame)) { this.WriteImageData(paletteQuantized, stream); } } } }
public void CloneIsDeep() { var metaData = new ImageFrameMetaData(); ImageFrameMetaData clone = metaData.DeepClone(); Assert.False(metaData.GetFormatMetaData(GifFormat.Instance).Equals(clone.GetFormatMetaData(GifFormat.Instance))); }
public void ConstructorImageFrameMetaData() { ImageFrameMetaData metaData = new ImageFrameMetaData(); metaData.FrameDelay = 42; ImageFrameMetaData clone = new ImageFrameMetaData(metaData); Assert.Equal(42, clone.FrameDelay); }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="width">The width of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(int width, int height, ImageFrameMetaData metaData) { Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); this.pixelBuffer = Buffer2D <TPixel> .CreateClean(width, height); this.MetaData = metaData; }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param> /// <param name="width">The width of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(MemoryManager memoryManager, int width, int height, ImageFrameMetaData metaData) { Guard.NotNull(memoryManager, nameof(memoryManager)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); this.MemoryManager = memoryManager; this.PixelBuffer = memoryManager.AllocateClean2D <TPixel>(width, height); this.MetaData = metaData; }
public void ConstructorImageFrameMetaData() { ImageFrameMetaData metaData = new ImageFrameMetaData(); metaData.FrameDelay = 42; metaData.DisposalMethod = DisposalMethod.RestoreToBackground; ImageFrameMetaData clone = new ImageFrameMetaData(metaData); Assert.Equal(42, clone.FrameDelay); Assert.Equal(DisposalMethod.RestoreToBackground, clone.DisposalMethod); }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class wrapping an existing buffer. /// </summary> internal ImageFrame( Configuration configuration, int width, int height, IBuffer <TPixel> consumedBuffer, ImageFrameMetaData metaData) { Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); this.configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = new Buffer2D <TPixel>(consumedBuffer, width, height); this.MetaData = metaData; }
public void ConstructorImageFrameMetaData() { const int frameDelay = 42; const int colorTableLength = 128; const GifDisposalMethod disposalMethod = GifDisposalMethod.RestoreToBackground; var metaData = new ImageFrameMetaData(); GifFrameMetaData gifFrameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); gifFrameMetaData.FrameDelay = frameDelay; gifFrameMetaData.ColorTableLength = colorTableLength; gifFrameMetaData.DisposalMethod = disposalMethod; var clone = new ImageFrameMetaData(metaData); GifFrameMetaData cloneGifFrameMetaData = clone.GetFormatMetaData(GifFormat.Instance); Assert.Equal(frameDelay, cloneGifFrameMetaData.FrameDelay); Assert.Equal(colorTableLength, cloneGifFrameMetaData.ColorTableLength); Assert.Equal(disposalMethod, cloneGifFrameMetaData.DisposalMethod); }
private void EncodeLocal <TPixel>(Image <TPixel> image, QuantizedFrame <TPixel> quantized, Stream stream) where TPixel : struct, IPixel <TPixel> { ImageFrame <TPixel> previousFrame = null; GifFrameMetaData previousMeta = null; foreach (ImageFrame <TPixel> frame in image.Frames) { ImageFrameMetaData metaData = frame.MetaData; GifFrameMetaData frameMetaData = metaData.GetFormatMetaData(GifFormat.Instance); 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) { quantized = this.quantizer.CreateFrameQuantizer <TPixel>( image.GetConfiguration(), frameMetaData.ColorTableLength).QuantizeFrame(frame); } else { quantized = this.quantizer.CreateFrameQuantizer <TPixel>(image.GetConfiguration()) .QuantizeFrame(frame); } } 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; } }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param> /// <param name="size">The <see cref="Size"/> of the frame.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(Configuration configuration, Size size, ImageFrameMetaData metaData) : this(configuration, size.Width, size.Height, metaData) { }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrameMetaData"/> class /// by making a copy from other metadata. /// </summary> /// <param name="other"> /// The other <see cref="ImageFrameMetaData"/> to create this instance from. /// </param> internal ImageFrameMetaData(ImageFrameMetaData other) { DebugGuard.NotNull(other, nameof(other)); this.FrameDelay = other.FrameDelay; }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="configuration">The <see cref="Configuration"/> to use for buffer allocation and parallel options to clear the buffer with.</param> /// <param name="width">The width of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param> /// <param name="backgroundColor">The color to clear the image with.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor, ImageFrameMetaData metaData) { Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.NotNull(metaData, nameof(metaData)); this.MemoryManager = configuration.MemoryManager; this.PixelBuffer = this.MemoryManager.Allocate2D <TPixel>(width, height, false); this.Clear(configuration.ParallelOptions, backgroundColor); this.MetaData = metaData; }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="size">The <see cref="Size"/> of the frame.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(Size size, ImageFrameMetaData metaData) : this(size.Width, size.Height, metaData) { }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param> /// <param name="width">The width of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(Configuration configuration, int width, int height, ImageFrameMetaData metaData) : this(configuration, width, height, default(TPixel), metaData) { }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param> /// <param name="width">The width of the image in pixels.</param> /// <param name="height">The height of the image in pixels.</param> /// <param name="backgroundColor">The color to clear the image with.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(Configuration configuration, int width, int height, TPixel backgroundColor, ImageFrameMetaData metaData) { Guard.NotNull(configuration, nameof(configuration)); Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); this.configuration = configuration; this.MemoryAllocator = configuration.MemoryAllocator; this.PixelBuffer = this.MemoryAllocator.Allocate2D <TPixel>(width, height); this.MetaData = metaData ?? new ImageFrameMetaData(); this.Clear(configuration.GetParallelOptions(), backgroundColor); }
/// <summary> /// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class. /// </summary> /// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param> /// <param name="size">The <see cref="Size"/> of the frame.</param> /// <param name="metaData">The meta data.</param> internal ImageFrame(MemoryManager memoryManager, Size size, ImageFrameMetaData metaData) : this(memoryManager, size.Width, size.Height, metaData) { }