diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlock.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlock.cs new file mode 100644 index 0000000000..bc93a18f7c --- /dev/null +++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlock.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats.Jpg +{ + using System; + + /// + /// A structure to store unprocessed instances and their coordinates while scanning the image. + /// The is present in a "raw" decoded frequency-domain form. + /// We need to apply IDCT and unzigging to transform them into color-space blocks. + /// + internal struct DecodedBlock + { + /// + /// A value indicating whether the instance is initialized. + /// + public bool Initialized; + + /// + /// X coordinate of the current block, in units of 8x8. (The third block in the first row has (bx, by) = (2, 0)) + /// + public int Bx; + + /// + /// Y coordinate of the current block, in units of 8x8. (The third block in the first row has (bx, by) = (2, 0)) + /// + public int By; + + /// + /// The + /// + public Block8x8F Block; + + /// + /// Store the block data into a at the given index of an . + /// + /// The array + /// The index in the array + /// X coordinate of the block + /// Y coordinate of the block + /// The + public static void Store(ref DecodedBlockArray blockArray, int index, int bx, int by, ref Block8x8F block) + { + if (index >= blockArray.Count) + { + throw new IndexOutOfRangeException("Block index is out of range in DecodedBlock.Store()!"); + } + + blockArray.Buffer[index].Initialized = true; + blockArray.Buffer[index].Bx = bx; + blockArray.Buffer[index].By = by; + blockArray.Buffer[index].Block = block; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockArray.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockArray.cs new file mode 100644 index 0000000000..97a79dd61b --- /dev/null +++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockArray.cs @@ -0,0 +1,55 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageSharp.Formats.Jpg +{ + using System; + using System.Buffers; + + /// + /// Because has no information for rented arrays, + /// we need to store the count and the buffer separately when storing pooled arrays. + /// + internal struct DecodedBlockArray : IDisposable + { + /// + /// The used to pool data in . + /// Should always clean arrays when returning! + /// + private static readonly ArrayPool ArrayPool = ArrayPool.Create(); + + /// + /// Initializes a new instance of the struct. Rents a buffer. + /// + /// The number of valid -s + public DecodedBlockArray(int count) + { + this.Count = count; + this.Buffer = ArrayPool.Rent(count); + } + + /// + /// Gets the number of actual -s inside + /// + public int Count { get; } + + /// + /// Gets the rented buffer. + /// + public DecodedBlock[] Buffer { get; private set; } + + /// + /// Returns the rented buffer to the pool. + /// + public void Dispose() + { + if (this.Buffer != null) + { + ArrayPool.Return(this.Buffer, true); + this.Buffer = null; + } + } + } +} \ No newline at end of file diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockMemento.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockMemento.cs deleted file mode 100644 index 04ece04ee8..0000000000 --- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockMemento.cs +++ /dev/null @@ -1,101 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// - -namespace ImageSharp.Formats.Jpg -{ - using System; - using System.Buffers; - - /// - /// A structure to store unprocessed instances and their coordinates while scanning the image. - /// - internal struct DecodedBlockMemento - { - /// - /// A value indicating whether the instance is initialized. - /// - public bool Initialized; - - /// - /// X coordinate of the current block, in units of 8x8. (The third block in the first row has (bx, by) = (2, 0)) - /// - public int Bx; - - /// - /// Y coordinate of the current block, in units of 8x8. (The third block in the first row has (bx, by) = (2, 0)) - /// - public int By; - - /// - /// The - /// - public Block8x8F Block; - - /// - /// Store the block data into a at the given index of an . - /// - /// The array - /// The index in the array - /// X coordinate of the block - /// Y coordinate of the block - /// The - public static void Store(ref DecodedBlockMemento.Array blockArray, int index, int bx, int by, ref Block8x8F block) - { - if (index >= blockArray.Count) - { - throw new IndexOutOfRangeException("Block index is out of range in DecodedBlockMemento.Store()!"); - } - - blockArray.Buffer[index].Initialized = true; - blockArray.Buffer[index].Bx = bx; - blockArray.Buffer[index].By = by; - blockArray.Buffer[index].Block = block; - } - - /// - /// Because has no information for rented arrays, we need to store the count and the buffer separately. - /// - public struct Array : IDisposable - { - /// - /// The used to pool data in . - /// Should always clean arrays when returning! - /// - private static readonly ArrayPool ArrayPool = ArrayPool.Create(); - - /// - /// Initializes a new instance of the struct. Rents a buffer. - /// - /// The number of valid -s - public Array(int count) - { - this.Count = count; - this.Buffer = ArrayPool.Rent(count); - } - - /// - /// Gets the number of actual -s inside - /// - public int Count { get; } - - /// - /// Gets the rented buffer. - /// - public DecodedBlockMemento[] Buffer { get; private set; } - - /// - /// Returns the rented buffer to the pool. - /// - public void Dispose() - { - if (this.Buffer != null) - { - ArrayPool.Return(this.Buffer, true); - this.Buffer = null; - } - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs index 0e389771c0..103ee60c02 100644 --- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs +++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs @@ -121,10 +121,10 @@ namespace ImageSharp.Formats.Jpg } /// - /// Loads the data from the given into the block. + /// Loads the data from the given into the block. /// - /// The - public void LoadMemento(ref DecodedBlockMemento memento) + /// The + public void LoadMemento(ref DecodedBlock memento) { this.bx = memento.Bx; this.by = memento.By; @@ -204,8 +204,8 @@ namespace ImageSharp.Formats.Jpg } // Store the decoded block - DecodedBlockMemento.Array blocks = decoder.DecodedBlocks[this.ComponentIndex]; - DecodedBlockMemento.Store(ref blocks, blockIndex, this.bx, this.by, ref this.data.Block); + DecodedBlockArray blocks = decoder.DecodedBlocks[this.ComponentIndex]; + DecodedBlock.Store(ref blocks, blockIndex, this.bx, this.by, ref this.data.Block); } // for j diff --git a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs index eca4d46229..fd06018a22 100644 --- a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs @@ -87,7 +87,7 @@ namespace ImageSharp.Formats this.QuantizationTables = new Block8x8F[MaxTq + 1]; this.Temp = new byte[2 * Block8x8F.ScalarCount]; this.ComponentArray = new Component[MaxComponents]; - this.DecodedBlocks = new DecodedBlockMemento.Array[MaxComponents]; + this.DecodedBlocks = new DecodedBlockArray[MaxComponents]; } /// @@ -101,10 +101,12 @@ namespace ImageSharp.Formats public HuffmanTree[] HuffmanTrees { get; } /// - /// Gets the saved state between progressive-mode scans. - /// TODO: Also save non-progressive data here. (Helps splitting and parallelizing JpegScanDecoder-s loop) + /// Gets the array of -s storing the "raw" frequency-domain decoded blocks. + /// We need to apply IDCT and unzigging to transform them into color-space blocks. + /// This is done by . + /// When ==true, we are touching these blocks each time we process a Scan. /// - public DecodedBlockMemento.Array[] DecodedBlocks { get; } + public DecodedBlockArray[] DecodedBlocks { get; } /// /// Gets the quantization tables, in zigzag order. @@ -191,7 +193,7 @@ namespace ImageSharp.Formats this.HuffmanTrees[i].Dispose(); } - foreach (DecodedBlockMemento.Array blockArray in this.DecodedBlocks) + foreach (DecodedBlockArray blockArray in this.DecodedBlocks) { blockArray.Dispose(); } @@ -461,7 +463,7 @@ namespace ImageSharp.Formats /// /// Process the blocks in into Jpeg image channels ( and ) - /// The blocks are expected in a "raw" frequency-domain decoded format. We need to apply IDCT and unzigging to transform them into color-space blocks. + /// are in a "raw" frequency-domain form. We need to apply IDCT and unzigging to transform them into color-space blocks. /// We can copy these blocks into -s afterwards. /// /// The pixel type @@ -477,7 +479,7 @@ namespace ImageSharp.Formats JpegScanDecoder.Init(&scanDecoder); scanDecoder.ComponentIndex = componentIndex; - DecodedBlockMemento.Array blockArray = this.DecodedBlocks[componentIndex]; + DecodedBlockArray blockArray = this.DecodedBlocks[componentIndex]; for (int i = 0; i < blockArray.Count; i++) { scanDecoder.LoadMemento(ref blockArray.Buffer[i]); @@ -1316,7 +1318,7 @@ namespace ImageSharp.Formats { int count = this.TotalMCUCount * this.ComponentArray[i].HorizontalFactor * this.ComponentArray[i].VerticalFactor; - this.DecodedBlocks[i] = new DecodedBlockMemento.Array(count); + this.DecodedBlocks[i] = new DecodedBlockArray(count); } } }