Browse Source

Merge branch 'master' into js/faster-gif

pull/637/head
James Jackson-South 8 years ago
parent
commit
891f6eb005
  1. 7
      src/ImageSharp/ColorSpaces/CieLab.cs
  2. 46
      src/ImageSharp/Common/Extensions/ListExtensions.cs
  3. 9
      src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs
  4. 2
      src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs
  5. 12
      src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs
  6. 10
      src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs
  7. 4
      src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs
  8. 9
      src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs
  9. 16
      src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs
  10. 34
      src/ImageSharp/MetaData/Profiles/ICC/IccProfileHeader.cs
  11. 28
      src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs
  12. 14
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs
  13. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs
  14. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs
  15. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs
  16. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs
  17. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs
  18. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs
  19. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs
  20. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs
  21. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs
  22. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs
  23. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs
  24. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs
  25. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs
  26. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs
  27. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs
  28. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs
  29. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs
  30. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs
  31. 14
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs
  32. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs
  33. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs
  34. 14
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs
  35. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs
  36. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs
  37. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs
  38. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs
  39. 12
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs
  40. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs
  41. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs
  42. 10
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs
  43. 14
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs
  44. 2
      src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs
  45. 10
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs
  46. 2
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs
  47. 53
      src/ImageSharp/MetaData/Profiles/ICC/Various/IccVersion.cs
  48. 2
      src/ImageSharp/PixelFormats/Bgr565.cs
  49. 2
      src/ImageSharp/PixelFormats/HalfSingle.cs
  50. 2
      src/ImageSharp/PixelFormats/HalfVector2.cs
  51. 2
      src/ImageSharp/PixelFormats/NormalizedShort2.cs
  52. 2
      src/ImageSharp/PixelFormats/Rg32.cs
  53. 3
      tests/ImageSharp.Tests/Memory/BufferTestSuite.cs
  54. 4
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs
  55. 2
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs
  56. 8
      tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs
  57. 2
      tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs

7
src/ImageSharp/ColorSpaces/CieLab.cs

@ -194,12 +194,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
if (obj is CieLab)
{
return this.Equals((CieLab)obj);
}
return false;
return obj is CieLab other && this.Equals(other);
}
/// <inheritdoc/>

46
src/ImageSharp/Common/Extensions/ListExtensions.cs

@ -1,46 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Collections.Generic;
namespace SixLabors.ImageSharp.Common.Extensions
{
/// <summary>
/// Encapsulates a series of time saving extension methods to the <see cref="T:System.Collections.Generic.List"/> class.
/// </summary>
internal static class ListExtensions
{
/// <summary>
/// Inserts an item at the given index automatically expanding the capacity if required.
/// </summary>
/// <typeparam name="T">The type of object within the list</typeparam>
/// <param name="list">The list</param>
/// <param name="index">The index</param>
/// <param name="item">The item to insert</param>
public static void SafeInsert<T>(this List<T> list, int index, T item)
{
if (index >= list.Count)
{
list.Add(item);
}
else
{
list[index] = item;
}
}
/// <summary>
/// Removes the last element from a list and returns that element. This method changes the length of the list.
/// </summary>
/// <typeparam name="T">The type of object within the list</typeparam>
/// <param name="list">The list</param>
/// <returns>The last element in the specified sequence.</returns>
public static T Pop<T>(this List<T> list)
{
int last = list.Count - 1;
T item = list[last];
list.RemoveAt(last);
return item;
}
}
}

9
src/ImageSharp/MetaData/Profiles/Exif/ExifReader.cs

@ -6,6 +6,7 @@ using System.Buffers.Binary;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using SixLabors.ImageSharp.IO;
@ -462,7 +463,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
}
}
private unsafe double ConvertToDouble(ReadOnlySpan<byte> buffer)
private double ConvertToDouble(ReadOnlySpan<byte> buffer)
{
if (buffer.Length < 8)
{
@ -473,7 +474,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
? BinaryPrimitives.ReadInt64BigEndian(buffer)
: BinaryPrimitives.ReadInt64LittleEndian(buffer);
return *((double*)&intValue);
return Unsafe.As<long, double>(ref intValue);
}
private uint ConvertToUInt32(ReadOnlySpan<byte> buffer)
@ -501,7 +502,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
: BinaryPrimitives.ReadUInt16LittleEndian(buffer);
}
private unsafe float ConvertToSingle(ReadOnlySpan<byte> buffer)
private float ConvertToSingle(ReadOnlySpan<byte> buffer)
{
if (buffer.Length < 4)
{
@ -512,7 +513,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
? BinaryPrimitives.ReadInt32BigEndian(buffer)
: BinaryPrimitives.ReadInt32LittleEndian(buffer);
return *((float*)&intValue);
return Unsafe.As<int, float>(ref intValue);
}
private Rational ToRational(ReadOnlySpan<byte> buffer)

2
src/ImageSharp/MetaData/Profiles/Exif/ExifValue.cs

@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Exif
/// <inheritdoc />
public bool Equals(ExifValue other)
{
if (ReferenceEquals(other, null))
if (other is null)
{
return false;
}

12
src/ImageSharp/MetaData/Profiles/ICC/Curves/IccParametricCurve.cs

@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccParametricCurve other)
{
if (other == null)
if (other is null)
{
return false;
}
@ -148,16 +148,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccParametricCurve other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/Curves/IccResponseCurve.cs

@ -67,16 +67,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccResponseCurve other && this.Equals(other);
}

4
src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs

@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// Reads an ICC profile version number
/// </summary>
/// <returns>the version number</returns>
public Version ReadVersionNumber()
public IccVersion ReadVersionNumber()
{
int version = this.ReadInt32();
@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
int minor = (version >> 20) & 0x0F;
int bugfix = (version >> 16) & 0x0F;
return new Version(major, minor, bugfix);
return new IccVersion(major, minor, bugfix);
}
/// <summary>

9
src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.Primitives.cs

@ -3,6 +3,7 @@
using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using System.Text;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
@ -70,22 +71,22 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// Reads a float.
/// </summary>
/// <returns>the value</returns>
public unsafe float ReadSingle()
public float ReadSingle()
{
int intValue = this.ReadInt32();
return *((float*)&intValue);
return Unsafe.As<int, float>(ref intValue);
}
/// <summary>
/// Reads a double
/// </summary>
/// <returns>the value</returns>
public unsafe double ReadDouble()
public double ReadDouble()
{
long intValue = this.ReadInt64();
return *((double*)&intValue);
return Unsafe.As<long, double>(ref intValue);
}
/// <summary>

16
src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs

@ -31,11 +31,11 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteVersionNumber(Version value)
public int WriteVersionNumber(in IccVersion value)
{
int major = value.Major.Clamp(0, byte.MaxValue);
int minor = value.Minor.Clamp(0, 15);
int bugfix = value.Build.Clamp(0, 15);
int bugfix = value.Patch.Clamp(0, 15);
// TODO: This is not used?
byte mb = (byte)((minor << 4) | bugfix);
@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteProfileId(IccProfileId value)
public int WriteProfileId(in IccProfileId value)
{
return this.WriteUInt32(value.Part1)
+ this.WriteUInt32(value.Part2)
@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WritePositionNumber(IccPositionNumber value)
public int WritePositionNumber(in IccPositionNumber value)
{
return this.WriteUInt32(value.Offset)
+ this.WriteUInt32(value.Size);
@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteResponseNumber(IccResponseNumber value)
public int WriteResponseNumber(in IccResponseNumber value)
{
return this.WriteUInt16(value.DeviceCode)
+ this.WriteFix16(value.MeasurementValue);
@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteNamedColor(IccNamedColor value)
public int WriteNamedColor(in IccNamedColor value)
{
return this.WriteAsciiString(value.Name, 32, true)
+ this.WriteArray(value.PcsCoordinates)
@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteProfileDescription(IccProfileDescription value)
public int WriteProfileDescription(in IccProfileDescription value)
{
return this.WriteUInt32(value.DeviceManufacturer)
+ this.WriteUInt32(value.DeviceModel)
@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// </summary>
/// <param name="value">The value to write</param>
/// <returns>the number of bytes written</returns>
public int WriteScreeningChannel(IccScreeningChannel value)
public int WriteScreeningChannel(in IccScreeningChannel value)
{
return this.WriteFix16(value.Frequency)
+ this.WriteFix16(value.Angle)

34
src/ImageSharp/MetaData/Profiles/ICC/IccProfileHeader.cs

@ -7,42 +7,42 @@ using System.Numerics;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
/// <summary>
/// Contains all values of an ICC profile header
/// Contains all values of an ICC profile header.
/// </summary>
public sealed class IccProfileHeader
{
/// <summary>
/// Gets or sets the profile size in bytes (will be ignored when writing a profile)
/// Gets or sets the profile size in bytes (will be ignored when writing a profile).
/// </summary>
public uint Size { get; set; }
/// <summary>
/// Gets or sets the preferred CMM (Color Management Module) type
/// Gets or sets the preferred CMM (Color Management Module) type.
/// </summary>
public string CmmType { get; set; }
/// <summary>
/// Gets or sets the profiles version number
/// Gets or sets the profiles version number.
/// </summary>
public Version Version { get; set; }
public IccVersion Version { get; set; }
/// <summary>
/// Gets or sets the type of the profile
/// Gets or sets the type of the profile.
/// </summary>
public IccProfileClass Class { get; set; }
/// <summary>
/// Gets or sets the data colorspace
/// Gets or sets the data colorspace.
/// </summary>
public IccColorSpaceType DataColorSpace { get; set; }
/// <summary>
/// Gets or sets the profile connection space
/// Gets or sets the profile connection space.
/// </summary>
public IccColorSpaceType ProfileConnectionSpace { get; set; }
/// <summary>
/// Gets or sets the date and time this profile was created
/// Gets or sets the date and time this profile was created.
/// </summary>
public DateTime CreationDate { get; set; }
@ -59,42 +59,42 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <summary>
/// Gets or sets the profile flags to indicate various options for the CMM
/// such as distributed processing and caching options
/// such as distributed processing and caching options.
/// </summary>
public IccProfileFlag Flags { get; set; }
/// <summary>
/// Gets or sets the device manufacturer of the device for which this profile is created
/// Gets or sets the device manufacturer of the device for which this profile is created.
/// </summary>
public uint DeviceManufacturer { get; set; }
/// <summary>
/// Gets or sets the model of the device for which this profile is created
/// Gets or sets the model of the device for which this profile is created.
/// </summary>
public uint DeviceModel { get; set; }
/// <summary>
/// Gets or sets the device attributes unique to the particular device setup such as media type
/// Gets or sets the device attributes unique to the particular device setup such as media type.
/// </summary>
public IccDeviceAttribute DeviceAttributes { get; set; }
/// <summary>
/// Gets or sets the rendering Intent
/// Gets or sets the rendering Intent.
/// </summary>
public IccRenderingIntent RenderingIntent { get; set; }
/// <summary>
/// Gets or sets The normalized XYZ values of the illuminant of the PCS
/// Gets or sets The normalized XYZ values of the illuminant of the PCS.
/// </summary>
public Vector3 PcsIlluminant { get; set; }
/// <summary>
/// Gets or sets Profile creator signature
/// Gets or sets profile creator signature.
/// </summary>
public string CreatorSignature { get; set; }
/// <summary>
/// Gets or sets the profile ID (hash)
/// Gets or sets the profile ID (hash).
/// </summary>
public IccProfileId Id { get; set; }
}

28
src/ImageSharp/MetaData/Profiles/ICC/IccTagDataEntry.cs

@ -44,28 +44,9 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccTagDataEntry entry && this.Equals(entry);
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (int)this.Signature * 397;
}
}
/// <inheritdoc/>
public virtual bool Equals(IccTagDataEntry other)
{
@ -81,5 +62,14 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return this.Signature == other.Signature;
}
/// <inheritdoc/>
public override int GetHashCode()
{
unchecked
{
return (int)this.Signature * 397;
}
}
}
}

14
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccChromaticityTagDataEntry.cs

@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccChromaticityTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -104,17 +104,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccChromaticityTagDataEntry && this.Equals((IccChromaticityTagDataEntry)obj);
return obj is IccChromaticityTagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantOrderTagDataEntry.cs

@ -65,16 +65,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccColorantOrderTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccColorantTableTagDataEntry.cs

@ -66,16 +66,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccColorantTableTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCrdInfoTagDataEntry.cs

@ -115,16 +115,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccCrdInfoTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccCurveTagDataEntry.cs

@ -113,16 +113,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccCurveTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDataTagDataEntry.cs

@ -89,16 +89,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccDataTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccDateTimeTagDataEntry.cs

@ -60,17 +60,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccDateTimeTagDataEntry && this.Equals((IccDateTimeTagDataEntry)obj);
return obj is IccDateTimeTagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccFix16ArrayTagDataEntry.cs

@ -62,16 +62,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccFix16ArrayTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut16TagDataEntry.cs

@ -137,17 +137,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccLut16TagDataEntry && this.Equals((IccLut16TagDataEntry)obj);
return obj is IccLut16TagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLut8TagDataEntry.cs

@ -140,17 +140,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccLut8TagDataEntry && this.Equals((IccLut8TagDataEntry)obj);
return obj is IccLut8TagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutAToBTagDataEntry.cs

@ -177,16 +177,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccLutAToBTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccLutBToATagDataEntry.cs

@ -177,16 +177,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccLutBToATagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMeasurementTagDataEntry.cs

@ -100,17 +100,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccMeasurementTagDataEntry && this.Equals((IccMeasurementTagDataEntry)obj);
return obj is IccMeasurementTagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiLocalizedUnicodeTagDataEntry.cs

@ -63,17 +63,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccMultiLocalizedUnicodeTagDataEntry && this.Equals((IccMultiLocalizedUnicodeTagDataEntry)obj);
return obj is IccMultiLocalizedUnicodeTagDataEntry other && this.Equals(other);
}
/// <inheritdoc />

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccMultiProcessElementsTagDataEntry.cs

@ -84,16 +84,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccMultiProcessElementsTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccNamedColor2TagDataEntry.cs

@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccNamedColor2TagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -148,16 +148,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccNamedColor2TagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccParametricCurveTagDataEntry.cs

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccParametricCurveTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -61,16 +61,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccParametricCurveTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceDescTagDataEntry.cs

@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccProfileSequenceDescTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -64,16 +64,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccProfileSequenceDescTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccProfileSequenceIdentifierTagDataEntry.cs

@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccProfileSequenceIdentifierTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -63,16 +63,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccProfileSequenceIdentifierTagDataEntry other && this.Equals(other);
}

14
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccResponseCurveSet16TagDataEntry.cs

@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccResponseCurveSet16TagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -77,17 +77,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccResponseCurveSet16TagDataEntry && this.Equals((IccResponseCurveSet16TagDataEntry)obj);
return obj is IccResponseCurveSet16TagDataEntry other && this.Equals(other);
}
/// <inheritdoc />

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccScreeningTagDataEntry.cs

@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccScreeningTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -74,16 +74,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccScreeningTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccSignatureTagDataEntry.cs

@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccSignatureTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -62,16 +62,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccSignatureTagDataEntry other && this.Equals(other);
}

14
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs

@ -139,7 +139,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccTextDescriptionTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -160,17 +160,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccTextDescriptionTagDataEntry && this.Equals((IccTextDescriptionTagDataEntry)obj);
return obj is IccTextDescriptionTagDataEntry other && this.Equals(other);
}
/// <inheritdoc />

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextTagDataEntry.cs

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public bool Equals(IccTextTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -61,16 +61,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc />
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccTextTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUFix16ArrayTagDataEntry.cs

@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccUFix16ArrayTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -62,16 +62,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUFix16ArrayTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt16ArrayTagDataEntry.cs

@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccUInt16ArrayTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -62,16 +62,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUInt16ArrayTagDataEntry other && this.Equals(other);
}

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt32ArrayTagDataEntry.cs

@ -62,17 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUInt32ArrayTagDataEntry && this.Equals((IccUInt32ArrayTagDataEntry)obj);
return obj is IccUInt32ArrayTagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

12
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt64ArrayTagDataEntry.cs

@ -62,17 +62,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUInt64ArrayTagDataEntry && this.Equals((IccUInt64ArrayTagDataEntry)obj);
return obj is IccUInt64ArrayTagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUInt8ArrayTagDataEntry.cs

@ -62,16 +62,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUInt8ArrayTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUcrBgTagDataEntry.cs

@ -85,16 +85,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUcrBgTagDataEntry other && this.Equals(other);
}

10
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccUnknownTagDataEntry.cs

@ -62,16 +62,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccUnknownTagDataEntry other && this.Equals(other);
}

14
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccViewingConditionsTagDataEntry.cs

@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public bool Equals(IccViewingConditionsTagDataEntry other)
{
if (ReferenceEquals(null, other))
if (other is null)
{
return false;
}
@ -80,17 +80,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccViewingConditionsTagDataEntry && this.Equals((IccViewingConditionsTagDataEntry)obj);
return obj is IccViewingConditionsTagDataEntry other && this.Equals(other);
}
/// <inheritdoc/>

2
src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccXyzTagDataEntry.cs

@ -55,4 +55,4 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
return this.Equals((IccTagDataEntry)other);
}
}
}
}

10
src/ImageSharp/MetaData/Profiles/ICC/Various/IccClut.cs

@ -136,16 +136,6 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj is IccClut other && this.Equals(other);
}

2
src/ImageSharp/MetaData/Profiles/ICC/Various/IccScreeningChannel.cs

@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
/// <inheritdoc/>
public override bool Equals(object obj)
{
return obj is IccScreeningChannel && this.Equals((IccScreeningChannel)obj);
return obj is IccScreeningChannel other && this.Equals(other);
}
/// <inheritdoc/>

53
src/ImageSharp/MetaData/Profiles/ICC/Various/IccVersion.cs

@ -0,0 +1,53 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.MetaData.Profiles.Icc
{
/// <summary>
/// Represents the ICC profile version number.
/// </summary>
public readonly struct IccVersion : IEquatable<IccVersion>
{
/// <summary>
/// Initializes a new instance of the <see cref="IccVersion"/> struct.
/// </summary>
/// <param name="major">The major version number.</param>
/// <param name="minor">The minor version number.</param>
/// <param name="patch">The patch version number.</param>
public IccVersion(int major, int minor, int patch)
{
this.Major = major;
this.Minor = minor;
this.Patch = patch;
}
/// <summary>
/// Gets the major version number.
/// </summary>
public int Major { get; }
/// <summary>
/// Gets the minor version number.
/// </summary>
public int Minor { get; }
/// <summary>
/// Gets the patch number.
/// </summary>
public int Patch { get; }
/// <inheritdoc/>
public bool Equals(IccVersion other) =>
this.Major == other.Major &&
this.Minor == other.Minor &&
this.Patch == other.Patch;
/// <inheritdoc/>
public override string ToString()
{
return string.Join(".", this.Major, this.Minor, this.Patch);
}
}
}

2
src/ImageSharp/PixelFormats/Bgr565.cs

@ -206,7 +206,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
public override bool Equals(object obj)
{
return (obj is Bgr565) && this.Equals((Bgr565)obj);
return obj is Bgr565 other && this.Equals(other);
}
/// <inheritdoc />

2
src/ImageSharp/PixelFormats/HalfSingle.cs

@ -211,7 +211,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
public override bool Equals(object obj)
{
return (obj is HalfSingle) && this.Equals((HalfSingle)obj);
return obj is HalfSingle other && this.Equals(other);
}
/// <inheritdoc />

2
src/ImageSharp/PixelFormats/HalfVector2.cs

@ -239,7 +239,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
public override bool Equals(object obj)
{
return (obj is HalfVector2) && this.Equals((HalfVector2)obj);
return obj is HalfVector2 other && this.Equals(other);
}
/// <inheritdoc />

2
src/ImageSharp/PixelFormats/NormalizedShort2.cs

@ -247,7 +247,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
public override bool Equals(object obj)
{
return (obj is NormalizedShort2) && this.Equals((NormalizedShort2)obj);
return obj is NormalizedShort2 other && this.Equals(other);
}
/// <inheritdoc />

2
src/ImageSharp/PixelFormats/Rg32.cs

@ -210,7 +210,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
public override bool Equals(object obj)
{
return (obj is Rg32) && this.Equals((Rg32)obj);
return obj is Rg32 other && this.Equals(other);
}
/// <inheritdoc />

3
tests/ImageSharp.Tests/Memory/BufferTestSuite.cs

@ -46,8 +46,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is CustomStruct && this.Equals((CustomStruct)obj);
return obj is CustomStruct other && this.Equals(other);
}
public override int GetHashCode()

4
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs

@ -23,11 +23,11 @@ namespace SixLabors.ImageSharp.Tests.Icc
[Theory]
[MemberData(nameof(IccTestDataNonPrimitives.VersionNumberTestData), MemberType = typeof(IccTestDataNonPrimitives))]
public void ReadVersionNumber(byte[] data, Version expected)
public void ReadVersionNumber(byte[] data, IccVersion expected)
{
IccDataReader reader = CreateReader(data);
Version output = reader.ReadVersionNumber();
IccVersion output = reader.ReadVersionNumber();
Assert.Equal(expected, output);
}

2
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Icc
[Theory]
[MemberData(nameof(IccTestDataNonPrimitives.VersionNumberTestData), MemberType = typeof(IccTestDataNonPrimitives))]
public void WriteVersionNumber(byte[] expected, Version data)
public void WriteVersionNumber(byte[] expected, IccVersion data)
{
IccDataWriter writer = CreateWriter();

8
tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs

@ -67,10 +67,10 @@ namespace SixLabors.ImageSharp.Tests
#region VersionNumber
public static readonly Version VersionNumber_ValMin = new Version(0, 0, 0);
public static readonly Version VersionNumber_Val211 = new Version(2, 1, 1);
public static readonly Version VersionNumber_Val430 = new Version(4, 3, 0);
public static readonly Version VersionNumber_ValMax = new Version(255, 15, 15);
public static readonly IccVersion VersionNumber_ValMin = new IccVersion(0, 0, 0);
public static readonly IccVersion VersionNumber_Val211 = new IccVersion(2, 1, 1);
public static readonly IccVersion VersionNumber_Val430 = new IccVersion(4, 3, 0);
public static readonly IccVersion VersionNumber_ValMax = new IccVersion(255, 15, 15);
public static readonly byte[] VersionNumber_Min = { 0x00, 0x00, 0x00, 0x00 };
public static readonly byte[] VersionNumber_211 = { 0x02, 0x11, 0x00, 0x00 };

2
tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs

@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Tests
ProfileConnectionSpace = IccColorSpaceType.CieXyz,
RenderingIntent = IccRenderingIntent.AbsoluteColorimetric,
Size = size,
Version = new Version(4, 3, 0),
Version = new IccVersion(4, 3, 0),
};
}

Loading…
Cancel
Save