diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs index 1216c1841..d6d24999e 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs @@ -305,26 +305,26 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common /// /// Level shift by +128, clip to [0, 255], and write to buffer. /// - /// Color buffer + /// Color buffer /// Stride offset /// Temp Block pointer [MethodImpl(MethodImplOptions.AggressiveInlining)] - public unsafe void CopyColorsTo(MutableSpan buffer, int stride, Block8x8F* tempBlockPtr) + public unsafe void CopyColorsTo(Span destinationBuffer, int stride, Block8x8F* tempBlockPtr) { this.TransformByteConvetibleColorValuesInto(ref *tempBlockPtr); - + ref byte d = ref destinationBuffer.DangerousGetPinnableReference(); float* src = (float*)tempBlockPtr; for (int i = 0; i < 8; i++) { - buffer[0] = (byte)src[0]; - buffer[1] = (byte)src[1]; - buffer[2] = (byte)src[2]; - buffer[3] = (byte)src[3]; - buffer[4] = (byte)src[4]; - buffer[5] = (byte)src[5]; - buffer[6] = (byte)src[6]; - buffer[7] = (byte)src[7]; - buffer.AddOffset(stride); + ref byte dRow = ref Unsafe.Add(ref d, i * stride); + Unsafe.Add(ref dRow, 0) = (byte)src[0]; + Unsafe.Add(ref dRow, 1) = (byte)src[1]; + Unsafe.Add(ref dRow, 2) = (byte)src[2]; + Unsafe.Add(ref dRow, 3) = (byte)src[3]; + Unsafe.Add(ref dRow, 4) = (byte)src[4]; + Unsafe.Add(ref dRow, 5) = (byte)src[5]; + Unsafe.Add(ref dRow, 6) = (byte)src[6]; + Unsafe.Add(ref dRow, 7) = (byte)src[7]; src += 8; } } diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecodedBlock.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecodedBlock.cs index 504c1174f..f5d9c1bf8 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecodedBlock.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/DecodedBlock.cs @@ -12,11 +12,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder /// 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)) /// diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs index a6c4e4f1a..3a98fd3e7 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs @@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder /// The instance public void ProcessAllBlocks(OldJpegDecoderCore decoder) { - Buffer blockArray = decoder.DecodedBlocks[this.componentIndex]; + Buffer blockArray = decoder.Components[this.componentIndex].DecodedBlocks; for (int i = 0; i < blockArray.Length; i++) { this.ProcessBlockColors(decoder, ref blockArray[i]); diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldComponent.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldComponent.cs index dca131961..e6669483a 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldComponent.cs @@ -43,6 +43,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder /// public byte Selector { get; private set; } + /// + /// Gets the 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 . + /// When ==true, we are touching these blocks multiple times - each time we process a Scan. + /// public Buffer DecodedBlocks { get; private set; } /// diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegPixelArea.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegPixelArea.cs index 9f8f8d71a..b2bfe189a 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegPixelArea.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegPixelArea.cs @@ -8,6 +8,8 @@ using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F; namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder { + using System; + /// /// Represents an area of a Jpeg subimage (channel) /// @@ -109,7 +111,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder public unsafe void LoadColorsFrom(Block8x8F* block, Block8x8F* temp) { // Level shift by +128, clip to [0, 255], and write to dst. - block->CopyColorsTo(new MutableSpan(this.Pixels.Array, this.Offset), this.Stride, temp); + block->CopyColorsTo(new Span(this.Pixels.Array, this.Offset), this.Stride, temp); } } } \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegScanDecoder.cs index 7fd6276d8..c90ab882c 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegScanDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OldJpegScanDecoder.cs @@ -171,7 +171,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder // Take an existing block (required when progressive): int blockIndex = this.GetBlockIndex(decoder); - this.data.Block = decoder.DecodedBlocks[this.ComponentIndex][blockIndex].Block; + + Buffer blocks = decoder.Components[this.ComponentIndex].DecodedBlocks; + + this.data.Block = blocks[blockIndex].Block; if (!decoder.InputProcessor.UnexpectedEndOfStreamReached) { @@ -179,7 +182,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder } // Store the decoded block - Buffer blocks = decoder.DecodedBlocks[this.ComponentIndex]; blocks[blockIndex].SaveBlock(this.bx, this.by, ref this.data.Block); } diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs index 250e6e0d2..a9027c7e9 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OldJpegDecoderCore.cs @@ -15,6 +15,8 @@ using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F; namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort { + using System.Linq; + /// /// Performs the jpeg decoding operation. /// @@ -107,7 +109,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort this.HuffmanTrees = OldHuffmanTree.CreateHuffmanTrees(); this.QuantizationTables = new Block8x8F[MaxTq + 1]; this.Temp = new byte[2 * Block8x8F.ScalarCount]; - this.DecodedBlocks = new Buffer[MaxComponents]; } /// @@ -119,15 +120,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort /// Gets the huffman trees /// public OldHuffmanTree[] HuffmanTrees { get; } - - /// - /// Gets the array of -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 . - /// When ==true, we are touching these blocks multiple times - each time we process a Scan. - /// - public Buffer[] DecodedBlocks { get; } - + /// /// Gets the quantization tables, in zigzag order. /// @@ -217,10 +210,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort this.HuffmanTrees[i].Dispose(); } - foreach (Buffer blockArray in this.DecodedBlocks) + if (this.Components != null) { - blockArray?.Dispose(); + foreach (Buffer blockArray in this.Components.Select(c => c.DecodedBlocks)) + { + blockArray?.Dispose(); + } } + this.ycbcrImage?.Dispose(); this.InputProcessor.Dispose(); @@ -1225,9 +1222,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort // As a preparation for parallelizing Scan decoder, we also allocate DecodedBlocks in the non-progressive case! for (int i = 0; i < this.ComponentCount; i++) { - int count = this.TotalMCUCount * this.Components[i].HorizontalFactor - * this.Components[i].VerticalFactor; - this.DecodedBlocks[i] = Buffer.CreateClean(count); + this.Components[i].InitializeBlocks(this); } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 3a5dd9c06..d59b46c3c 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -18,6 +18,8 @@ using Xunit.Abstractions; namespace SixLabors.ImageSharp.Tests { + using System; + public class Block8x8FTests : JpegUtilityTestFixture { #if BENCHMARKING @@ -321,7 +323,7 @@ namespace SixLabors.ImageSharp.Tests ReferenceImplementations.CopyColorsTo(ref block, new MutableSpan(colorsExpected, offset), stride); - block.CopyColorsTo(new MutableSpan(colorsActual, offset), stride, &temp); + block.CopyColorsTo(new Span(colorsActual, offset), stride, &temp); // Output.WriteLine("******* EXPECTED: *********"); // PrintLinearData(colorsExpected);