Beispiel #1
0
        public void Test_ReadOnlyMemory2DT_Slice_2()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            ReadOnlyMemory2D <int> slice1 = memory2d.Slice(0, 0, 2, 2);

            Assert.AreEqual(slice1.Length, 4);
            Assert.AreEqual(slice1.Height, 2);
            Assert.AreEqual(slice1.Width, 2);
            Assert.AreEqual(slice1.Span[0, 0], 1);
            Assert.AreEqual(slice1.Span[1, 1], 5);

            ReadOnlyMemory2D <int> slice2 = slice1.Slice(1, 0, 1, 2);

            Assert.AreEqual(slice2.Length, 2);
            Assert.AreEqual(slice2.Height, 1);
            Assert.AreEqual(slice2.Width, 2);
            Assert.AreEqual(slice2.Span[0, 0], 4);
            Assert.AreEqual(slice2.Span[0, 1], 5);

            ReadOnlyMemory2D <int> slice3 = slice2.Slice(0, 1, 1, 1);

            Assert.AreEqual(slice3.Length, 1);
            Assert.AreEqual(slice3.Height, 1);
            Assert.AreEqual(slice3.Width, 1);
            Assert.AreEqual(slice3.Span[0, 0], 5);
        }
Beispiel #2
0
        public void Test_ReadOnlyMemory2DT_Array1DConstructor()
        {
            int[] array =
            {
                1, 2, 3, 4, 5, 6
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array, 1, 2, 2, 1);

            Assert.IsFalse(memory2d.IsEmpty);
            Assert.AreEqual(memory2d.Length, 4);
            Assert.AreEqual(memory2d.Width, 2);
            Assert.AreEqual(memory2d.Height, 2);
            Assert.AreEqual(memory2d.Span[0, 0], 2);
            Assert.AreEqual(memory2d.Span[1, 1], 6);

            // Here we check to ensure a covariant array conversion is allowed for ReadOnlyMemory2D<T>
            _ = new ReadOnlyMemory2D <object>(new string[1], 1, 1);

            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, -99, 1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 0, -10, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 0, 1, 1, -1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 0, 1, -100, 1));
            Assert.ThrowsException <ArgumentException>(() => new ReadOnlyMemory2D <int>(array, 0, 2, 4, 0));
            Assert.ThrowsException <ArgumentException>(() => new ReadOnlyMemory2D <int>(array, 0, 3, 3, 0));
            Assert.ThrowsException <ArgumentException>(() => new ReadOnlyMemory2D <int>(array, 1, 2, 3, 0));
            Assert.ThrowsException <ArgumentException>(() => new ReadOnlyMemory2D <int>(array, 0, 10, 1, 120));
        }
Beispiel #3
0
        public void Test_ReadOnlyMemory2DT_ReadOnlyMemoryConstructor()
        {
            ReadOnlyMemory <int> memory = new[]
            {
                1, 2, 3, 4, 5, 6
            };

            ReadOnlyMemory2D <int> memory2d = memory.AsMemory2D(1, 2, 2, 1);

            Assert.IsFalse(memory2d.IsEmpty);
            Assert.AreEqual(memory2d.Length, 4);
            Assert.AreEqual(memory2d.Width, 2);
            Assert.AreEqual(memory2d.Height, 2);
            Assert.AreEqual(memory2d.Span[0, 0], 2);
            Assert.AreEqual(memory2d.Span[1, 1], 6);

            Assert.ThrowsException <ArgumentOutOfRangeException>(() => memory.AsMemory2D(-99, 1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => memory.AsMemory2D(0, -10, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => memory.AsMemory2D(0, 1, 1, -1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => memory.AsMemory2D(0, 1, -100, 1));
            Assert.ThrowsException <ArgumentException>(() => memory.AsMemory2D(0, 2, 4, 0));
            Assert.ThrowsException <ArgumentException>(() => memory.AsMemory2D(0, 3, 3, 0));
            Assert.ThrowsException <ArgumentException>(() => memory.AsMemory2D(1, 2, 3, 0));
            Assert.ThrowsException <ArgumentException>(() => memory.AsMemory2D(0, 10, 1, 120));
        }
Beispiel #4
0
        public void Test_ReadOnlyMemory2DT_Array3DConstructor_2()
        {
            int[,,] array =
            {
                {
                    {  1,  2,  3 },
                    {  4,  5,  6 }
                },
                {
                    { 10, 20, 30 },
                    { 40, 50, 60 }
                }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array, 1, 0, 1, 2, 2);

            Assert.IsFalse(memory2d.IsEmpty);
            Assert.AreEqual(memory2d.Length, 4);
            Assert.AreEqual(memory2d.Width, 2);
            Assert.AreEqual(memory2d.Height, 2);
            Assert.AreEqual(memory2d.Span[0, 0], 20);
            Assert.AreEqual(memory2d.Span[1, 1], 60);

            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, -1, 1, 1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 1, -1, 1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 1, 1, -1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 1, 1, 1, -1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 1, 1, 1, 1, -1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 2, 0, 0, 2, 3));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 0, 0, 1, 2, 3));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 0, 0, 0, 2, 4));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array, 0, 0, 0, 3, 3));
        }
Beispiel #5
0
        public NaiveHPQuadtree(ReadOnlyMemory2D <byte> data)
        {
            Debug.Assert(CeilToNextPowerOfTwo(data.Height) == data.Height);
            Debug.Assert(CeilToNextPowerOfTwo(data.Width) == data.Width);
            Debug.Assert(data.Width == data.Height);

            Data = data;
            if (data.Length == 1)
            {
                _leafs = default;
                return;
            }

            var span  = data.Span;
            var start = span[0, 0];

            foreach (var val in span)
            {
                if (val == start)
                {
                    continue;
                }

                // split
                var halfWidth  = Data.Width / 2;
                var halfHeight = Data.Height / 2;
                var width      = Data.Width;
                var height     = Data.Height;
                _leafs = new[]
            static GoodHPQuadtree[] Split(ReadOnlyMemory2D <byte> data)
            {
                var halfWidth  = data.Width / 2;
                var halfHeight = data.Height / 2;
                var width      = data.Width;
                var height     = data.Height;

                return(new[]
Beispiel #7
0
        public unsafe void Test_ReadOnlyMemory2DT_Pin_2()
        {
            int[] array = { 1, 2, 3, 4 };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array, 2, 2);

            using var pin = memory2d.Pin();

            Assert.AreEqual(((int *)pin.Pointer)[0], 1);
            Assert.AreEqual(((int *)pin.Pointer)[3], 4);
        }
Beispiel #8
0
        public void Test_ReadOnlyMemory2DT_TryGetReadOnlyMemory_2()
        {
            int[] array = { 1, 2, 3, 4 };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array, 2, 2);

            bool success = memory2d.TryGetMemory(out ReadOnlyMemory <int> memory);

            Assert.IsTrue(success);
            Assert.AreEqual(memory.Length, array.Length);
            Assert.AreEqual(memory.Span[2], 3);
        }
        public GoodHPQuadtree(ReadOnlyMemory2D <byte> data)
        {
            Debug.Assert(CeilToNextPowerOfTwo(data.Height) == data.Height);
            Debug.Assert(CeilToNextPowerOfTwo(data.Width) == data.Width);
            Debug.Assert(data.Width == data.Height);

            Data = data;
            if (data.Length == (nint)1)
            {
                _leafs = default;
                return;
            }
Beispiel #10
0
        public void Test_ReadOnlyMemory2DT_TryGetReadOnlyMemory_3()
        {
            ReadOnlyMemory <int> data = new[] { 1, 2, 3, 4 };

            ReadOnlyMemory2D <int> memory2d = data.AsMemory2D(2, 2);

            bool success = memory2d.TryGetMemory(out ReadOnlyMemory <int> memory);

            Assert.IsTrue(success);
            Assert.AreEqual(memory.Length, data.Length);
            Assert.AreEqual(memory.Span[2], 3);
        }
Beispiel #11
0
        public void Test_ReadOnlyMemory2DT_Empty()
        {
            ReadOnlyMemory2D <int> empty1 = default;

            Assert.IsTrue(empty1.IsEmpty);
            Assert.AreEqual(empty1.Length, 0);
            Assert.AreEqual(empty1.Width, 0);
            Assert.AreEqual(empty1.Height, 0);

            ReadOnlyMemory2D <string> empty2 = ReadOnlyMemory2D <string> .Empty;

            Assert.IsTrue(empty2.IsEmpty);
            Assert.AreEqual(empty2.Length, 0);
            Assert.AreEqual(empty2.Width, 0);
            Assert.AreEqual(empty2.Height, 0);
        }
Beispiel #12
0
        public void Test_ReadOnlyMemory2DT_ToString()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            string text = memory2d.ToString();

            const string expected = "Microsoft.Toolkit.HighPerformance.Memory.ReadOnlyMemory2D<System.Int32>[2, 3]";

            Assert.AreEqual(text, expected);
        }
Beispiel #13
0
        public void Test_ReadOnlyMemory2DT_ToArray_1()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            int[,] copy = memory2d.ToArray();

            Assert.AreEqual(copy.GetLength(0), array.GetLength(0));
            Assert.AreEqual(copy.GetLength(1), array.GetLength(1));

            CollectionAssert.AreEqual(array, copy);
        }
Beispiel #14
0
        public void Test_ReadOnlyMemory2DT_Array2DConstructor_1()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            Assert.IsFalse(memory2d.IsEmpty);
            Assert.AreEqual(memory2d.Length, 6);
            Assert.AreEqual(memory2d.Width, 3);
            Assert.AreEqual(memory2d.Height, 2);
            Assert.AreEqual(memory2d.Span[0, 1], 2);
            Assert.AreEqual(memory2d.Span[1, 2], 6);

            _ = new ReadOnlyMemory2D <object>(new string[1, 2]);
        }
Beispiel #15
0
        public void Test_ReadOnlyMemory2DT_GetHashCode()
        {
            Assert.AreEqual(ReadOnlyMemory2D <int> .Empty.GetHashCode(), 0);

            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            int a = memory2d.GetHashCode(), b = memory2d.GetHashCode();

            Assert.AreEqual(a, b);

            int c = new ReadOnlyMemory2D <int>(array, 0, 1, 2, 2).GetHashCode();

            Assert.AreNotEqual(a, c);
        }
Beispiel #16
0
        public void Test_ReadOnlyMemory2DT_Equals()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> readOnlyMemory2D = new ReadOnlyMemory2D <int>(array);

            Assert.IsFalse(readOnlyMemory2D.Equals(null));
            Assert.IsFalse(readOnlyMemory2D.Equals(new ReadOnlyMemory2D <int>(array, 0, 1, 2, 2)));
            Assert.IsTrue(readOnlyMemory2D.Equals(new ReadOnlyMemory2D <int>(array)));
            Assert.IsTrue(readOnlyMemory2D.Equals(readOnlyMemory2D));

            Memory2D <int> memory2d = array;

            Assert.IsTrue(readOnlyMemory2D.Equals((object)memory2d));
            Assert.IsFalse(readOnlyMemory2D.Equals((object)memory2d.Slice(0, 1, 2, 2)));
        }
Beispiel #17
0
        public void Test_ReadOnlyMemory2DT_Array2DConstructor_2()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array, 0, 1, 2, 2);

            Assert.IsFalse(memory2d.IsEmpty);
            Assert.AreEqual(memory2d.Length, 4);
            Assert.AreEqual(memory2d.Width, 2);
            Assert.AreEqual(memory2d.Height, 2);
            Assert.AreEqual(memory2d.Span[0, 0], 2);
            Assert.AreEqual(memory2d.Span[1, 1], 6);

            _ = new ReadOnlyMemory2D <object>(new string[1, 2]);

            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <object>(new string[1, 2], 0, 0, 2, 2));
        }
Beispiel #18
0
        public void Test_ReadOnlyMemory2DT_TryGetReadOnlyMemory_1()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            bool success = memory2d.TryGetMemory(out ReadOnlyMemory <int> memory);

#if WINDOWS_UWP
            Assert.IsFalse(success);
            Assert.IsTrue(memory.IsEmpty);
#else
            Assert.IsTrue(success);
            Assert.AreEqual(memory.Length, array.Length);
            Assert.IsTrue(Unsafe.AreSame(ref array[0, 0], ref Unsafe.AsRef(memory.Span[0])));
#endif
        }
Beispiel #19
0
        public void Test_ReadOnlyMemory2DT_Slice_1()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array);

            ReadOnlyMemory2D <int> slice1 = memory2d.Slice(1, 1, 1, 2);

            Assert.AreEqual(slice1.Length, 2);
            Assert.AreEqual(slice1.Height, 1);
            Assert.AreEqual(slice1.Width, 2);
            Assert.AreEqual(slice1.Span[0, 0], 5);
            Assert.AreEqual(slice1.Span[0, 1], 6);

            ReadOnlyMemory2D <int> slice2 = memory2d.Slice(0, 1, 2, 2);

            Assert.AreEqual(slice2.Length, 4);
            Assert.AreEqual(slice2.Height, 2);
            Assert.AreEqual(slice2.Width, 2);
            Assert.AreEqual(slice2.Span[0, 0], 2);
            Assert.AreEqual(slice2.Span[1, 0], 5);
            Assert.AreEqual(slice2.Span[1, 1], 6);

            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(-1, 1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(1, -1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(1, 1, 1, -1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(1, 1, -1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(10, 1, 1, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(1, 12, 1, 12));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(1, 1, 55, 1));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(0, 0, 2, 4));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(0, 0, 3, 3));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(0, 1, 2, 3));
            Assert.ThrowsException <ArgumentOutOfRangeException>(() => new ReadOnlyMemory2D <int>(array).Slice(1, 0, 2, 3));
        }
Beispiel #20
0
        public void Test_Memory2DT_Equals()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            // Here we want to verify that the Memory2D<T>.Equals method works correctly. This is true
            // when the wrapped instance is the same, and the various internal offsets and sizes match.
            Memory2D <int> memory2d = new Memory2D <int>(array);

            Assert.IsFalse(memory2d.Equals(null));
            Assert.IsFalse(memory2d.Equals(new Memory2D <int>(array, 0, 1, 2, 2)));
            Assert.IsTrue(memory2d.Equals(new Memory2D <int>(array)));
            Assert.IsTrue(memory2d.Equals(memory2d));

            // This should work also when casting to a ReadOnlyMemory2D<T> instance
            ReadOnlyMemory2D <int> readOnlyMemory2d = memory2d;

            Assert.IsTrue(memory2d.Equals(readOnlyMemory2d));
            Assert.IsFalse(memory2d.Equals(readOnlyMemory2d.Slice(0, 1, 2, 2)));
        }
Beispiel #21
0
        public void Test_ReadOnlyMemory2DT_ToArray_2()
        {
            int[,] array =
            {
                { 1, 2, 3 },
                { 4, 5, 6 }
            };

            ReadOnlyMemory2D <int> memory2d = new ReadOnlyMemory2D <int>(array, 0, 0, 2, 2);

            int[,] copy = memory2d.ToArray();

            Assert.AreEqual(copy.GetLength(0), 2);
            Assert.AreEqual(copy.GetLength(1), 2);

            int[,] expected =
            {
                { 1, 2 },
                { 4, 5 }
            };

            CollectionAssert.AreEqual(expected, copy);
        }
Beispiel #22
0
 /// <summary>
 /// Executes a specified action in an optimized parallel loop over the input data.
 /// </summary>
 /// <typeparam name="TItem">The type of items to iterate over.</typeparam>
 /// <typeparam name="TAction">The type of action (implementing <see cref="IInAction{T}"/> of <typeparamref name="TItem"/>) to invoke over each item.</typeparam>
 /// <param name="memory">The input <see cref="ReadOnlyMemory2D{T}"/> representing the data to process.</param>
 /// <param name="action">The <typeparamref name="TAction"/> instance representing the action to invoke.</param>
 /// <param name="minimumActionsPerThread">
 /// The minimum number of actions to run per individual thread. Set to 1 if all invocations
 /// should be parallelized, or to a greater number if each individual invocation is fast
 /// enough that it is more efficient to set a lower bound per each running thread.
 /// </param>
 public static void ForEach <TItem, TAction>(ReadOnlyMemory2D <TItem> memory, in TAction action, int minimumActionsPerThread)
Beispiel #23
0
 public static void ForEach <TItem, TAction>(ReadOnlyMemory2D <TItem> memory, in TAction action)
Beispiel #24
0
 public static void ForEach <TItem, TAction>(ReadOnlyMemory2D <TItem> memory, int minimumActionsPerThread)
     where TAction : struct, IInAction <TItem>
 {
     ForEach(memory, default(TAction), minimumActionsPerThread);
 }
Beispiel #25
0
 public static void ForEach <TItem, TAction>(ReadOnlyMemory2D <TItem> memory)
     where TAction : struct, IInAction <TItem>
 {
     ForEach(memory, default(TAction), 1);
 }
            static BetterHPQuadtree[] Split(ReadOnlyMemory2D <byte> data)
            {
                var halfWidth  = data.Width / 2;
                var halfHeight = data.Height / 2;

                return(new[]
 /// <summary>
 /// Initializes a new instance of the <see cref="MemoryDebugView2D{T}"/> class with the specified parameters.
 /// </summary>
 /// <param name="memory">The input <see cref="ReadOnlyMemory2D{T}"/> instance with the items to display.</param>
 public MemoryDebugView2D(ReadOnlyMemory2D <T> memory)
 {
     this.Items = memory.ToArray();
 }
Beispiel #28
0
        public static void WritePAA(BinaryWriterEx writer, ReadOnlyMemory2D <ColorRgba32> image, ColorRgba32 max, ColorRgba32 avg, PAAType type = PAAType.DXT5, PAAFlags flags = PAAFlags.InterpolatedAlpha)
        {
            if (type != PAAType.DXT5 && type != PAAType.DXT1)
            {
                throw new NotSupportedException();
            }

            var enc = new BCnEncoder.Encoder.BcEncoder(type == PAAType.DXT5 ? CompressionFormat.Bc3 : CompressionFormat.Bc1);

            var mipmaps = new List <MipmapEncoder>();

            var width  = image.Width;
            var height = image.Width;
            var offset = type == PAAType.DXT5 ? 128 : 112;

            foreach (var mipmap in enc.EncodeToRawBytes(image))
            {
                if (width > 2 || height > 2)
                {
                    var menc = new MipmapEncoder(mipmap, width, height, offset);
                    offset += menc.MipmapEntrySize;
                    mipmaps.Add(menc);
                    width  = width / 2;
                    height = height / 2;
                }
            }

            writer.Write(type == PAAType.DXT5 ? (ushort)0xff05 : (ushort)0xff01);

            writer.WriteAscii("GGATCGVA", 8);
            writer.Write((uint)4);
            writer.Write(avg.r);
            writer.Write(avg.g);
            writer.Write(avg.b);
            writer.Write(avg.a);

            writer.WriteAscii("GGATCXAM", 8);
            writer.Write((uint)4);
            writer.Write(max.r);
            writer.Write(max.g);
            writer.Write(max.b);
            writer.Write(max.a);

            if (type == PAAType.DXT5)
            {
                writer.WriteAscii("GGATGALF", 8);
                writer.Write((uint)4);
                writer.Write((uint)flags);
            }

            writer.WriteAscii("GGATSFFO", 8);
            writer.Write(16 * 4);
            for (int i = 0; i < 16; ++i)
            {
                if (i < mipmaps.Count)
                {
                    writer.Write((uint)mipmaps[i].Offset);
                }
                else
                {
                    writer.Write((uint)0);
                }
            }

            writer.Write((ushort)0x0000);

            int index = 0;

            foreach (var mipmap in mipmaps)
            {
                if (writer.Position != mipmap.Offset)
                {
                    throw new Exception($"Wrong offset @{mipmap.Width} : {writer.Position} != { mipmap.Offset}");
                }
                writer.Write(mipmap.WidthEncoded);
                writer.Write(mipmap.Height);
                writer.WriteUInt24((uint)mipmap.PaaData.Length);
                writer.Write(mipmap.PaaData);
                index++;
                width  = width / 2;
                height = height / 2;
            }
            writer.Write((uint)0x0000);
            writer.Write((ushort)0x0000);
        }