@@ -38,6 +38,34 @@ private static unsafe void RunQuantizeBlockTest()
3838 Assert . Equal ( expectedResult , actualResult ) ;
3939 }
4040
41+ /// <summary>
42+ /// Checks luma sharpening at quantization boundaries against fixed results from local libwebp.
43+ /// </summary>
44+ private static void RunQuantizeBlockWithSharpeningTest ( )
45+ {
46+ // The AC quantizer step is 200. Its sharpening biases are 2, 5 or 8.
47+ // Several magnitudes require that bias to reach the next level.
48+ // The input includes positive and negative coefficients.
49+ // The expected values come from libwebp's scalar quantizer.
50+ // Levels use VP8 zigzag order. Reconstructed coefficients use the input's 4 by 4 order.
51+ short [ ] input = [ 300 , - 110 , 112 , - 310 , 113 , - 500 , 290 , - 115 , 700 , - 108 , 295 , - 490 , 111 , - 298 , 505 , - 299 ] ;
52+ short [ ] output = new short [ 16 ] ;
53+ short [ ] expectedOutput = [ 7 , 0 , 1 , 3 , - 2 , 1 , - 2 , 1 , - 1 , 1 , - 1 , 1 , - 1 , - 2 , 2 , - 1 ] ;
54+ short [ ] expectedReconstructed = [ 280 , 0 , 200 , - 400 , 200 , - 400 , 200 , - 200 , 600 , - 200 , 200 , - 400 , 200 , - 200 , 400 , - 200 ] ;
55+ Vp8Matrix vp8Matrix = default ;
56+ vp8Matrix . Q [ 0 ] = 40 ;
57+ vp8Matrix . Q [ 1 ] = 200 ;
58+ vp8Matrix . Expand ( 0 ) ;
59+
60+ // act
61+ int actualResult = QuantEnc . QuantizeBlock ( input , output , ref vp8Matrix ) ;
62+
63+ // assert
64+ Assert . Equal ( expectedOutput , output ) ;
65+ Assert . Equal ( expectedReconstructed , input ) ;
66+ Assert . Equal ( 1 , actualResult ) ;
67+ }
68+
4169 [ Fact ]
4270 public void QuantizeBlock_Works ( ) => RunQuantizeBlockTest ( ) ;
4371
@@ -49,4 +77,24 @@ private static unsafe void RunQuantizeBlockTest()
4977
5078 [ Fact ]
5179 public void QuantizeBlock_WithoutAVX2_Works ( ) => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunQuantizeBlockTest , HwIntrinsics . DisableAVX2 ) ;
80+
81+ /// <summary>
82+ /// Runs the sharpening regression with the available hardware intrinsics.
83+ /// </summary>
84+ [ Fact ]
85+ public void QuantizeBlock_WithSharpening_Works ( ) => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunQuantizeBlockWithSharpeningTest , HwIntrinsics . AllowAll ) ;
86+
87+ /// <summary>
88+ /// Runs the sharpening regression through the scalar fallback.
89+ /// </summary>
90+ [ Fact ]
91+ public void QuantizeBlock_WithSharpening_WithoutHardwareIntrinsics_Works ( )
92+ => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunQuantizeBlockWithSharpeningTest , HwIntrinsics . DisableHWIntrinsic ) ;
93+
94+ /// <summary>
95+ /// Runs the sharpening regression without AVX2, including the SSE4.1 path on supported x86 hardware.
96+ /// </summary>
97+ [ Fact ]
98+ public void QuantizeBlock_WithSharpening_WithoutAVX2_Works ( )
99+ => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunQuantizeBlockWithSharpeningTest , HwIntrinsics . DisableAVX2 ) ;
52100}
0 commit comments