// Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. using System; using System.Buffers.Binary; using System.Text; namespace SixLabors.ImageSharp.MetaData.Profiles.Icc { /// /// Provides methods to read ICC data types /// internal sealed partial class IccDataReader { /// /// Reads an ushort /// /// the value public ushort ReadUInt16() { return BinaryPrimitives.ReadUInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2)); } /// /// Reads a short /// /// the value public short ReadInt16() { return BinaryPrimitives.ReadInt16BigEndian(this.data.AsSpan(this.AddIndex(2), 2)); } /// /// Reads an uint /// /// the value public uint ReadUInt32() { return BinaryPrimitives.ReadUInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4)); } /// /// Reads an int /// /// the value public int ReadInt32() { return BinaryPrimitives.ReadInt32BigEndian(this.data.AsSpan(this.AddIndex(4), 4)); } /// /// Reads an ulong /// /// the value public ulong ReadUInt64() { return BinaryPrimitives.ReadUInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8)); } /// /// Reads a long /// /// the value public long ReadInt64() { return BinaryPrimitives.ReadInt64BigEndian(this.data.AsSpan(this.AddIndex(8), 8)); } /// /// Reads a float. /// /// the value public unsafe float ReadSingle() { int intValue = this.ReadInt32(); return *((float*)&intValue); } /// /// Reads a double /// /// the value public unsafe double ReadDouble() { long intValue = this.ReadInt64(); return *((double*)&intValue); } /// /// Reads an ASCII encoded string. /// /// number of bytes to read /// The value as a string public string ReadAsciiString(int length) { if (length == 0) { return string.Empty; } Guard.MustBeGreaterThan(length, 0, nameof(length)); string value = AsciiEncoding.GetString(this.data, this.AddIndex(length), length); // remove data after (potential) null terminator int pos = value.IndexOf('\0'); if (pos >= 0) { value = value.Substring(0, pos); } return value; } /// /// Reads an UTF-16 big-endian encoded string. /// /// number of bytes to read /// The value as a string public string ReadUnicodeString(int length) { if (length == 0) { return string.Empty; } Guard.MustBeGreaterThan(length, 0, nameof(length)); return Encoding.BigEndianUnicode.GetString(this.data, this.AddIndex(length), length); } /// /// Reads a signed 32bit number with 1 sign bit, 15 value bits and 16 fractional bits. /// /// The number as double public float ReadFix16() => this.ReadInt32() / 65536f; /// /// Reads an unsigned 32bit number with 16 value bits and 16 fractional bits. /// /// The number as double public float ReadUFix16() => this.ReadUInt32() / 65536f; /// /// Reads an unsigned 16bit number with 1 value bit and 15 fractional bits. /// /// The number as double public float ReadU1Fix15() => this.ReadUInt16() / 32768f; /// /// Reads an unsigned 16bit number with 8 value bits and 8 fractional bits. /// /// The number as double public float ReadUFix8() { return this.ReadUInt16() / 256f; } /// /// Reads a number of bytes and advances the index. /// /// The number of bytes to read /// The read bytes public byte[] ReadBytes(int count) { byte[] bytes = new byte[count]; Buffer.BlockCopy(this.data, this.AddIndex(count), bytes, 0, count); return bytes; } } }