diff --git a/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockMemento.cs b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockMemento.cs
new file mode 100644
index 000000000..4c3c7689f
--- /dev/null
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/DecodedBlockMemento.cs
@@ -0,0 +1,31 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats.Jpg
+{
+ using System.Buffers;
+
+ internal struct DecodedBlockMemento
+ {
+ ///
+ /// The used to pool data in .
+ /// Should always clean arrays when returning!
+ ///
+ public static readonly ArrayPool ArrayPool = ArrayPool.Create();
+
+ public int Bx;
+
+ public int By;
+
+ public Block8x8F Block;
+
+ public static void Store(DecodedBlockMemento[] blockArray, int index, int bx, int by, ref Block8x8F block)
+ {
+ blockArray[index].Bx = bx;
+ blockArray[index].By = by;
+ blockArray[index].Block = block;
+ }
+ }
+}
\ 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 70c4402e8..a1fe6444b 100644
--- a/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
+++ b/src/ImageSharp.Formats.Jpeg/Components/Decoder/JpegScanDecoder.cs
@@ -136,7 +136,7 @@ namespace ImageSharp.Formats.Jpg
/// 3 4 5
///
/// The instance
- public void ProcessBlocks(JpegDecoderCore decoder)
+ public void ReadBlocks(JpegDecoderCore decoder)
{
int blockCount = 0;
int mcu = 0;
@@ -213,6 +213,26 @@ namespace ImageSharp.Formats.Jpg
}
}
+ ///
+ /// Dequantize, perform the inverse DCT and store the block to the into the corresponding instances.
+ ///
+ /// The instance
+ public void ProcessBlock(JpegDecoderCore decoder)
+ {
+ int qtIndex = decoder.ComponentArray[this.componentIndex].Selector;
+ this.data.QuantiazationTable = decoder.QuantizationTables[qtIndex];
+
+ Block8x8F* b = this.pointers.Block;
+
+ Block8x8F.UnZig(b, this.pointers.QuantiazationTable, this.pointers.Unzig);
+
+ DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2);
+
+ var destChannel = decoder.GetDestinationChannel(this.componentIndex);
+ var destArea = destChannel.GetOffsetedSubAreaForBlock(this.bx, this.by);
+ destArea.LoadColorsFrom(this.pointers.Temp1, this.pointers.Temp2);
+ }
+
private void ResetDc()
{
Unsafe.InitBlock(this.pointers.Dc, default(byte), sizeof(int) * JpegDecoderCore.MaxComponents);
@@ -248,7 +268,7 @@ namespace ImageSharp.Formats.Jpg
for (int i = 0; i < this.componentScanCount; i++)
{
- this.ProcessScanImpl(decoder, i, ref this.pointers.ComponentScan[i], ref totalHv);
+ this.InitComponentScan(decoder, i, ref this.pointers.ComponentScan[i], ref totalHv);
}
// Section B.2.3 states that if there is more than one component then the
@@ -293,7 +313,7 @@ namespace ImageSharp.Formats.Jpg
private void ReadBlock(JpegDecoderCore decoder, int scanIndex)
{
int blockIndex = this.GetBlockIndex(decoder);
- this.data.Block = decoder.DecodedBlocks[this.componentIndex][blockIndex];
+ this.data.Block = decoder.DecodedBlocks[this.componentIndex][blockIndex].Block;
var b = this.pointers.Block;
DecoderErrorCode errorCode;
@@ -379,31 +399,13 @@ namespace ImageSharp.Formats.Jpg
}
}
- decoder.DecodedBlocks[this.componentIndex][blockIndex] = this.data.Block;
+ DecodedBlockMemento[] blocks = decoder.DecodedBlocks[this.componentIndex];
+ DecodedBlockMemento.Store(blocks, blockIndex, this.bx, this.by, ref *b);
}
private bool IsProgressiveBlockFinished(JpegDecoderCore decoder)
=> decoder.IsProgressive && (this.zigEnd != Block8x8F.ScalarCount - 1 || this.al != 0);
- ///
- /// Dequantize, perform the inverse DCT and store the block to the into the corresponding instances.
- ///
- /// The instance
- private void ProcessBlock(JpegDecoderCore decoder)
- {
- int qtIndex = decoder.ComponentArray[this.componentIndex].Selector;
- this.data.QuantiazationTable = decoder.QuantizationTables[qtIndex];
-
- Block8x8F* b = this.pointers.Block;
-
- Block8x8F.UnZig(b, this.pointers.QuantiazationTable, this.pointers.Unzig);
-
- DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2);
-
- var destChannel = decoder.GetDestinationChannel(this.componentIndex);
- var destArea = destChannel.GetOffsetedSubAreaForBlock(this.bx, this.by);
- destArea.LoadColorsFrom(this.pointers.Temp1, this.pointers.Temp2);
- }
private DecoderErrorCode DecodeEobRun(int count, JpegDecoderCore decoder)
{
@@ -428,7 +430,7 @@ namespace ImageSharp.Formats.Jpg
return ((this.by * decoder.MCUCountX) * this.hi) + this.bx;
}
- private void ProcessScanImpl(JpegDecoderCore decoder, int i, ref ComponentScan currentComponentScan, ref int totalHv)
+ private void InitComponentScan(JpegDecoderCore decoder, int i, ref ComponentScan currentComponentScan, ref int totalHv)
{
// Component selector.
int cs = decoder.Temp[1 + (2 * i)];
@@ -649,5 +651,7 @@ namespace ImageSharp.Formats.Jpg
return zig;
}
+
+
}
}
\ No newline at end of file
diff --git a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
index 1e1210387..30367e93e 100644
--- a/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
+++ b/src/ImageSharp.Formats.Jpeg/JpegDecoderCore.cs
@@ -40,11 +40,7 @@ namespace ImageSharp.Formats
public Bytes Bytes;
#pragma warning restore SA401
- ///
- /// The used to pool data in .
- /// Should always clean arrays when returning!
- ///
- private static readonly ArrayPool BlockPool = ArrayPool.Create();
+
///
/// The App14 marker color-space
@@ -95,7 +91,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 Block8x8F[MaxComponents][];
+ this.DecodedBlocks = new DecodedBlockMemento[MaxComponents][];
this.Bits = default(Bits);
this.Bytes = Bytes.Create();
}
@@ -114,7 +110,7 @@ namespace ImageSharp.Formats
/// Gets the saved state between progressive-mode scans.
/// TODO: Also save non-progressive data here. (Helps splitting and parallelizing JpegScanDecoder-s loop)
///
- public Block8x8F[][] DecodedBlocks { get; }
+ public DecodedBlockMemento[][] DecodedBlocks { get; }
///
/// Gets the quantization tables, in zigzag order.
@@ -413,12 +409,11 @@ namespace ImageSharp.Formats
this.HuffmanTrees[i].Dispose();
}
- for (int i = 0; i < this.DecodedBlocks.Length; i++)
+ foreach (DecodedBlockMemento[] blockArray in this.DecodedBlocks)
{
- Block8x8F[] blockArray = this.DecodedBlocks[i];
if (blockArray != null)
{
- BlockPool.Return(blockArray, true);
+ DecodedBlockMemento.ArrayPool.Return(blockArray, true);
}
}
@@ -1443,7 +1438,7 @@ namespace ImageSharp.Formats
{
int size = this.TotalMCUCount * this.ComponentArray[i].HorizontalFactor
* this.ComponentArray[i].VerticalFactor;
- this.DecodedBlocks[i] = BlockPool.Rent(size);
+ this.DecodedBlocks[i] = DecodedBlockMemento.ArrayPool.Rent(size);
}
}
@@ -1461,7 +1456,7 @@ namespace ImageSharp.Formats
JpegScanDecoder.Init(&scan, this, remaining);
this.Bits = default(Bits);
this.MakeImage();
- scan.ProcessBlocks(this);
+ scan.ReadBlocks(this);
}
///
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
index b02f99be1..37aff8338 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
@@ -41,5 +41,30 @@ namespace ImageSharp.Tests
provider.Utility.SaveTestOutputFile(image, "bmp");
}
+ unsafe struct Buzisag
+ {
+ public int Value;
+
+ public delegate void BlockAction(Buzisag* b);
+
+ public static void Foo(Buzisag* buzisag)
+ {
+ Bar(buzisag, b => b->Value++);
+ }
+
+ public static void Bar(Buzisag* buzisag, BlockAction action)
+ {
+ action(buzisag);
+ }
+ }
+
+ [Fact]
+ public unsafe void Kabbe()
+ {
+ Buzisag b = default(Buzisag);
+ Buzisag.Foo(&b);
+
+ Assert.Equal(1, b.Value);
+ }
}
}
\ No newline at end of file