// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // using System; using System.Buffers; using System.Runtime.CompilerServices; namespace ImageSharp.Formats { /// /// Represents an 8x8 block of coefficients to transform and encode. /// internal struct Block : IDisposable { private static readonly ArrayPool ArrayPool = ArrayPool.Create(BlockSize, 50); /// /// Gets the size of the block. /// public const int BlockSize = 64; /// /// The array of block data. /// public int[] Data; /// /// Initializes a new instance of the class. /// //public Block() //{ // this.data = new int[BlockSize]; //} public void Init() { //this.Data = new int[BlockSize]; this.Data = ArrayPool.Rent(BlockSize); } public static Block Create() { var block = new Block(); block.Init(); return block; } public static Block[] CreateArray(int size) { Block[] result = new Block[size]; for (int i = 0; i < result.Length; i++) { result[i].Init(); } return result; } public bool IsInitialized => this.Data != null; /// /// Gets the pixel data at the given block index. /// /// The index of the data to return. /// /// The . /// public int this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return this.Data[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { this.Data[index] = value; } } // TODO: Refactor Block.Dispose() callers to always use 'using' or 'finally' statement! public void Dispose() { if (Data != null) { ArrayPool.Return(Data, true); Data = null; } } public static void DisposeAll(Block[] blocks) { for (int i = 0; i < blocks.Length; i++) { blocks[i].Dispose(); } } public void Clear() { for (int i = 0; i < Data.Length; i++) { Data[i] = 0; } } public Block Clone() { Block clone = Create(); Array.Copy(Data, clone.Data, BlockSize); return clone; } } /// /// Temporal class to make refactoring easier. /// 1. Refactor Block -> BlockF /// 2. Test /// 3. Refactor BlockF -> Block8x8F /// internal struct BlockF : IDisposable { private static readonly ArrayPool ArrayPool = ArrayPool.Create(BlockSize, 50); /// /// Gets the size of the block. /// public const int BlockSize = 64; /// /// The array of block data. /// public float[] Data; /// /// Initializes a new instance of the class. /// //public Block() //{ // this.data = new int[BlockSize]; //} public void Init() { //this.Data = new int[BlockSize]; this.Data = ArrayPool.Rent(BlockSize); } public static BlockF Create() { var block = new BlockF(); block.Init(); return block; } public static BlockF[] CreateArray(int size) { BlockF[] result = new BlockF[size]; for (int i = 0; i < result.Length; i++) { result[i].Init(); } return result; } public bool IsInitialized => this.Data != null; /// /// Gets the pixel data at the given block index. /// /// The index of the data to return. /// /// The . /// public float this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return this.Data[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { this.Data[index] = value; } } // TODO: Refactor Block.Dispose() callers to always use 'using' or 'finally' statement! public void Dispose() { if (Data != null) { ArrayPool.Return(Data, true); Data = null; } } public static void DisposeAll(BlockF[] blocks) { for (int i = 0; i < blocks.Length; i++) { blocks[i].Dispose(); } } public void Clear() { for (int i = 0; i < Data.Length; i++) { Data[i] = 0; } } public BlockF Clone() { BlockF clone = Create(); Array.Copy(Data, clone.Data, BlockSize); return clone; } } }