Browse Source

Remove DecodedBlockArray and replace usages with Buffer<DecodedBlock> to centralize memory management.

af/merge-core
Mykhailo Matviiv 9 years ago
parent
commit
a8481c80fb
  1. 55
      src/ImageSharp/Formats/Jpeg/Components/Decoder/DecodedBlockArray.cs
  2. 8
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockProcessor.cs
  3. 6
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegScanDecoder.cs
  4. 12
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

55
src/ImageSharp/Formats/Jpeg/Components/Decoder/DecodedBlockArray.cs

@ -1,55 +0,0 @@
// <copyright file="DecodedBlockArray.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Formats.Jpg
{
using System;
using System.Buffers;
/// <summary>
/// Because <see cref="System.Array.Length"/> has no information for rented arrays,
/// we need to store the count and the buffer separately when storing pooled <see cref="DecodedBlock"/> arrays.
/// </summary>
internal struct DecodedBlockArray : IDisposable
{
/// <summary>
/// The <see cref="ArrayPool{T}"/> used to pool data in <see cref="JpegDecoderCore.DecodedBlocks"/>.
/// Should always clean arrays when returning!
/// </summary>
private static readonly ArrayPool<DecodedBlock> ArrayPool = ArrayPool<DecodedBlock>.Create();
/// <summary>
/// Initializes a new instance of the <see cref="DecodedBlockArray"/> struct. Rents a buffer.
/// </summary>
/// <param name="count">The number of valid <see cref="DecodedBlock"/>-s</param>
public DecodedBlockArray(int count)
{
this.Count = count;
this.Buffer = ArrayPool.Rent(count);
}
/// <summary>
/// Gets the number of actual <see cref="DecodedBlock"/>-s inside <see cref="Buffer"/>
/// </summary>
public int Count { get; }
/// <summary>
/// Gets the rented buffer.
/// </summary>
public DecodedBlock[] Buffer { get; private set; }
/// <summary>
/// Returns the rented buffer to the pool.
/// </summary>
public void Dispose()
{
if (this.Buffer != null)
{
ArrayPool.Return(this.Buffer, true);
this.Buffer = null;
}
}
}
}

8
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockProcessor.cs

@ -9,7 +9,7 @@ namespace ImageSharp.Formats.Jpg
using System.Runtime.InteropServices;
/// <summary>
/// Encapsulates the implementation of processing "raw" <see cref="DecodedBlockArray"/>-s into Jpeg image channels.
/// Encapsulates the implementation of processing "raw" <see cref="Buffer{T}"/>-s into Jpeg image channels.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct JpegBlockProcessor
@ -47,10 +47,10 @@ namespace ImageSharp.Formats.Jpg
/// <param name="decoder">The <see cref="JpegDecoderCore"/> instance</param>
public void ProcessAllBlocks(JpegDecoderCore decoder)
{
DecodedBlockArray blockArray = decoder.DecodedBlocks[this.componentIndex];
for (int i = 0; i < blockArray.Count; i++)
Buffer<DecodedBlock> blockArray = decoder.DecodedBlocks[this.componentIndex];
for (int i = 0; i < blockArray.Length; i++)
{
this.ProcessBlockColors(decoder, ref blockArray.Buffer[i]);
this.ProcessBlockColors(decoder, ref blockArray[i]);
}
}

6
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegScanDecoder.cs

@ -171,7 +171,7 @@ namespace ImageSharp.Formats.Jpg
// Take an existing block (required when progressive):
int blockIndex = this.GetBlockIndex(decoder);
this.data.Block = decoder.DecodedBlocks[this.ComponentIndex].Buffer[blockIndex].Block;
this.data.Block = decoder.DecodedBlocks[this.ComponentIndex][blockIndex].Block;
if (!decoder.InputProcessor.UnexpectedEndOfStreamReached)
{
@ -179,8 +179,8 @@ namespace ImageSharp.Formats.Jpg
}
// Store the decoded block
DecodedBlockArray blocks = decoder.DecodedBlocks[this.ComponentIndex];
blocks.Buffer[blockIndex].SaveBlock(this.bx, this.by, ref this.data.Block);
Buffer<DecodedBlock> blocks = decoder.DecodedBlocks[this.ComponentIndex];
blocks[blockIndex].SaveBlock(this.bx, this.by, ref this.data.Block);
}
// for j

12
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -111,7 +111,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 DecodedBlockArray[MaxComponents];
this.DecodedBlocks = new Buffer<DecodedBlock>[MaxComponents];
}
/// <summary>
@ -125,12 +125,12 @@ namespace ImageSharp.Formats
public HuffmanTree[] HuffmanTrees { get; }
/// <summary>
/// Gets the array of <see cref="DecodedBlockArray"/>-s storing the "raw" frequency-domain decoded blocks.
/// Gets the array of <see cref="Buffer{T}"/>-s storing the "raw" frequency-domain decoded blocks.
/// We need to apply IDCT, dequantiazition and unzigging to transform them into color-space blocks.
/// This is done by <see cref="ProcessBlocksIntoJpegImageChannels{TPixel}"/>.
/// When <see cref="IsProgressive"/>==true, we are touching these blocks multiple times - each time we process a Scan.
/// </summary>
public DecodedBlockArray[] DecodedBlocks { get; }
public Buffer<DecodedBlock>[] DecodedBlocks { get; }
/// <summary>
/// Gets the quantization tables, in zigzag order.
@ -216,9 +216,9 @@ namespace ImageSharp.Formats
this.HuffmanTrees[i].Dispose();
}
foreach (DecodedBlockArray blockArray in this.DecodedBlocks)
foreach (Buffer<DecodedBlock> blockArray in this.DecodedBlocks)
{
blockArray.Dispose();
blockArray?.Dispose();
}
this.ycbcrImage?.Dispose();
@ -1308,7 +1308,7 @@ namespace ImageSharp.Formats
{
int count = this.TotalMCUCount * this.ComponentArray[i].HorizontalFactor
* this.ComponentArray[i].VerticalFactor;
this.DecodedBlocks[i] = new DecodedBlockArray(count);
this.DecodedBlocks[i] = Buffer<DecodedBlock>.CreateClean(count);
}
}
}

Loading…
Cancel
Save