Browse Source

Fix Number casting and description parsing.

pull/1067/head
James Jackson-South 6 years ago
parent
commit
505f07762a
  1. 7
      src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.cs
  2. 95
      src/ImageSharp/Primitives/Number.cs
  3. 4
      src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs
  4. 4
      tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs

7
src/ImageSharp/Metadata/Profiles/Exif/ExifTagDescriptionAttribute.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.
using System;
@ -31,7 +31,8 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
/// </returns>
public static string GetDescription(ExifTag tag, object value)
{
FieldInfo field = tag.GetType().GetTypeInfo().GetDeclaredField(tag.ToString());
var tagValue = (ExifTagValue)(ushort)tag;
FieldInfo field = tagValue.GetType().GetTypeInfo().GetDeclaredField(tagValue.ToString());
if (field is null)
{
@ -42,7 +43,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
object attributeValue = customAttribute.ConstructorArguments[0].Value;
if (object.Equals(attributeValue, value))
if (Equals(attributeValue, value))
{
return (string)customAttribute.ConstructorArguments[1].Value;
}

95
src/ImageSharp/Primitives/Number.cs

@ -3,21 +3,52 @@
using System;
using System.Globalization;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Primitives
{
/// <summary>
/// Represents an integral number.
/// </summary>
[StructLayout(LayoutKind.Explicit)]
public struct Number : IEquatable<Number>, IComparable<Number>
{
private readonly uint value;
[FieldOffset(0)]
private readonly int signedValue;
[FieldOffset(0)]
private readonly uint unsignedValue;
[FieldOffset(4)]
private readonly bool isSigned;
/// <summary>
/// Initializes a new instance of the <see cref="Number"/> struct.
/// </summary>
/// <param name="value">The value of the number.</param>
public Number(int value)
: this()
{
this.signedValue = value;
this.isSigned = true;
}
/// <summary>
/// Initializes a new instance of the <see cref="Number"/> struct.
/// </summary>
/// <param name="value">The value of the number.</param>
public Number(uint value) => this.value = value;
public Number(uint value)
: this()
{
this.unsignedValue = value;
this.isSigned = false;
}
/// <summary>
/// Converts the specified <see cref="int"/> to an instance of this type.
/// </summary>
/// <param name="value">The value.</param>
public static implicit operator Number(int value) => new Number(value);
/// <summary>
/// Converts the specified <see cref="uint"/> to an instance of this type.
@ -29,19 +60,40 @@ namespace SixLabors.ImageSharp.Primitives
/// Converts the specified <see cref="ushort"/> to an instance of this type.
/// </summary>
/// <param name="value">The value.</param>
public static implicit operator Number(ushort value) => new Number(value);
public static implicit operator Number(ushort value) => new Number((uint)value);
/// <summary>
/// Converts the specified <see cref="Number"/> to a <see cref="int"/>.
/// </summary>
/// <param name="number">The <see cref="Number"/> to convert.</param>
public static explicit operator int(Number number)
{
return number.isSigned
? number.signedValue
: (int)number.unsignedValue.Clamp(0, int.MaxValue);
}
/// <summary>
/// Converts the specified <see cref="Number"/> to a <see cref="uint"/>.
/// </summary>
/// <param name="number">The <see cref="Number"/> to convert.</param>
public static explicit operator uint(Number number) => number.value;
public static explicit operator uint(Number number)
{
return number.isSigned
? (uint)number.signedValue.Clamp(0, int.MaxValue)
: number.unsignedValue;
}
/// <summary>
/// Converts the specified <see cref="Number"/> to a <see cref="ushort"/>.
/// </summary>
/// <param name="number">The <see cref="Number"/> to convert.</param>
public static explicit operator ushort(Number number) => (ushort)number.value;
public static explicit operator ushort(Number number)
{
return number.isSigned
? (ushort)number.signedValue.Clamp(ushort.MinValue, ushort.MaxValue)
: (ushort)number.unsignedValue.Clamp(ushort.MinValue, ushort.MaxValue);
}
/// <summary>
/// Determines whether the specified <see cref="Number"/> instances are considered equal.
@ -86,16 +138,36 @@ namespace SixLabors.ImageSharp.Primitives
public static bool operator <=(Number left, Number right) => left.CompareTo(right) <= 0;
/// <inheritdoc/>
public int CompareTo(Number other) => this.value.CompareTo(other.value);
public int CompareTo(Number other)
{
return this.isSigned
? this.signedValue.CompareTo(other.signedValue)
: this.unsignedValue.CompareTo(other.unsignedValue);
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj is Number other && this.Equals(other);
/// <inheritdoc/>
public bool Equals(Number other) => this.value.Equals(other.value);
public bool Equals(Number other)
{
if (this.isSigned != other.isSigned)
{
return false;
}
return this.isSigned
? this.signedValue.Equals(other.signedValue)
: this.unsignedValue.Equals(other.unsignedValue);
}
/// <inheritdoc/>
public override int GetHashCode() => this.value.GetHashCode();
public override int GetHashCode()
{
return this.isSigned
? this.signedValue.GetHashCode()
: this.unsignedValue.GetHashCode();
}
/// <inheritdoc/>
public override string ToString() => this.ToString(CultureInfo.InvariantCulture);
@ -105,6 +177,11 @@ namespace SixLabors.ImageSharp.Primitives
/// </summary>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <returns>The string representation of the value of this instance, which consists of a sequence of digits ranging from 0 to 9, without a sign or leading zeros.</returns>
public string ToString(IFormatProvider provider) => this.value.ToString(provider);
public string ToString(IFormatProvider provider)
{
return this.isSigned
? this.signedValue.ToString(provider)
: this.unsignedValue.ToString(provider);
}
}
}

4
src/ImageSharp/Processing/Processors/Transforms/TransformProcessorHelpers.cs

@ -29,12 +29,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Only set the value if it already exists.
if (profile.GetValue(ExifTag.PixelXDimension) != null)
{
profile.SetValue(ExifTag.PixelXDimension, new Number((uint)image.Width));
profile.SetValue(ExifTag.PixelXDimension, image.Width);
}
if (profile.GetValue(ExifTag.PixelYDimension) != null)
{
profile.SetValue(ExifTag.PixelYDimension, new Number((uint)image.Height));
profile.SetValue(ExifTag.PixelYDimension, image.Height);
}
}
}

4
tests/ImageSharp.Tests/Processing/Transforms/TransformsHelpersTest.cs

@ -19,8 +19,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms
{
var profile = new ExifProfile();
img.Metadata.ExifProfile = profile;
profile.SetValue(ExifTag.PixelXDimension, (uint)xy + ushort.MaxValue);
profile.SetValue(ExifTag.PixelYDimension, (uint)xy + ushort.MaxValue);
profile.SetValue(ExifTag.PixelXDimension, xy + ushort.MaxValue);
profile.SetValue(ExifTag.PixelYDimension, xy + ushort.MaxValue);
Assert.Equal(ExifDataType.Long, profile.GetValue(ExifTag.PixelXDimension).DataType);
Assert.Equal(ExifDataType.Long, profile.GetValue(ExifTag.PixelYDimension).DataType);

Loading…
Cancel
Save