Browse Source

Decode Jpegs to non-contiguous buffers

af/octree-no-pixelmap
Anton Firszov 6 years ago
parent
commit
d2b99294f7
  1. 2
      src/ImageSharp/ImageFrame{TPixel}.cs
  2. 21
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs
  3. 21
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs
  4. 21
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  5. 20
      tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs
  6. 11
      tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs

2
src/ImageSharp/ImageFrame{TPixel}.cs

@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp
Guard.NotNull(source, nameof(source));
this.PixelBuffer = this.GetConfiguration().MemoryAllocator.Allocate2D<TPixel>(source.PixelBuffer.Width, source.PixelBuffer.Height);
source.PixelBuffer.GetSingleSpan().CopyTo(this.PixelBuffer.GetSingleSpan());
source.PixelBuffer.MemoryGroup.CopyTo(this.PixelBuffer.MemoryGroup);
}
/// <summary>

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

@ -4,6 +4,7 @@
using Microsoft.DotNet.RemoteExecutor;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using Xunit;
// ReSharper disable InconsistentNaming
@ -12,17 +13,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public partial class JpegDecoderTests
{
[Theory]
[WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32)]
public void DecodeBaselineJpeg<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32, false)]
[WithFile(TestImages.Jpeg.Baseline.Calliphora, PixelTypes.Rgba32, true)]
public void DecodeBaselineJpeg<TPixel>(TestImageProvider<TPixel> provider, bool enforceNonContiguousBuffers)
where TPixel : struct, IPixel<TPixel>
{
static void RunTest(string providerDump)
static void RunTest(string providerDump, string nonContiguousBuffersStr)
{
TestImageProvider<TPixel> provider =
BasicSerializer.Deserialize<TestImageProvider<TPixel>>(providerDump);
if (!string.IsNullOrEmpty(nonContiguousBuffersStr))
{
provider.LimitAllocatorBufferCapacity();
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
image.DebugSave(provider, testOutputDetails: nonContiguousBuffersStr);
provider.Utility.TestName = DecodeBaselineJpegOutputName;
image.CompareToReferenceOutput(
@ -32,7 +39,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
string providerDump = BasicSerializer.Serialize(provider);
RemoteExecutor.Invoke(RunTest, providerDump).Dispose();
RemoteExecutor.Invoke(
RunTest,
providerDump,
enforceNonContiguousBuffers ? "NonContiguous" : string.Empty)
.Dispose();
}
[Theory]

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

@ -14,17 +14,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public const string DecodeProgressiveJpegOutputName = "DecodeProgressiveJpeg";
[Theory]
[WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32)]
public void DecodeProgressiveJpeg<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32, false)]
[WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32, true)]
public void DecodeProgressiveJpeg<TPixel>(TestImageProvider<TPixel> provider, bool enforceNonContiguousBuffers)
where TPixel : struct, IPixel<TPixel>
{
static void RunTest(string providerDump)
static void RunTest(string providerDump, string nonContiguousBuffersStr)
{
TestImageProvider<TPixel> provider =
BasicSerializer.Deserialize<TestImageProvider<TPixel>>(providerDump);
if (!string.IsNullOrEmpty(nonContiguousBuffersStr))
{
provider.LimitAllocatorBufferCapacity();
}
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
image.DebugSave(provider, nonContiguousBuffersStr);
provider.Utility.TestName = DecodeProgressiveJpegOutputName;
image.CompareToReferenceOutput(
@ -33,8 +39,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
appendPixelTypeToFileName: false);
}
string dump = BasicSerializer.Serialize(provider);
RemoteExecutor.Invoke(RunTest, dump).Dispose();
string providerDump = BasicSerializer.Serialize(provider);
RemoteExecutor.Invoke(
RunTest,
providerDump,
enforceNonContiguousBuffers ? "NonContiguous" : string.Empty);
}
}
}

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

@ -95,19 +95,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void JpegDecoder_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
static void RunTest(string providerDump)
{
TestImageProvider<TPixel> provider =
BasicSerializer.Deserialize<TestImageProvider<TPixel>>(providerDump);
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
provider.Utility.TestName = DecodeBaselineJpegOutputName;
image.CompareToReferenceOutput(ImageComparer.Tolerant(BaselineTolerance), provider, appendPixelTypeToFileName: false);
}
string dump = BasicSerializer.Serialize(provider);
RemoteExecutor.Invoke(RunTest, dump).Dispose();
using Image<TPixel> image = provider.GetImage(JpegDecoder);
image.DebugSave(provider);
provider.Utility.TestName = DecodeBaselineJpegOutputName;
image.CompareToReferenceOutput(
ImageComparer.Tolerant(BaselineTolerance),
provider,
appendPixelTypeToFileName: false);
}
// DEBUG ONLY!

20
tests/ImageSharp.Tests/TestUtilities/ImageProviders/FileProvider.cs

@ -22,14 +22,18 @@ namespace SixLabors.ImageSharp.Tests
// are shared between PixelTypes.Color & PixelTypes.Rgba32
private class Key : IEquatable<Key>
{
private Tuple<PixelTypes, string, Type> commonValues;
private readonly Tuple<PixelTypes, string, Type, int> commonValues;
private Dictionary<string, object> decoderParameters;
private readonly Dictionary<string, object> decoderParameters;
public Key(PixelTypes pixelType, string filePath, IImageDecoder customDecoder)
public Key(PixelTypes pixelType, string filePath, int allocatorBufferCapacity, IImageDecoder customDecoder)
{
Type customType = customDecoder?.GetType();
this.commonValues = new Tuple<PixelTypes, string, Type>(pixelType, filePath, customType);
this.commonValues = new Tuple<PixelTypes, string, Type, int>(
pixelType,
filePath,
customType,
allocatorBufferCapacity);
this.decoderParameters = GetDecoderParameters(customDecoder);
}
@ -147,12 +151,8 @@ namespace SixLabors.ImageSharp.Tests
{
Guard.NotNull(decoder, nameof(decoder));
if (!TestEnvironment.Is64BitProcess)
{
return this.LoadImage(decoder);
}
var key = new Key(this.PixelType, this.FilePath, decoder);
int bufferCapacity = this.Configuration.MemoryAllocator.GetBufferCapacityInBytes();
var key = new Key(this.PixelType, this.FilePath, bufferCapacity, decoder);
Image<TPixel> cachedImage = Cache.GetOrAdd(key, _ => this.LoadImage(decoder));

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

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Advanced.ParallelUtils;
using SixLabors.ImageSharp.Formats;
@ -666,6 +666,15 @@ namespace SixLabors.ImageSharp.Tests
}
}
internal static void LimitAllocatorBufferCapacity<TPixel>(
this TestImageProvider<TPixel> provider,
int bufferCapacityInPixels = 40000) // 200 x 200
where TPixel : struct, IPixel<TPixel>
{
var allocator = (ArrayPoolMemoryAllocator)provider.Configuration.MemoryAllocator;
allocator.BufferCapacityInBytes = Unsafe.SizeOf<TPixel>() * bufferCapacityInPixels;
}
internal static Image<Rgba32> ToGrayscaleImage(this Buffer2D<float> buffer, float scale)
{
var image = new Image<Rgba32>(buffer.Width, buffer.Height);

Loading…
Cancel
Save