Browse Source

fix JpegDecoder

pull/1109/head
Anton Firszov 6 years ago
parent
commit
da08852291
  1. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.CopyTo.cs
  2. 10
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs
  3. 9
      src/ImageSharp/Memory/Buffer2DExtensions.cs
  4. 3
      src/ImageSharp/Memory/Buffer2D{T}.cs
  5. 20
      src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
  6. 3
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs
  7. 8
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs
  8. 25
      tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs
  9. 13
      tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
  10. 4
      tests/ImageSharp.Tests/TestImages.cs
  11. 14
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

2
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.CopyTo.cs

@ -139,4 +139,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
}
}
}
}

10
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegComponentPostProcessor.cs

@ -31,12 +31,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
this.Component = component;
this.ImagePostProcessor = imagePostProcessor;
this.ColorBuffer = memoryAllocator.Allocate2D<float>(
this.blockAreaSize = this.Component.SubSamplingDivisors * 8;
this.ColorBuffer = memoryAllocator.Allocate2DOveraligned<float>(
imagePostProcessor.PostProcessorBufferSize.Width,
imagePostProcessor.PostProcessorBufferSize.Height);
imagePostProcessor.PostProcessorBufferSize.Height,
this.blockAreaSize.Height);
this.BlockRowsPerStep = JpegImagePostProcessor.BlockRowsPerStep / this.Component.SubSamplingDivisors.Height;
this.blockAreaSize = this.Component.SubSamplingDivisors * 8;
}
/// <summary>
@ -111,4 +113,4 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
this.currentComponentRowInBlocks += this.BlockRowsPerStep;
}
}
}
}

9
src/ImageSharp/Memory/Buffer2DExtensions.cs

@ -156,15 +156,6 @@ namespace SixLabors.ImageSharp.Memory
where T : struct =>
new BufferArea<T>(buffer);
/// <summary>
/// Gets a span for all the pixels in <paramref name="buffer"/> defined by <paramref name="rows"/>
/// </summary>
internal static Span<T> GetMultiRowSpan<T>(this Buffer2D<T> buffer, in RowInterval rows)
where T : struct
{
return buffer.GetSingleSpan().Slice(rows.Min * buffer.Width, rows.Height * buffer.Width);
}
/// <summary>
/// Returns the size of the buffer.
/// </summary>

3
src/ImageSharp/Memory/Buffer2D{T}.cs

@ -95,6 +95,7 @@ namespace SixLabors.ImageSharp.Memory
/// <see cref="ArgumentOutOfRangeException"/> is being propagated from lower levels.
/// </remarks>
/// <param name="y">The row index.</param>
/// <returns>The <see cref="Span{T}"/> of the pixels in the row.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when row index is out of range.</exception>
[MethodImpl(InliningOptions.ShortMethod)]
public Span<T> GetRowSpan(int y)
@ -117,7 +118,7 @@ namespace SixLabors.ImageSharp.Memory
return ref Unsafe.Add(ref start, (y * this.Width) + x);
}
return ref GetElementSlow(x, y);
return ref this.GetElementSlow(x, y);
}
/// <summary>

20
src/ImageSharp/Memory/MemoryAllocatorExtensions.cs

@ -28,8 +28,8 @@ namespace SixLabors.ImageSharp.Memory
where T : struct
{
long groupLength = (long)width * height;
MemoryGroup<T> memorySource = memoryAllocator.AllocateGroup<T>(groupLength, width, options);
return new Buffer2D<T>(memorySource, width, height);
MemoryGroup<T> memoryGroup = memoryAllocator.AllocateGroup<T>(groupLength, width, options);
return new Buffer2D<T>(memoryGroup, width, height);
}
/// <summary>
@ -48,6 +48,22 @@ namespace SixLabors.ImageSharp.Memory
where T : struct =>
Allocate2D<T>(memoryAllocator, size.Width, size.Height, options);
internal static Buffer2D<T> Allocate2DOveraligned<T>(
this MemoryAllocator memoryAllocator,
int width,
int height,
int alignmentMultiplier,
AllocationOptions options = AllocationOptions.None)
where T : struct
{
long groupLength = (long)width * height;
MemoryGroup<T> memoryGroup = memoryAllocator.AllocateGroup<T>(
groupLength,
width * alignmentMultiplier,
options);
return new Buffer2D<T>(memoryGroup, width, height);
}
/// <summary>
/// Allocates padded buffers for BMP encoder/decoder. (Replacing old PixelRow/PixelArea).
/// </summary>

3
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs

@ -16,6 +16,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Theory]
[WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32, false)]
[WithFile(TestImages.Jpeg.Baseline.Calliphora, PixelTypes.Rgba32, true)]
[WithFile(TestImages.Jpeg.Baseline.Turtle420, PixelTypes.Rgba32, true)]
public void DecodeBaselineJpeg<TPixel>(TestImageProvider<TPixel> provider, bool enforceDiscontiguousBuffers)
where TPixel : struct, IPixel<TPixel>
{
@ -26,7 +27,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
if (!string.IsNullOrEmpty(nonContiguousBuffersStr))
{
provider.LimitAllocatorBufferCapacity().InBytesSqrt(200);
provider.LimitAllocatorBufferCapacity().InPixels(1000 * 8);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);

8
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Images.cs

@ -13,10 +13,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
TestImages.Jpeg.Baseline.Cmyk,
TestImages.Jpeg.Baseline.Ycck,
TestImages.Jpeg.Baseline.Jpeg400,
TestImages.Jpeg.Baseline.Turtle420,
TestImages.Jpeg.Baseline.Testorig420,
// BUG: The following image has a high difference compared to the expected output: 1.0096%
// TestImages.Jpeg.Baseline.Jpeg420Small,
TestImages.Jpeg.Baseline.Jpeg420Small,
TestImages.Jpeg.Issues.Fuzz.AccessViolationException922,
TestImages.Jpeg.Baseline.Jpeg444,
TestImages.Jpeg.Baseline.Bad.BadEOF,
@ -95,9 +96,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
// Baseline:
[TestImages.Jpeg.Baseline.Calliphora] = 0.00002f / 100,
[TestImages.Jpeg.Baseline.Bad.BadEOF] = 0.38f / 100,
[TestImages.Jpeg.Baseline.Testorig420] = 0.38f / 100,
[TestImages.Jpeg.Baseline.Bad.BadRST] = 0.0589f / 100,
[TestImages.Jpeg.Baseline.Testorig420] = 0.38f / 100,
[TestImages.Jpeg.Baseline.Jpeg420Small] = 1.1f / 100,
[TestImages.Jpeg.Baseline.Turtle420] = 1.0f / 100,
// Progressive:
[TestImages.Jpeg.Issues.MissingFF00ProgressiveGirl159] = 0.34f / 100,
[TestImages.Jpeg.Issues.BadCoeffsProgressive178] = 0.38f / 100,

25
tests/ImageSharp.Tests/Helpers/RowIntervalTests.cs

@ -10,31 +10,6 @@ namespace SixLabors.ImageSharp.Tests.Helpers
{
public class RowIntervalTests
{
[Theory]
[InlineData(10, 20, 5, 10)]
[InlineData(1, 10, 0, 10)]
[InlineData(1, 10, 5, 8)]
[InlineData(1, 1, 0, 1)]
[InlineData(10, 20, 9, 10)]
[InlineData(10, 20, 0, 1)]
public void GetMultiRowSpan(int width, int height, int min, int max)
{
using (Buffer2D<int> buffer = Configuration.Default.MemoryAllocator.Allocate2D<int>(width, height))
{
var rows = new RowInterval(min, max);
Span<int> span = buffer.GetMultiRowSpan(rows);
ref int expected0 = ref buffer.GetSingleSpan()[min * width];
int expectedLength = (max - min) * width;
ref int actual0 = ref span[0];
Assert.Equal(span.Length, expectedLength);
Assert.True(Unsafe.AreSame(ref expected0, ref actual0));
}
}
[Fact]
public void Slice1()
{

13
tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

@ -69,6 +69,19 @@ namespace SixLabors.ImageSharp.Tests.Memory
}
}
[Theory]
[InlineData(50, 10, 20, 4)]
public void Allocate2DOveraligned(int bufferCapacity, int width, int height, int alignmentMultiplier)
{
this.MemoryAllocator.BufferCapacityInBytes = sizeof(int) * bufferCapacity;
using Buffer2D<int> buffer = this.MemoryAllocator.Allocate2DOveraligned<int>(width, height, alignmentMultiplier);
MemoryGroup<int> memoryGroup = buffer.MemoryGroup;
int expectedAlignment = width * alignmentMultiplier;
Assert.Equal(expectedAlignment, memoryGroup.BufferLength);
}
[Fact]
public void CreateClean()
{

4
tests/ImageSharp.Tests/TestImages.cs

@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Tests
public const string Floorplan = "Jpg/baseline/Floorplan.jpg";
public const string Calliphora = "Jpg/baseline/Calliphora.jpg";
public const string Ycck = "Jpg/baseline/ycck.jpg";
public const string Turtle = "Jpg/baseline/turtle.jpg";
public const string Turtle420 = "Jpg/baseline/turtle.jpg";
public const string GammaDalaiLamaGray = "Jpg/baseline/gamma_dalai_lama_gray.jpg";
public const string Hiyamugi = "Jpg/baseline/Hiyamugi.jpg";
public const string Snake = "Jpg/baseline/Snake.jpg";
@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.Tests
public static readonly string[] All =
{
Cmyk, Ycck, Exif, Floorplan,
Calliphora, Turtle, GammaDalaiLamaGray,
Calliphora, Turtle420, GammaDalaiLamaGray,
Hiyamugi, Jpeg400, Jpeg420Exif, Jpeg444,
Ratio1x1, Testorig12bit, YcckSubsample1222
};

14
tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

@ -762,20 +762,18 @@ namespace SixLabors.ImageSharp.Tests
this.pixelSizeInBytes = pixelSizeInBytes;
}
public void InBytes(int totalBytes) => this.allocator.BufferCapacityInBytes = totalBytes;
public void InPixels(int totalPixels) => this.InBytes(totalPixels * this.pixelSizeInBytes);
/// <summary>
/// Set the maximum buffer capacity to bytesSqrt^2 bytes.
/// </summary>
public void InBytesSqrt(int bytesSqrt)
{
this.allocator.BufferCapacityInBytes = bytesSqrt * bytesSqrt;
}
public void InBytesSqrt(int bytesSqrt) => this.InBytes(bytesSqrt * bytesSqrt);
/// <summary>
/// Set the maximum buffer capacity to pixelsSqrt^2 x sizeof(TPixel) bytes.
/// </summary>
public void InPixelsSqrt(int pixelsSqrt)
{
this.allocator.BufferCapacityInBytes = pixelsSqrt * pixelsSqrt * this.pixelSizeInBytes;
}
public void InPixelsSqrt(int pixelsSqrt) => this.InPixels(pixelsSqrt * pixelsSqrt);
}
}

Loading…
Cancel
Save