Browse Source

CalculateJpegChannelSize()

af/merge-core
Anton Firszov 9 years ago
parent
commit
352198db4d
  1. 65
      src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs
  2. 5
      src/ImageSharp/Formats/Jpeg/Common/IJpegComponent.cs
  3. 41
      src/ImageSharp/Formats/Jpeg/Common/SubsampleRatio.cs
  4. 20
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs
  5. 15
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs
  6. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrImage.cs
  7. 23
      src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs
  8. 14
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs
  9. 2
      src/ImageSharp/Formats/Jpeg/PdfJsPort/JpegDecoderCore.cs
  10. 9
      src/ImageSharp/Memory/Buffer2D.cs
  11. 2
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
  12. 2
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs
  13. 124
      tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs
  14. 16
      tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs
  15. 7
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs
  16. 4
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs
  17. 10
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs
  18. 4
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs
  19. 2
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.cs
  20. 67
      tests/ImageSharp.Tests/Formats/Jpg/SubsampleRatioTests.cs
  21. 18
      tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs

65
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/SubsampleRatio.cs → src/ImageSharp/Formats/Jpeg/Common/ComponentUtils.cs

@ -1,54 +1,18 @@
using System.Collections.Generic;
using System.Linq;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{
/// <summary>
/// Provides enumeration of the various available subsample ratios.
/// https://en.wikipedia.org/wiki/Chroma_subsampling
/// </summary>
internal enum SubsampleRatio
{
Undefined,
/// <summary>
/// 4:4:4
/// </summary>
Ratio444,
/// <summary>
/// 4:2:2
/// </summary>
Ratio422,
/// <summary>
/// 4:2:0
/// </summary>
Ratio420,
/// <summary>
/// 4:4:0
/// </summary>
Ratio440,
/// <summary>
/// 4:1:1
/// </summary>
Ratio411,
/// <summary>
/// 4:1:0
/// </summary>
Ratio410,
}
using System;
/// <summary>
/// Various utilities for <see cref="SubsampleRatio"/>
/// Various utilities for <see cref="SubsampleRatio"/> and <see cref="IJpegComponent"/>.
/// </summary>
internal static class Subsampling
internal static class ComponentUtils
{
public static Size SizeInBlocks(this IJpegComponent component) => new Size(component.WidthInBlocks, component.HeightInBlocks);
public static SubsampleRatio GetSubsampleRatio(int horizontalRatio, int verticalRatio)
{
switch ((horizontalRatio << 4) | verticalRatio)
@ -113,5 +77,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
return new Size(width, height);
}
}
public static bool IsChromaComponent(this IJpegComponent component) =>
component.Index > 0 && component.Index < 3;
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;
}
}
}
}

5
src/ImageSharp/Formats/Jpeg/Common/IJpegComponent.cs

@ -2,6 +2,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{
internal interface IJpegComponent
{
/// <summary>
/// Gets the component's position in the components array.
/// </summary>
int Index { get; }
/// <summary>
/// Gets the number of blocks per line
/// </summary>

41
src/ImageSharp/Formats/Jpeg/Common/SubsampleRatio.cs

@ -0,0 +1,41 @@
namespace SixLabors.ImageSharp.Formats.Jpeg.Common
{
/// <summary>
/// Provides enumeration of the various available subsample ratios.
/// https://en.wikipedia.org/wiki/Chroma_subsampling
/// </summary>
internal enum SubsampleRatio
{
Undefined,
/// <summary>
/// 4:4:4
/// </summary>
Ratio444,
/// <summary>
/// 4:2:2
/// </summary>
Ratio422,
/// <summary>
/// 4:2:0
/// </summary>
Ratio420,
/// <summary>
/// 4:4:0
/// </summary>
Ratio440,
/// <summary>
/// 4:1:1
/// </summary>
Ratio411,
/// <summary>
/// 4:1:0
/// </summary>
Ratio410,
}
}

20
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigComponent.cs

@ -25,9 +25,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// </summary>
public byte Identifier { get; }
/// <summary>
/// Gets the component's position in <see cref="OrigJpegDecoderCore.Components"/>
/// </summary>
/// <inheritdoc />
public int Index { get; }
/// <inheritdoc />
@ -44,7 +42,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// <summary>
/// Gets the <see cref="Buffer{T}"/> storing the "raw" frequency-domain decoded blocks.
/// We need to apply IDCT, dequantiazition and unzigging to transform them into color-space blocks.
/// This is done by <see cref="OrigJpegDecoderCore.ProcessBlocksIntoJpegImageChannels{TPixel}"/>.
/// This is done by <see cref="OrigJpegDecoderCore.ProcessBlocksIntoJpegImageChannels"/>.
/// When <see cref="OrigJpegDecoderCore.IsProgressive"/> us true, we are touching these blocks multiple times - each time we process a Scan.
/// </summary>
public Buffer2D<Block8x8> SpectralBlocks { get; private set; }
@ -224,20 +222,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.VerticalSamplingFactor = v;
}
public Size CalculateJpegChannelSize(SubsampleRatio ratio)
{
Size size = new Size(this.WidthInBlocks, this.HeightInBlocks) * 8;
if (this.Index > 0 && this.Index < 3) // Chroma component:
{
return ratio.CalculateChrominanceSize(size.Width, size.Height);
}
else
{
return size;
}
}
public void Dispose()
{
this.SpectralBlocks.Dispose();

15
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigJpegPixelArea.cs

@ -5,9 +5,11 @@ using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{
{
/// <summary>
/// Represents an area of a Jpeg subimage (channel)
/// </summary>
@ -36,6 +38,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{
}
public OrigJpegPixelArea(Size size)
: this(Buffer2D<byte>.CreateClean(size))
{
}
/// <summary>
/// Gets the pixels buffer.
/// </summary>
@ -76,6 +83,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
}
}
public static OrigJpegPixelArea CreateForComponent(IJpegComponent component, SubsampleRatio ratio = SubsampleRatio.Undefined)
{
Size size = component.CalculateJpegChannelSize(ratio);
return new OrigJpegPixelArea(size);
}
/// <summary>
/// Gets the subarea that belongs to the Block8x8 defined by block indices
/// </summary>

2
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/YCbCrImage.cs

@ -7,6 +7,8 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{
using SixLabors.ImageSharp.Formats.Jpeg.Common;
/// <summary>
/// Represents an image made up of three color components (luminance, blue chroma, red chroma)
/// </summary>

23
src/ImageSharp/Formats/Jpeg/GolangPort/OrigJpegDecoderCore.cs

@ -17,6 +17,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
{
using System.Linq;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.Primitives;
/// <summary>
/// Performs the jpeg decoding operation.
/// </summary>
@ -112,7 +115,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
}
/// <summary>
/// Gets the <see cref="GolangPort.Components.Decoder.SubsampleRatio"/> ratio.
/// Gets the <see cref="Common.SubsampleRatio"/> ratio.
/// </summary>
public SubsampleRatio SubsampleRatio { get; private set; }
@ -775,29 +778,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
}
/// <summary>
/// Makes the image from the buffer.
/// Initializes the image channels.
/// </summary>
private void InitJpegImageChannels()
{
if (this.ComponentCount == 1)
{
var buffer = Buffer2D<byte>.CreateClean(8 * this.MCUCountX, 8 * this.MCUCountY);
this.grayImage = new OrigJpegPixelArea(buffer);
this.grayImage = OrigJpegPixelArea.CreateForComponent(this.Components[0]);
}
else
{
int h0 = this.Components[0].HorizontalSamplingFactor;
int v0 = this.Components[0].VerticalSamplingFactor;
Size size = this.Components[0].CalculateJpegChannelSize();
this.ycbcrImage = new YCbCrImage(8 * h0 * this.MCUCountX, 8 * v0 * this.MCUCountY, this.SubsampleRatio);
this.ycbcrImage = new YCbCrImage(size.Width, size.Height, this.SubsampleRatio);
if (this.ComponentCount == 4)
{
int h3 = this.Components[3].HorizontalSamplingFactor;
int v3 = this.Components[3].VerticalSamplingFactor;
var buffer = Buffer2D<byte>.CreateClean(8 * h3 * this.MCUCountX, 8 * v3 * this.MCUCountY);
this.blackImage = new OrigJpegPixelArea(buffer);
this.blackImage = OrigJpegPixelArea.CreateForComponent(this.Components[3]);
}
}
}
@ -1198,7 +1195,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
this.Components[i].InitializeBlocks(this);
}
this.SubsampleRatio = Subsampling.GetSubsampleRatio(this.Components);
this.SubsampleRatio = ComponentUtils.GetSubsampleRatio(this.Components);
}
}
}

14
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs

@ -16,13 +16,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
#pragma warning disable SA1401 // Fields should be private
public PdfJsFrameComponent(PdfJsFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationIdentifier)
public PdfJsFrameComponent(PdfJsFrame frame, byte id, int horizontalFactor, int verticalFactor, byte quantizationIdentifier, int index)
{
this.Frame = frame;
this.Id = id;
this.HorizontalSamplingFactor = horizontalFactor;
this.VerticalSamplingFactor = verticalFactor;
this.QuantizationIdentifier = quantizationIdentifier;
this.Index = index;
}
/// <summary>
@ -35,14 +36,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary>
public int Pred { get; set; }
/// <summary>
/// Gets the horizontal sampling factor.
/// </summary>
/// <inheritdoc />
public int HorizontalSamplingFactor { get; }
/// <summary>
/// Gets the vertical sampling factor.
/// </summary>
/// <inheritdoc />
public int VerticalSamplingFactor { get; }
/// <summary>
@ -55,6 +52,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary>
public Buffer<short> BlockData { get; private set; }
/// <inheritdoc />
public int Index { get; }
/// <summary>
/// Gets the number of blocks per line
/// </summary>

2
src/ImageSharp/Formats/Jpeg/PdfJsPort/JpegDecoderCore.cs

@ -676,7 +676,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
maxV = v;
}
var component = new PdfJsFrameComponent(this.Frame, this.temp[index], h, v, this.temp[index + 2]);
var component = new PdfJsFrameComponent(this.Frame, this.temp[index], h, v, this.temp[index + 2], i);
this.Frame.Components[i] = component;
this.Frame.ComponentIds[i] = component.Id;

9
src/ImageSharp/Memory/Buffer2D.cs

@ -5,6 +5,8 @@ using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Memory
{
using SixLabors.Primitives;
/// <summary>
/// Represents a buffer of value type objects
/// interpreted as a 2D region of <see cref="Width"/> x <see cref="Height"/> elements.
@ -71,5 +73,12 @@ namespace SixLabors.ImageSharp.Memory
buffer.Clear();
return buffer;
}
/// <summary>
/// Creates a clean instance of <see cref="Buffer2D{T}"/> initializing it's elements with 'default(T)'.
/// </summary>
/// <param name="size">The size of the buffer</param>
/// <returns>The <see cref="Buffer2D{T}"/> instance</returns>
public static Buffer2D<T> CreateClean(Size size) => CreateClean(size.Width, size.Height);
}
}

2
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 : JpegUtilityTestFixture
public class Block8x8FTests : JpegFixture
{
#if BENCHMARKING
public const int Times = 1000000;

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

@ -7,7 +7,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
using Xunit;
using Xunit.Abstractions;
public class Block8x8Tests : JpegUtilityTestFixture
public class Block8x8Tests : JpegFixture
{
public Block8x8Tests(ITestOutputHelper output)
: base(output)

124
tests/ImageSharp.Tests/Formats/Jpg/ComponentUtilsTests.cs

@ -0,0 +1,124 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder;
using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils;
using SixLabors.Primitives;
using Xunit;
using Xunit.Abstractions;
public class ComponentUtilsTests
{
public ComponentUtilsTests(ITestOutputHelper output)
{
this.Output = output;
}
private ITestOutputHelper Output { get; }
[Theory]
[InlineData(SubsampleRatio.Ratio410, 4, 2)]
[InlineData(SubsampleRatio.Ratio411, 4, 1)]
[InlineData(SubsampleRatio.Ratio420, 2, 2)]
[InlineData(SubsampleRatio.Ratio422, 2, 1)]
[InlineData(SubsampleRatio.Ratio440, 1, 2)]
[InlineData(SubsampleRatio.Ratio444, 1, 1)]
internal void CalculateChrominanceSize(
SubsampleRatio ratio,
int expectedDivX,
int expectedDivY)
{
//this.Output.WriteLine($"RATIO: {ratio}");
Size size = ratio.CalculateChrominanceSize(400, 400);
//this.Output.WriteLine($"Ch Size: {size}");
Assert.Equal(new Size(400 / expectedDivX, 400 / expectedDivY), size);
}
[Theory]
[InlineData(SubsampleRatio.Ratio410, 4)]
[InlineData(SubsampleRatio.Ratio411, 4)]
[InlineData(SubsampleRatio.Ratio420, 2)]
[InlineData(SubsampleRatio.Ratio422, 2)]
[InlineData(SubsampleRatio.Ratio440, 1)]
[InlineData(SubsampleRatio.Ratio444, 1)]
internal void Create(SubsampleRatio ratio, int expectedCStrideDiv)
{
this.Output.WriteLine($"RATIO: {ratio}");
YCbCrImage img = new YCbCrImage(400, 400, ratio);
//this.PrintChannel("Y", img.YChannel);
//this.PrintChannel("Cb", img.CbChannel);
//this.PrintChannel("Cr", img.CrChannel);
Assert.Equal(400, img.YChannel.Width);
Assert.Equal(img.CbChannel.Width, 400 / expectedCStrideDiv);
Assert.Equal(img.CrChannel.Width, 400 / expectedCStrideDiv);
}
private void PrintChannel(string name, OrigJpegPixelArea channel)
{
this.Output.WriteLine($"{name}: Stride={channel.Stride}");
}
[Fact]
public void CalculateJpegChannelSize_Grayscale()
{
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(TestImages.Jpeg.Baseline.Jpeg400))
{
Assert.Equal(1, decoder.ComponentCount);
Size expected = decoder.Components[0].SizeInBlocks() * 8;
Size actual = decoder.Components[0].CalculateJpegChannelSize(decoder.SubsampleRatio);
Assert.Equal(expected, actual);
}
}
[Theory]
[InlineData(TestImages.Jpeg.Baseline.Calliphora, 1)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg444, 1)]
[InlineData(TestImages.Jpeg.Baseline.Jpeg420, 2)]
public void CalculateJpegChannelSize_YCbCr(
string imageFile,
int chromaDiv)
{
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile))
{
Size ySize = decoder.Components[0].SizeInBlocks() * 8;
Size cSize = decoder.Components[1].SizeInBlocks() * 8 / chromaDiv;
Size s0 = decoder.Components[0].CalculateJpegChannelSize(decoder.SubsampleRatio);
Size s1 = decoder.Components[1].CalculateJpegChannelSize(decoder.SubsampleRatio);
Size s2 = decoder.Components[2].CalculateJpegChannelSize(decoder.SubsampleRatio);
Assert.Equal(ySize, s0);
Assert.Equal(cSize, s1);
Assert.Equal(cSize, s2);
}
}
[Theory]
[InlineData(TestImages.Jpeg.Baseline.Ycck)]
[InlineData(TestImages.Jpeg.Baseline.Cmyk)]
public void CalculateJpegChannelSize_4Chan(string imageFile)
{
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(imageFile))
{
Size expected = decoder.Components[0].SizeInBlocks() * 8;
foreach (OrigComponent component in decoder.Components)
{
Size actual = component.CalculateJpegChannelSize(decoder.SubsampleRatio);
Assert.Equal(expected, actual);
}
}
}
}
}

16
tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public static class DCTTests
{
public class FastFloatingPoint : JpegUtilityTestFixture
public class FastFloatingPoint : JpegFixture
{
public FastFloatingPoint(ITestOutputHelper output)
: base(output)
@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact]
public void iDCT2D8x4_LeftPart()
{
float[] sourceArray = JpegUtilityTestFixture.Create8x8FloatData();
float[] sourceArray = JpegFixture.Create8x8FloatData();
float[] expectedDestArray = new float[64];
ReferenceImplementations.LLM_FloatingPoint_DCT.iDCT2D8x4_32f(sourceArray, expectedDestArray);
@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact]
public void iDCT2D8x4_RightPart()
{
float[] sourceArray = JpegUtilityTestFixture.Create8x8FloatData();
float[] sourceArray = JpegFixture.Create8x8FloatData();
float[] expectedDestArray = new float[64];
ReferenceImplementations.LLM_FloatingPoint_DCT.iDCT2D8x4_32f(sourceArray.AsSpan().Slice(4), expectedDestArray.AsSpan().Slice(4));
@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(3)]
public void LLM_TransformIDCT_CompareToNonOptimized(int seed)
{
float[] sourceArray = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed);
float[] sourceArray = JpegFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed);
var source = Block8x8F.Load(sourceArray);
@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(3)]
public void LLM_TransformIDCT_CompareToAccurate(int seed)
{
float[] sourceArray = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed);
float[] sourceArray = JpegFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed);
var source = Block8x8F.Load(sourceArray);
@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)]
public void FDCT8x4_LeftPart(int seed)
{
Span<float> src = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-200, 200, seed);
Span<float> src = JpegFixture.Create8x8RoundedRandomFloatData(-200, 200, seed);
Block8x8F srcBlock = new Block8x8F();
srcBlock.LoadFrom(src);
@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)]
public void FDCT8x4_RightPart(int seed)
{
Span<float> src = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-200, 200, seed);
Span<float> src = JpegFixture.Create8x8RoundedRandomFloatData(-200, 200, seed);
Block8x8F srcBlock = new Block8x8F();
srcBlock.LoadFrom(src);
@ -158,7 +158,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)]
public void TransformFDCT(int seed)
{
Span<float> src = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-200, 200, seed);
Span<float> src = JpegFixture.Create8x8RoundedRandomFloatData(-200, 200, seed);
Block8x8F srcBlock = new Block8x8F();
srcBlock.LoadFrom(src);

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

@ -65,12 +65,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Fact(Skip = "Doesn't really matter")]
public void ParseStream_BasicPropertiesAreCorrect1_Orig()
{
byte[] bytes = TestFile.Create(TestImages.Jpeg.Progressive.Progress).Bytes;
using (var ms = new MemoryStream(bytes))
using (OrigJpegDecoderCore decoder = JpegFixture.ParseStream(TestImages.Jpeg.Progressive.Progress))
{
var decoder = new OrigJpegDecoderCore(Configuration.Default, new JpegDecoder());
decoder.ParseStream(ms);
VerifyJpeg.Components3(decoder.Components, 43, 61, 22, 31, 22, 31);
}
}
@ -95,7 +91,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void DecodeBaselineJpeg_PdfJs<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(PdfJsJpegDecoder))
{
image.DebugSave(provider);

4
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public partial class ReferenceImplementationsTests
{
public class AccurateDCT : JpegUtilityTestFixture
public class AccurateDCT : JpegFixture
{
public AccurateDCT(ITestOutputHelper output)
: base(output)
@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)]
public void ForwardThenInverse(int seed)
{
float[] data = JpegUtilityTestFixture.Create8x8RandomFloatData(-1000, 1000, seed);
float[] data = JpegFixture.Create8x8RandomFloatData(-1000, 1000, seed);
var b0 = default(Block8x8F);
b0.LoadFrom(data);

10
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public partial class ReferenceImplementationsTests
{
public class FastFloatingPointDCT : JpegUtilityTestFixture
public class FastFloatingPointDCT : JpegFixture
{
public FastFloatingPointDCT(ITestOutputHelper output)
: base(output)
@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2, 0)]
public void LLM_ForwardThenInverse(int seed, int startAt)
{
int[] data = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed);
int[] data = JpegFixture.Create8x8RandomIntData(-1000, 1000, seed);
float[] original = data.ConvertAllToFloat();
float[] src = data.ConvertAllToFloat();
float[] dest = new float[64];
@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2, 200)]
public void LLM_IDCT_IsEquivalentTo_AccurateImplementation(int seed, int range)
{
float[] sourceArray = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed);
float[] sourceArray = JpegFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed);
var source = Block8x8F.Load(sourceArray);
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)]
public void LLM_FDCT_IsEquivalentTo_AccurateImplementation(int seed)
{
float[] floatData = JpegUtilityTestFixture.Create8x8RandomFloatData(-1000, 1000);
float[] floatData = JpegFixture.Create8x8RandomFloatData(-1000, 1000);
Block8x8F source = default(Block8x8F);
source.LoadFrom(floatData);
@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2, 200)]
public void GT_IDCT_IsEquivalentTo_AccurateImplementation(int seed, int range)
{
int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-range, range, seed);
int[] intData = JpegFixture.Create8x8RandomIntData(-range, range, seed);
float[] floatSrc = intData.ConvertAllToFloat();
ReferenceImplementations.AccurateDCT.TransformIDCTInplace(intData);

4
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public partial class ReferenceImplementationsTests
{
public class StandardIntegerDCT : JpegUtilityTestFixture
public class StandardIntegerDCT : JpegFixture
{
public StandardIntegerDCT(ITestOutputHelper output)
: base(output)
@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2, 0)]
public void ForwardThenInverse(int seed, int startAt)
{
Span<int> original = JpegUtilityTestFixture.Create8x8RandomIntData(-200, 200, seed);
Span<int> original = JpegFixture.Create8x8RandomIntData(-200, 200, seed);
Span<int> block = original.AddScalarToAllValues(128);

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

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils;
public partial class ReferenceImplementationsTests : JpegUtilityTestFixture
public partial class ReferenceImplementationsTests : JpegFixture
{
public ReferenceImplementationsTests(ITestOutputHelper output)
: base(output)

67
tests/ImageSharp.Tests/Formats/Jpg/SubsampleRatioTests.cs

@ -1,67 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder;
using SixLabors.Primitives;
using Xunit;
using Xunit.Abstractions;
public class SubsampleRatioTests
{
public SubsampleRatioTests(ITestOutputHelper output)
{
this.Output = output;
}
private ITestOutputHelper Output { get; }
[Theory]
[InlineData(SubsampleRatio.Ratio410, 4, 2)]
[InlineData(SubsampleRatio.Ratio411, 4, 1)]
[InlineData(SubsampleRatio.Ratio420, 2, 2)]
[InlineData(SubsampleRatio.Ratio422, 2, 1)]
[InlineData(SubsampleRatio.Ratio440, 1, 2)]
[InlineData(SubsampleRatio.Ratio444, 1, 1)]
internal void CalculateChrominanceSize(
SubsampleRatio ratio,
int expectedDivX,
int expectedDivY)
{
//this.Output.WriteLine($"RATIO: {ratio}");
Size size = ratio.CalculateChrominanceSize(400, 400);
//this.Output.WriteLine($"Ch Size: {size}");
Assert.Equal(new Size(400 / expectedDivX, 400 / expectedDivY), size);
}
[Theory]
[InlineData(SubsampleRatio.Ratio410, 4)]
[InlineData(SubsampleRatio.Ratio411, 4)]
[InlineData(SubsampleRatio.Ratio420, 2)]
[InlineData(SubsampleRatio.Ratio422, 2)]
[InlineData(SubsampleRatio.Ratio440, 1)]
[InlineData(SubsampleRatio.Ratio444, 1)]
internal void Create(SubsampleRatio ratio, int expectedCStrideDiv)
{
this.Output.WriteLine($"RATIO: {ratio}");
YCbCrImage img = new YCbCrImage(400, 400, ratio);
//this.PrintChannel("Y", img.YChannel);
//this.PrintChannel("Cb", img.CbChannel);
//this.PrintChannel("Cr", img.CrChannel);
Assert.Equal(400, img.YChannel.Width);
Assert.Equal(img.CbChannel.Width, 400 / expectedCStrideDiv);
Assert.Equal(img.CrChannel.Width, 400 / expectedCStrideDiv);
}
private void PrintChannel(string name, OrigJpegPixelArea channel)
{
this.Output.WriteLine($"{name}: Stride={channel.Stride}");
}
}
}

18
tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegUtilityTestFixture.cs → tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegFixture.cs

@ -9,16 +9,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
{
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.Formats.Jpeg.Common;
using SixLabors.ImageSharp.Formats.Jpeg.GolangPort;
using Xunit;
using Xunit.Abstractions;
public class JpegUtilityTestFixture : MeasureFixture
public class JpegFixture : MeasureFixture
{
public JpegUtilityTestFixture(ITestOutputHelper output) : base(output)
public JpegFixture(ITestOutputHelper output) : base(output)
{
}
@ -166,5 +169,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
this.Output.WriteLine("TOTAL DIFF: "+totalDifference);
Assert.False(failed);
}
internal static OrigJpegDecoderCore ParseStream(string testFileName)
{
byte[] bytes = TestFile.Create(testFileName).Bytes;
using (var ms = new MemoryStream(bytes))
{
var decoder = new OrigJpegDecoderCore(Configuration.Default, new JpegDecoder());
decoder.ParseStream(ms);
return decoder;
}
}
}
}
Loading…
Cancel
Save