Browse Source

ready to apply Block8x8

pull/34/head
Anton Firszov 10 years ago
parent
commit
9d9af91f18
  1. 107
      src/ImageSharp46/Formats/Jpg/Components/Block.cs
  2. 25
      src/ImageSharp46/Formats/Jpg/Components/Block8x8.cs
  3. 2
      src/ImageSharp46/Formats/Jpg/Components/ReferenceDCT.cs
  4. 114
      src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs
  5. 4
      tests/ImageSharp.Tests46/Formats/Jpg/Block8x8Tests.cs

107
src/ImageSharp46/Formats/Jpg/Components/Block.cs

@ -12,9 +12,9 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Represents an 8x8 block of coefficients to transform and encode. /// Represents an 8x8 block of coefficients to transform and encode.
/// </summary> /// </summary>
public struct Block : IDisposable internal struct Block : IDisposable
{ {
private static ArrayPool<int> IntArrayPool = ArrayPool<int>.Create(BlockSize, 50); private static readonly ArrayPool<int> ArrayPool = ArrayPool<int>.Create(BlockSize, 50);
/// <summary> /// <summary>
/// Gets the size of the block. /// Gets the size of the block.
@ -37,7 +37,7 @@ namespace ImageSharp.Formats
public void Init() public void Init()
{ {
//this.Data = new int[BlockSize]; //this.Data = new int[BlockSize];
this.Data = IntArrayPool.Rent(BlockSize); this.Data = ArrayPool.Rent(BlockSize);
} }
public static Block Create() public static Block Create()
@ -79,7 +79,7 @@ namespace ImageSharp.Formats
{ {
if (Data != null) if (Data != null)
{ {
IntArrayPool.Return(Data, true); ArrayPool.Return(Data, true);
Data = null; Data = null;
} }
} }
@ -108,4 +108,103 @@ namespace ImageSharp.Formats
return clone; return clone;
} }
} }
internal struct BlockF : IDisposable
{
private static readonly ArrayPool<float> ArrayPool = ArrayPool<float>.Create(BlockSize, 50);
/// <summary>
/// Gets the size of the block.
/// </summary>
public const int BlockSize = 64;
/// <summary>
/// The array of block data.
/// </summary>
public float[] Data;
/// <summary>
/// Initializes a new instance of the <see cref="Block"/> class.
/// </summary>
//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;
/// <summary>
/// Gets the pixel data at the given block index.
/// </summary>
/// <param name="index">The index of the data to return.</param>
/// <returns>
/// The <see cref="int"/>.
/// </returns>
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;
}
}
} }

25
src/ImageSharp46/Formats/Jpg/Components/Block8x8.cs

@ -189,6 +189,15 @@ namespace ImageSharp.Formats
dest.MultiplyAllInplace(_0_125); dest.MultiplyAllInplace(_0_125);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void IDCTInplace()
{
Block8x8 result = new Block8x8();
Block8x8 temp = new Block8x8();
IDCTInto(ref result, ref temp);
this = result;
}
private static readonly Vector4 _1_175876 = new Vector4(1.175876f); private static readonly Vector4 _1_175876 = new Vector4(1.175876f);
private static readonly Vector4 _1_961571 = new Vector4(-1.961571f); private static readonly Vector4 _1_961571 = new Vector4(-1.961571f);
private static readonly Vector4 _0_390181 = new Vector4(-0.390181f); private static readonly Vector4 _0_390181 = new Vector4(-0.390181f);
@ -416,8 +425,8 @@ namespace ImageSharp.Formats
for(i = 0;i < 8;i++){ x[i] *= 0.353554f; } for(i = 0;i < 8;i++){ x[i] *= 0.353554f; }
*/ */
} }
public static void SuchIDCT(ref Block block) internal static void SuchIDCT(ref Block block)
{ {
Block8x8 source = new Block8x8(); Block8x8 source = new Block8x8();
source.LoadFrom(block.Data); source.LoadFrom(block.Data);
@ -429,6 +438,18 @@ namespace ImageSharp.Formats
dest.CopyTo(block.Data); dest.CopyTo(block.Data);
} }
internal static void SuchIDCT(ref BlockF block)
{
Block8x8 source = new Block8x8();
source.LoadFrom(block.Data);
Block8x8 dest = new Block8x8();
Block8x8 temp = new Block8x8();
source.IDCTInto(ref dest, ref temp);
dest.CopyTo(block.Data);
}
public unsafe float this[int idx] public unsafe float this[int idx]
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

2
src/ImageSharp46/Formats/Jpg/Components/ReferenceDCT.cs

@ -215,7 +215,7 @@ namespace ImageSharp.Formats
} }
} }
public static void IDCT(ref Block block) internal static void IDCT(ref Block block)
{ {
Span<float> src = Span<float>.RentFromPool(64); Span<float> src = Span<float>.RentFromPool(64);

114
src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs

@ -84,7 +84,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Saved state between progressive-mode scans. /// Saved state between progressive-mode scans.
/// </summary> /// </summary>
private readonly Block[][] progCoeffs; private readonly BlockF[][] progCoeffs;
/// <summary> /// <summary>
/// The huffman trees /// The huffman trees
@ -96,7 +96,7 @@ namespace ImageSharp.Formats
/// <summary> /// <summary>
/// Quantization tables, in zigzag order. /// Quantization tables, in zigzag order.
/// </summary> /// </summary>
private readonly Block[] quantizationTables; private readonly BlockF[] quantizationTables;
/// <summary> /// <summary>
/// A temporary buffer for holding pixels /// A temporary buffer for holding pixels
@ -201,12 +201,12 @@ namespace ImageSharp.Formats
public JpegDecoderCore() public JpegDecoderCore()
{ {
//this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1]; //this.huffmanTrees = new Huffman[MaxTc + 1, MaxTh + 1];
this.huffmanTrees = new Huffman[(MaxTc + 1)*(MaxTh + 1)]; this.huffmanTrees = new Huffman[(MaxTc + 1) * (MaxTh + 1)];
this.quantizationTables = Block.CreateArray(MaxTq + 1); this.quantizationTables = BlockF.CreateArray(MaxTq + 1);
this.temp = new byte[2 * Block.BlockSize]; this.temp = new byte[2 * BlockF.BlockSize];
this.componentArray = new Component[MaxComponents]; this.componentArray = new Component[MaxComponents];
this.progCoeffs = new Block[MaxComponents][]; this.progCoeffs = new BlockF[MaxComponents][];
this.bits = new Bits(); this.bits = new Bits();
this.bytes = new Bytes(); this.bytes = new Bytes();
@ -217,7 +217,7 @@ namespace ImageSharp.Formats
for (int j = 0; j < MaxTh + 1; j++) for (int j = 0; j < MaxTh + 1; j++)
{ {
//this.huffmanTrees[i, j].Init(LutSize, MaxNCodes, MaxCodeLength); //this.huffmanTrees[i, j].Init(LutSize, MaxNCodes, MaxCodeLength);
this.huffmanTrees[i* ThRowSize + j].Init(LutSize, MaxNCodes, MaxCodeLength); this.huffmanTrees[i * ThRowSize + j].Init(LutSize, MaxNCodes, MaxCodeLength);
} }
} }
@ -515,7 +515,7 @@ namespace ImageSharp.Formats
throw new ImageFormatException("Bad Th value"); throw new ImageFormatException("Bad Th value");
} }
ProcessDefineHuffmanTablesMarkerLoop(ref this.huffmanTrees[tc* ThRowSize + th], ref remaining); ProcessDefineHuffmanTablesMarkerLoop(ref this.huffmanTrees[tc * ThRowSize + th], ref remaining);
} }
} }
@ -571,8 +571,8 @@ namespace ImageSharp.Formats
// whose codeLength's high bits matches code. // whose codeLength's high bits matches code.
// The high 8 bits of lutValue are the encoded value. // The high 8 bits of lutValue are the encoded value.
// The low 8 bits are 1 plus the codeLength. // The low 8 bits are 1 plus the codeLength.
byte base2 = (byte) (code << (7 - i)); byte base2 = (byte)(code << (7 - i));
ushort lutValue = (ushort) ((huffman.Values[x] << 8) | (2 + i)); ushort lutValue = (ushort)((huffman.Values[x] << 8) | (2 + i));
for (int k = 0; k < 1 << (7 - i); k++) for (int k = 0; k < 1 << (7 - i); k++)
{ {
@ -1117,32 +1117,32 @@ namespace ImageSharp.Formats
switch (x >> 4) switch (x >> 4)
{ {
case 0: case 0:
if (remaining < Block.BlockSize) if (remaining < BlockF.BlockSize)
{ {
done = true; done = true;
break; break;
} }
remaining -= Block.BlockSize; remaining -= BlockF.BlockSize;
this.ReadFull(this.temp, 0, Block.BlockSize); this.ReadFull(this.temp, 0, BlockF.BlockSize);
for (int i = 0; i < Block.BlockSize; i++) for (int i = 0; i < BlockF.BlockSize; i++)
{ {
this.quantizationTables[tq][i] = this.temp[i]; this.quantizationTables[tq][i] = this.temp[i];
} }
break; break;
case 1: case 1:
if (remaining < 2 * Block.BlockSize) if (remaining < 2 * BlockF.BlockSize)
{ {
done = true; done = true;
break; break;
} }
remaining -= 2 * Block.BlockSize; remaining -= 2 * BlockF.BlockSize;
this.ReadFull(this.temp, 0, 2 * Block.BlockSize); this.ReadFull(this.temp, 0, 2 * BlockF.BlockSize);
for (int i = 0; i < Block.BlockSize; i++) for (int i = 0; i < BlockF.BlockSize; i++)
{ {
this.quantizationTables[tq][i] = (this.temp[2 * i] << 8) | this.temp[(2 * i) + 1]; this.quantizationTables[tq][i] = (this.temp[2 * i] << 8) | this.temp[(2 * i) + 1];
} }
@ -1471,7 +1471,7 @@ namespace ImageSharp.Formats
} }
} }
private Block scanWorkerBlock = Block.Create(); private BlockF scanWorkerBlock = BlockF.Create();
/// <summary> /// <summary>
/// Processes the SOS (Start of scan marker). /// Processes the SOS (Start of scan marker).
@ -1535,7 +1535,7 @@ namespace ImageSharp.Formats
// significant bit. // significant bit.
// For baseline JPEGs, these parameters are hard-coded to 0/63/0/0. // For baseline JPEGs, these parameters are hard-coded to 0/63/0/0.
int zigStart = 0; int zigStart = 0;
int zigEnd = Block.BlockSize - 1; int zigEnd = BlockF.BlockSize - 1;
int ah = 0; int ah = 0;
int al = 0; int al = 0;
@ -1546,7 +1546,7 @@ namespace ImageSharp.Formats
ah = this.temp[3 + scanComponentCountX2] >> 4; ah = this.temp[3 + scanComponentCountX2] >> 4;
al = this.temp[3 + scanComponentCountX2] & 0x0f; al = this.temp[3 + scanComponentCountX2] & 0x0f;
if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || Block.BlockSize <= zigEnd) if ((zigStart == 0 && zigEnd != 0) || zigStart > zigEnd || BlockF.BlockSize <= zigEnd)
{ {
throw new ImageFormatException("Bad spectral selection bounds"); throw new ImageFormatException("Bad spectral selection bounds");
} }
@ -1580,7 +1580,7 @@ namespace ImageSharp.Formats
int compIndex = scan[i].Index; int compIndex = scan[i].Index;
if (this.progCoeffs[compIndex] == null) if (this.progCoeffs[compIndex] == null)
{ {
this.progCoeffs[compIndex] = Block.CreateArray(mxx * myy * this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor); this.progCoeffs[compIndex] = BlockF.CreateArray(mxx * myy * this.componentArray[compIndex].HorizontalFactor * this.componentArray[compIndex].VerticalFactor);
for (int j = 0; j < this.progCoeffs[compIndex].Length; j++) for (int j = 0; j < this.progCoeffs[compIndex].Length; j++)
{ {
@ -1612,7 +1612,7 @@ namespace ImageSharp.Formats
int compIndex = scan[i].Index; int compIndex = scan[i].Index;
int hi = this.componentArray[compIndex].HorizontalFactor; int hi = this.componentArray[compIndex].HorizontalFactor;
int vi = this.componentArray[compIndex].VerticalFactor; int vi = this.componentArray[compIndex].VerticalFactor;
for (int j = 0; j < hi * vi; j++) for (int j = 0; j < hi * vi; j++)
{ {
@ -1656,12 +1656,12 @@ namespace ImageSharp.Formats
} }
var qtIndex = this.componentArray[compIndex].Selector; var qtIndex = this.componentArray[compIndex].Selector;
if (this.isProgressive) // Load the previous partially decoded coefficients, if applicable. if (this.isProgressive) // Load the previous partially decoded coefficients, if applicable.
{ {
blockIndex = ((@by * mxx) * hi) + bx; blockIndex = ((@by * mxx) * hi) + bx;
ProcessBlockImpl(ah, ProcessBlockImpl(ah,
ref this.progCoeffs[compIndex][blockIndex], ref this.progCoeffs[compIndex][blockIndex],
scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, bx, scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, bx,
ref this.quantizationTables[qtIndex] ref this.quantizationTables[qtIndex]
); );
@ -1670,11 +1670,11 @@ namespace ImageSharp.Formats
{ {
//var b = Block.Create(); //var b = Block.Create();
scanWorkerBlock.Clear(); scanWorkerBlock.Clear();
ProcessBlockImpl(ah, ref scanWorkerBlock, scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi, ProcessBlockImpl(ah, ref scanWorkerBlock, scan, i, zigStart, zigEnd, al, dc, compIndex, @by, mxx, hi,
bx, ref this.quantizationTables[qtIndex] bx, ref this.quantizationTables[qtIndex]
); );
//b.Dispose(); //b.Dispose();
} }
} }
@ -1718,8 +1718,8 @@ namespace ImageSharp.Formats
// for my // for my
} }
private void ProcessBlockImpl(int ah, ref Block b, Scan[] scan, int i, int zigStart, int zigEnd, int al, private void ProcessBlockImpl(int ah, ref BlockF b, Scan[] scan, int i, int zigStart, int zigEnd, int al,
int[] dc, int compIndex, int @by, int mxx, int hi, int bx, ref Block qt) int[] dc, int compIndex, int @by, int mxx, int hi, int bx, ref BlockF qt)
{ {
if (ah != 0) if (ah != 0)
{ {
@ -1755,8 +1755,8 @@ namespace ImageSharp.Formats
for (; zig <= zigEnd; zig++) for (; zig <= zigEnd; zig++)
{ {
byte value = this.DecodeHuffman(ref this.huffmanTrees[AcTable * ThRowSize + scan[i].AcTableSelector]); byte value = this.DecodeHuffman(ref this.huffmanTrees[AcTable * ThRowSize + scan[i].AcTableSelector]);
byte val0 = (byte) (value >> 4); byte val0 = (byte)(value >> 4);
byte val1 = (byte) (value & 0x0f); byte val1 = (byte)(value & 0x0f);
if (val1 != 0) if (val1 != 0)
{ {
zig += val0; zig += val0;
@ -1772,10 +1772,10 @@ namespace ImageSharp.Formats
{ {
if (val0 != 0x0f) if (val0 != 0x0f)
{ {
this.eobRun = (ushort) (1 << val0); this.eobRun = (ushort)(1 << val0);
if (val0 != 0) if (val0 != 0)
{ {
this.eobRun |= (ushort) this.DecodeBits(val0); this.eobRun |= (ushort)this.DecodeBits(val0);
} }
this.eobRun--; this.eobRun--;
@ -1790,11 +1790,11 @@ namespace ImageSharp.Formats
if (this.isProgressive) if (this.isProgressive)
{ {
if (zigEnd != Block.BlockSize - 1 || al != 0) if (zigEnd != BlockF.BlockSize - 1 || al != 0)
{ {
// We haven't completely decoded this 8x8 block. Save the coefficients. // We haven't completely decoded this 8x8 block. Save the coefficients.
this.progCoeffs[compIndex][((@by*mxx)*hi) + bx] = b.Clone(); this.progCoeffs[compIndex][((@by * mxx) * hi) + bx] = b.Clone();
// At this point, we could execute the rest of the loop body to dequantize and // At this point, we could execute the rest of the loop body to dequantize and
// perform the inverse DCT, to save early stages of a progressive image to the // perform the inverse DCT, to save early stages of a progressive image to the
@ -1806,7 +1806,7 @@ namespace ImageSharp.Formats
} }
// Dequantize, perform the inverse DCT and store the block to the image. // Dequantize, perform the inverse DCT and store the block to the image.
for (int zig = 0; zig < Block.BlockSize; zig++) for (int zig = 0; zig < BlockF.BlockSize; zig++)
{ {
b[Unzig[zig]] *= qt[zig]; b[Unzig[zig]] *= qt[zig];
} }
@ -1824,7 +1824,7 @@ namespace ImageSharp.Formats
{ {
dst = this.grayImage.Pixels; dst = this.grayImage.Pixels;
stride = this.grayImage.Stride; stride = this.grayImage.Stride;
offset = this.grayImage.Offset + (8*((@by*this.grayImage.Stride) + bx)); offset = this.grayImage.Offset + (8 * ((@by * this.grayImage.Stride) + bx));
} }
else else
{ {
@ -1833,26 +1833,26 @@ namespace ImageSharp.Formats
case 0: case 0:
dst = this.ycbcrImage.YChannel; dst = this.ycbcrImage.YChannel;
stride = this.ycbcrImage.YStride; stride = this.ycbcrImage.YStride;
offset = this.ycbcrImage.YOffset + (8*((@by*this.ycbcrImage.YStride) + bx)); offset = this.ycbcrImage.YOffset + (8 * ((@by * this.ycbcrImage.YStride) + bx));
break; break;
case 1: case 1:
dst = this.ycbcrImage.CbChannel; dst = this.ycbcrImage.CbChannel;
stride = this.ycbcrImage.CStride; stride = this.ycbcrImage.CStride;
offset = this.ycbcrImage.COffset + (8*((@by*this.ycbcrImage.CStride) + bx)); offset = this.ycbcrImage.COffset + (8 * ((@by * this.ycbcrImage.CStride) + bx));
break; break;
case 2: case 2:
dst = this.ycbcrImage.CrChannel; dst = this.ycbcrImage.CrChannel;
stride = this.ycbcrImage.CStride; stride = this.ycbcrImage.CStride;
offset = this.ycbcrImage.COffset + (8*((@by*this.ycbcrImage.CStride) + bx)); offset = this.ycbcrImage.COffset + (8 * ((@by * this.ycbcrImage.CStride) + bx));
break; break;
case 3: case 3:
dst = this.blackPixels; dst = this.blackPixels;
stride = this.blackStride; stride = this.blackStride;
offset = 8*((@by*this.blackStride) + bx); offset = 8 * ((@by * this.blackStride) + bx);
break; break;
default: default:
@ -1863,12 +1863,12 @@ namespace ImageSharp.Formats
// Level shift by +128, clip to [0, 255], and write to dst. // Level shift by +128, clip to [0, 255], and write to dst.
for (int y = 0; y < 8; y++) for (int y = 0; y < 8; y++)
{ {
int y8 = y*8; int y8 = y * 8;
int yStride = y*stride; int yStride = y * stride;
for (int x = 0; x < 8; x++) for (int x = 0; x < 8; x++)
{ {
int c = b[y8 + x]; float c = b[y8 + x];
if (c < -128) if (c < -128)
{ {
c = 0; c = 0;
@ -1882,7 +1882,7 @@ namespace ImageSharp.Formats
c += 128; c += 128;
} }
dst[yStride + x + offset] = (byte) c; dst[yStride + x + offset] = (byte)c;
} }
} }
} }
@ -1927,15 +1927,15 @@ namespace ImageSharp.Formats
} }
totalHv += currentComponent.HorizontalFactor*currentComponent.VerticalFactor; totalHv += currentComponent.HorizontalFactor * currentComponent.VerticalFactor;
currentScan.DcTableSelector = (byte) (this.temp[2 + (2*i)] >> 4); currentScan.DcTableSelector = (byte)(this.temp[2 + (2 * i)] >> 4);
if (currentScan.DcTableSelector > MaxTh) if (currentScan.DcTableSelector > MaxTh)
{ {
throw new ImageFormatException("Bad DC table selector value"); throw new ImageFormatException("Bad DC table selector value");
} }
currentScan.AcTableSelector = (byte) (this.temp[2 + (2*i)] & 0x0f); currentScan.AcTableSelector = (byte)(this.temp[2 + (2 * i)] & 0x0f);
if (currentScan.AcTableSelector > MaxTh) if (currentScan.AcTableSelector > MaxTh)
{ {
throw new ImageFormatException("Bad AC table selector value"); throw new ImageFormatException("Bad AC table selector value");
@ -1950,7 +1950,7 @@ namespace ImageSharp.Formats
/// <param name="zigStart">The zig-zag start index</param> /// <param name="zigStart">The zig-zag start index</param>
/// <param name="zigEnd">The zig-zag end index</param> /// <param name="zigEnd">The zig-zag end index</param>
/// <param name="delta">The low transform offset</param> /// <param name="delta">The low transform offset</param>
private void Refine(ref Block b, ref Huffman h, int zigStart, int zigEnd, int delta) private void Refine(ref BlockF b, ref Huffman h, int zigStart, int zigEnd, int delta)
{ {
// Refining a DC component is trivial. // Refining a DC component is trivial.
if (zigStart == 0) if (zigStart == 0)
@ -1963,7 +1963,9 @@ namespace ImageSharp.Formats
bool bit = this.DecodeBit(); bool bit = this.DecodeBit();
if (bit) if (bit)
{ {
b[0] |= delta; int stuff = (int)b[0];
stuff |= delta;
b[0] = stuff;
} }
return; return;
@ -2044,7 +2046,7 @@ namespace ImageSharp.Formats
/// <param name="nz">The non-zero entry</param> /// <param name="nz">The non-zero entry</param>
/// <param name="delta">The low transform offset</param> /// <param name="delta">The low transform offset</param>
/// <returns>The <see cref="int"/></returns> /// <returns>The <see cref="int"/></returns>
private int RefineNonZeroes(ref Block b, int zig, int zigEnd, int nz, int delta) private int RefineNonZeroes(ref BlockF b, int zig, int zigEnd, int nz, int delta)
{ {
for (; zig <= zigEnd; zig++) for (; zig <= zigEnd; zig++)
{ {
@ -2264,13 +2266,13 @@ namespace ImageSharp.Formats
public void Dispose() public void Dispose()
{ {
scanWorkerBlock.Dispose(); scanWorkerBlock.Dispose();
Block.DisposeAll(this.quantizationTables); BlockF.DisposeAll(this.quantizationTables);
foreach (Block[] blocks in progCoeffs) foreach (BlockF[] blocks in progCoeffs)
{ {
if (blocks != null) if (blocks != null)
{ {
Block.DisposeAll(blocks); BlockF.DisposeAll(blocks);
} }
} }

4
tests/ImageSharp.Tests46/Formats/Jpg/Block8x8Tests.cs

@ -73,11 +73,11 @@ namespace ImageSharp.Tests.Formats.Jpg
{ {
float sum = 0; float sum = 0;
float[] block = new float[64];
Measure(Times, () => Measure(Times, () =>
{ {
//Block8x8 block = new Block8x8(); //Block8x8 block = new Block8x8();
float[] block = new float[64];
for (int i = 0; i < Block8x8.ScalarCount; i++) for (int i = 0; i < Block8x8.ScalarCount; i++)
{ {
block[i] = i; block[i] = i;

Loading…
Cancel
Save