Browse Source

tests improvements:

- add failing tests for BmpDecoder
- more sophisticated and verbose buffer capacity configurator
af/octree-no-pixelmap
Anton Firszov 6 years ago
parent
commit
1366168a6c
  1. 2
      src/ImageSharp/Advanced/AdvancedImageExtensions.cs
  2. 18
      src/ImageSharp/Formats/Bmp/BmpDecoder.cs
  3. 2
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  4. 2
      src/ImageSharp/Formats/Jpeg/JpegDecoder.cs
  5. 6
      tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs
  6. 33
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  7. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs
  8. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs
  9. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  10. 2
      tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs
  11. 4
      tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs
  12. 2
      tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs
  13. 35
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

2
src/ImageSharp/Advanced/AdvancedImageExtensions.cs

@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Advanced
IMemoryGroup<TPixel> mg = source.GetPixelMemoryGroup();
if (mg.Count > 1)
{
throw new InvalidOperationException($"GetPixelSpan is invalid, since the backing buffer of this {source.Width}x{source.Height} sized image is discontiguos!");
throw new InvalidOperationException($"GetPixelSpan is invalid, since the backing buffer of this {source.Width}x{source.Height} sized image is discontiguous!");
}
return mg.Single().Span;

18
src/ImageSharp/Formats/Bmp/BmpDecoder.cs

@ -1,7 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Bmp
@ -32,7 +33,20 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
Guard.NotNull(stream, nameof(stream));
return new BmpDecoderCore(configuration, this).Decode<TPixel>(stream);
var decoder = new BmpDecoderCore(configuration, this);
try
{
return decoder.Decode<TPixel>(stream);
}
catch (InvalidMemoryOperationException ex)
{
Size dims = decoder.Dimensions;
// TODO: use InvalidImageContentException here, if we decide to define it
// https://github.com/SixLabors/ImageSharp/issues/1110
throw new ImageFormatException($"Can not decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}.", ex);
}
}
/// <inheritdoc />

2
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -114,6 +114,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp
this.options = options;
}
public Size Dimensions => new Size(this.infoHeader.Width, this.infoHeader.Height);
/// <summary>
/// Decodes the image from the specified this._stream and sets
/// the data to image.

2
src/ImageSharp/Formats/Jpeg/JpegDecoder.cs

@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// TODO: use InvalidImageContentException here, if we decide to define it
// https://github.com/SixLabors/ImageSharp/issues/1110
throw new ImageFormatException($"Can not decode the image having degenerate dimensions of {w}x{h}.", ex);
throw new ImageFormatException($"Can not decode image. Failed to allocate buffers for possibly degenerate dimensions: {w}x{h}.", ex);
}
}

6
tests/ImageSharp.Tests/Advanced/AdvancedImageExtensionsTests.cs

@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced
public void OwnedMemory_PixelDataIsCorrect<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InPixels(200);
using Image<TPixel> image = provider.GetImage();
@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced
public void GetPixelRowMemory_PixelDataIsCorrect<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InPixels(200);
using Image<TPixel> image = provider.GetImage();
@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Tests.Advanced
public void GetPixelRowSpan_ShouldReferenceSpanOfMemory<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InPixels(200);
using Image<TPixel> image = provider.GetImage();

33
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
if (!string.IsNullOrEmpty(nonContiguousBuffersStr))
{
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InPixels(100);
}
using Image<TPixel> image = provider.GetImage(BmpDecoder);
@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
public void BmpDecoder_DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity(100);
provider.LimitAllocatorBufferCapacity().InPixels(10);
ImageFormatException ex = Assert.Throws<ImageFormatException>(provider.GetImage);
Assert.IsType<InvalidMemoryOperationException>(ex.InnerException);
}
@ -253,11 +253,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
}
[Theory]
[WithFile(RLE8, PixelTypes.Rgba32)]
[WithFile(RLE8Inverted, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(RLE8, PixelTypes.Rgba32, false)]
[WithFile(RLE8Inverted, PixelTypes.Rgba32, false)]
[WithFile(RLE8, PixelTypes.Rgba32, true)]
[WithFile(RLE8Inverted, PixelTypes.Rgba32, true)]
public void BmpDecoder_CanDecode_RunLengthEncoded_8Bit<TPixel>(TestImageProvider<TPixel> provider, bool enforceDiscontiguousBuffers)
where TPixel : struct, IPixel<TPixel>
{
if (enforceDiscontiguousBuffers)
{
provider.LimitAllocatorBufferCapacity().InBytes(100);
}
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.FirstColorOfPalette }))
{
image.DebugSave(provider);
@ -266,12 +273,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
}
[Theory]
[WithFile(RLE24, PixelTypes.Rgba32)]
[WithFile(RLE24Cut, PixelTypes.Rgba32)]
[WithFile(RLE24Delta, PixelTypes.Rgba32)]
public void BmpDecoder_CanDecode_RunLengthEncoded_24Bit<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(RLE24, PixelTypes.Rgba32, false)]
[WithFile(RLE24Cut, PixelTypes.Rgba32, false)]
[WithFile(RLE24Delta, PixelTypes.Rgba32, false)]
[WithFile(RLE24, PixelTypes.Rgba32, true)]
[WithFile(RLE24Cut, PixelTypes.Rgba32, true)]
[WithFile(RLE24Delta, PixelTypes.Rgba32, true)]
public void BmpDecoder_CanDecode_RunLengthEncoded_24Bit<TPixel>(TestImageProvider<TPixel> provider, bool enforceNonContiguous)
where TPixel : struct, IPixel<TPixel>
{
if (enforceNonContiguous)
{
provider.LimitAllocatorBufferCapacity().InBytes(50);
}
using (Image<TPixel> image = provider.GetImage(new BmpDecoder { RleSkippedPixelHandling = RleSkippedPixelHandling.Black }))
{
image.DebugSave(provider);

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

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
if (!string.IsNullOrEmpty(nonContiguousBuffersStr))
{
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InBytes(200);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);

2
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
if (!string.IsNullOrEmpty(nonContiguousBuffersStr))
{
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InBytes(200);
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);

2
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs

@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity(100);
provider.LimitAllocatorBufferCapacity().InBytes(10);
ImageFormatException ex = Assert.Throws<ImageFormatException>(provider.GetImage);
this.Output.WriteLine(ex.Message);
Assert.IsType<InvalidMemoryOperationException>(ex.InnerException);

2
tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs

@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
? ImageComparer.TolerantPercentage(0.1f)
: ImageComparer.TolerantPercentage(5f);
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InBytes(200);
TestJpegEncoderCore(provider, subsample, 100, comparer);
}

4
tests/ImageSharp.Tests/Formats/Tga/TgaDecoderTests.cs

@ -204,7 +204,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
public void TgaDecoder_DegenerateMemoryRequest_ShouldTranslateTo_ImageFormatException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity(100);
provider.LimitAllocatorBufferCapacity().InPixels(10);
ImageFormatException ex = Assert.Throws<ImageFormatException>(provider.GetImage);
Assert.IsType<InvalidMemoryOperationException>(ex.InnerException);
}
@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
{
TestImageProvider<TPixel> provider = BasicSerializer.Deserialize<TestImageProvider<TPixel>>(providerDump);
provider.LimitAllocatorBufferCapacity();
provider.LimitAllocatorBufferCapacity().InPixels(200);
using Image<TPixel> image = provider.GetImage(new TgaDecoder());
image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr);

2
tests/ImageSharp.Tests/Formats/Tga/TgaEncoderTests.cs

@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tga
public void Encode_WorksWithDiscontiguousBuffers<TPixel>(TestImageProvider<TPixel> provider, TgaBitsPerPixel bitsPerPixel)
where TPixel : struct, IPixel<TPixel>
{
provider.LimitAllocatorBufferCapacity(10000);
provider.LimitAllocatorBufferCapacity().InPixels(100);
TestTgaEncoderCore(provider, bitsPerPixel, TgaCompression.RunLength);
}

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

@ -666,13 +666,12 @@ namespace SixLabors.ImageSharp.Tests
}
}
internal static void LimitAllocatorBufferCapacity<TPixel>(
this TestImageProvider<TPixel> provider,
int bufferCapacityInPixels = 40000) // 200 x 200
internal static AllocatorBufferCapacityConfigurator LimitAllocatorBufferCapacity<TPixel>(
this TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
var allocator = (ArrayPoolMemoryAllocator)provider.Configuration.MemoryAllocator;
allocator.BufferCapacityInBytes = Unsafe.SizeOf<TPixel>() * bufferCapacityInPixels;
return new AllocatorBufferCapacityConfigurator(allocator, Unsafe.SizeOf<TPixel>());
}
internal static Image<Rgba32> ToGrayscaleImage(this Buffer2D<float> buffer, float scale)
@ -734,4 +733,32 @@ namespace SixLabors.ImageSharp.Tests
}
}
}
internal class AllocatorBufferCapacityConfigurator
{
private readonly ArrayPoolMemoryAllocator allocator;
private readonly int pixelSizeInBytes;
public AllocatorBufferCapacityConfigurator(ArrayPoolMemoryAllocator allocator, int pixelSizeInBytes)
{
this.allocator = allocator;
this.pixelSizeInBytes = pixelSizeInBytes;
}
/// <summary>
/// Set the maximum buffer capacity to (areaDimensionBytes x areaDimensionBytes) bytes.
/// </summary>
public void InBytes(int areaDimensionBytes)
{
this.allocator.BufferCapacityInBytes = areaDimensionBytes * areaDimensionBytes;
}
/// <summary>
/// Set the maximum buffer capacity to (areaDimensionPixels x areaDimensionPixels x size of the pixel) bytes.
/// </summary>
public void InPixels(int areaDimensionPixels)
{
this.allocator.BufferCapacityInBytes = areaDimensionPixels * areaDimensionPixels * this.pixelSizeInBytes;
}
}
}

Loading…
Cancel
Save