diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
index 1c130b54d0..711de818b3 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
@@ -464,17 +464,31 @@ namespace ImageSharp
int start = this.currentIndex - 8; // 8 is the tag header size
uint recordCount = this.ReadUInt32();
- // TODO: Why are we storing variable
- uint recordSize = this.ReadUInt32();
+ this.ReadUInt32(); // Record size (always 12)
IccLocalizedString[] text = new IccLocalizedString[recordCount];
- string[] culture = new string[recordCount];
+ CultureInfo[] culture = new CultureInfo[recordCount];
uint[] length = new uint[recordCount];
uint[] offset = new uint[recordCount];
for (int i = 0; i < recordCount; i++)
{
- culture[i] = $"{this.ReadAsciiString(2)}-{this.ReadAsciiString(2)}";
+ string languageCode = this.ReadAsciiString(2);
+ string countryCode = this.ReadAsciiString(2);
+
+ if (string.IsNullOrWhiteSpace(languageCode))
+ {
+ culture[i] = CultureInfo.InvariantCulture;
+ }
+ else if (string.IsNullOrWhiteSpace(countryCode))
+ {
+ culture[i] = new CultureInfo(languageCode);
+ }
+ else
+ {
+ culture[i] = new CultureInfo($"{languageCode}-{countryCode}");
+ }
+
length[i] = this.ReadUInt32();
offset[i] = this.ReadUInt32();
}
@@ -482,7 +496,7 @@ namespace ImageSharp
for (int i = 0; i < recordCount; i++)
{
this.currentIndex = (int)(start + offset[i]);
- text[i] = new IccLocalizedString(new CultureInfo(culture[i]), this.ReadUnicodeString((int)length[i]));
+ text[i] = new IccLocalizedString(culture[i], this.ReadUnicodeString((int)length[i]));
}
return new IccMultiLocalizedUnicodeTagDataEntry(text);
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
index 8e8065cee8..b74f22054e 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
@@ -5,6 +5,8 @@
namespace ImageSharp
{
+ using System.Linq;
+
///
/// Provides methods to write ICC data types
///
@@ -560,27 +562,45 @@ namespace ImageSharp
long tpos = this.dataStream.Position;
this.dataStream.Position += cultureCount * 12;
- uint[] offset = new uint[cultureCount];
- int[] lengths = new int[cultureCount];
+ IGrouping[] texts = value.Texts.GroupBy(t => t.Text).ToArray();
+
+ uint[] offset = new uint[texts.Length];
+ int[] lengths = new int[texts.Length];
- for (int i = 0; i < cultureCount; i++)
+ for (int i = 0; i < texts.Length; i++)
{
offset[i] = (uint)(this.dataStream.Position - start);
- count += lengths[i] = this.WriteUnicodeString(value.Texts[i].Text);
+ count += lengths[i] = this.WriteUnicodeString(texts[i].Key);
}
// Write position table
long lpos = this.dataStream.Position;
this.dataStream.Position = tpos;
- for (int i = 0; i < cultureCount; i++)
+ for (int i = 0; i < texts.Length; i++)
{
- string[] code = value.Texts[i].Culture.Name.Split('-');
-
- count += this.WriteAsciiString(code[0].ToLower(), 2, false);
- count += this.WriteAsciiString(code[1].ToUpper(), 2, false);
-
- count += this.WriteUInt32((uint)lengths[i]);
- count += this.WriteUInt32(offset[i]);
+ foreach (IccLocalizedString localizedString in texts[i])
+ {
+ string cultureName = localizedString.Culture.Name;
+ if (string.IsNullOrEmpty(cultureName))
+ {
+ count += this.WriteAsciiString("xx", 2, false);
+ count += this.WriteAsciiString("\0\0", 2, false);
+ }
+ else if (cultureName.Contains("-"))
+ {
+ string[] code = cultureName.Split('-');
+ count += this.WriteAsciiString(code[0].ToLower(), 2, false);
+ count += this.WriteAsciiString(code[1].ToUpper(), 2, false);
+ }
+ else
+ {
+ count += this.WriteAsciiString(cultureName, 2, false);
+ count += this.WriteAsciiString("\0\0", 2, false);
+ }
+
+ count += this.WriteUInt32((uint)lengths[i]);
+ count += this.WriteUInt32(offset[i]);
+ }
}
this.dataStream.Position = lpos;
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs
index 6f003cc4d6..76bb1cda19 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs
@@ -167,7 +167,7 @@ namespace ImageSharp.Tests.Icc
[Theory]
[MemberData(
- nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData),
+ nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData_Read),
MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadMultiLocalizedUnicodeTagDataEntry(byte[] data, IccMultiLocalizedUnicodeTagDataEntry expected)
{
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs
index affe9835e9..ea85bd16df 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs
@@ -154,7 +154,7 @@ namespace ImageSharp.Tests.Icc
}
[Theory]
- [MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))]
+ [MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData_Write), MemberType = typeof(IccTestDataTagDataEntry))]
internal void WriteMultiLocalizedUnicodeTagDataEntry(byte[] expected, IccMultiLocalizedUnicodeTagDataEntry data)
{
IccDataWriter writer = CreateWriter();
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs
index 769ec3a016..05942ab618 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs
@@ -455,21 +455,29 @@ namespace ImageSharp.Tests
#region MultiLocalizedUnicodeTagDataEntry
- private static readonly IccLocalizedString LocalizedString_Rand1 = new IccLocalizedString(new CultureInfo("en-US"), IccTestDataPrimitives.Unicode_ValRand2);
- private static readonly IccLocalizedString LocalizedString_Rand2 = new IccLocalizedString(new CultureInfo("de-DE"), IccTestDataPrimitives.Unicode_ValRand3);
+ private static readonly IccLocalizedString LocalizedString_Rand_enUs = new IccLocalizedString(new CultureInfo("en-US"), IccTestDataPrimitives.Unicode_ValRand2);
+ private static readonly IccLocalizedString LocalizedString_Rand_deDE = new IccLocalizedString(new CultureInfo("de-DE"), IccTestDataPrimitives.Unicode_ValRand3);
+ private static readonly IccLocalizedString LocalizedString_Rand2_deDE = new IccLocalizedString(new CultureInfo("de-DE"), IccTestDataPrimitives.Unicode_ValRand2);
+ private static readonly IccLocalizedString LocalizedString_Rand_en = new IccLocalizedString(new CultureInfo("en"), IccTestDataPrimitives.Unicode_ValRand2);
+ private static readonly IccLocalizedString LocalizedString_Rand_Invariant = new IccLocalizedString(CultureInfo.InvariantCulture, IccTestDataPrimitives.Unicode_ValRand3);
- private static readonly IccLocalizedString[] LocalizedString_RandArr1 = new IccLocalizedString[]
+ private static readonly IccLocalizedString[] LocalizedString_RandArr_enUs_deDE = new IccLocalizedString[]
{
- LocalizedString_Rand1,
- LocalizedString_Rand2,
+ LocalizedString_Rand_enUs,
+ LocalizedString_Rand_deDE,
};
- private static readonly IccLocalizedString[] LocalizedString_RandArr2 = new IccLocalizedString[]
+ private static readonly IccLocalizedString[] LocalizedString_RandArr_en_Invariant = new IccLocalizedString[]
{
- LocalizedString_Rand2,
- LocalizedString_Rand1,
+ LocalizedString_Rand_en,
+ LocalizedString_Rand_Invariant,
+ };
+ private static readonly IccLocalizedString[] LocalizedString_SameArr_enUs_deDE = new IccLocalizedString[]
+ {
+ LocalizedString_Rand_enUs,
+ LocalizedString_Rand2_deDE
};
- public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_RandArr1);
+ public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_RandArr_enUs_deDE);
public static readonly byte[] MultiLocalizedUnicode_Arr = ArrayHelper.Concat
(
IccTestDataPrimitives.UInt32_2,
@@ -487,9 +495,70 @@ namespace ImageSharp.Tests
IccTestDataPrimitives.Unicode_Rand3
);
- public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestData =
+ public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val2 = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_RandArr_en_Invariant);
+ public static readonly byte[] MultiLocalizedUnicode_Arr2_Read = ArrayHelper.Concat
+ (
+ IccTestDataPrimitives.UInt32_2,
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+
+ new byte[] { (byte)'e', (byte)'n', 0x00, 0x00 },
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+ new byte[] { 0x00, 0x00, 0x00, 0x28 }, // 40
+
+ new byte[] { 0x00, 0x00, 0x00, 0x00 },
+ new byte[] { 0x00, 0x00, 0x00, 0x0E }, // 14
+ new byte[] { 0x00, 0x00, 0x00, 0x34 }, // 52
+
+ IccTestDataPrimitives.Unicode_Rand2,
+ IccTestDataPrimitives.Unicode_Rand3
+ );
+
+ public static readonly byte[] MultiLocalizedUnicode_Arr2_Write = ArrayHelper.Concat
+ (
+ IccTestDataPrimitives.UInt32_2,
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+
+ new byte[] { (byte)'e', (byte)'n', 0x00, 0x00 },
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+ new byte[] { 0x00, 0x00, 0x00, 0x28 }, // 40
+
+ new byte[] { (byte)'x', (byte)'x', 0x00, 0x00 },
+ new byte[] { 0x00, 0x00, 0x00, 0x0E }, // 14
+ new byte[] { 0x00, 0x00, 0x00, 0x34 }, // 52
+
+ IccTestDataPrimitives.Unicode_Rand2,
+ IccTestDataPrimitives.Unicode_Rand3
+ );
+
+ public static readonly IccMultiLocalizedUnicodeTagDataEntry MultiLocalizedUnicode_Val3 = new IccMultiLocalizedUnicodeTagDataEntry(LocalizedString_SameArr_enUs_deDE);
+ public static readonly byte[] MultiLocalizedUnicode_Arr3 = ArrayHelper.Concat
+ (
+ IccTestDataPrimitives.UInt32_2,
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+
+ new byte[] { (byte)'e', (byte)'n', (byte)'U', (byte)'S' },
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+ new byte[] { 0x00, 0x00, 0x00, 0x28 }, // 40
+
+ new byte[] { (byte)'d', (byte)'e', (byte)'D', (byte)'E' },
+ new byte[] { 0x00, 0x00, 0x00, 0x0C }, // 12
+ new byte[] { 0x00, 0x00, 0x00, 0x28 }, // 40
+
+ IccTestDataPrimitives.Unicode_Rand2
+ );
+
+ public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestData_Read =
+ {
+ new object[] { MultiLocalizedUnicode_Arr, MultiLocalizedUnicode_Val },
+ new object[] { MultiLocalizedUnicode_Arr2_Read, MultiLocalizedUnicode_Val2 },
+ new object[] { MultiLocalizedUnicode_Arr3, MultiLocalizedUnicode_Val3 },
+ };
+
+ public static readonly object[][] MultiLocalizedUnicodeTagDataEntryTestData_Write =
{
new object[] { MultiLocalizedUnicode_Arr, MultiLocalizedUnicode_Val },
+ new object[] { MultiLocalizedUnicode_Arr2_Write, MultiLocalizedUnicode_Val2 },
+ new object[] { MultiLocalizedUnicode_Arr3, MultiLocalizedUnicode_Val3 },
};
#endregion
@@ -601,8 +670,8 @@ namespace ImageSharp.Tests
(
new IccProfileSequenceIdentifier[]
{
- new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr1),
- new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr1),
+ new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUs_deDE),
+ new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUs_deDE),
}
);
public static readonly byte[] ProfileSequenceIdentifier_Arr = ArrayHelper.Concat
@@ -951,7 +1020,7 @@ namespace ImageSharp.Tests
IccTestDataPrimitives.UInt16_7,
IccTestDataPrimitives.UInt16_2,
IccTestDataPrimitives.UInt16_5,
-
+
IccTestDataPrimitives.Ascii_Rand,
new byte[] { 0 }
);