diff --git a/src/ImageSharp46/Formats/Jpg/Components/Block.cs b/src/ImageSharp46/Formats/Jpg/Components/Block.cs
index 168413292..e0be19206 100644
--- a/src/ImageSharp46/Formats/Jpg/Components/Block.cs
+++ b/src/ImageSharp46/Formats/Jpg/Components/Block.cs
@@ -3,6 +3,7 @@
// Licensed under the Apache License, Version 2.0.
//
+using System;
using System.Buffers;
namespace ImageSharp.Formats
@@ -10,8 +11,10 @@ namespace ImageSharp.Formats
///
/// Represents an 8x8 block of coefficients to transform and encode.
///
- internal struct Block
+ internal struct Block : IDisposable
{
+ private static ArrayPool IntArrayPool => ArrayPool.Shared; /*= ArrayPool.Create(BlockSize, 50);*/
+
///
/// Gets the size of the block.
///
@@ -32,7 +35,25 @@ namespace ImageSharp.Formats
public void Init()
{
- this.Data = new int[BlockSize];
+ //this.Data = new int[BlockSize];
+ this.Data = IntArrayPool.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;
@@ -49,5 +70,23 @@ namespace ImageSharp.Formats
get { return this.Data[index]; }
set { this.Data[index] = value; }
}
+
+ // TODO: Refactor Block.Dispose() callers to always use 'using' or 'finally' statement!
+ public void Dispose()
+ {
+ if (Data != null)
+ {
+ IntArrayPool.Return(Data, true);
+ Data = null;
+ }
+ }
+
+ public static void DisposeAll(Block[] blocks)
+ {
+ for (int i = 0; i < blocks.Length; i++)
+ {
+ blocks[i].Dispose();
+ }
+ }
}
}
diff --git a/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs b/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs
index 8bbbae357..4ca4ba903 100644
--- a/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs
+++ b/src/ImageSharp46/Formats/Jpg/Components/IDCT.cs
@@ -41,10 +41,8 @@ namespace ImageSharp.Formats
/// ASSP, Vol. ASSP- 32, pp. 803-816, Aug. 1984.
///
/// The source block of coefficients
- public static void Transform(ref Block block)
+ public static void Transform(ref Block src)
{
-
- var src = block.Data;
// Horizontal 1-D IDCT.
for (int y = 0; y < 8; y++)
{
diff --git a/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs b/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs
index 666f1b35a..d3c64a9c0 100644
--- a/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs
+++ b/src/ImageSharp46/Formats/Jpg/JpegDecoder.cs
@@ -83,8 +83,10 @@ namespace ImageSharp.Formats
Guard.NotNull(image, "image");
Guard.NotNull(stream, "stream");
- JpegDecoderCore decoder = new JpegDecoderCore();
- decoder.Decode(image, stream, false);
+ using (JpegDecoderCore decoder = new JpegDecoderCore())
+ {
+ decoder.Decode(image, stream, false);
+ }
}
///
diff --git a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs
index d64803eb4..181211f4d 100644
--- a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs
+++ b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs
@@ -12,7 +12,7 @@ namespace ImageSharp.Formats
///
/// Performs the jpeg decoding operation.
///
- internal class JpegDecoderCore
+ internal class JpegDecoderCore : IDisposable
{
///
/// The maximum (inclusive) number of bits in a Huffman code.
@@ -201,7 +201,7 @@ namespace ImageSharp.Formats
//this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1];
this.huffmanTrees = new Huffman[(MaxTc + 1)*(MaxTh + 1)];
- this.quantizationTables = new Block[MaxTq + 1];
+ this.quantizationTables = Block.CreateArray(MaxTq + 1);
this.temp = new byte[2 * Block.BlockSize];
this.componentArray = new Component[MaxComponents];
this.progCoeffs = new Block[MaxComponents][];
@@ -219,11 +219,11 @@ namespace ImageSharp.Formats
}
}
- for (int i = 0; i < this.quantizationTables.Length; i++)
- {
- //this.quantizationTables[i] = new Block();
- this.quantizationTables[i].Init();
- }
+ //for (int i = 0; i < this.quantizationTables.Length; i++)
+ //{
+ // //this.quantizationTables[i] = new Block();
+ // this.quantizationTables[i].Init();
+ //}
//for (int i = 0; i < this.componentArray.Length; i++)
//{
@@ -1576,7 +1576,7 @@ namespace ImageSharp.Formats
int compIndex = scan[i].Index;
if (this.progCoeffs[compIndex] == null)
{
- this.progCoeffs[compIndex] = new Block[mxx * myy * this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor];
+ this.progCoeffs[compIndex] = Block.CreateArray(mxx * myy * this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor);
for (int j = 0; j < this.progCoeffs[compIndex].Length; j++)
{
@@ -1668,11 +1668,13 @@ namespace ImageSharp.Formats
}
else
{
- var b = new Block();
- b.Init();
+ var b = Block.Create();
+
ProcessBlockImpl(ah, ref b, scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi,
bx, ref this.quantizationTables[qtIndex]
);
+
+ b.Dispose();
}
}
@@ -2252,5 +2254,18 @@ namespace ImageSharp.Formats
private class EOFException : Exception
{
}
+
+ public void Dispose()
+ {
+ Block.DisposeAll(this.quantizationTables);
+
+ foreach (Block[] blocks in progCoeffs)
+ {
+ if (blocks != null)
+ {
+ Block.DisposeAll(blocks);
+ }
+ }
+ }
}
}
diff --git a/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs
index 9a282a72b..75e00bc76 100644
--- a/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs
+++ b/src/ImageSharp46/Formats/Jpg/JpegEncoderCore.cs
@@ -579,7 +579,7 @@ namespace ImageSharp.Formats
///
/// The destination block array
/// The source block array.
- private void Scale16X16To8X8(Block destination, Block[] source)
+ private void Scale16X16To8X8(ref Block destination, Block[] source)
{
for (int i = 0; i < 4; i++)
{
@@ -849,9 +849,9 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel
where TPacked : struct
{
- Block b = new Block();
- Block cb = new Block();
- Block cr = new Block();
+ Block b = Block.Create();
+ Block cb = Block.Create();
+ Block cr = Block.Create();
// ReSharper disable once InconsistentNaming
int prevDCY = 0, prevDCCb = 0, prevDCCr = 0;
@@ -865,6 +865,9 @@ namespace ImageSharp.Formats
prevDCCr = this.WriteBlock(ref cr, QuantIndex.Chrominance, prevDCCr);
}
}
+ b.Dispose();
+ cb.Dispose();
+ cr.Dispose();
}
///
@@ -878,22 +881,12 @@ namespace ImageSharp.Formats
where TColor : struct, IPackedPixel
where TPacked : struct
{
- Block b = new Block();
- Block[] cb = new Block[4];
- Block[] cr = new Block[4];
+ Block b = Block.Create();
+ Block[] cb = Block.CreateArray(4);
+ Block[] cr = Block.CreateArray(4);
// ReSharper disable once InconsistentNaming
int prevDCY = 0, prevDCCb = 0, prevDCCr = 0;
-
- for (int i = 0; i < 4; i++)
- {
- cb[i] = new Block();
- }
-
- for (int i = 0; i < 4; i++)
- {
- cr[i] = new Block();
- }
-
+
for (int y = 0; y < pixels.Height; y += 16)
{
for (int x = 0; x < pixels.Width; x += 16)
@@ -907,12 +900,16 @@ namespace ImageSharp.Formats
prevDCY = this.WriteBlock(ref b, QuantIndex.Luminance, prevDCY);
}
- this.Scale16X16To8X8(b, cb);
+ this.Scale16X16To8X8(ref b, cb);
prevDCCb = this.WriteBlock(ref b, QuantIndex.Chrominance, prevDCCb);
- this.Scale16X16To8X8(b, cr);
+ this.Scale16X16To8X8(ref b, cr);
prevDCCr = this.WriteBlock(ref b, QuantIndex.Chrominance, prevDCCr);
}
}
+
+ b.Dispose();
+ Block.DisposeAll(cb);
+ Block.DisposeAll(cr);
}
///
diff --git a/tests/ImageSharp.Tests46/JpegSandbox.cs b/tests/ImageSharp.Tests46/JpegSandbox.cs
index 2e9cdb894..d6e5bff4b 100644
--- a/tests/ImageSharp.Tests46/JpegSandbox.cs
+++ b/tests/ImageSharp.Tests46/JpegSandbox.cs
@@ -68,6 +68,9 @@ namespace ImageSharp.Tests
{
Vector hej = new Vector();
+
+
+ Output.WriteLine(Vector.Count.ToString());
}
}