public void CalculateLevelCosts() { if (!this.Dirty) { return; // Nothing to do. } for (int ctype = 0; ctype < WebpConstants.NumTypes; ++ctype) { for (int band = 0; band < WebpConstants.NumBands; ++band) { for (int ctx = 0; ctx < WebpConstants.NumCtx; ++ctx) { Vp8ProbaArray p = this.Coeffs[ctype][band].Probabilities[ctx]; Vp8CostArray table = this.LevelCost[ctype][band].Costs[ctx]; int cost0 = ctx > 0 ? LossyUtils.Vp8BitCost(1, p.Probabilities[0]) : 0; int costBase = LossyUtils.Vp8BitCost(1, p.Probabilities[1]) + cost0; int v; table.Costs[0] = (ushort)(LossyUtils.Vp8BitCost(0, p.Probabilities[1]) + cost0); for (v = 1; v <= MaxVariableLevel; ++v) { table.Costs[v] = (ushort)(costBase + VariableLevelCost(v, p.Probabilities)); } // Starting at level 67 and up, the variable part of the cost is actually constant } } for (int n = 0; n < 16; ++n) { for (int ctx = 0; ctx < WebpConstants.NumCtx; ++ctx) { Vp8CostArray dst = this.RemappedCosts[ctype][n].Costs[ctx]; Vp8CostArray src = this.LevelCost[ctype][WebpConstants.Vp8EncBands[n]].Costs[ctx]; src.Costs.CopyTo(dst.Costs.AsSpan()); } } } this.Dirty = false; }
/// <summary> /// Initializes a new instance of the <see cref="Vp8EncProba"/> class. /// </summary> public Vp8EncProba() { this.Dirty = true; this.UseSkipProba = false; this.Segments = new byte[3]; this.Coeffs = new Vp8BandProbas[WebpConstants.NumTypes][]; for (int i = 0; i < this.Coeffs.Length; i++) { this.Coeffs[i] = new Vp8BandProbas[WebpConstants.NumBands]; for (int j = 0; j < this.Coeffs[i].Length; j++) { this.Coeffs[i][j] = new Vp8BandProbas(); } } this.Stats = new Vp8Stats[WebpConstants.NumTypes][]; for (int i = 0; i < this.Coeffs.Length; i++) { this.Stats[i] = new Vp8Stats[WebpConstants.NumBands]; for (int j = 0; j < this.Stats[i].Length; j++) { this.Stats[i][j] = new Vp8Stats(); } } this.LevelCost = new Vp8Costs[WebpConstants.NumTypes][]; for (int i = 0; i < this.LevelCost.Length; i++) { this.LevelCost[i] = new Vp8Costs[WebpConstants.NumBands]; for (int j = 0; j < this.LevelCost[i].Length; j++) { this.LevelCost[i][j] = new Vp8Costs(); } } this.RemappedCosts = new Vp8Costs[WebpConstants.NumTypes][]; for (int i = 0; i < this.RemappedCosts.Length; i++) { this.RemappedCosts[i] = new Vp8Costs[16]; for (int j = 0; j < this.RemappedCosts[i].Length; j++) { this.RemappedCosts[i][j] = new Vp8Costs(); } } // Initialize with default probabilities. this.Segments.AsSpan().Fill(255); for (int t = 0; t < WebpConstants.NumTypes; ++t) { for (int b = 0; b < WebpConstants.NumBands; ++b) { for (int c = 0; c < WebpConstants.NumCtx; ++c) { Vp8ProbaArray dst = this.Coeffs[t][b].Probabilities[c]; for (int p = 0; p < WebpConstants.NumProbas; ++p) { dst.Probabilities[p] = WebpLookupTables.DefaultCoeffsProba[t, b, c, p]; } } } } }