11// Copyright (c) Six Labors.
22// Licensed under the Six Labors Split License.
33
4+ using System . Text ;
5+ using SixLabors . ImageSharp . Formats . Webp ;
46using SixLabors . ImageSharp . Formats . Webp . Lossy ;
57using SixLabors . ImageSharp . Tests . TestUtilities ;
68
@@ -9,10 +11,234 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp;
911[ Trait ( "Format" , "Webp" ) ]
1012public class Vp8ResidualTests
1113{
14+ private static void WriteVp8Residual ( string filename , Vp8Residual residual )
15+ {
16+ using FileStream stream = File . Open ( filename , FileMode . Create ) ;
17+ using BinaryWriter writer = new ( stream , Encoding . UTF8 , false ) ;
18+
19+ writer . Write ( residual . First ) ;
20+ writer . Write ( residual . Last ) ;
21+ writer . Write ( residual . CoeffType ) ;
22+
23+ for ( int i = 0 ; i < residual . Coeffs . Length ; i ++ )
24+ {
25+ writer . Write ( residual . Coeffs [ i ] ) ;
26+ }
27+
28+ for ( int i = 0 ; i < residual . Prob . Length ; i ++ )
29+ {
30+ for ( int j = 0 ; j < residual . Prob [ i ] . Probabilities . Length ; j ++ )
31+ {
32+ writer . Write ( residual . Prob [ i ] . Probabilities [ j ] . Probabilities ) ;
33+ }
34+ }
35+
36+ for ( int i = 0 ; i < residual . Costs . Length ; i ++ )
37+ {
38+ Vp8Costs costs = residual . Costs [ i ] ;
39+ Vp8CostArray [ ] costsArray = costs . Costs ;
40+ for ( int j = 0 ; j < costsArray . Length ; j ++ )
41+ {
42+ for ( int k = 0 ; k < costsArray [ j ] . Costs . Length ; k ++ )
43+ {
44+ writer . Write ( costsArray [ j ] . Costs [ k ] ) ;
45+ }
46+ }
47+ }
48+
49+ for ( int i = 0 ; i < residual . Stats . Length ; i ++ )
50+ {
51+ for ( int j = 0 ; j < residual . Stats [ i ] . Stats . Length ; j ++ )
52+ {
53+ for ( int k = 0 ; k < residual . Stats [ i ] . Stats [ j ] . Stats . Length ; k ++ )
54+ {
55+ writer . Write ( residual . Stats [ i ] . Stats [ j ] . Stats [ k ] ) ;
56+ }
57+ }
58+ }
59+
60+ writer . Flush ( ) ;
61+ }
62+
63+ private static Vp8Residual ReadVp8Residual ( string fileName )
64+ {
65+ using FileStream stream = File . Open ( fileName , FileMode . Open ) ;
66+ using BinaryReader reader = new ( stream , Encoding . UTF8 , false ) ;
67+
68+ Vp8Residual residual = new ( )
69+ {
70+ First = reader . ReadInt32 ( ) ,
71+ Last = reader . ReadInt32 ( ) ,
72+ CoeffType = reader . ReadInt32 ( )
73+ } ;
74+
75+ for ( int i = 0 ; i < residual . Coeffs . Length ; i ++ )
76+ {
77+ residual . Coeffs [ i ] = reader . ReadInt16 ( ) ;
78+ }
79+
80+ Vp8BandProbas [ ] bandProbas = new Vp8BandProbas [ 8 ] ;
81+ for ( int i = 0 ; i < bandProbas . Length ; i ++ )
82+ {
83+ bandProbas [ i ] = new Vp8BandProbas ( ) ;
84+ for ( int j = 0 ; j < bandProbas [ i ] . Probabilities . Length ; j ++ )
85+ {
86+ for ( int k = 0 ; k < 11 ; k ++ )
87+ {
88+ bandProbas [ i ] . Probabilities [ j ] . Probabilities [ k ] = reader . ReadByte ( ) ;
89+ }
90+ }
91+ }
92+
93+ residual . Prob = bandProbas ;
94+
95+ residual . Costs = new Vp8Costs [ 16 ] ;
96+ for ( int i = 0 ; i < residual . Costs . Length ; i ++ )
97+ {
98+ residual . Costs [ i ] = new Vp8Costs ( ) ;
99+ Vp8CostArray [ ] costsArray = residual . Costs [ i ] . Costs ;
100+ for ( int j = 0 ; j < costsArray . Length ; j ++ )
101+ {
102+ for ( int k = 0 ; k < costsArray [ j ] . Costs . Length ; k ++ )
103+ {
104+ costsArray [ j ] . Costs [ k ] = reader . ReadUInt16 ( ) ;
105+ }
106+ }
107+ }
108+
109+ residual . Stats = new Vp8Stats [ 8 ] ;
110+ for ( int i = 0 ; i < residual . Stats . Length ; i ++ )
111+ {
112+ residual . Stats [ i ] = new Vp8Stats ( ) ;
113+ for ( int j = 0 ; j < residual . Stats [ i ] . Stats . Length ; j ++ )
114+ {
115+ for ( int k = 0 ; k < residual . Stats [ i ] . Stats [ j ] . Stats . Length ; k ++ )
116+ {
117+ residual . Stats [ i ] . Stats [ j ] . Stats [ k ] = reader . ReadUInt32 ( ) ;
118+ }
119+ }
120+ }
121+
122+ return residual ;
123+ }
124+
125+ [ Fact ]
126+ public void Vp8Residual_Serialization_Works ( )
127+ {
128+ // arrange
129+ Vp8Residual expected = new ( ) ;
130+ Vp8EncProba encProb = new ( ) ;
131+ Random rand = new ( 439 ) ;
132+ CreateRandomProbas ( encProb , rand ) ;
133+ CreateCosts ( encProb , rand ) ;
134+ expected . Init ( 1 , 0 , encProb ) ;
135+ for ( int i = 0 ; i < expected . Coeffs . Length ; i ++ )
136+ {
137+ expected . Coeffs [ i ] = ( byte ) rand . Next ( 255 ) ;
138+ }
139+
140+ // act
141+ string fileName = "Vp8SerializationTest.bin" ;
142+ WriteVp8Residual ( fileName , expected ) ;
143+ Vp8Residual actual = ReadVp8Residual ( fileName ) ;
144+ File . Delete ( fileName ) ;
145+
146+ // assert
147+ Assert . Equal ( expected . CoeffType , actual . CoeffType ) ;
148+ Assert . Equal ( expected . Coeffs , actual . Coeffs ) ;
149+ Assert . Equal ( expected . Costs . Length , actual . Costs . Length ) ;
150+ Assert . Equal ( expected . First , actual . First ) ;
151+ Assert . Equal ( expected . Last , actual . Last ) ;
152+ Assert . Equal ( expected . Stats . Length , actual . Stats . Length ) ;
153+ for ( int i = 0 ; i < expected . Stats . Length ; i ++ )
154+ {
155+ Vp8StatsArray [ ] expectedStats = expected . Stats [ i ] . Stats ;
156+ Vp8StatsArray [ ] actualStats = actual . Stats [ i ] . Stats ;
157+ Assert . Equal ( expectedStats . Length , actualStats . Length ) ;
158+ for ( int j = 0 ; j < expectedStats . Length ; j ++ )
159+ {
160+ Assert . Equal ( expectedStats [ j ] . Stats , actualStats [ j ] . Stats ) ;
161+ }
162+ }
163+
164+ Assert . Equal ( expected . Prob . Length , actual . Prob . Length ) ;
165+ for ( int i = 0 ; i < expected . Prob . Length ; i ++ )
166+ {
167+ Vp8ProbaArray [ ] expectedProbabilities = expected . Prob [ i ] . Probabilities ;
168+ Vp8ProbaArray [ ] actualProbabilities = actual . Prob [ i ] . Probabilities ;
169+ Assert . Equal ( expectedProbabilities . Length , actualProbabilities . Length ) ;
170+ for ( int j = 0 ; j < expectedProbabilities . Length ; j ++ )
171+ {
172+ Assert . Equal ( expectedProbabilities [ j ] . Probabilities , actualProbabilities [ j ] . Probabilities ) ;
173+ }
174+ }
175+
176+ for ( int i = 0 ; i < expected . Costs . Length ; i ++ )
177+ {
178+ Vp8CostArray [ ] expectedCosts = expected . Costs [ i ] . Costs ;
179+ Vp8CostArray [ ] actualCosts = actual . Costs [ i ] . Costs ;
180+ Assert . Equal ( expectedCosts . Length , actualCosts . Length ) ;
181+ for ( int j = 0 ; j < expectedCosts . Length ; j ++ )
182+ {
183+ Assert . Equal ( expectedCosts [ j ] . Costs , actualCosts [ j ] . Costs ) ;
184+ }
185+ }
186+ }
187+
188+ [ Fact ]
189+ public void GetResidualCost_Works ( )
190+ {
191+ // arrange
192+ int ctx0 = 0 ;
193+ int expected = 20911 ;
194+ Vp8Residual residual = ReadVp8Residual ( Path . Combine ( "TestDataWebp" , "Vp8Residual.bin" ) ) ;
195+
196+ // act
197+ int actual = residual . GetResidualCost ( ctx0 ) ;
198+
199+ // assert
200+ Assert . Equal ( expected , actual ) ;
201+ }
202+
203+ private static void CreateRandomProbas ( Vp8EncProba probas , Random rand )
204+ {
205+ for ( int t = 0 ; t < WebpConstants . NumTypes ; ++ t )
206+ {
207+ for ( int b = 0 ; b < WebpConstants . NumBands ; ++ b )
208+ {
209+ for ( int c = 0 ; c < WebpConstants . NumCtx ; ++ c )
210+ {
211+ for ( int p = 0 ; p < WebpConstants . NumProbas ; ++ p )
212+ {
213+ probas . Coeffs [ t ] [ b ] . Probabilities [ c ] . Probabilities [ p ] = ( byte ) rand . Next ( 255 ) ;
214+ }
215+ }
216+ }
217+ }
218+ }
219+
220+ private static void CreateCosts ( Vp8EncProba probas , Random rand )
221+ {
222+ for ( int i = 0 ; i < probas . RemappedCosts . Length ; i ++ )
223+ {
224+ for ( int j = 0 ; j < probas . RemappedCosts [ i ] . Length ; j ++ )
225+ {
226+ for ( int k = 0 ; k < probas . RemappedCosts [ i ] [ j ] . Costs . Length ; k ++ )
227+ {
228+ ushort [ ] costs = probas . RemappedCosts [ i ] [ j ] . Costs [ k ] . Costs ;
229+ for ( int m = 0 ; m < costs . Length ; m ++ )
230+ {
231+ costs [ m ] = ( byte ) rand . Next ( 255 ) ;
232+ }
233+ }
234+ }
235+ }
236+ }
237+
12238 private static void RunSetCoeffsTest ( )
13239 {
14240 // arrange
15- var residual = new Vp8Residual ( ) ;
241+ Vp8Residual residual = new ( ) ;
16242 short [ ] coeffs = { 110 , 0 , - 2 , 0 , 0 , 0 , 0 , 0 , 0 , - 1 , 0 , 0 , 0 , 0 , 0 , 0 } ;
17243
18244 // act
@@ -23,11 +249,8 @@ private static void RunSetCoeffsTest()
23249 }
24250
25251 [ Fact ]
26- public void RunSetCoeffsTest_Works ( ) => RunSetCoeffsTest ( ) ;
27-
28- [ Fact ]
29- public void RunSetCoeffsTest_WithHardwareIntrinsics_Works ( ) => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunSetCoeffsTest , HwIntrinsics . AllowAll ) ;
252+ public void SetCoeffsTest_Works ( ) => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunSetCoeffsTest , HwIntrinsics . AllowAll ) ;
30253
31254 [ Fact ]
32- public void RunSetCoeffsTest_WithoutHardwareIntrinsics_Works ( ) => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunSetCoeffsTest , HwIntrinsics . DisableHWIntrinsic ) ;
255+ public void SetCoeffsTest_WithoutSSE2_Works ( ) => FeatureTestRunner . RunWithHwIntrinsicsFeature ( RunSetCoeffsTest , HwIntrinsics . DisableSSE2 ) ;
33256}
0 commit comments