Browse Source

Add SetDateTimeValue which makes sure the formatting will be as specified in the spec

pull/1574/head
Brian Popow 6 years ago
parent
commit
4c0d8842e2
  1. 22
      src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs
  2. 22
      src/ImageSharp/Metadata/Profiles/IPTC/IptcTag.cs
  3. 43
      src/ImageSharp/Metadata/Profiles/IPTC/IptcTagExtensions.cs
  4. 6
      src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs
  5. 43
      tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs

22
src/ImageSharp/Metadata/Profiles/IPTC/IptcProfile.cs

@ -174,6 +174,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
public void SetValue(IptcTag tag, Encoding encoding, string value, bool strict = true)
{
Guard.NotNull(encoding, nameof(encoding));
Guard.NotNull(value, nameof(value));
if (!tag.IsRepeatable())
{
@ -192,6 +193,27 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
this.values.Add(new IptcValue(tag, encoding, value, strict));
}
/// <summary>
/// Makes sure the datetime is formatted according to the iptc specification.
/// A date will be formatted as CCYYMMDD.
/// A time value will be formatted as HHMMSS±HHMM.
/// </summary>
/// <param name="tag">The tag of the iptc value.</param>
/// <param name="dateTime">The datetime.</param>
public void SetDateTimeValue(IptcTag tag, DateTime dateTime)
{
if (!tag.IsDate() && !tag.IsTime())
{
throw new ArgumentException("iptc tag is not a time or date type");
}
var formattedDate = tag.IsDate()
? dateTime.ToString("yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture)
: dateTime.ToString("HHmmsszzzz", System.Globalization.CultureInfo.InvariantCulture).Replace(":", string.Empty);
this.SetValue(tag, Encoding.UTF8, formattedDate);
}
/// <summary>
/// Sets the value of the specified tag.
/// </summary>

22
src/ImageSharp/Metadata/Profiles/IPTC/IptcTag.cs

@ -86,30 +86,28 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
/// <summary>
/// Release date. Format should be CCYYMMDD,
/// e.g. "19890317" indicates data for release on 17 March 1989.
/// e.g. "19890317" for the 17 March 1989.
/// Not repeatable, max length is 8.
/// </summary>
ReleaseDate = 30,
/// <summary>
/// Release time. Format should be HHMMSS±HHMM,
/// e.g. "090000-0500" indicates object for use after 0900 in
/// New York (five hours behind UTC)
/// e.g. "090000-0500" for 9 o'clock New York time (five hours behind UTC).
/// Not repeatable, max length is 11.
/// </summary>
ReleaseTime = 35,
/// <summary>
/// Expiration date. Format should be CCYYMMDD,
/// e.g. "19890317" indicates data for release on 17 March 1989.
/// e.g. "19890317" for the 17 March 1989.
/// Not repeatable, max length is 8.
/// </summary>
ExpirationDate = 37,
/// <summary>
/// Expiration time. Format should be HHMMSS±HHMM,
/// e.g. "090000-0500" indicates object for use after 0900 in
/// New York (five hours behind UTC)
/// e.g. "090000-0500" for 9 o'clock New York time (five hours behind UTC).
/// Not repeatable, max length is 11.
/// </summary>
ExpirationTime = 38,
@ -131,7 +129,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
/// <summary>
/// Reference date. Format should be CCYYMMDD,
/// e.g. "19890317" indicates data for release on 17 March 1989.
/// e.g. "19890317" for the 17 March 1989.
/// Not repeatable, max length is 8.
/// </summary>
ReferenceDate = 47,
@ -143,30 +141,28 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
/// <summary>
/// Created date. Format should be CCYYMMDD,
/// e.g. "19890317" indicates data for release on 17 March 1989.
/// e.g. "19890317" for the 17 March 1989.
/// Not repeatable, max length is 8.
/// </summary>
CreatedDate = 55,
/// <summary>
/// Created time. Format should be HHMMSS±HHMM,
/// e.g. "090000-0500" indicates object for use after 0900 in
/// New York (five hours behind UTC)
/// e.g. "090000-0500" for 9 o'clock New York time (five hours behind UTC).
/// Not repeatable, max length is 11.
/// </summary>
CreatedTime = 60,
/// <summary>
/// Digital creation date. Format should be CCYYMMDD,
/// e.g. "19890317" indicates data for release on 17 March 1989.
/// e.g. "19890317" for the 17 March 1989.
/// Not repeatable, max length is 8.
/// </summary>
DigitalCreationDate = 62,
/// <summary>
/// Digital creation time. Format should be HHMMSS±HHMM,
/// e.g. "090000-0500" indicates object for use after 0900 in
/// New York (five hours behind UTC)
/// e.g. "090000-0500" for 9 o'clock New York time (five hours behind UTC).
/// Not repeatable, max length is 11.
/// </summary>
DigitalCreationTime = 63,

43
src/ImageSharp/Metadata/Profiles/IPTC/IptcTagExtensions.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
@ -117,5 +117,46 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
return true;
}
}
/// <summary>
/// Determines if the tag is a datetime tag which needs to be formatted as CCYYMMDD.
/// </summary>
/// <param name="tag">The tag to check.</param>
/// <returns>True, if its a datetime tag.</returns>
public static bool IsDate(this IptcTag tag)
{
switch (tag)
{
case IptcTag.CreatedDate:
case IptcTag.DigitalCreationDate:
case IptcTag.ExpirationDate:
case IptcTag.ReferenceDate:
case IptcTag.ReleaseDate:
return true;
default:
return false;
}
}
/// <summary>
/// Determines if the tag is a time tag which need to be formatted as HHMMSS±HHMM.
/// </summary>
/// <param name="tag">The tag to check.</param>
/// <returns>True, if its a time tag.</returns>
public static bool IsTime(this IptcTag tag)
{
switch (tag)
{
case IptcTag.CreatedTime:
case IptcTag.DigitalCreationTime:
case IptcTag.ExpirationTime:
case IptcTag.ReleaseTime:
return true;
default:
return false;
}
}
}
}

6
src/ImageSharp/Metadata/Profiles/IPTC/IptcValue.cs

@ -103,6 +103,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Iptc
{
var cappedValue = value.Substring(0, maxLength);
valueBytes = this.encoding.GetBytes(cappedValue);
// It is still possible that the bytes of the string exceed the limit.
if (valueBytes.Length > maxLength)
{
throw new ArgumentException($"The iptc value exceeds the limit of {maxLength} bytes for the tag {this.Tag}");
}
}
else
{

43
tests/ImageSharp.Tests/Metadata/Profiles/IPTC/IptcProfileTests.cs

@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
{
private static JpegDecoder JpegDecoder => new JpegDecoder() { IgnoreMetadata = false };
public static IEnumerable<object[]> allIptcTags()
public static IEnumerable<object[]> AllIptcTags()
{
foreach (object tag in Enum.GetValues(typeof(IptcTag)))
{
@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
}
[Theory]
[MemberData("allIptcTags")]
[MemberData("AllIptcTags")]
public void IptcProfile_SetValue_WithStrictOption_Works(IptcTag tag)
{
// arrange
@ -41,6 +41,45 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.IPTC
Assert.Equal(expectedLength, actual.Value.Length);
}
[Theory]
[InlineData(IptcTag.DigitalCreationDate)]
[InlineData(IptcTag.ExpirationDate)]
[InlineData(IptcTag.CreatedDate)]
[InlineData(IptcTag.ReferenceDate)]
[InlineData(IptcTag.ReleaseDate)]
public void IptcProfile_SetDateValue_Works(IptcTag tag)
{
// arrange
var profile = new IptcProfile();
var datetime = new DateTime(1994, 3, 17);
// act
profile.SetDateTimeValue(tag, datetime);
// assert
IptcValue actual = profile.GetValues(tag).First();
Assert.Equal("19940317", actual.Value);
}
[Theory]
[InlineData(IptcTag.CreatedTime)]
[InlineData(IptcTag.DigitalCreationTime)]
[InlineData(IptcTag.ExpirationTime)]
[InlineData(IptcTag.ReleaseTime)]
public void IptcProfile_SetTimeValue_Works(IptcTag tag)
{
// arrange
var profile = new IptcProfile();
DateTime datetime = new DateTimeOffset(new DateTime(1994, 3, 17, 14, 15, 16), new TimeSpan(1, 0, 0)).DateTime;
// act
profile.SetDateTimeValue(tag, datetime);
// assert
IptcValue actual = profile.GetValues(tag).First();
Assert.Equal("141516+0100", actual.Value);
}
[Theory]
[WithFile(TestImages.Jpeg.Baseline.Iptc, PixelTypes.Rgba32)]
public void ReadIptcMetadata_Works<TPixel>(TestImageProvider<TPixel> provider)

Loading…
Cancel
Save