Browse Source

Enable PickBestIntra16 and PickBestUv

pull/1552/head
Brian Popow 5 years ago
parent
commit
a368f41586
  1. 2
      src/ImageSharp/Formats/WebP/Lossy/Vp8CostArray.cs
  2. 7
      src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs
  3. 19
      src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs
  4. 2
      src/ImageSharp/Formats/WebP/Lossy/Vp8Residual.cs

2
src/ImageSharp/Formats/WebP/Lossy/Vp8CostArray.cs

@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Vp8CostArray"/> class. /// Initializes a new instance of the <see cref="Vp8CostArray"/> class.
/// </summary> /// </summary>
public Vp8CostArray() => this.Costs = new ushort[WebpConstants.NumCtx * (67 + 1)]; public Vp8CostArray() => this.Costs = new ushort[67 + 1];
public ushort[] Costs { get; } public ushort[] Costs { get; }
} }

7
src/ImageSharp/Formats/WebP/Lossy/Vp8EncIterator.cs

@ -415,11 +415,10 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
this.MakeIntra4Preds(); this.MakeIntra4Preds();
for (mode = 0; mode < maxMode; ++mode) for (mode = 0; mode < maxMode; ++mode)
{ {
int alpha;
histos[curHisto] = new Vp8Histogram(); histos[curHisto] = new Vp8Histogram();
histos[curHisto].CollectHistogram(src, this.YuvP.AsSpan(Vp8Encoding.Vp8I4ModeOffsets[mode]), 0, 1); histos[curHisto].CollectHistogram(src, this.YuvP.AsSpan(Vp8Encoding.Vp8I4ModeOffsets[mode]), 0, 1);
alpha = histos[curHisto].GetAlpha(); var alpha = histos[curHisto].GetAlpha();
if (alpha > bestModeAlpha) if (alpha > bestModeAlpha)
{ {
bestModeAlpha = alpha; bestModeAlpha = alpha;
@ -522,7 +521,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
for (int x = 0; x < 4; ++x) for (int x = 0; x < 4; ++x)
{ {
int ctx = this.TopNz[x] + this.LeftNz[y]; int ctx = this.TopNz[x] + this.LeftNz[y];
res.SetCoeffs(rd.YAcLevels.AsSpan(x + (y * 4))); res.SetCoeffs(rd.YAcLevels.AsSpan((x + (y * 4)) * 16, 16));
r += res.GetResidualCost(ctx); r += res.GetResidualCost(ctx);
this.TopNz[x] = this.LeftNz[y] = (res.Last >= 0) ? 1 : 0; this.TopNz[x] = this.LeftNz[y] = (res.Last >= 0) ? 1 : 0;
} }
@ -572,7 +571,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
for (int x = 0; x < 2; ++x) for (int x = 0; x < 2; ++x)
{ {
int ctx = this.TopNz[4 + ch + x] + this.LeftNz[4 + ch + y]; int ctx = this.TopNz[4 + ch + x] + this.LeftNz[4 + ch + y];
res.SetCoeffs(rd.UvLevels.AsSpan((ch * 2) + x + (y * 2))); res.SetCoeffs(rd.UvLevels.AsSpan(((ch * 2) + x + (y * 2)) * 16, 16));
r += res.GetResidualCost(ctx); r += res.GetResidualCost(ctx);
this.TopNz[4 + ch + x] = this.LeftNz[4 + ch + y] = (res.Last >= 0) ? 1 : 0; this.TopNz[4 + ch + x] = this.LeftNz[4 + ch + y] = (res.Last >= 0) ? 1 : 0;
} }

19
src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs

@ -311,7 +311,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// Warning! order is important: first call VP8Decimate() and // Warning! order is important: first call VP8Decimate() and
// *then* decide how to code the skip decision if there's one. // *then* decide how to code the skip decision if there's one.
if (!this.Decimate(it, info, this.rdOptLevel) || dontUseSkip) if (!this.Decimate(it, ref info, this.rdOptLevel) || dontUseSkip)
{ {
this.CodeResiduals(it, info); this.CodeResiduals(it, info);
} }
@ -411,7 +411,8 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
this.Proba.FinalizeTokenProbas(); this.Proba.FinalizeTokenProbas();
} }
this.Proba.CalculateLevelCosts(); // Finalize costs. // Finalize costs.
this.Proba.CalculateLevelCosts();
} }
private long OneStatPass(int width, int height, int yStride, int uvStride, Vp8RdLevel rdOpt, int nbMbs, PassStats stats) private long OneStatPass(int width, int height, int yStride, int uvStride, Vp8RdLevel rdOpt, int nbMbs, PassStats stats)
@ -425,12 +426,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
long distortion = 0; long distortion = 0;
long pixelCount = nbMbs * 384; long pixelCount = nbMbs * 384;
it.Init();
this.SetLoopParams(stats.Q); this.SetLoopParams(stats.Q);
do do
{ {
var info = new Vp8ModeScore(); var info = new Vp8ModeScore();
it.Import(y, u, v, yStride, uvStride, width, height, false); it.Import(y, u, v, yStride, uvStride, width, height, false);
if (this.Decimate(it, info, rdOpt)) if (this.Decimate(it, ref info, rdOpt))
{ {
// Just record the number of skips and act like skipProba is not used. // Just record the number of skips and act like skipProba is not used.
++this.Proba.NbSkip; ++this.Proba.NbSkip;
@ -877,7 +879,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
return bestAlpha; // Mixed susceptibility (not just luma). return bestAlpha; // Mixed susceptibility (not just luma).
} }
private bool Decimate(Vp8EncIterator it, Vp8ModeScore rd, Vp8RdLevel rdOpt) private bool Decimate(Vp8EncIterator it, ref Vp8ModeScore rd, Vp8RdLevel rdOpt)
{ {
rd.InitScore(); rd.InitScore();
@ -886,13 +888,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
it.MakeLuma16Preds(); it.MakeLuma16Preds();
it.MakeChroma8Preds(); it.MakeChroma8Preds();
// TODO: disabled picking best mode because its still bugged. if (rdOpt > Vp8RdLevel.RdOptNone)
/* if (rdOpt > Vp8RdLevel.RdOptNone)
{ {
QuantEnc.PickBestIntra16(it, ref rd, this.SegmentInfos, this.Proba); QuantEnc.PickBestIntra16(it, ref rd, this.SegmentInfos, this.Proba);
if (this.method >= 2) if (this.method >= 2)
{ {
QuantEnc.PickBestIntra4(it, ref rd, this.SegmentInfos, this.Proba, this.maxI4HeaderBits); // TODO: there is still a bug in PickBestIntra4, therefore disabled.
// QuantEnc.PickBestIntra4(it, ref rd, this.SegmentInfos, this.Proba, this.maxI4HeaderBits);
} }
QuantEnc.PickBestUv(it, ref rd, this.SegmentInfos, this.Proba); QuantEnc.PickBestUv(it, ref rd, this.SegmentInfos, this.Proba);
@ -905,9 +907,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
// quantization/reconstruction. // quantization/reconstruction.
QuantEnc.RefineUsingDistortion(it, this.SegmentInfos, rd, this.method >= 2, this.method >= 1, this.MbHeaderLimit); QuantEnc.RefineUsingDistortion(it, this.SegmentInfos, rd, this.method >= 2, this.method >= 1, this.MbHeaderLimit);
} }
*/
QuantEnc.RefineUsingDistortion(it, this.SegmentInfos, rd, this.method >= 2, this.method >= 1, this.MbHeaderLimit);
bool isSkipped = rd.Nz == 0; bool isSkipped = rd.Nz == 0;
it.SetSkip(isSkipped); it.SetSkip(isSkipped);

2
src/ImageSharp/Formats/WebP/Lossy/Vp8Residual.cs

@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy
} }
} }
this.Coeffs = coeffs.ToArray(); this.Coeffs = coeffs.Slice(0, 16).ToArray();
} }
// Simulate block coding, but only record statistics. // Simulate block coding, but only record statistics.

Loading…
Cancel
Save