/// <summary>
        /// Reads a profile description
        /// </summary>
        /// <returns>the profile description</returns>
        public IccProfileDescription ReadProfileDescription()
        {
            uint manufacturer   = this.ReadUInt32();
            uint model          = this.ReadUInt32();
            var  attributes     = (IccDeviceAttribute)this.ReadInt64();
            var  technologyInfo = (IccProfileTag)this.ReadUInt32();

            IccMultiLocalizedUnicodeTagDataEntry manufacturerInfo = ReadText();
            IccMultiLocalizedUnicodeTagDataEntry modelInfo        = ReadText();

            return(new IccProfileDescription(
                       manufacturer,
                       model,
                       attributes,
                       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");
                }
            }
        }
        /// <summary>
        /// Writes a <see cref="IccMultiLocalizedUnicodeTagDataEntry"/>
        /// </summary>
        /// <param name="value">The entry to write</param>
        /// <returns>The number of bytes written</returns>
        public int WriteMultiLocalizedUnicodeTagDataEntry(IccMultiLocalizedUnicodeTagDataEntry value)
        {
            long start = this.dataStream.Position - 8;  // 8 is the tag header size

            int cultureCount = value.Texts.Length;

            int count = this.WriteUInt32((uint)cultureCount);

            count += this.WriteUInt32(12);  // One record has always 12 bytes size

            // Jump over position table
            long tpos = this.dataStream.Position;

            this.dataStream.Position += cultureCount * 12;

            IGrouping <string, IccLocalizedString>[] 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 < texts.Length; i++)
            {
                offset[i] = (uint)(this.dataStream.Position - start);
                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 < texts.Length; 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;
            return(count);
        }
        /// <summary>
        /// Reads a <see cref="IccProfileSequenceIdentifierTagDataEntry"/>
        /// </summary>
        /// <returns>The read entry</returns>
        public IccProfileSequenceIdentifierTagDataEntry ReadProfileSequenceIdentifierTagDataEntry()
        {
            int  start = this.currentIndex - 8; // 8 is the tag header size
            uint count = this.ReadUInt32();

            IccPositionNumber[] table = new IccPositionNumber[count];
            for (int i = 0; i < count; i++)
            {
                table[i] = this.ReadPositionNumber();
            }

            IccProfileSequenceIdentifier[] entries = new IccProfileSequenceIdentifier[count];
            for (int i = 0; i < count; i++)
            {
                this.currentIndex = (int)(start + table[i].Offset);
                IccProfileId id = this.ReadProfileId();
                this.ReadCheckTagDataEntryHeader(IccTypeSignature.MultiLocalizedUnicode);
                IccMultiLocalizedUnicodeTagDataEntry description = this.ReadMultiLocalizedUnicodeTagDataEntry();
                entries[i] = new IccProfileSequenceIdentifier(id, description.Texts);
            }

            return(new IccProfileSequenceIdentifierTagDataEntry(entries));
        }