Browse Source

Merge pull request #99 from dlemstra/MetaData

Move meta data properties to new classes.
af/merge-core
Dirk Lemstra 9 years ago
committed by GitHub
parent
commit
7f3bda482f
  1. 1
      ImageSharp.ruleset
  2. 31
      src/ImageSharp.Formats.Gif/GifDecoderCore.cs
  3. 35
      src/ImageSharp.Formats.Gif/GifEncoderCore.cs
  4. 6
      src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
  5. 4
      src/ImageSharp.Formats.Jpeg/JpegEncoder.cs
  6. 5
      src/ImageSharp.Formats.Jpeg/JpegEncoderCore.cs
  7. 8
      src/ImageSharp.Formats.Png/PngDecoderCore.cs
  8. 12
      src/ImageSharp.Formats.Png/PngEncoderCore.cs
  9. 6
      src/ImageSharp.Processing/Transforms/AutoOrient.cs
  10. 25
      src/ImageSharp/Image/IImage.cs
  11. 18
      src/ImageSharp/Image/IImageBase.cs
  12. 18
      src/ImageSharp/Image/IImageFrame.cs
  13. 16
      src/ImageSharp/Image/ImageBase{TColor}.cs
  14. 27
      src/ImageSharp/Image/ImageFrame{TColor}.cs
  15. 113
      src/ImageSharp/Image/Image{TColor}.cs
  16. 21
      src/ImageSharp/MetaData/IMetaData.cs
  17. 44
      src/ImageSharp/MetaData/ImageFrameMetaData.cs
  18. 148
      src/ImageSharp/MetaData/ImageMetaData.cs
  19. 16
      src/ImageSharp/MetaData/ImageProperty.cs
  20. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs
  21. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifParts.cs
  22. 20
      src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs
  23. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
  24. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs
  25. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifTagDescriptionAttribute.cs
  26. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
  27. 0
      src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs
  28. 0
      src/ImageSharp/MetaData/Profiles/Exif/README.md
  29. 4
      tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs
  30. 4
      tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
  31. 2
      tests/ImageSharp.Tests/Formats/Png/PngTests.cs
  32. 26
      tests/ImageSharp.Tests/MetaData/ImageFrameMetaDataTests.cs
  33. 92
      tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs
  34. 0
      tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs
  35. 126
      tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs
  36. 0
      tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifTagDescriptionAttributeTests.cs
  37. 2
      tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs
  38. 4
      tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs

1
ImageSharp.ruleset

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="ImageSharp" ToolsVersion="14.0">
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1405" Action="None" />
<Rule Id="SA1413" Action="None" />
</Rules>
</RuleSet>

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

@ -239,7 +239,7 @@ namespace ImageSharp.Formats
try
{
this.currentStream.Read(flagBuffer, 0, flag);
this.decodedImage.Properties.Add(new ImageProperty("Comments", BitConverter.ToString(flagBuffer, 0, flag)));
this.decodedImage.MetaData.Properties.Add(new ImageProperty("Comments", BitConverter.ToString(flagBuffer, 0, flag)));
}
finally
{
@ -321,12 +321,14 @@ namespace ImageSharp.Formats
if (this.previousFrame == null)
{
image = this.decodedImage;
image.Quality = colorTableLength / 3;
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;
}
}
}
}

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

@ -65,7 +65,7 @@ namespace ImageSharp.Formats
EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);
// Ensure that quality can be set but has a fallback.
int quality = this.Quality > 0 ? this.Quality : image.Quality;
int quality = this.Quality > 0 ? this.Quality : image.MetaData.Quality;
this.Quality = quality > 0 ? quality.Clamp(1, 256) : 256;
// Get the number of bits.
@ -91,7 +91,7 @@ namespace ImageSharp.Formats
// Write additional frames.
if (image.Frames.Any())
{
this.WriteApplicationExtension(writer, image.RepeatCount, image.Frames.Count);
this.WriteApplicationExtension(writer, image.MetaData.RepeatCount, image.Frames.Count);
// ReSharper disable once ForCanBeConvertedToForeach
for (int i = 0; i < image.Frames.Count; i++)
@ -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.

6
src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs

@ -547,8 +547,8 @@ namespace ImageSharp.Formats
{
if (this.isJfif && this.horizontalResolution > 0 && this.verticalResolution > 0)
{
image.HorizontalResolution = this.horizontalResolution;
image.VerticalResolution = this.verticalResolution;
image.MetaData.HorizontalResolution = this.horizontalResolution;
image.MetaData.VerticalResolution = this.verticalResolution;
}
}
@ -951,7 +951,7 @@ namespace ImageSharp.Formats
if (profile[0] == 'E' && profile[1] == 'x' && profile[2] == 'i' && profile[3] == 'f' && profile[4] == '\0'
&& profile[5] == '\0')
{
image.ExifProfile = new ExifProfile(profile);
image.MetaData.ExifProfile = new ExifProfile(profile);
}
}

4
src/ImageSharp.Formats.Jpeg/JpegEncoder.cs

@ -65,9 +65,9 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
// Ensure that quality can be set but has a fallback.
if (image.Quality > 0)
if (image.MetaData.Quality > 0)
{
this.Quality = image.Quality;
this.Quality = image.MetaData.Quality;
}
JpegEncoderCore encode = new JpegEncoderCore();

5
src/ImageSharp.Formats.Jpeg/JpegEncoderCore.cs

@ -200,7 +200,7 @@ namespace ImageSharp.Formats
int componentCount = 3;
// Write the Start Of Image marker.
this.WriteApplicationHeader((short)image.HorizontalResolution, (short)image.VerticalResolution);
this.WriteApplicationHeader((short)image.MetaData.HorizontalResolution, (short)image.MetaData.VerticalResolution);
this.WriteProfiles(image);
@ -706,7 +706,8 @@ namespace ImageSharp.Formats
private void WriteProfiles<TColor>(Image<TColor> image)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
this.WriteProfile(image.ExifProfile);
image.MetaData.SyncProfiles();
this.WriteProfile(image.MetaData.ExifProfile);
}
/// <summary>

8
src/ImageSharp.Formats.Png/PngDecoderCore.cs

@ -174,7 +174,7 @@ namespace ImageSharp.Formats
byte[] pal = new byte[currentChunk.Length];
Buffer.BlockCopy(currentChunk.Data, 0, pal, 0, currentChunk.Length);
this.palette = pal;
image.Quality = pal.Length / 3;
image.MetaData.Quality = pal.Length / 3;
break;
case PngChunkTypes.PaletteAlpha:
byte[] alpha = new byte[currentChunk.Length];
@ -268,8 +268,8 @@ namespace ImageSharp.Formats
data.ReverseBytes(4, 4);
// 39.3700787 = inches in a meter.
image.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d;
image.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d;
image.MetaData.HorizontalResolution = BitConverter.ToInt32(data, 0) / 39.3700787d;
image.MetaData.VerticalResolution = BitConverter.ToInt32(data, 4) / 39.3700787d;
}
/// <summary>
@ -777,7 +777,7 @@ namespace ImageSharp.Formats
string name = Encoding.Unicode.GetString(data, 0, zeroIndex);
string value = Encoding.Unicode.GetString(data, zeroIndex + 1, length - zeroIndex - 1);
image.Properties.Add(new ImageProperty(name, value));
image.MetaData.Properties.Add(new ImageProperty(name, value));
}
/// <summary>

12
src/ImageSharp.Formats.Png/PngEncoderCore.cs

@ -126,12 +126,12 @@ namespace ImageSharp.Formats
public byte Threshold { get; set; }
/// <summary>
/// Encodes the image to the specified stream from the <see cref="ImageBase{TColor}"/>.
/// Encodes the image to the specified stream from the <see cref="Image{TColor}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="image">The <see cref="ImageBase{TColor}"/> to encode from.</param>
/// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
public void Encode<TColor>(ImageBase<TColor> image, Stream stream)
public void Encode<TColor>(Image<TColor> image, Stream stream)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
Guard.NotNull(image, nameof(image));
@ -153,7 +153,7 @@ namespace ImageSharp.Formats
stream.Write(this.chunkDataBuffer, 0, 8);
// Ensure that quality can be set but has a fallback.
int quality = this.Quality > 0 ? this.Quality : image.Quality;
int quality = this.Quality > 0 ? this.Quality : image.MetaData.Quality;
this.Quality = quality > 0 ? quality.Clamp(1, int.MaxValue) : int.MaxValue;
// Set correct color type if the color count is 256 or less.
@ -557,11 +557,11 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
Image<TColor> image = imageBase as Image<TColor>;
if (image != null && image.HorizontalResolution > 0 && image.VerticalResolution > 0)
if (image != null && image.MetaData.HorizontalResolution > 0 && image.MetaData.VerticalResolution > 0)
{
// 39.3700787 = inches in a meter.
int dpmX = (int)Math.Round(image.HorizontalResolution * 39.3700787D);
int dpmY = (int)Math.Round(image.VerticalResolution * 39.3700787D);
int dpmX = (int)Math.Round(image.MetaData.HorizontalResolution * 39.3700787D);
int dpmY = (int)Math.Round(image.MetaData.VerticalResolution * 39.3700787D);
WriteInteger(this.chunkDataBuffer, 0, dpmX);
WriteInteger(this.chunkDataBuffer, 4, dpmY);

6
src/ImageSharp.Processing/Transforms/AutoOrient.cs

@ -66,12 +66,12 @@ namespace ImageSharp
private static Orientation GetExifOrientation<TColor>(Image<TColor> source)
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
if (source.ExifProfile == null)
if (source.MetaData.ExifProfile == null)
{
return Orientation.Unknown;
}
ExifValue value = source.ExifProfile.GetValue(ExifTag.Orientation);
ExifValue value = source.MetaData.ExifProfile.GetValue(ExifTag.Orientation);
if (value == null)
{
return Orientation.Unknown;
@ -79,7 +79,7 @@ namespace ImageSharp
Orientation orientation = (Orientation)value.Value;
source.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft);
source.MetaData.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft);
return orientation;
}

25
src/ImageSharp/Image/IImage.cs

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

18
src/ImageSharp/Image/IImageBase.cs

@ -15,19 +15,6 @@ namespace ImageSharp
/// </summary>
Rectangle Bounds { get; }
/// <summary>
/// Gets or sets the quality of the image. This affects the output quality of lossy image formats.
/// </summary>
int Quality { 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>
int FrameDelay { get; set; }
/// <summary>
/// Gets or sets the maximum allowable width in pixels.
/// </summary>
@ -52,5 +39,10 @@ namespace ImageSharp
/// Gets the pixel ratio made up of the width and height.
/// </summary>
double PixelRatio { get; }
/// <summary>
/// Gets the configuration providing initialization code which allows extending the library.
/// </summary>
Configuration Configuration { get; }
}
}

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; }
}
}

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

@ -110,12 +110,6 @@ namespace ImageSharp
/// <inheritdoc/>
public Rectangle Bounds => new Rectangle(0, 0, this.Width, this.Height);
/// <inheritdoc/>
public int Quality { get; set; }
/// <inheritdoc/>
public int FrameDelay { get; set; }
/// <summary>
/// Gets the configuration providing initialization code which allows extending the library.
/// </summary>
@ -181,16 +175,16 @@ namespace ImageSharp
}
/// <summary>
/// Copies the properties from the other <see cref="ImageBase{TColor}"/>.
/// Copies the properties from the other <see cref="IImageBase"/>.
/// </summary>
/// <param name="other">
/// The other <see cref="ImageBase{TColor}"/> to copy the properties from.
/// The other <see cref="IImageBase"/> to copy the properties from.
/// </param>
protected void CopyProperties(ImageBase<TColor> other)
protected void CopyProperties(IImageBase other)
{
Debug.Assert(other != null);
this.Configuration = other.Configuration;
this.Quality = other.Quality;
this.FrameDelay = other.FrameDelay;
}
/// <summary>

27
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()
{
@ -55,11 +60,8 @@ namespace ImageSharp
{
scaleFunc = PackedPixelConverterHelper.ComputeScaleFunction<TColor, TColor2>(scaleFunc);
ImageFrame<TColor2> target = new ImageFrame<TColor2>(this.Width, this.Height, this.Configuration)
{
Quality = this.Quality,
FrameDelay = this.FrameDelay
};
ImageFrame<TColor2> target = new ImageFrame<TColor2>(this.Width, this.Height, this.Configuration);
target.CopyProperties(this);
using (PixelAccessor<TColor> pixels = this.Lock())
using (PixelAccessor<TColor2> targetPixels = target.Lock())
@ -90,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);
}
}
}

113
src/ImageSharp/Image/Image{TColor}.cs

@ -23,21 +23,9 @@ namespace ImageSharp
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
[DebuggerDisplay("Image: {Width}x{Height}")]
public class Image<TColor> : ImageBase<TColor>
public class Image<TColor> : ImageBase<TColor>, IImage
where TColor : struct, IPackedPixel, IEquatable<TColor>
{
/// <summary>
/// The default horizontal resolution value (dots per inch) in x direction.
/// <remarks>The default value is 96 dots per inch.</remarks>
/// </summary>
public const double DefaultHorizontalResolution = 96;
/// <summary>
/// The default vertical resolution value (dots per inch) in y direction.
/// <remarks>The default value is 96 dots per inch.</remarks>
/// </summary>
public const double DefaultVerticalResolution = 96;
/// <summary>
/// Initializes a new instance of the <see cref="Image{TColor}"/> class
/// with the height and the width of the image.
@ -129,18 +117,9 @@ namespace ImageSharp
}
/// <summary>
/// Gets or sets the resolution of the image in x- direction. It is defined as
/// number of dots per inch and should be an positive value.
/// </summary>
/// <value>The density of the image in x- direction.</value>
public double HorizontalResolution { get; set; } = DefaultHorizontalResolution;
/// <summary>
/// Gets or sets the resolution of the image in y- direction. It is defined as
/// number of dots per inch and should be an positive value.
/// Gets the meta data of the image.
/// </summary>
/// <value>The density of the image in y- direction.</value>
public double VerticalResolution { get; set; } = DefaultVerticalResolution;
public ImageMetaData MetaData { get; private set; } = new ImageMetaData();
/// <summary>
/// Gets the width of the image in inches. It is calculated as the width of the image
@ -152,14 +131,7 @@ namespace ImageSharp
{
get
{
double resolution = this.HorizontalResolution;
if (resolution <= 0)
{
resolution = DefaultHorizontalResolution;
}
return this.Width / resolution;
return this.Width / this.MetaData.HorizontalResolution;
}
}
@ -173,14 +145,7 @@ namespace ImageSharp
{
get
{
double resolution = this.VerticalResolution;
if (resolution <= 0)
{
resolution = DefaultVerticalResolution;
}
return this.Height / resolution;
return this.Height / this.MetaData.VerticalResolution;
}
}
@ -192,34 +157,17 @@ namespace ImageSharp
/// </value>
public bool IsAnimated => this.Frames.Count > 0;
/// <summary>
/// Gets or sets the number of times any animation is repeated.
/// <remarks>0 means to repeat indefinitely.</remarks>
/// </summary>
public ushort RepeatCount { get; set; }
/// <summary>
/// Gets the other frames for the animation.
/// </summary>
/// <value>The list of frame images.</value>
public IList<ImageFrame<TColor>> Frames { get; } = new List<ImageFrame<TColor>>();
/// <summary>
/// Gets the list of properties for storing meta information about this image.
/// </summary>
/// <value>A list of image properties.</value>
public IList<ImageProperty> Properties { get; } = new List<ImageProperty>();
/// <summary>
/// Gets the currently loaded image format.
/// </summary>
public IImageFormat CurrentImageFormat { get; internal set; }
/// <summary>
/// Gets or sets the Exif profile.
/// </summary>
public ExifProfile ExifProfile { get; set; }
/// <summary>
/// Applies the processor to the image.
/// </summary>
@ -317,15 +265,8 @@ namespace ImageSharp
{
scaleFunc = PackedPixelConverterHelper.ComputeScaleFunction<TColor, TColor2>(scaleFunc);
Image<TColor2> target = new Image<TColor2>(this.Width, this.Height, this.Configuration)
{
Quality = this.Quality,
FrameDelay = this.FrameDelay,
HorizontalResolution = this.HorizontalResolution,
VerticalResolution = this.VerticalResolution,
CurrentImageFormat = this.CurrentImageFormat,
RepeatCount = this.RepeatCount
};
Image<TColor2> target = new Image<TColor2>(this.Width, this.Height, this.Configuration);
target.CopyProperties(this);
using (PixelAccessor<TColor> pixels = this.Lock())
using (PixelAccessor<TColor2> targetPixels = target.Lock())
@ -345,11 +286,6 @@ namespace ImageSharp
});
}
if (this.ExifProfile != null)
{
target.ExifProfile = new ExifProfile(this.ExifProfile);
}
for (int i = 0; i < this.Frames.Count; i++)
{
target.Frames.Add(this.Frames[i].To<TColor2>());
@ -358,27 +294,6 @@ namespace ImageSharp
return target;
}
/// <summary>
/// Copies the properties from the other <see cref="Image{TColor}"/>.
/// </summary>
/// <param name="other">
/// The other <see cref="Image{TColor}"/> to copy the properties from.
/// </param>
internal void CopyProperties(Image<TColor> other)
{
base.CopyProperties(other);
this.HorizontalResolution = other.HorizontalResolution;
this.VerticalResolution = other.VerticalResolution;
this.CurrentImageFormat = other.CurrentImageFormat;
this.RepeatCount = other.RepeatCount;
if (other.ExifProfile != null)
{
this.ExifProfile = new ExifProfile(other.ExifProfile);
}
}
/// <summary>
/// Creates a new <see cref="ImageFrame{TColor}"/> from this instance
/// </summary>
@ -400,6 +315,20 @@ namespace ImageSharp
base.Dispose(disposing);
}
/// <summary>
/// Copies the properties from the other <see cref="IImage"/>.
/// </summary>
/// <param name="other">
/// The other <see cref="IImage"/> to copy the properties from.
/// </param>
private void CopyProperties(IImage other)
{
base.CopyProperties(other);
this.CurrentImageFormat = other.CurrentImageFormat;
this.MetaData = new ImageMetaData(other.MetaData);
}
/// <summary>
/// Loads the image from the given stream.
/// </summary>

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; }
}
}

148
src/ImageSharp/MetaData/ImageMetaData.cs

@ -0,0 +1,148 @@
// <copyright file="ImageMetaData.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.Collections.Generic;
using System.Diagnostics;
/// <summary>
/// Encapsulates the metadata of an image.
/// </summary>
public sealed class ImageMetaData : IMetaData
{
/// <summary>
/// The default horizontal resolution value (dots per inch) in x direction.
/// <remarks>The default value is 96 dots per inch.</remarks>
/// </summary>
public const double DefaultHorizontalResolution = 96;
/// <summary>
/// The default vertical resolution value (dots per inch) in y direction.
/// <remarks>The default value is 96 dots per inch.</remarks>
/// </summary>
public const double DefaultVerticalResolution = 96;
private double horizontalResolution;
private double verticalResolution;
/// <summary>
/// Initializes a new instance of the <see cref="ImageMetaData"/> class.
/// </summary>
internal ImageMetaData()
{
this.horizontalResolution = DefaultHorizontalResolution;
this.verticalResolution = DefaultVerticalResolution;
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageMetaData"/> class
/// by making a copy from other metadata.
/// </summary>
/// <param name="other">
/// The other <see cref="ImageMetaData"/> to create this instance from.
/// </param>
internal ImageMetaData(ImageMetaData other)
{
Debug.Assert(other != null);
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)
{
this.Properties.Add(new ImageProperty(property));
}
if (other.ExifProfile != null)
{
this.ExifProfile = new ExifProfile(other.ExifProfile);
}
}
/// <summary>
/// Gets or sets the resolution of the image in x- direction. It is defined as
/// number of dots per inch and should be an positive value.
/// </summary>
/// <value>The density of the image in x- direction.</value>
public double HorizontalResolution
{
get
{
return this.horizontalResolution;
}
set
{
if (value > 0)
{
this.horizontalResolution = value;
}
}
}
/// <summary>
/// Gets or sets the resolution of the image in y- direction. It is defined as
/// number of dots per inch and should be an positive value.
/// </summary>
/// <value>The density of the image in y- direction.</value>
public double VerticalResolution
{
get
{
return this.verticalResolution;
}
set
{
if (value > 0)
{
this.verticalResolution = value;
}
}
}
/// <summary>
/// Gets or sets the Exif profile.
/// </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>
/// <value>A list of image properties.</value>
public IList<ImageProperty> Properties { get; } = new List<ImageProperty>();
/// <summary>
/// Gets or sets the quality of the image. This affects the output quality of lossy image formats.
/// </summary>
public int Quality { get; set; }
/// <summary>
/// Gets or sets the number of times any animation is repeated.
/// <remarks>0 means to repeat indefinitely.</remarks>
/// </summary>
public ushort RepeatCount { get; set; }
/// <summary>
/// Synchronizes the profiles with the current meta data.
/// </summary>
internal void SyncProfiles()
{
this.ExifProfile?.Sync(this);
}
}
}

16
src/ImageSharp/Image/ImageProperty.cs → src/ImageSharp/MetaData/ImageProperty.cs

@ -6,6 +6,7 @@
namespace ImageSharp
{
using System;
using System.Diagnostics;
/// <summary>
/// Stores meta information about a image, like the name of the author,
@ -27,6 +28,21 @@ namespace ImageSharp
this.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="ImageProperty"/> class
/// by making a copy from another property.
/// </summary>
/// <param name="other">
/// The other <see cref="ImageProperty"/> to create this instance from.
/// </param>
internal ImageProperty(ImageProperty other)
{
Debug.Assert(other != null);
this.Name = other.Name;
this.Value = other.Value;
}
/// <summary>
/// Gets the name of this <see cref="ImageProperty"/> indicating which kind of
/// information this property stores.

0
src/ImageSharp/Profiles/Exif/ExifDataType.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifDataType.cs

0
src/ImageSharp/Profiles/Exif/ExifParts.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifParts.cs

20
src/ImageSharp/Profiles/Exif/ExifProfile.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifProfile.cs

@ -224,6 +224,26 @@ namespace ImageSharp
return writer.GetData();
}
/// <summary>
/// Synchronizes the profiles with the specified meta data.
/// </summary>
/// <param name="metaData">The meta data.</param>
internal void Sync(ImageMetaData metaData)
{
this.SyncResolution(ExifTag.XResolution, metaData.HorizontalResolution);
this.SyncResolution(ExifTag.YResolution, metaData.VerticalResolution);
}
private void SyncResolution(ExifTag tag, double resolution)
{
ExifValue value = this.GetValue(tag);
if (value != null)
{
Rational newResolution = new Rational(resolution, false);
this.SetValue(tag, newResolution);
}
}
private void InitializeValues()
{
if (this.values != null)

0
src/ImageSharp/Profiles/Exif/ExifReader.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs

0
src/ImageSharp/Profiles/Exif/ExifTag.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifTag.cs

0
src/ImageSharp/Profiles/Exif/ExifTagDescriptionAttribute.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifTagDescriptionAttribute.cs

0
src/ImageSharp/Profiles/Exif/ExifValue.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs

0
src/ImageSharp/Profiles/Exif/ExifWriter.cs → src/ImageSharp/MetaData/Profiles/Exif/ExifWriter.cs

0
src/ImageSharp/Profiles/Exif/README.md → src/ImageSharp/MetaData/Profiles/Exif/README.md

4
tests/ImageSharp.Tests/Formats/GeneralFormatTests.cs

@ -24,8 +24,8 @@ namespace ImageSharp.Tests
{
using (FileStream output = File.OpenWrite($"{path}/{file.FileName}"))
{
image.VerticalResolution = 150;
image.HorizontalResolution = 150;
image.MetaData.VerticalResolution = 150;
image.MetaData.HorizontalResolution = 150;
image.Save(output);
}
}

4
tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs

@ -36,8 +36,8 @@ namespace ImageSharp.Tests
{
using (Image<TColor> image = provider.GetImage().Resize(new ResizeOptions { Size = new Size(150, 100), Mode = ResizeMode.Max }))
{
image.Quality = quality;
image.ExifProfile = null; // Reduce the size of the file
image.MetaData.Quality = quality;
image.MetaData.ExifProfile = null; // Reduce the size of the file
JpegEncoder encoder = new JpegEncoder { Subsample = subsample, Quality = quality };
provider.Utility.TestName += $"{subsample}_Q{quality}";

2
tests/ImageSharp.Tests/Formats/Png/PngTests.cs

@ -27,7 +27,7 @@ namespace ImageSharp.Tests
{
using (FileStream output = File.OpenWrite($"{path}/{file.FileNameWithoutExtension}.png"))
{
image.Quality = 256;
image.MetaData.Quality = 256;
image.Save(output, new PngFormat());
}
}

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);
}
}
}

92
tests/ImageSharp.Tests/MetaData/ImageMetaDataTests.cs

@ -0,0 +1,92 @@
// <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);
}
[Fact]
public void HorizontalResolution()
{
ImageMetaData metaData = new ImageMetaData();
Assert.Equal(96, metaData.HorizontalResolution);
metaData.HorizontalResolution=0;
Assert.Equal(96, metaData.HorizontalResolution);
metaData.HorizontalResolution=-1;
Assert.Equal(96, metaData.HorizontalResolution);
metaData.HorizontalResolution=1;
Assert.Equal(1, metaData.HorizontalResolution);
}
[Fact]
public void VerticalResolution()
{
ImageMetaData metaData = new ImageMetaData();
Assert.Equal(96, metaData.VerticalResolution);
metaData.VerticalResolution = 0;
Assert.Equal(96, metaData.VerticalResolution);
metaData.VerticalResolution = -1;
Assert.Equal(96, metaData.VerticalResolution);
metaData.VerticalResolution = 1;
Assert.Equal(1, metaData.VerticalResolution);
}
[Fact]
public void SyncProfiles()
{
ExifProfile exifProfile = new ExifProfile();
exifProfile.SetValue(ExifTag.XResolution, new Rational(200));
exifProfile.SetValue(ExifTag.YResolution, new Rational(300));
Image image = new Image(1, 1);
image.MetaData.ExifProfile = exifProfile;
image.MetaData.HorizontalResolution = 400;
image.MetaData.VerticalResolution = 500;
image.MetaData.SyncProfiles();
Assert.Equal(400, ((Rational)image.MetaData.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble());
Assert.Equal(500, ((Rational)image.MetaData.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble());
}
}
}

0
tests/ImageSharp.Tests/Image/ImagePropertyTests.cs → tests/ImageSharp.Tests/MetaData/ImagePropertyTests.cs

126
tests/ImageSharp.Tests/Profiles/Exif/ExifProfileTests.cs → tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifProfileTests.cs

@ -19,20 +19,18 @@ namespace ImageSharp.Tests
{
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Calliphora).CreateImage();
Assert.Null(image.ExifProfile);
Assert.Null(image.MetaData.ExifProfile);
image.ExifProfile = new ExifProfile();
image.ExifProfile.SetValue(ExifTag.Copyright, "Dirk Lemstra");
image.MetaData.ExifProfile = new ExifProfile();
image.MetaData.ExifProfile.SetValue(ExifTag.Copyright, "Dirk Lemstra");
image = WriteAndRead(image);
Assert.NotNull(image.ExifProfile);
Assert.Equal(1, image.ExifProfile.Values.Count());
Assert.NotNull(image.MetaData.ExifProfile);
Assert.Equal(1, image.MetaData.ExifProfile.Values.Count());
ExifValue value = image.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright);
ExifValue value = image.MetaData.ExifProfile.Values.FirstOrDefault(val => val.Tag == ExifTag.Copyright);
TestValue(value, "Dirk Lemstra");
}
[Fact]
@ -70,14 +68,14 @@ namespace ImageSharp.Tests
profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime));
Image image = new Image(1, 1);
image.ExifProfile = profile;
image.MetaData.ExifProfile = profile;
image.SaveAsJpeg(memStream);
memStream.Position = 0;
image = new Image(memStream);
profile = image.ExifProfile;
profile = image.MetaData.ExifProfile;
Assert.NotNull(profile);
ExifValue value = profile.GetValue(ExifTag.ExposureTime);
@ -88,14 +86,14 @@ namespace ImageSharp.Tests
profile = GetExifProfile();
profile.SetValue(ExifTag.ExposureTime, new Rational(exposureTime, true));
image.ExifProfile = profile;
image.MetaData.ExifProfile = profile;
image.SaveAsJpeg(memStream);
memStream.Position = 0;
image = new Image(memStream);
profile = image.ExifProfile;
profile = image.MetaData.ExifProfile;
Assert.NotNull(profile);
value = profile.GetValue(ExifTag.ExposureTime);
@ -107,24 +105,24 @@ namespace ImageSharp.Tests
public void ReadWriteInfinity()
{
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage();
image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity));
image.MetaData.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.PositiveInfinity));
image = WriteAndRead(image);
ExifValue value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
ExifValue value = image.MetaData.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
Assert.NotNull(value);
Assert.Equal(new SignedRational(double.PositiveInfinity), value.Value);
image.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.NegativeInfinity));
image.MetaData.ExifProfile.SetValue(ExifTag.ExposureBiasValue, new SignedRational(double.NegativeInfinity));
image = WriteAndRead(image);
value = image.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
value = image.MetaData.ExifProfile.GetValue(ExifTag.ExposureBiasValue);
Assert.NotNull(value);
Assert.Equal(new SignedRational(double.NegativeInfinity), value.Value);
image.ExifProfile.SetValue(ExifTag.FlashEnergy, new Rational(double.NegativeInfinity));
image.MetaData.ExifProfile.SetValue(ExifTag.FlashEnergy, new Rational(double.NegativeInfinity));
image = WriteAndRead(image);
value = image.ExifProfile.GetValue(ExifTag.FlashEnergy);
value = image.MetaData.ExifProfile.GetValue(ExifTag.FlashEnergy);
Assert.NotNull(value);
Assert.Equal(new Rational(double.PositiveInfinity), value.Value);
}
@ -135,71 +133,107 @@ namespace ImageSharp.Tests
Rational[] latitude = new Rational[] { new Rational(12.3), new Rational(4.56), new Rational(789.0) };
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage();
image.ExifProfile.SetValue(ExifTag.Software, "ImageSharp");
image.MetaData.ExifProfile.SetValue(ExifTag.Software, "ImageSharp");
ExifValue value = image.ExifProfile.GetValue(ExifTag.Software);
ExifValue value = image.MetaData.ExifProfile.GetValue(ExifTag.Software);
TestValue(value, "ImageSharp");
Assert.Throws<ArgumentException>(() => { value.Value = 15; });
image.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55));
image.MetaData.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55));
value = image.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
value = image.MetaData.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
TestValue(value, new SignedRational(7555, 100));
Assert.Throws<ArgumentException>(() => { value.Value = 75; });
image.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0));
image.MetaData.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0));
value = image.ExifProfile.GetValue(ExifTag.XResolution);
// We also need to change this value because this overrides XResolution when the image is written.
image.MetaData.HorizontalResolution = 150.0;
value = image.MetaData.ExifProfile.GetValue(ExifTag.XResolution);
TestValue(value, new Rational(150, 1));
Assert.Throws<ArgumentException>(() => { value.Value = "ImageSharp"; });
image.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null);
image.MetaData.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null);
value = image.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite);
value = image.MetaData.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite);
TestValue(value, (string)null);
image.ExifProfile.SetValue(ExifTag.GPSLatitude, latitude);
image.MetaData.ExifProfile.SetValue(ExifTag.GPSLatitude, latitude);
value = image.ExifProfile.GetValue(ExifTag.GPSLatitude);
value = image.MetaData.ExifProfile.GetValue(ExifTag.GPSLatitude);
TestValue(value, latitude);
image = WriteAndRead(image);
Assert.NotNull(image.ExifProfile);
Assert.Equal(17, image.ExifProfile.Values.Count());
Assert.NotNull(image.MetaData.ExifProfile);
Assert.Equal(17, image.MetaData.ExifProfile.Values.Count());
value = image.ExifProfile.GetValue(ExifTag.Software);
value = image.MetaData.ExifProfile.GetValue(ExifTag.Software);
TestValue(value, "ImageSharp");
value = image.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
value = image.MetaData.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
TestValue(value, new SignedRational(75.55));
value = image.ExifProfile.GetValue(ExifTag.XResolution);
value = image.MetaData.ExifProfile.GetValue(ExifTag.XResolution);
TestValue(value, new Rational(150.0));
value = image.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite);
value = image.MetaData.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite);
Assert.Null(value);
value = image.ExifProfile.GetValue(ExifTag.GPSLatitude);
value = image.MetaData.ExifProfile.GetValue(ExifTag.GPSLatitude);
TestValue(value, latitude);
image.ExifProfile.Parts = ExifParts.ExifTags;
image.MetaData.ExifProfile.Parts = ExifParts.ExifTags;
image = WriteAndRead(image);
Assert.NotNull(image.ExifProfile);
Assert.Equal(8, image.ExifProfile.Values.Count());
Assert.NotNull(image.MetaData.ExifProfile);
Assert.Equal(8, image.MetaData.ExifProfile.Values.Count());
Assert.NotNull(image.MetaData.ExifProfile.GetValue(ExifTag.ColorSpace));
Assert.True(image.MetaData.ExifProfile.RemoveValue(ExifTag.ColorSpace));
Assert.False(image.MetaData.ExifProfile.RemoveValue(ExifTag.ColorSpace));
Assert.Null(image.MetaData.ExifProfile.GetValue(ExifTag.ColorSpace));
Assert.Equal(7, image.MetaData.ExifProfile.Values.Count());
}
[Fact]
public void Syncs()
{
ExifProfile exifProfile = new ExifProfile();
exifProfile.SetValue(ExifTag.XResolution, new Rational(200));
exifProfile.SetValue(ExifTag.YResolution, new Rational(300));
ImageMetaData metaData = new ImageMetaData();
metaData.ExifProfile = exifProfile;
metaData.HorizontalResolution = 200;
metaData.VerticalResolution = 300;
metaData.HorizontalResolution = 100;
Assert.Equal(200, ((Rational)metaData.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble());
Assert.Equal(300, ((Rational)metaData.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble());
exifProfile.Sync(metaData);
Assert.Equal(100, ((Rational)metaData.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble());
Assert.Equal(300, ((Rational)metaData.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble());
metaData.VerticalResolution = 150;
Assert.Equal(100, ((Rational)metaData.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble());
Assert.Equal(300, ((Rational)metaData.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble());
Assert.NotNull(image.ExifProfile.GetValue(ExifTag.ColorSpace));
Assert.True(image.ExifProfile.RemoveValue(ExifTag.ColorSpace));
Assert.False(image.ExifProfile.RemoveValue(ExifTag.ColorSpace));
Assert.Null(image.ExifProfile.GetValue(ExifTag.ColorSpace));
exifProfile.Sync(metaData);
Assert.Equal(7, image.ExifProfile.Values.Count());
Assert.Equal(100, ((Rational)metaData.ExifProfile.GetValue(ExifTag.XResolution).Value).ToDouble());
Assert.Equal(150, ((Rational)metaData.ExifProfile.GetValue(ExifTag.YResolution).Value).ToDouble());
}
[Fact]
@ -225,8 +259,8 @@ namespace ImageSharp.Tests
}
Image image = new Image(100, 100);
image.ExifProfile = new ExifProfile();
image.ExifProfile.SetValue(ExifTag.ImageDescription, junk.ToString());
image.MetaData.ExifProfile = new ExifProfile();
image.MetaData.ExifProfile.SetValue(ExifTag.ImageDescription, junk.ToString());
using (MemoryStream memStream = new MemoryStream())
{
@ -238,7 +272,7 @@ namespace ImageSharp.Tests
{
Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage();
ExifProfile profile = image.ExifProfile;
ExifProfile profile = image.MetaData.ExifProfile;
Assert.NotNull(profile);
return profile;

0
tests/ImageSharp.Tests/Profiles/Exif/ExifTagDescriptionAttributeTests.cs → tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifTagDescriptionAttributeTests.cs

2
tests/ImageSharp.Tests/Profiles/Exif/ExifValueTests.cs → tests/ImageSharp.Tests/MetaData/Profiles/Exif/ExifValueTests.cs

@ -15,7 +15,7 @@ namespace ImageSharp.Tests
ExifProfile profile;
using (Image image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateImage())
{
profile = image.ExifProfile;
profile = image.MetaData.ExifProfile;
}
Assert.NotNull(profile);

4
tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs

@ -35,8 +35,8 @@ namespace ImageSharp.Tests
using (Image image = file.CreateImage())
{
image.ExifProfile = new ExifProfile();
image.ExifProfile.SetValue(ExifTag.Orientation, orientation);
image.MetaData.ExifProfile = new ExifProfile();
image.MetaData.ExifProfile.SetValue(ExifTag.Orientation, orientation);
using (FileStream before = File.OpenWrite($"{path}/before-{file.FileName}"))
using (FileStream after = File.OpenWrite($"{path}/after-{file.FileName}"))

Loading…
Cancel
Save