diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs
index d7f556a81..b24c96f02 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/IccReader.cs
@@ -5,6 +5,8 @@
namespace ImageSharp
{
+ using System.Collections.Generic;
+
///
/// Reads and parses ICC data from a byte array
///
@@ -85,9 +87,21 @@ namespace ImageSharp
{
IccTagTableEntry[] tagTable = this.ReadTagTable(reader);
IccTagDataEntry[] entries = new IccTagDataEntry[tagTable.Length];
+ var store = new Dictionary();
for (int i = 0; i < tagTable.Length; i++)
{
- IccTagDataEntry entry = reader.ReadTagDataEntry(tagTable[i]);
+ IccTagDataEntry entry;
+ uint offset = tagTable[i].Offset;
+ if (store.ContainsKey(offset))
+ {
+ entry = store[offset];
+ }
+ else
+ {
+ entry = reader.ReadTagDataEntry(tagTable[i]);
+ store.Add(offset, entry);
+ }
+
entry.TagSignature = tagTable[i].Signature;
entries[i] = entry;
}
diff --git a/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs b/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs
index b4e5f2868..19c00e8f5 100644
--- a/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs
+++ b/src/ImageSharp/MetaData/Profiles/ICC/IccWriter.cs
@@ -5,6 +5,7 @@
namespace ImageSharp
{
+ using System;
using System.Collections.Generic;
using System.Linq;
@@ -76,30 +77,18 @@ namespace ImageSharp
private IccTagTableEntry[] WriteTagData(IccDataWriter writer, List entries)
{
- var inData = new List(entries);
- var dupData = new List();
-
- while (inData.Count > 0)
- {
- IccTagDataEntry[] items = inData.Where(t => inData[0].Equals(t)).ToArray();
- dupData.Add(items);
- foreach (IccTagDataEntry item in items)
- {
- inData.Remove(item);
- }
- }
-
- var table = new List();
+ IEnumerable> grouped = entries.GroupBy(t => t);
// (Header size) + (entry count) + (nr of entries) * (size of table entry)
writer.SetIndex(128 + 4 + (entries.Count * 12));
- foreach (IccTagDataEntry[] entry in dupData)
+ var table = new List();
+ foreach (IGrouping group in grouped)
{
- writer.WriteTagDataEntry(entry[0], out IccTagTableEntry tentry);
- foreach (IccTagDataEntry item in entry)
+ writer.WriteTagDataEntry(group.Key, out IccTagTableEntry tableEntry);
+ foreach (IccTagDataEntry item in group)
{
- table.Add(new IccTagTableEntry(item.TagSignature, tentry.Offset, tentry.DataSize));
+ table.Add(new IccTagTableEntry(item.TagSignature, tableEntry.Offset, tableEntry.DataSize));
}
}
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs
index 0db64c47f..34aa24fa6 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccReaderTests.cs
@@ -10,10 +10,10 @@ namespace ImageSharp.Tests.Icc
public class IccReaderTests
{
[Fact]
- public void ReadProfile()
+ public void ReadProfile_NoEntries()
{
IccReader reader = CreateReader();
-
+
IccProfile output = reader.Read(IccTestDataProfiles.Header_Random_Array);
Assert.Equal(0, output.Entries.Count);
@@ -40,6 +40,18 @@ namespace ImageSharp.Tests.Icc
Assert.Equal(header.Version, expected.Version);
}
+ [Fact]
+ public void ReadProfile_DuplicateEntry()
+ {
+ IccReader reader = CreateReader();
+
+ IccProfile output = reader.Read(IccTestDataProfiles.Profile_Random_Array);
+
+ Assert.Equal(2, output.Entries.Count);
+ Assert.True(ReferenceEquals(output.Entries[0], output.Entries[1]));
+ }
+
+
private IccReader CreateReader()
{
return new IccReader();
diff --git a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs
index 6192e6eae..7e3f8c0c9 100644
--- a/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs
+++ b/tests/ImageSharp.Tests/MetaData/Profiles/ICC/IccWriterTests.cs
@@ -10,7 +10,7 @@ namespace ImageSharp.Tests.Icc
public class IccWriterTests
{
[Fact]
- public void WriteProfile()
+ public void WriteProfile_NoEntries()
{
IccWriter writer = CreateWriter();
@@ -23,6 +23,16 @@ namespace ImageSharp.Tests.Icc
Assert.Equal(IccTestDataProfiles.Header_Random_Array, output);
}
+ [Fact]
+ public void WriteProfile_DuplicateEntry()
+ {
+ IccWriter writer = CreateWriter();
+
+ byte[] output = writer.Write(IccTestDataProfiles.Profile_Random_Val);
+
+ Assert.Equal(IccTestDataProfiles.Profile_Random_Array, output);
+ }
+
private IccWriter CreateWriter()
{
return new IccWriter();
diff --git a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs
index 20fff50a8..32a4a8e57 100644
--- a/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs
+++ b/tests/ImageSharp.Tests/TestDataIcc/IccTestDataProfiles.cs
@@ -10,83 +10,124 @@ namespace ImageSharp.Tests
{
internal static class IccTestDataProfiles
{
- public static readonly IccProfileHeader Header_Random_Write = new IccProfileHeader
+ public static readonly IccProfileHeader Header_Random_Write = CreateHeaderRandomValue(
+ 562, // should be overwritten
+ new IccProfileId(1, 2, 3, 4), // should be overwritten
+ "ijkl"); // should be overwritten to "acsp"
+
+ public static readonly IccProfileHeader Header_Random_Read = CreateHeaderRandomValue(132,
+#if !NETSTANDARD1_1
+ new IccProfileId(2931428592, 418415738, 3086756963, 2237536530),
+#else
+ IccProfileId.Zero,
+#endif
+ "acsp");
+
+ public static readonly byte[] Header_Random_Array = CreateHeaderRandomArray(132, 0, new byte[]
{
- Class = IccProfileClass.DisplayDevice,
- CmmType = "abcd",
- CreationDate = new DateTime(1990, 11, 26, 7, 21, 42),
- CreatorSignature = "dcba",
- DataColorSpace = IccColorSpaceType.Rgb,
- DeviceAttributes = IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.OpacityTransparent,
- DeviceManufacturer = 123456789u,
- DeviceModel = 987654321u,
- FileSignature = "ijkl", // should be overwritten to "acsp"
- Flags = IccProfileFlag.Embedded | IccProfileFlag.Independent,
- Id = new IccProfileId(1, 2, 3, 4), // should be overwritten
- PcsIlluminant = new Vector3(4, 5, 6),
- PrimaryPlatformSignature = IccPrimaryPlatformType.MicrosoftCorporation,
- ProfileConnectionSpace = IccColorSpaceType.CieXyz,
- RenderingIntent = IccRenderingIntent.AbsoluteColorimetric,
- Size = 562, // should be overwritten
- Version = new Version(4, 3, 0),
- };
+#if !NETSTANDARD1_1
+ 0xAE, 0xBA, 0x0C, 0xF0, 0x18, 0xF0, 0x84, 0x7A, 0xB7, 0xFC, 0x2C, 0x63, 0x85, 0x5E, 0x19, 0x12,
+#else
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+#endif
+ });
- public static readonly IccProfileHeader Header_Random_Read = new IccProfileHeader
+ public static IccProfileHeader CreateHeaderRandomValue(uint size, IccProfileId id, string fileSignature)
{
- Class = IccProfileClass.DisplayDevice,
- CmmType = "abcd",
- CreationDate = new DateTime(1990, 11, 26, 7, 21, 42),
- CreatorSignature = "dcba",
- DataColorSpace = IccColorSpaceType.Rgb,
- DeviceAttributes = IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.OpacityTransparent,
- DeviceManufacturer = 123456789u,
- DeviceModel = 987654321u,
- FileSignature = "acsp",
- Flags = IccProfileFlag.Embedded | IccProfileFlag.Independent,
+ return new IccProfileHeader
+ {
+ Class = IccProfileClass.DisplayDevice,
+ CmmType = "abcd",
+ CreationDate = new DateTime(1990, 11, 26, 7, 21, 42),
+ CreatorSignature = "dcba",
+ DataColorSpace = IccColorSpaceType.Rgb,
+ DeviceAttributes = IccDeviceAttribute.ChromaBlackWhite | IccDeviceAttribute.OpacityTransparent,
+ DeviceManufacturer = 123456789u,
+ DeviceModel = 987654321u,
+ FileSignature = "acsp",
+ Flags = IccProfileFlag.Embedded | IccProfileFlag.Independent,
#if !NETSTANDARD1_1
- Id = new IccProfileId(2931428592, 418415738, 3086756963, 2237536530),
+ Id = new IccProfileId(2931428592, 418415738, 3086756963, 2237536530),
#else
Id = IccProfileId.Zero,
#endif
- PcsIlluminant = new Vector3(4, 5, 6),
- PrimaryPlatformSignature = IccPrimaryPlatformType.MicrosoftCorporation,
- ProfileConnectionSpace = IccColorSpaceType.CieXyz,
- RenderingIntent = IccRenderingIntent.AbsoluteColorimetric,
- Size = 132,
- Version = new Version(4, 3, 0),
- };
+ PcsIlluminant = new Vector3(4, 5, 6),
+ PrimaryPlatformSignature = IccPrimaryPlatformType.MicrosoftCorporation,
+ ProfileConnectionSpace = IccColorSpaceType.CieXyz,
+ RenderingIntent = IccRenderingIntent.AbsoluteColorimetric,
+ Size = size,
+ Version = new Version(4, 3, 0),
+ };
+ }
- public static readonly byte[] Header_Random_Array =
+ public static byte[] CreateHeaderRandomArray(uint size, uint nrOfEntries, byte[] profileId)
{
- 0x00, 0x00, 0x00, 0x84, // Size (132)
- 0x61, 0x62, 0x63, 0x64, // CmmType
- 0x04, 0x30, 0x00, 0x00, // Version
- 0x6D, 0x6E, 0x74, 0x72, // Class
- 0x52, 0x47, 0x42, 0x20, // DataColorSpace
- 0x58, 0x59, 0x5A, 0x20, // ProfileConnectionSpace
- 0x07, 0xC6, 0x00, 0x0B, 0x00, 0x1A, 0x00, 0x07, 0x00, 0x15, 0x00, 0x2A, // CreationDate
- 0x61, 0x63, 0x73, 0x70, // FileSignature
- 0x4D, 0x53, 0x46, 0x54, // PrimaryPlatformSignature
- 0x00, 0x00, 0x00, 0x01, // Flags
- 0x07, 0x5B, 0xCD, 0x15, // DeviceManufacturer
- 0x3A, 0xDE, 0x68, 0xB1, // DeviceModel
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, // DeviceAttributes
- 0x00, 0x00, 0x00, 0x03, // RenderingIntent
- 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, // PcsIlluminant
- 0x64, 0x63, 0x62, 0x61, // CreatorSignature
+ return ArrayHelper.Concat(
+ new byte[]
+ {
+ (byte)(size >> 24), (byte)(size >> 16), (byte)(size >> 8), (byte)size, // Size
+ 0x61, 0x62, 0x63, 0x64, // CmmType
+ 0x04, 0x30, 0x00, 0x00, // Version
+ 0x6D, 0x6E, 0x74, 0x72, // Class
+ 0x52, 0x47, 0x42, 0x20, // DataColorSpace
+ 0x58, 0x59, 0x5A, 0x20, // ProfileConnectionSpace
+ 0x07, 0xC6, 0x00, 0x0B, 0x00, 0x1A, 0x00, 0x07, 0x00, 0x15, 0x00, 0x2A, // CreationDate
+ 0x61, 0x63, 0x73, 0x70, // FileSignature
+ 0x4D, 0x53, 0x46, 0x54, // PrimaryPlatformSignature
+ 0x00, 0x00, 0x00, 0x01, // Flags
+ 0x07, 0x5B, 0xCD, 0x15, // DeviceManufacturer
+ 0x3A, 0xDE, 0x68, 0xB1, // DeviceModel
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, // DeviceAttributes
+ 0x00, 0x00, 0x00, 0x03, // RenderingIntent
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, // PcsIlluminant
+ 0x64, 0x63, 0x62, 0x61, // CreatorSignature
+ },
+ profileId,
+ new byte[]
+ {
+ // Padding
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ // Nr of tag table entries (0)
+ (byte)(nrOfEntries >> 24), (byte)(nrOfEntries >> 16), (byte)(nrOfEntries >> 8), (byte)nrOfEntries
+ });
+ }
+
+ public static byte[] Profile_Random_Array = ArrayHelper.Concat(CreateHeaderRandomArray(168, 2, new byte[]
+ {
+#if !NETSTANDARD1_1
+ 0xA9, 0x71, 0x8F, 0xC1, 0x1E, 0x2D, 0x64, 0x1B, 0x10, 0xF4, 0x7D, 0x6A, 0x5B, 0xF6, 0xAC, 0xB9
+#else
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+#endif
+ }),
+ new byte[]
+ {
+ 0x00, 0x00, 0x00, 0x00, // tag signature (Unknown)
+ 0x00, 0x00, 0x00, 0x9C, // tag offset (156)
+ 0x00, 0x00, 0x00, 0x0C, // tag size (12)
+
+ 0x00, 0x00, 0x00, 0x00, // tag signature (Unknown)
+ 0x00, 0x00, 0x00, 0x9C, // tag offset (156)
+ 0x00, 0x00, 0x00, 0x0C, // tag size (12)
+ },
+ IccTestDataTagDataEntry.TagDataEntryHeader_UnknownArr,
+ IccTestDataTagDataEntry.Unknown_Arr
+ );
+ public static IccProfile Profile_Random_Val = new IccProfile(CreateHeaderRandomValue(168,
#if !NETSTANDARD1_1
- 0xAE, 0xBA, 0x0C, 0xF0, 0x18, 0xF0, 0x84, 0x7A, 0xB7, 0xFC, 0x2C, 0x63, 0x85, 0x5E, 0x19, 0x12, // Id
+ new IccProfileId(0xA9718FC1, 0x1E2D641B, 0x10F47D6A, 0x5BF6ACB9),
#else
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Id
+ IccProfileId.Zero,
#endif
- // Padding
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- // Nr of tag table entries (0)
- 0x00, 0x00, 0x00, 0x00,
- };
+ "acsp"),
+ new IccTagDataEntry[]
+ {
+ IccTestDataTagDataEntry.Unknown_Val,
+ IccTestDataTagDataEntry.Unknown_Val
+ });
}
}