mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
5 changed files with 394 additions and 52 deletions
@ -0,0 +1,241 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.ImageSharp.Formats.Jpeg.Components; |
|||
using SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder; |
|||
using SixLabors.ImageSharp.Tests.TestUtilities; |
|||
using Xunit; |
|||
using Xunit.Abstractions; |
|||
|
|||
// ReSharper disable InconsistentNaming
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Jpg |
|||
{ |
|||
[Trait("Format", "Jpg")] |
|||
public class HuffmanScanEncoderTests |
|||
{ |
|||
private ITestOutputHelper Output { get; } |
|||
|
|||
public HuffmanScanEncoderTests(ITestOutputHelper output) |
|||
{ |
|||
this.Output = output; |
|||
} |
|||
|
|||
private static int GetHuffmanEncodingLength_Reference(uint number) |
|||
{ |
|||
int bits = 0; |
|||
if (number > 32767) |
|||
{ |
|||
number >>= 16; |
|||
bits += 16; |
|||
} |
|||
|
|||
if (number > 127) |
|||
{ |
|||
number >>= 8; |
|||
bits += 8; |
|||
} |
|||
|
|||
if (number > 7) |
|||
{ |
|||
number >>= 4; |
|||
bits += 4; |
|||
} |
|||
|
|||
if (number > 1) |
|||
{ |
|||
number >>= 2; |
|||
bits += 2; |
|||
} |
|||
|
|||
if (number > 0) |
|||
{ |
|||
bits++; |
|||
} |
|||
|
|||
return bits; |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetHuffmanEncodingLength_Zero() |
|||
{ |
|||
int expected = 0; |
|||
|
|||
int actual = HuffmanScanEncoder.GetHuffmanEncodingLength(0); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(1)] |
|||
[InlineData(2)] |
|||
public void GetHuffmanEncodingLength_Random(int seed) |
|||
{ |
|||
int maxNumber = 1 << 16; |
|||
|
|||
var rng = new Random(seed); |
|||
for (int i = 0; i < 1000; i++) |
|||
{ |
|||
uint number = (uint)rng.Next(0, maxNumber); |
|||
|
|||
int expected = GetHuffmanEncodingLength_Reference(number); |
|||
|
|||
int actual = HuffmanScanEncoder.GetHuffmanEncodingLength(number); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetLastValuableElementIndex_AllZero() |
|||
{ |
|||
static void RunTest() |
|||
{ |
|||
Block8x8F data = default; |
|||
|
|||
int expectedLessThan = 1; |
|||
|
|||
int actual = HuffmanScanEncoder.GetLastValuableElementIndex(ref data); |
|||
|
|||
Assert.True(actual < expectedLessThan); |
|||
} |
|||
|
|||
FeatureTestRunner.RunWithHwIntrinsicsFeature( |
|||
RunTest, |
|||
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); |
|||
} |
|||
|
|||
[Fact] |
|||
public void GetLastValuableElementIndex_AllNonZero() |
|||
{ |
|||
static void RunTest() |
|||
{ |
|||
Block8x8F data = default; |
|||
for (int i = 0; i < Block8x8F.Size; i++) |
|||
{ |
|||
data[i] = 10; |
|||
} |
|||
|
|||
int expected = Block8x8F.Size - 1; |
|||
|
|||
int actual = HuffmanScanEncoder.GetLastValuableElementIndex(ref data); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
|
|||
FeatureTestRunner.RunWithHwIntrinsicsFeature( |
|||
RunTest, |
|||
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(1)] |
|||
[InlineData(2)] |
|||
public void GetLastValuableElementIndex_RandomFilledSingle(int seed) |
|||
{ |
|||
static void RunTest(string seedSerialized) |
|||
{ |
|||
int seed = FeatureTestRunner.Deserialize<int>(seedSerialized); |
|||
var rng = new Random(seed); |
|||
|
|||
for (int i = 0; i < 1000; i++) |
|||
{ |
|||
Block8x8F data = default; |
|||
|
|||
int setIndex = rng.Next(1, Block8x8F.Size); |
|||
data[setIndex] = rng.Next(); |
|||
|
|||
int expected = setIndex; |
|||
|
|||
int actual = HuffmanScanEncoder.GetLastValuableElementIndex(ref data); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
} |
|||
|
|||
FeatureTestRunner.RunWithHwIntrinsicsFeature( |
|||
RunTest, |
|||
seed, |
|||
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(1)] |
|||
[InlineData(2)] |
|||
public void GetLastValuableElementIndex_RandomFilledPartially(int seed) |
|||
{ |
|||
static void RunTest(string seedSerialized) |
|||
{ |
|||
int seed = FeatureTestRunner.Deserialize<int>(seedSerialized); |
|||
var rng = new Random(seed); |
|||
|
|||
for (int i = 0; i < 1000; i++) |
|||
{ |
|||
Block8x8F data = default; |
|||
|
|||
int lastIndex = rng.Next(1, Block8x8F.Size); |
|||
int fillValue = rng.Next(); |
|||
for (int dataIndex = 0; dataIndex <= lastIndex; dataIndex++) |
|||
{ |
|||
data[dataIndex] = fillValue; |
|||
} |
|||
|
|||
int expected = lastIndex; |
|||
|
|||
int actual = HuffmanScanEncoder.GetLastValuableElementIndex(ref data); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
} |
|||
|
|||
FeatureTestRunner.RunWithHwIntrinsicsFeature( |
|||
RunTest, |
|||
seed, |
|||
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(1)] |
|||
[InlineData(2)] |
|||
public void GetLastValuableElementIndex_RandomFilledFragmented(int seed) |
|||
{ |
|||
static void RunTest(string seedSerialized) |
|||
{ |
|||
int seed = FeatureTestRunner.Deserialize<int>(seedSerialized); |
|||
var rng = new Random(seed); |
|||
|
|||
for (int i = 0; i < 1000; i++) |
|||
{ |
|||
Block8x8F data = default; |
|||
|
|||
int fillValue = rng.Next(); |
|||
|
|||
// first filled chunk
|
|||
int lastIndex1 = rng.Next(1, Block8x8F.Size / 2); |
|||
for (int dataIndex = 0; dataIndex <= lastIndex1; dataIndex++) |
|||
{ |
|||
data[dataIndex] = fillValue; |
|||
} |
|||
|
|||
// second filled chunk, there might be a spot with zero(s) between first and second chunk
|
|||
int lastIndex2 = rng.Next(lastIndex1 + 1, Block8x8F.Size); |
|||
for (int dataIndex = 0; dataIndex <= lastIndex2; dataIndex++) |
|||
{ |
|||
data[dataIndex] = fillValue; |
|||
} |
|||
|
|||
int expected = lastIndex2; |
|||
|
|||
int actual = HuffmanScanEncoder.GetLastValuableElementIndex(ref data); |
|||
|
|||
Assert.Equal(expected, actual); |
|||
} |
|||
} |
|||
|
|||
FeatureTestRunner.RunWithHwIntrinsicsFeature( |
|||
RunTest, |
|||
seed, |
|||
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX2); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue