diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs index 65484e15c..fa823b9b0 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitives.cs @@ -127,10 +127,9 @@ namespace ImageSharp uint model = this.ReadUInt32(); IccDeviceAttribute attributes = (IccDeviceAttribute)this.ReadInt64(); IccProfileTag technologyInfo = (IccProfileTag)this.ReadUInt32(); - this.ReadCheckTagDataEntryHeader(IccTypeSignature.MultiLocalizedUnicode); - IccMultiLocalizedUnicodeTagDataEntry manufacturerInfo = this.ReadMultiLocalizedUnicodeTagDataEntry(); - this.ReadCheckTagDataEntryHeader(IccTypeSignature.MultiLocalizedUnicode); - IccMultiLocalizedUnicodeTagDataEntry modelInfo = this.ReadMultiLocalizedUnicodeTagDataEntry(); + + IccMultiLocalizedUnicodeTagDataEntry manufacturerInfo = ReadText(); + IccMultiLocalizedUnicodeTagDataEntry modelInfo = ReadText(); return new IccProfileDescription( manufacturer, @@ -139,6 +138,21 @@ namespace ImageSharp technologyInfo, manufacturerInfo.Texts, modelInfo.Texts); + + IccMultiLocalizedUnicodeTagDataEntry ReadText() + { + IccTypeSignature type = this.ReadTagDataEntryHeader(); + switch (type) + { + case IccTypeSignature.MultiLocalizedUnicode: + return this.ReadMultiLocalizedUnicodeTagDataEntry(); + case IccTypeSignature.TextDescription: + return (IccMultiLocalizedUnicodeTagDataEntry)this.ReadTextDescriptionTagDataEntry(); + + default: + throw new InvalidIccProfileException("Profile description can only have multi-localized Unicode or text description entries"); + } + } } /// diff --git a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs index f54818c4d..b87538196 100644 --- a/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs +++ b/src/ImageSharp/MetaData/Profiles/ICC/TagDataEntries/IccTextDescriptionTagDataEntry.cs @@ -6,6 +6,7 @@ namespace ImageSharp { using System; + using System.Globalization; /// /// The TextDescriptionType contains three types of text description. @@ -69,6 +70,75 @@ namespace ImageSharp /// public ushort ScriptCodeCode { get; } + /// + /// Performs an explicit conversion from + /// to . + /// + /// The entry to convert + /// The converted entry + public static explicit operator IccMultiLocalizedUnicodeTagDataEntry(IccTextDescriptionTagDataEntry textEntry) + { + if (textEntry == null) + { + return null; + } + + IccLocalizedString localString; + if (!string.IsNullOrEmpty(textEntry.Unicode)) + { + CultureInfo culture = GetCulture(textEntry.UnicodeLanguageCode); + if (culture != null) + { + localString = new IccLocalizedString(culture, textEntry.Unicode); + } + else + { + localString = new IccLocalizedString(textEntry.Unicode); + } + } + else if (!string.IsNullOrEmpty(textEntry.Ascii)) + { + localString = new IccLocalizedString(textEntry.Ascii); + } + else if (!string.IsNullOrEmpty(textEntry.ScriptCode)) + { + localString = new IccLocalizedString(textEntry.ScriptCode); + } + else + { + localString = new IccLocalizedString(string.Empty); + } + + return new IccMultiLocalizedUnicodeTagDataEntry(new IccLocalizedString[] { localString }, textEntry.TagSignature); + + CultureInfo GetCulture(uint value) + { + if (value == 0) + { + return null; + } + + byte p1 = (byte)(value >> 24); + byte p2 = (byte)(value >> 16); + byte p3 = (byte)(value >> 8); + byte p4 = (byte)value; + + // Check if the values are [a-z]{2}[A-Z]{2} + if (p1 >= 0x61 && p1 <= 0x7A + && p2 >= 0x61 && p2 <= 0x7A + && p3 >= 0x41 && p3 <= 0x5A + && p4 >= 0x41 && p4 <= 0x5A) + { + string culture = new string(new char[] { (char)p1, (char)p2, '-', (char)p3, (char)p4 }); + return new CultureInfo(culture); + } + else + { + return null; + } + } + } + /// public override bool Equals(IccTagDataEntry other) { diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs index 3df131125..e3593bfa9 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.NonPrimitivesTests.cs @@ -89,7 +89,7 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataNonPrimitives.ProfileDescriptionTestData), MemberType = typeof(IccTestDataNonPrimitives))] + [MemberData(nameof(IccTestDataNonPrimitives.ProfileDescriptionReadTestData), MemberType = typeof(IccTestDataNonPrimitives))] internal void ReadProfileDescription(byte[] data, IccProfileDescription expected) { IccDataReader reader = CreateReader(data); diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs index f4e316070..ae8345805 100644 --- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs +++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitivesTests.cs @@ -96,7 +96,7 @@ namespace ImageSharp.Tests.Icc } [Theory] - [MemberData(nameof(IccTestDataNonPrimitives.ProfileDescriptionTestData), MemberType = typeof(IccTestDataNonPrimitives))] + [MemberData(nameof(IccTestDataNonPrimitives.ProfileDescriptionWriteTestData), MemberType = typeof(IccTestDataNonPrimitives))] internal void WriteProfileDescription(byte[] expected, IccProfileDescription data) { IccDataWriter writer = CreateWriter(); diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs index e9bdc39be..fdbcb3127 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataNonPrimitives.cs @@ -269,6 +269,27 @@ IccTestDataPrimitives.Unicode_Rand3 ); + public static readonly IccTextDescriptionTagDataEntry TextDescription_Val1 = new IccTextDescriptionTagDataEntry + ( + IccTestDataPrimitives.Ascii_ValRand, IccTestDataPrimitives.Unicode_ValRand1, ArrayHelper.Fill('A', 66), + 1701729619, 2 + ); + public static readonly byte[] TextDescription_Arr1 = ArrayHelper.Concat + ( + new byte[] { 0x00, 0x00, 0x00, 0x0B }, // 11 + IccTestDataPrimitives.Ascii_Rand, + new byte[] { 0x00 }, // Null terminator + + new byte[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' }, + new byte[] { 0x00, 0x00, 0x00, 0x07 }, // 7 + IccTestDataPrimitives.Unicode_Rand2, + new byte[] { 0x00, 0x00 }, // Null terminator + + new byte[] { 0x00, 0x02, 0x43 }, // 2, 67 + ArrayHelper.Fill((byte)0x41, 66), + new byte[] { 0x00 } // Null terminator + ); + public static readonly IccProfileDescription ProfileDescription_ValRand1 = new IccProfileDescription ( 1, 2, @@ -278,6 +299,15 @@ MultiLocalizedUnicode_Val.Texts ); + public static readonly IccProfileDescription ProfileDescription_ValRand2 = new IccProfileDescription + ( + 1, 2, + IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.ReflectivityMatte, + IccProfileTag.ProfileDescription, + new IccLocalizedString[] { LocalizedString_Rand1 }, + new IccLocalizedString[] { LocalizedString_Rand1 } + ); + public static readonly byte[] ProfileDescription_Rand1 = ArrayHelper.Concat ( IccTestDataPrimitives.UInt32_1, @@ -293,7 +323,28 @@ MultiLocalizedUnicode_Arr ); - public static readonly object[][] ProfileDescriptionTestData = + public static readonly byte[] ProfileDescription_Rand2 = ArrayHelper.Concat + ( + IccTestDataPrimitives.UInt32_1, + IccTestDataPrimitives.UInt32_2, + new byte[] { 0, 0, 0, 0, 0, 0, 0, 10 }, + new byte[] { 0x64, 0x65, 0x73, 0x63 }, + + new byte[] { 0x64, 0x65, 0x73, 0x63 }, + new byte[] { 0x00, 0x00, 0x00, 0x00 }, + TextDescription_Arr1, + new byte[] { 0x64, 0x65, 0x73, 0x63 }, + new byte[] { 0x00, 0x00, 0x00, 0x00 }, + TextDescription_Arr1 + ); + + public static readonly object[][] ProfileDescriptionReadTestData = + { + new object[] { ProfileDescription_Rand1, ProfileDescription_ValRand1 }, + new object[] { ProfileDescription_Rand2, ProfileDescription_ValRand2 }, + }; + + public static readonly object[][] ProfileDescriptionWriteTestData = { new object[] { ProfileDescription_Rand1, ProfileDescription_ValRand1 }, }; diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs index caff1b31b..769ec3a01 100644 --- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs +++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs @@ -832,7 +832,7 @@ namespace ImageSharp.Tests public static readonly IccTextDescriptionTagDataEntry TextDescription_Val1 = new IccTextDescriptionTagDataEntry ( IccTestDataPrimitives.Ascii_ValRand, IccTestDataPrimitives.Unicode_ValRand1, ArrayHelper.Fill('A', 66), - 9, 2 + 1701729619, 2 ); public static readonly byte[] TextDescription_Arr1 = ArrayHelper.Concat ( @@ -840,7 +840,7 @@ namespace ImageSharp.Tests IccTestDataPrimitives.Ascii_Rand, new byte[] { 0x00 }, // Null terminator - IccTestDataPrimitives.UInt32_9, + new byte[] { 0x65, 0x6E, 0x55, 0x53 }, // enUS new byte[] { 0x00, 0x00, 0x00, 0x0E }, // 14 IccTestDataPrimitives.Unicode_Rand1, new byte[] { 0x00, 0x00 }, // Null terminator