diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
index 8cd3004c3..13208822e 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8.cs
@@ -5,6 +5,8 @@ using System.Text;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{
+ using SixLabors.ImageSharp.Memory;
+
///
/// Represents a Jpeg block with coefficiens.
///
@@ -44,7 +46,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
}
}
- public short this[int y, int x]
+ public short this[int x, int y]
{
get => this[(y * 8) + x];
set => this[(y * 8) + x] = value;
diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
index 5d30e345f..71a1e001c 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
@@ -10,6 +10,8 @@ using System.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{
+ using SixLabors.ImageSharp.Memory;
+
///
/// Represents a Jpeg block with coefficients.
///
@@ -83,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
}
}
- public float this[int y, int x]
+ public float this[int x, int y]
{
get => this[(y * 8) + x];
set => this[(y * 8) + x] = value;
@@ -304,6 +306,60 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
}
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void CopyRowImpl(ref byte selfBase, ref byte destBase, int destStride, int row)
+ {
+ ref byte s = ref Unsafe.Add(ref selfBase, row * 8 * sizeof(float));
+ ref byte d = ref Unsafe.Add(ref destBase, row * destStride);
+ Unsafe.CopyBlock(ref d, ref s, 8 * sizeof(float));
+ }
+
+ public void CopyTo(BufferArea area)
+ {
+ ref byte selfBase = ref Unsafe.As(ref this);
+ ref byte destBase = ref Unsafe.As(ref area.DangerousGetPinnableReference());
+ int destStride = area.Stride * sizeof(float);
+
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 0);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 1);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 2);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 3);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 4);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 5);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 6);
+ CopyRowImpl(ref selfBase, ref destBase, destStride, 7);
+ }
+
+ public void CopyTo(BufferArea area, int horizontalScale, int verticalScale)
+ {
+ if (horizontalScale == 1 && verticalScale == 1)
+ {
+ this.CopyTo(area);
+ return;
+ }
+
+ // TODO: Optimize: implement all the cases with loopless special code! (T4?)
+ for (int y = 0; y < 8; y++)
+ {
+ int yy = y * verticalScale;
+
+ for (int x = 0; x < 8; x++)
+ {
+ int xx = x * horizontalScale;
+
+ float value = this[(y * 8) + x];
+
+ for (int i = 0; i < verticalScale; i++)
+ {
+ for (int j = 0; j < horizontalScale; j++)
+ {
+ area[xx + j, yy + i] = value;
+ }
+ }
+ }
+ }
+ }
+
public float[] ToArray()
{
float[] result = new float[Size];
@@ -520,5 +576,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
DebugGuard.MustBeLessThan(idx, Size, nameof(idx));
DebugGuard.MustBeGreaterThanOrEqualTo(idx, 0, nameof(idx));
}
+
+ [StructLayout(LayoutKind.Explicit, Size = 8 * sizeof(float))]
+ private struct Row
+ {
+ }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/ComponentPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Common/ComponentPostProcessor.cs
new file mode 100644
index 000000000..93e6a6705
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Common/ComponentPostProcessor.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Linq;
+using SixLabors.ImageSharp.Memory;
+using SixLabors.Primitives;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Common
+{
+ internal class JpegPostProcessor
+ {
+ private ComponentPostProcessor[] componentProcessors;
+
+ public JpegPostProcessor(IRawJpegData data)
+ {
+ this.Data = data;
+ this.componentProcessors = data.Components.Select(c => new ComponentPostProcessor(this, c)).ToArray();
+ }
+
+ public IRawJpegData Data { get; }
+ }
+
+ internal class ComponentPostProcessor : IDisposable
+ {
+ public ComponentPostProcessor(JpegPostProcessor jpegPostProcessor, IJpegComponent component)
+ {
+ this.Component = component;
+ this.JpegPostProcessor = jpegPostProcessor;
+ }
+
+ public JpegPostProcessor JpegPostProcessor { get; }
+
+ public IJpegComponent Component { get; }
+
+ public int NumberOfRowGroupSteps { get; }
+
+ public Buffer2D ColorBuffer { get; }
+
+ public void Dispose()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs b/src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs
index 78405a313..7d38d1b50 100644
--- a/src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs
+++ b/src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs
@@ -13,6 +13,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{
public static Size SizeInBlocks(this IJpegComponent component) => new Size(component.WidthInBlocks, component.HeightInBlocks);
+ public static ref Block8x8 GetBlockReference(this IJpegComponent component, int bx, int by)
+ {
+ return ref component.SpectralBlocks[bx, by];
+ }
+
public static SubsampleRatio GetSubsampleRatio(int horizontalRatio, int verticalRatio)
{
switch ((horizontalRatio << 4) | verticalRatio)
@@ -107,19 +112,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
return sizes;
}
-
- //public static Size CalculateJpegChannelSize(this IJpegComponent component, SubsampleRatio ratio = SubsampleRatio.Undefined)
- //{
- // Size size = new Size(component.WidthInBlocks, component.HeightInBlocks) * 8;
-
- // if (component.IsChromaComponent())
- // {
- // return ratio.CalculateChrominanceSize(size.Width, size.Height);
- // }
- // else
- // {
- // return size;
- // }
- //}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/Common/IRawJpegData.cs b/src/ImageSharp/Formats/Jpeg/Common/IRawJpegData.cs
new file mode 100644
index 000000000..7b3318f56
--- /dev/null
+++ b/src/ImageSharp/Formats/Jpeg/Common/IRawJpegData.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+using SixLabors.Primitives;
+
+namespace SixLabors.ImageSharp.Formats.Jpeg.Common
+{
+ internal interface IRawJpegData
+ {
+ Size ImageSize { get; }
+
+ Size ImageSizeInBlocks { get; }
+
+ int ComponentCount { get; }
+
+ IEnumerable Components { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/ComponentPostprocessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/ComponentPostprocessor.cs
deleted file mode 100644
index 6fe07df02..000000000
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/ComponentPostprocessor.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using SixLabors.ImageSharp.Memory;
-using SixLabors.Primitives;
-
-namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
-{
- internal class ComponentPostProcessor : IDisposable
- {
- public Size ImageSizeInBlocks { get; }
-
- public int NumberOfRowGroupScans
- {
- get;
-
- }
-
- class RowGroupProcessor : IDisposable
- {
- public Buffer2D ColorBuffer { get; }
-
- public void Dispose()
- {
- }
- }
-
-
-
- public void Dispose()
- {
-
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs
index ea55f0b93..95ac196d4 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockPostProcessor.cs
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// The
/// The x index of the block in
/// The y index of the block in
- private void ProcessBlockColors(OrigJpegDecoderCore decoder, OrigComponent component, int bx, int by)
+ private void ProcessBlockColors(OrigJpegDecoderCore decoder, IJpegComponent component, int bx, int by)
{
ref Block8x8 sourceBlock = ref component.GetBlockReference(bx, by);
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
index 391708441..7f0037cb0 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
@@ -52,12 +52,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
///
public int HeightInBlocks { get; private set; }
-
- public ref Block8x8 GetBlockReference(int bx, int by)
- {
- return ref this.SpectralBlocks[bx, by];
- }
-
+
///
/// Initializes
///
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
index 7b7bf000c..ad5141c3a 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
@@ -18,10 +18,13 @@ using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
+ using System.Collections.Generic;
+ using System.Numerics;
+
///
/// Performs the jpeg decoding operation.
///
- internal sealed unsafe class OrigJpegDecoderCore : IDisposable
+ internal sealed unsafe class OrigJpegDecoderCore : IDisposable, IRawJpegData
{
///
/// The maximum number of color components
@@ -138,20 +141,26 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
///
public byte[] Temp { get; }
+ public Size ImageSize { get; private set; }
+
+ public Size ImageSizeInBlocks { get; private set; }
+
///
/// Gets the number of color components within the image.
///
public int ComponentCount { get; private set; }
+ IEnumerable IRawJpegData.Components => this.Components;
+
///
/// Gets the image height
///
- public int ImageHeight { get; private set; }
+ public int ImageHeight => this.ImageSize.Height;
///
/// Gets the image width
///
- public int ImageWidth { get; private set; }
+ public int ImageWidth => this.ImageSize.Width;
///
/// Gets the input stream.
@@ -1167,8 +1176,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
throw new ImageFormatException("Only 8-Bit precision supported.");
}
- this.ImageHeight = (this.Temp[1] << 8) + this.Temp[2];
- this.ImageWidth = (this.Temp[3] << 8) + this.Temp[4];
+ int height = (this.Temp[1] << 8) + this.Temp[2];
+ int width = (this.Temp[3] << 8) + this.Temp[4];
+
+ this.InitSizes(width, height);
+
if (this.Temp[5] != this.ComponentCount)
{
throw new ImageFormatException("SOF has wrong length");
@@ -1197,5 +1209,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.SubsampleRatio = ComponentUtils.GetSubsampleRatio(this.Components);
}
+
+ private void InitSizes(int width, int height)
+ {
+ this.ImageSize = new Size(width, height);
+
+ var sizeInBlocks = (Vector2)(SizeF)this.ImageSize;
+ sizeInBlocks /= 8;
+ sizeInBlocks.X = MathF.Ceiling(sizeInBlocks.X);
+ sizeInBlocks.Y = MathF.Ceiling(sizeInBlocks.Y);
+ this.ImageSizeInBlocks = new Size((int)sizeInBlocks.X, (int)sizeInBlocks.Y);
+ }
}
}
diff --git a/src/ImageSharp/Memory/BufferArea.cs b/src/ImageSharp/Memory/BufferArea.cs
index 542420d0c..12843e209 100644
--- a/src/ImageSharp/Memory/BufferArea.cs
+++ b/src/ImageSharp/Memory/BufferArea.cs
@@ -34,8 +34,13 @@ namespace SixLabors.ImageSharp.Memory
public Size Size => this.Rectangle.Size;
+ public int Stride => this.DestinationBuffer.Width;
+
public ref T this[int x, int y] => ref this.DestinationBuffer.Span[this.GetIndexOf(x, y)];
+ public ref T DangerousGetPinnableReference() =>
+ ref this.DestinationBuffer.Span[(this.Rectangle.Y * this.DestinationBuffer.Width) + this.Rectangle.X];
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span GetRowSpan(int y)
{
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs
new file mode 100644
index 000000000..d8cb8af8c
--- /dev/null
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.CopyToBufferArea.cs
@@ -0,0 +1,101 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+
+
+// Uncomment this to turn unit tests into benchmarks:
+//#define BENCHMARKING
+
+// ReSharper disable InconsistentNaming
+
+namespace SixLabors.ImageSharp.Tests.Formats.Jpg
+{
+ using SixLabors.ImageSharp.Formats.Jpeg.Common;
+ using SixLabors.ImageSharp.Memory;
+ using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils;
+ using SixLabors.Primitives;
+
+ using Xunit;
+ using Xunit.Abstractions;
+
+ public partial class Block8x8FTests : JpegFixture
+ {
+ public class CopyToBufferArea : JpegFixture
+ {
+ public CopyToBufferArea(ITestOutputHelper output)
+ : base(output)
+ {
+ }
+
+ private static void VerifyAllZeroOutsideSubArea(Buffer2D buffer, int subX, int subY, int horizontalFactor = 1, int verticalFactor = 1)
+ {
+ for (int y = 0; y < 20; y++)
+ {
+ for (int x = 0; x < 20; x++)
+ {
+ if (x < subX || x >= subX + 8 * horizontalFactor || y < subY || y >= subY + 8 * verticalFactor)
+ {
+ Assert.Equal(0, buffer[x, y]);
+ }
+ }
+ }
+ }
+
+ [Fact]
+ public void Unscaled()
+ {
+ Block8x8F block = CreateRandomFloatBlock(0, 100);
+
+ using (var buffer = new Buffer2D(20, 20))
+ {
+ BufferArea area = buffer.GetArea(5, 10, 8, 8);
+ block.CopyTo(area);
+
+ Assert.Equal(block[0, 0], buffer[5, 10]);
+ Assert.Equal(block[1, 0], buffer[6, 10]);
+ Assert.Equal(block[0, 1], buffer[5, 11]);
+ Assert.Equal(block[0, 7], buffer[5, 17]);
+ Assert.Equal(block[63], buffer[12, 17]);
+
+ VerifyAllZeroOutsideSubArea(buffer, 5, 10);
+ }
+ }
+
+ [Theory]
+ [InlineData(1, 1)]
+ [InlineData(1, 2)]
+ [InlineData(2, 1)]
+ [InlineData(2, 2)]
+ [InlineData(4, 2)]
+ [InlineData(4, 4)]
+ public void Scaled(int horizontalFactor, int verticalFactor)
+ {
+ Block8x8F block = CreateRandomFloatBlock(0, 100);
+
+ var start = new Point(50, 50);
+
+ using (var buffer = new Buffer2D(100, 100))
+ {
+ BufferArea area = buffer.GetArea(start.X, start.Y, 8 * horizontalFactor, 8 * verticalFactor);
+ block.CopyTo(area, horizontalFactor, verticalFactor);
+
+ for (int y = 0; y < 8 * verticalFactor; y++)
+ {
+ for (int x = 0; x < 8 * horizontalFactor; x++)
+ {
+ int yy = y / verticalFactor;
+ int xx = x / horizontalFactor;
+
+ float expected = block[xx, yy];
+ float actual = area[x, y];
+
+ Assert.Equal(expected, actual);
+ }
+ }
+
+ VerifyAllZeroOutsideSubArea(buffer, start.X, start.Y, horizontalFactor, verticalFactor);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
index 3f643344b..aa224fd70 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
@@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
using Xunit;
using Xunit.Abstractions;
- public class Block8x8FTests : JpegFixture
+ public partial class Block8x8FTests : JpegFixture
{
#if BENCHMARKING
public const int Times = 1000000;
@@ -313,23 +313,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Equal(expected, actual);
}
}
-
- //[Fact]
- //public void AsInt16Block()
- //{
- // float[] data = Create8x8FloatData();
-
- // var source = default(Block8x8F);
- // source.LoadFrom(data);
-
- // Block8x8 dest = source.AsInt16Block();
-
- // for (int i = 0; i < Block8x8F.Size; i++)
- // {
- // Assert.Equal((short)data[i], dest[i]);
- // }
- //}
-
+
[Fact]
public void RoundInto()
{
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs
index d1a128b53..c2fa8c8d4 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs
@@ -115,12 +115,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
[Fact]
- public void IndexerYX()
+ public void IndexerXY()
{
var block = default(Block8x8);
block[8 * 3 + 5] = 42;
- short value = block[3, 5];
+ short value = block[5, 3];
Assert.Equal(42, value);
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
index 351d57bd7..4eb55ccfe 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
@@ -28,6 +28,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Baseline.Calliphora, TestImages.Jpeg.Baseline.Cmyk,
TestImages.Jpeg.Baseline.Jpeg400, TestImages.Jpeg.Baseline.Jpeg444,
TestImages.Jpeg.Baseline.Testorig420,
+ TestImages.Jpeg.Baseline.Jpeg420Small,
TestImages.Jpeg.Baseline.Bad.BadEOF,
TestImages.Jpeg.Baseline.Bad.ExifUndefType,
};
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs
index ab5d072a4..4404d2cfe 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs
@@ -103,6 +103,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
return result;
}
+ internal static Block8x8F CreateRandomFloatBlock(float minValue, float maxValue, int seed = 42) =>
+ Block8x8F.Load(Create8x8RandomFloatData(minValue, maxValue, seed));
+
internal void Print8x8Data(T[] data) => this.Print8x8Data(new Span(data));
internal void Print8x8Data(Span data)
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs
index f46155ac4..6a1e09a9b 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.AccurateDCT.cs
@@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
}
tmp += CosLut[y, v] * tmp2;
}
- res[y, x] = (float)tmp;
+ res[y * 8 + x] = (float)tmp;
}
}
return res;
@@ -88,11 +88,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
tmp2 = 0.0;
for (x = 0; x < 8; x++)
{
- tmp2 += (double)block[y,x] * CosLut[x,u];
+ tmp2 += (double)block[y * 8 + x] * CosLut[x,u];
}
- tmp += CosLut[y,v] * tmp2;
+ tmp += CosLut[y, v] * tmp2;
}
- res[v,u] = (float) tmp;
+ res[v * 8 + u] = (float) tmp;
}
}
diff --git a/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs b/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs
index 961380033..226e49aec 100644
--- a/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs
+++ b/tests/ImageSharp.Tests/Memory/BufferAreaTests.cs
@@ -117,5 +117,19 @@ namespace SixLabors.ImageSharp.Tests.Memory
Assert.Equal(value00, area1[0, 0]);
}
}
+
+ [Fact]
+ public void DangerousGetPinnableReference()
+ {
+ using (Buffer2D buffer = CreateTestBuffer(20, 30))
+ {
+ BufferArea area0 = buffer.GetArea(6, 8, 10, 10);
+
+ ref int r = ref area0.DangerousGetPinnableReference();
+
+ int expected = buffer[6, 8];
+ Assert.Equal(expected, r);
+ }
+ }
}
}
\ No newline at end of file