Browse Source

Merge pull request #264 from JBildstein/icc-multilocalizedunicode-refactor

Refactor reading and writing of ICC multilocalized unicode tag data entry
af/merge-core
James Jackson-South 9 years ago
committed by GitHub
parent
commit
8844cf6d6e
  1. 24
      src/ImageSharp/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntry.cs
  2. 44
      src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
  3. 2
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs
  4. 2
      tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntryTests.cs
  5. 95
      tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs

24
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 int start = this.currentIndex - 8; // 8 is the tag header size
uint recordCount = this.ReadUInt32(); uint recordCount = this.ReadUInt32();
// TODO: Why are we storing variable this.ReadUInt32(); // Record size (always 12)
uint recordSize = this.ReadUInt32();
IccLocalizedString[] text = new IccLocalizedString[recordCount]; IccLocalizedString[] text = new IccLocalizedString[recordCount];
string[] culture = new string[recordCount]; CultureInfo[] culture = new CultureInfo[recordCount];
uint[] length = new uint[recordCount]; uint[] length = new uint[recordCount];
uint[] offset = new uint[recordCount]; uint[] offset = new uint[recordCount];
for (int i = 0; i < recordCount; i++) 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(); length[i] = this.ReadUInt32();
offset[i] = this.ReadUInt32(); offset[i] = this.ReadUInt32();
} }
@ -482,7 +496,7 @@ namespace ImageSharp
for (int i = 0; i < recordCount; i++) for (int i = 0; i < recordCount; i++)
{ {
this.currentIndex = (int)(start + offset[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); return new IccMultiLocalizedUnicodeTagDataEntry(text);

44
src/ImageSharp/MetaData/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs

@ -5,6 +5,8 @@
namespace ImageSharp namespace ImageSharp
{ {
using System.Linq;
/// <summary> /// <summary>
/// Provides methods to write ICC data types /// Provides methods to write ICC data types
/// </summary> /// </summary>
@ -560,27 +562,45 @@ namespace ImageSharp
long tpos = this.dataStream.Position; long tpos = this.dataStream.Position;
this.dataStream.Position += cultureCount * 12; this.dataStream.Position += cultureCount * 12;
uint[] offset = new uint[cultureCount]; IGrouping<string, IccLocalizedString>[] texts = value.Texts.GroupBy(t => t.Text).ToArray();
int[] lengths = new int[cultureCount];
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); 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 // Write position table
long lpos = this.dataStream.Position; long lpos = this.dataStream.Position;
this.dataStream.Position = tpos; 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('-'); foreach (IccLocalizedString localizedString in texts[i])
{
count += this.WriteAsciiString(code[0].ToLower(), 2, false); string cultureName = localizedString.Culture.Name;
count += this.WriteAsciiString(code[1].ToUpper(), 2, false); if (string.IsNullOrEmpty(cultureName))
{
count += this.WriteUInt32((uint)lengths[i]); count += this.WriteAsciiString("xx", 2, false);
count += this.WriteUInt32(offset[i]); 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; this.dataStream.Position = lpos;

2
tests/ImageSharp.Tests/MetaData/Profiles/ICC/DataReader/IccDataReader.TagDataEntryTests.cs

@ -167,7 +167,7 @@ namespace ImageSharp.Tests.Icc
[Theory] [Theory]
[MemberData( [MemberData(
nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData), nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData_Read),
MemberType = typeof(IccTestDataTagDataEntry))] MemberType = typeof(IccTestDataTagDataEntry))]
internal void ReadMultiLocalizedUnicodeTagDataEntry(byte[] data, IccMultiLocalizedUnicodeTagDataEntry expected) internal void ReadMultiLocalizedUnicodeTagDataEntry(byte[] data, IccMultiLocalizedUnicodeTagDataEntry expected)
{ {

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

@ -154,7 +154,7 @@ namespace ImageSharp.Tests.Icc
} }
[Theory] [Theory]
[MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData), MemberType = typeof(IccTestDataTagDataEntry))] [MemberData(nameof(IccTestDataTagDataEntry.MultiLocalizedUnicodeTagDataEntryTestData_Write), MemberType = typeof(IccTestDataTagDataEntry))]
internal void WriteMultiLocalizedUnicodeTagDataEntry(byte[] expected, IccMultiLocalizedUnicodeTagDataEntry data) internal void WriteMultiLocalizedUnicodeTagDataEntry(byte[] expected, IccMultiLocalizedUnicodeTagDataEntry data)
{ {
IccDataWriter writer = CreateWriter(); IccDataWriter writer = CreateWriter();

95
tests/ImageSharp.Tests/TestDataIcc/IccTestDataTagDataEntry.cs

@ -455,21 +455,29 @@ namespace ImageSharp.Tests
#region MultiLocalizedUnicodeTagDataEntry #region MultiLocalizedUnicodeTagDataEntry
private static readonly IccLocalizedString LocalizedString_Rand1 = new IccLocalizedString(new CultureInfo("en-US"), IccTestDataPrimitives.Unicode_ValRand2); private static readonly IccLocalizedString LocalizedString_Rand_enUs = 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_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_Rand_enUs,
LocalizedString_Rand2, LocalizedString_Rand_deDE,
}; };
private static readonly IccLocalizedString[] LocalizedString_RandArr2 = new IccLocalizedString[] private static readonly IccLocalizedString[] LocalizedString_RandArr_en_Invariant = new IccLocalizedString[]
{ {
LocalizedString_Rand2, LocalizedString_Rand_en,
LocalizedString_Rand1, 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 public static readonly byte[] MultiLocalizedUnicode_Arr = ArrayHelper.Concat
( (
IccTestDataPrimitives.UInt32_2, IccTestDataPrimitives.UInt32_2,
@ -487,9 +495,70 @@ namespace ImageSharp.Tests
IccTestDataPrimitives.Unicode_Rand3 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_Arr, MultiLocalizedUnicode_Val },
new object[] { MultiLocalizedUnicode_Arr2_Write, MultiLocalizedUnicode_Val2 },
new object[] { MultiLocalizedUnicode_Arr3, MultiLocalizedUnicode_Val3 },
}; };
#endregion #endregion
@ -601,8 +670,8 @@ namespace ImageSharp.Tests
( (
new IccProfileSequenceIdentifier[] new IccProfileSequenceIdentifier[]
{ {
new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr1), new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUs_deDE),
new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr1), new IccProfileSequenceIdentifier(IccTestDataNonPrimitives.ProfileId_ValRand, LocalizedString_RandArr_enUs_deDE),
} }
); );
public static readonly byte[] ProfileSequenceIdentifier_Arr = ArrayHelper.Concat public static readonly byte[] ProfileSequenceIdentifier_Arr = ArrayHelper.Concat
@ -951,7 +1020,7 @@ namespace ImageSharp.Tests
IccTestDataPrimitives.UInt16_7, IccTestDataPrimitives.UInt16_7,
IccTestDataPrimitives.UInt16_2, IccTestDataPrimitives.UInt16_2,
IccTestDataPrimitives.UInt16_5, IccTestDataPrimitives.UInt16_5,
IccTestDataPrimitives.Ascii_Rand, IccTestDataPrimitives.Ascii_Rand,
new byte[] { 0 } new byte[] { 0 }
); );

Loading…
Cancel
Save