Browse Source

Fixed new spectral tests for progressive and multi-scan images

pull/1694/head
Dmitry Pentin 5 years ago
parent
commit
19e2e3d40d
  1. 62
      tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
  2. 31
      tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.ComponentData.cs

62
tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs

@ -61,7 +61,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
VerifyJpeg.SaveSpectralImage(provider, data);
}
[Theory(Skip = "Temporary skipped due to new decoder core architecture")]
//[Theory(Skip = "Temporary skipped due to new decoder core architecture")]
[Theory]
[WithFileCollection(nameof(AllTestJpegs), PixelTypes.Rgba32)]
public void VerifySpectralCorrectness<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
@ -86,12 +87,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var scanDecoder = new HuffmanScanDecoder(bufferedStream, debugConverter, cancellationToken: default);
// This would parse entire image
// Due to underlying architecture, baseline interleaved jpegs would be tested inside the parsing loop
// Everything else must be checked manually after this method
decoder.ParseStream(bufferedStream, scanDecoder, ct: default);
var imageSharpData = LibJpegTools.SpectralData.LoadFromImageSharpDecoder(decoder);
this.VerifySpectralCorrectnessImpl(libJpegData, imageSharpData);
// Actual verification
this.VerifySpectralCorrectnessImpl(libJpegData, debugConverter.SpectralData);
}
private void VerifySpectralCorrectnessImpl(
@ -141,27 +140,74 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
private readonly SpectralConverter<TPixel> converter;
private JpegFrame frame;
private LibJpegTools.SpectralData spectralData;
private int baselineScanRowCounter;
public DebugSpectralConverter(Configuration configuration, CancellationToken cancellationToken)
=> this.converter = new SpectralConverter<TPixel>(configuration, cancellationToken);
public LibJpegTools.SpectralData SpectralData
{
get
{
// Due to underlying architecture, baseline interleaved jpegs would inject spectral data during parsing
// Progressive and multi-scan images must be loaded manually
if (this.frame.Progressive || this.frame.MultiScan)
{
LibJpegTools.ComponentData[] components = this.spectralData.Components;
for (int i = 0; i < components.Length; i++)
{
components[i].LoadSpectral(this.frame.Components[i]);
}
}
return this.spectralData;
}
}
public override void ConvertStrideBaseline()
{
this.converter.ConvertStrideBaseline();
// This would be called only for baseline non-interleaved images
// We must test spectral strides here
LibJpegTools.ComponentData[] components = this.spectralData.Components;
for (int i = 0; i < components.Length; i++)
{
components[i].LoadSpectralStride(this.frame.Components[i].SpectralBlocks, this.baselineScanRowCounter);
}
this.baselineScanRowCounter++;
}
public override void Dispose()
{
this.converter?.Dispose();
// As we are only testing spectral data we don't care about pixels
// But we need to dispose allocated pixel buffer
this.converter.PixelBuffer.Dispose();
// Converter Dispose must be called after pixel buffer disposal because pixel buffer getter can do a full scan conversion
this.converter?.Dispose();
}
public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) => this.converter.InjectFrameData(frame, jpegData);
public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData)
{
this.converter.InjectFrameData(frame, jpegData);
this.frame = frame;
var spectralComponents = new LibJpegTools.ComponentData[frame.ComponentCount];
for (int i = 0; i < spectralComponents.Length; i++)
{
JpegComponent component = frame.Components[i];
spectralComponents[i] = new LibJpegTools.ComponentData(component.WidthInBlocks, component.HeightInBlocks, component.Index);
}
this.spectralData = new LibJpegTools.SpectralData(spectralComponents);
}
}
}
}

31
tests/ImageSharp.Tests/Formats/Jpg/Utils/LibJpegTools.ComponentData.cs

@ -56,6 +56,37 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
this.SpectralBlocks[x, y] = new Block8x8(data);
}
public void LoadSpectralStride(Buffer2D<Block8x8> data, int strideIndex)
{
for (int y = 0; y < data.Height; y++)
{
Span<Block8x8> blockRow = data.GetRowSpan(y);
for (int x = 0; x < data.Width; x++)
{
short[] block = blockRow[x].ToArray();
// x coordinate stays the same - we load entire stride
// y coordinate is tricky as we load single stride to full buffer - offset is needed
int yOffset = strideIndex * data.Height;
this.MakeBlock(block, y + yOffset, x);
}
}
}
public void LoadSpectral(JpegComponent c)
{
Buffer2D<Block8x8> data = c.SpectralBlocks;
for (int y = 0; y < c.HeightInBlocks; y++)
{
Span<Block8x8> blockRow = data.GetRowSpan(y);
for (int x = 0; x < c.WidthInBlocks; x++)
{
short[] block = blockRow[x].ToArray();
this.MakeBlock(block, y, x);
}
}
}
public static ComponentData Load(JpegComponent c, int index)
{
var result = new ComponentData(

Loading…
Cancel
Save