Browse Source

Added metadata class for image frames.

pull/99/head
Dirk Lemstra 9 years ago
parent
commit
bacac40115
  1. 27
      src/ImageSharp.Formats.Gif/GifDecoderCore.cs
  2. 31
      src/ImageSharp.Formats.Gif/GifEncoderCore.cs
  3. 8
      src/ImageSharp/Image/IImageBase.cs
  4. 18
      src/ImageSharp/Image/IImageFrame.cs
  5. 4
      src/ImageSharp/Image/ImageBase{TColor}.cs
  6. 20
      src/ImageSharp/Image/ImageFrame{TColor}.cs
  7. 21
      src/ImageSharp/Metadata/IMetaData.cs
  8. 44
      src/ImageSharp/Metadata/ImageFrameMetaData.cs
  9. 12
      src/ImageSharp/Metadata/ImageMetaData.cs
  10. 26
      tests/ImageSharp.Tests/Metadata/ImageFrameMetaDataTests.cs
  11. 42
      tests/ImageSharp.Tests/Metadata/ImageMetaDataTests.cs

27
src/ImageSharp.Formats.Gif/GifDecoderCore.cs

@ -321,12 +321,14 @@ namespace ImageSharp.Formats
if (this.previousFrame == null)
{
image = this.decodedImage;
this.decodedImage.MetaData.Quality = colorTableLength / 3;
// This initializes the image to become fully transparent because the alpha channel is zero.
image.InitPixels(imageWidth, imageHeight);
this.decodedImage.InitPixels(imageWidth, imageHeight);
this.SetFrameDelay(this.decodedImage.MetaData);
image = this.decodedImage;
}
else
{
@ -338,6 +340,8 @@ namespace ImageSharp.Formats
currentFrame = this.previousFrame.Clone();
this.SetFrameDelay(currentFrame.MetaData);
image = currentFrame;
this.RestoreToBackground(image);
@ -345,11 +349,6 @@ namespace ImageSharp.Formats
this.decodedImage.Frames.Add(currentFrame);
}
if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
{
image.FrameDelay = this.graphicsControlExtension.DelayTime;
}
int i = 0;
int interlacePass = 0; // The interlace pass
int interlaceIncrement = 8; // The interlacing line increment
@ -465,5 +464,17 @@ namespace ImageSharp.Formats
this.restoreArea = null;
}
/// <summary>
/// Sets the frame delay in the metadata.
/// </summary>
/// <param name="metaData">The meta data.</param>
private void SetFrameDelay(IMetaData metaData)
{
if (this.graphicsControlExtension != null && this.graphicsControlExtension.DelayTime > 0)
{
metaData.FrameDelay = this.graphicsControlExtension.DelayTime;
}
}
}
}

31
src/ImageSharp.Formats.Gif/GifEncoderCore.cs

@ -229,14 +229,41 @@ namespace ImageSharp.Formats
}
}
/// <summary>
/// Writes the graphics control extension to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="Image{TColor}"/> to encode.</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<TColor>(Image<TColor> image, EndianBinaryWriter writer, int transparencyIndex)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
this.WriteGraphicalControlExtension(image, image.MetaData, writer, transparencyIndex);
}
/// <summary>
/// Writes the graphics control extension to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="imageFrame">The <see cref="ImageFrame{TColor}"/> to encode.</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<TColor>(ImageFrame<TColor> imageFrame, EndianBinaryWriter writer, int transparencyIndex)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
this.WriteGraphicalControlExtension(imageFrame, imageFrame.MetaData, writer, transparencyIndex);
}
/// <summary>
/// Writes the graphics control extension to the stream.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to encode.</param>
/// <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<TColor>(ImageBase<TColor> image, EndianBinaryWriter writer, int transparencyIndex)
private void WriteGraphicalControlExtension<TColor>(ImageBase<TColor> image, IMetaData metaData, EndianBinaryWriter writer, int transparencyIndex)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// TODO: Check transparency logic.
@ -250,7 +277,7 @@ namespace ImageSharp.Formats
DisposalMethod = disposalMethod,
TransparencyFlag = hasTransparent,
TransparencyIndex = transparencyIndex,
DelayTime = image.FrameDelay
DelayTime = metaData.FrameDelay
};
// Write the intro.

8
src/ImageSharp/Image/IImageBase.cs

@ -15,14 +15,6 @@ namespace ImageSharp
/// </summary>
Rectangle Bounds { get; }
/// <summary>
/// Gets or sets the frame delay for animated images.
/// If not 0, this field specifies the number of hundredths (1/100) of a second to
/// wait before continuing with the processing of the Data Stream.
/// The clock starts ticking immediately after the graphic is rendered.
/// </summary>
int FrameDelay { get; set; }
/// <summary>
/// Gets or sets the maximum allowable width in pixels.
/// </summary>

18
src/ImageSharp/Image/IImageFrame.cs

@ -0,0 +1,18 @@
// <copyright file="IImageFrame.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Encapsulates the basic properties and methods required to manipulate images.
/// </summary>
internal interface IImageFrame : IImageBase
{
/// <summary>
/// Gets the meta data of the image.
/// </summary>
ImageFrameMetaData MetaData { get; }
}
}

4
src/ImageSharp/Image/ImageBase{TColor}.cs

@ -110,9 +110,6 @@ namespace ImageSharp
/// <inheritdoc/>
public Rectangle Bounds => new Rectangle(0, 0, this.Width, this.Height);
/// <inheritdoc/>
public int FrameDelay { get; set; }
/// <summary>
/// Gets the configuration providing initialization code which allows extending the library.
/// </summary>
@ -187,7 +184,6 @@ namespace ImageSharp
{
Debug.Assert(other != null);
this.FrameDelay = other.FrameDelay;
this.Configuration = other.Configuration;
}

20
src/ImageSharp/Image/ImageFrame{TColor}.cs

@ -13,7 +13,7 @@ namespace ImageSharp
/// Represents a single frame in a animation.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
public class ImageFrame<TColor> : ImageBase<TColor>
public class ImageFrame<TColor> : ImageBase<TColor>, IImageFrame
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
@ -38,6 +38,11 @@ namespace ImageSharp
{
}
/// <summary>
/// Gets the meta data of the frame.
/// </summary>
public ImageFrameMetaData MetaData { get; private set; } = new ImageFrameMetaData();
/// <inheritdoc/>
public override string ToString()
{
@ -87,5 +92,18 @@ namespace ImageSharp
{
return new ImageFrame<TColor>(this);
}
/// <summary>
/// Copies the properties from the other <see cref="IImageFrame"/>.
/// </summary>
/// <param name="other">
/// The other <see cref="IImageFrame"/> to copy the properties from.
/// </param>
private void CopyProperties(IImageFrame other)
{
base.CopyProperties(other);
this.MetaData = new ImageFrameMetaData(other.MetaData);
}
}
}

21
src/ImageSharp/Metadata/IMetaData.cs

@ -0,0 +1,21 @@
// <copyright file="IMetaData.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Encapsulates the metadata of an image frame.
/// </summary>
internal interface IMetaData
{
/// <summary>
/// Gets or sets the frame delay for animated images.
/// If not 0, this field specifies the number of hundredths (1/100) of a second to
/// wait before continuing with the processing of the Data Stream.
/// The clock starts ticking immediately after the graphic is rendered.
/// </summary>
int FrameDelay { get; set; }
}
}

44
src/ImageSharp/Metadata/ImageFrameMetaData.cs

@ -0,0 +1,44 @@
// <copyright file="ImageFrameMetaData.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System.Diagnostics;
/// <summary>
/// Encapsulates the metadata of an image frame.
/// </summary>
public sealed class ImageFrameMetaData : IMetaData
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageFrameMetaData"/> class.
/// </summary>
internal ImageFrameMetaData()
{
}
/// <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)
{
Debug.Assert(other != null);
this.FrameDelay = other.FrameDelay;
}
/// <summary>
/// Gets or sets the frame delay for animated images.
/// If not 0, this field specifies the number of hundredths (1/100) of a second to
/// wait before continuing with the processing of the Data Stream.
/// The clock starts ticking immediately after the graphic is rendered.
/// </summary>
public int FrameDelay { get; set; }
}
}

12
src/ImageSharp/Metadata/ImageMetaData.cs

@ -11,7 +11,7 @@ namespace ImageSharp
/// <summary>
/// Encapsulates the metadata of an image.
/// </summary>
public sealed class ImageMetaData
public sealed class ImageMetaData : IMetaData
{
/// <summary>
/// The default horizontal resolution value (dots per inch) in x direction.
@ -51,6 +51,8 @@ namespace ImageSharp
this.HorizontalResolution = other.HorizontalResolution;
this.VerticalResolution = other.VerticalResolution;
this.Quality = other.Quality;
this.FrameDelay = other.FrameDelay;
this.RepeatCount = other.RepeatCount;
foreach (ImageProperty property in other.Properties)
{
@ -110,6 +112,14 @@ namespace ImageSharp
/// </summary>
public ExifProfile ExifProfile { get; set; }
/// <summary>
/// Gets or sets the frame delay for animated images.
/// If not 0, this field specifies the number of hundredths (1/100) of a second to
/// wait before continuing with the processing of the Data Stream.
/// The clock starts ticking immediately after the graphic is rendered.
/// </summary>
public int FrameDelay { get; set; }
/// <summary>
/// Gets the list of properties for storing meta information about this image.
/// </summary>

26
tests/ImageSharp.Tests/Metadata/ImageFrameMetaDataTests.cs

@ -0,0 +1,26 @@
// <copyright file="ImageFrameMetaDataTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using Xunit;
/// <summary>
/// Tests the <see cref="ImageFrameMetaDataTests"/> class.
/// </summary>
public class ImageFrameMetaDataTests
{
[Fact]
public void ConstructorImageFrameMetaData()
{
ImageFrameMetaData metaData = new ImageFrameMetaData();
metaData.FrameDelay = 42;
ImageFrameMetaData clone = new ImageFrameMetaData(metaData);
Assert.Equal(42, clone.FrameDelay);
}
}
}

42
tests/ImageSharp.Tests/Metadata/ImageMetaDataTests.cs

@ -0,0 +1,42 @@
// <copyright file="ImageMetaDataTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using Xunit;
/// <summary>
/// Tests the <see cref="ImageMetaData"/> class.
/// </summary>
public class ImageMetaDataTests
{
[Fact]
public void ConstructorImageMetaData()
{
ImageMetaData metaData = new ImageMetaData();
ExifProfile exifProfile = new ExifProfile();
ImageProperty imageProperty = new ImageProperty("name", "value");
metaData.ExifProfile = exifProfile;
metaData.FrameDelay = 42;
metaData.HorizontalResolution = 4;
metaData.VerticalResolution = 2;
metaData.Properties.Add(imageProperty);
metaData.Quality = 24;
metaData.RepeatCount = 1;
ImageMetaData clone = new ImageMetaData(metaData);
Assert.Equal(exifProfile.ToByteArray(), clone.ExifProfile.ToByteArray());
Assert.Equal(42, clone.FrameDelay);
Assert.Equal(4, clone.HorizontalResolution);
Assert.Equal(2, clone.VerticalResolution);
Assert.Equal(imageProperty, clone.Properties[0]);
Assert.Equal(24, clone.Quality);
Assert.Equal(1, clone.RepeatCount);
}
}
}
Loading…
Cancel
Save