diff --git a/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs index b1159fc6cc..b2f5c88b77 100644 --- a/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs +++ b/src/ImageSharp/Formats/WebP/Lossless/PredictorEncoder.cs @@ -1112,27 +1112,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless } [MethodImpl(InliningOptions.ShortMethod)] - private static byte NearLosslessDiff(byte a, byte b) - { - return (byte)((a - b) & 0xff); - } + private static byte NearLosslessDiff(byte a, byte b) => (byte)((a - b) & 0xff); [MethodImpl(InliningOptions.ShortMethod)] - private static uint MultipliersToColorCode(Vp8LMultipliers m) - { - return 0xff000000u | ((uint)m.RedToBlue << 16) | ((uint)m.GreenToBlue << 8) | m.GreenToRed; - } + private static uint MultipliersToColorCode(Vp8LMultipliers m) => 0xff000000u | ((uint)m.RedToBlue << 16) | ((uint)m.GreenToBlue << 8) | m.GreenToRed; [MethodImpl(InliningOptions.ShortMethod)] - private static int GetMin(int a, int b) - { - return (a > b) ? b : a; - } + private static int GetMin(int a, int b) => (a > b) ? b : a; [MethodImpl(InliningOptions.ShortMethod)] - private static int GetMax(int a, int b) - { - return (a < b) ? b : a; - } + private static int GetMax(int a, int b) => (a < b) ? b : a; } } diff --git a/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs b/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs index e0d2cd093d..b2a254a610 100644 --- a/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs +++ b/src/ImageSharp/Formats/WebP/Lossless/Vp8LEncoder.cs @@ -279,7 +279,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless // Apply transforms and write transform data. if (this.UseSubtractGreenTransform) { - this.ApplySubtractGreen(this.CurrentWidth, height); + this.ApplySubtractGreen(); } if (this.UsePredictorTransform) @@ -409,7 +409,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless { if (cacheBits == 0) { - // TODO: not sure if this should be 10 or 11. Original code comment says "The maximum allowed limit is 11.", but the value itself is 10. cacheBits = WebpConstants.MaxColorCacheBits; } } @@ -441,7 +440,6 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless // two as a temporary for later usage. Vp8LBackwardRefs refsTmp = refsArray[refsBest.Equals(refsArray[0]) ? 1 : 0]; - // TODO : Loop based on cache/no cache this.bitWriter.Reset(bwInit); var tmpHisto = new Vp8LHistogram(cacheBits); var histogramImage = new List(histogramImageXySize); @@ -561,9 +559,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless /// /// Applies the subtract green transformation to the pixel data of the image. /// - /// The width of the image. - /// The height of the image. - private void ApplySubtractGreen(int width, int height) + private void ApplySubtractGreen() { this.bitWriter.PutBits(WebpConstants.TransformPresent, 1); this.bitWriter.PutBits((uint)Vp8LTransformType.SubtractGreen, 2); @@ -1642,45 +1638,24 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossless } [MethodImpl(InliningOptions.ShortMethod)] - private static uint ApplyPaletteHash0(uint color) - { - // Focus on the green color. - return (color >> 8) & 0xff; - } + private static uint ApplyPaletteHash0(uint color) => (color >> 8) & 0xff; // Focus on the green color. [MethodImpl(InliningOptions.ShortMethod)] - private static uint ApplyPaletteHash1(uint color) - { - // Forget about alpha. - return ((uint)((color & 0x00ffffffu) * 4222244071ul)) >> (32 - PaletteInvSizeBits); - } + private static uint ApplyPaletteHash1(uint color) => ((uint)((color & 0x00ffffffu) * 4222244071ul)) >> (32 - PaletteInvSizeBits); // Forget about alpha. [MethodImpl(InliningOptions.ShortMethod)] - private static uint ApplyPaletteHash2(uint color) - { - // Forget about alpha. - return ((uint)((color & 0x00ffffffu) * ((1ul << 31) - 1))) >> (32 - PaletteInvSizeBits); - } + private static uint ApplyPaletteHash2(uint color) => ((uint)((color & 0x00ffffffu) * ((1ul << 31) - 1))) >> (32 - PaletteInvSizeBits); // Forget about alpha. + // Note that masking with 0xffffffffu is for preventing an + // 'unsigned int overflow' warning. Doesn't impact the compiled code. [MethodImpl(InliningOptions.ShortMethod)] - private static uint HashPix(uint pix) - { - // Note that masking with 0xffffffffu is for preventing an - // 'unsigned int overflow' warning. Doesn't impact the compiled code. - return (uint)((((long)pix + (pix >> 19)) * 0x39c5fba7L) & 0xffffffffu) >> 24; - } + private static uint HashPix(uint pix) => (uint)((((long)pix + (pix >> 19)) * 0x39c5fba7L) & 0xffffffffu) >> 24; [MethodImpl(InliningOptions.ShortMethod)] - private static int PaletteCompareColorsForSort(uint p1, uint p2) - { - return (p1 < p2) ? -1 : 1; - } + private static int PaletteCompareColorsForSort(uint p1, uint p2) => (p1 < p2) ? -1 : 1; [MethodImpl(InliningOptions.ShortMethod)] - private static uint PaletteComponentDistance(uint v) - { - return (v <= 128) ? v : (256 - v); - } + private static uint PaletteComponentDistance(uint v) => (v <= 128) ? v : (256 - v); public void AllocateTransformBuffer(int width, int height) { diff --git a/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs index eed716c1b2..7cac484af9 100644 --- a/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/WebP/Lossy/Vp8Encoder.cs @@ -37,63 +37,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy /// private readonly int entropyPasses; - /// - /// Stride of the prediction plane (=4*mb_w + 1) - /// - private readonly int predsWidth; - - /// - /// Macroblock width. - /// - private readonly int mbw; - - /// - /// Macroblock height. - /// - private readonly int mbh; - /// /// A bit writer for writing lossy webp streams. /// private Vp8BitWriter bitWriter; - /// - /// The segment features. - /// - private Vp8EncSegmentHeader segmentHeader; - - /// - /// The filter header info's. - /// - private readonly Vp8FilterHeader filterHeader; - - /// - /// The segment infos. - /// - private readonly Vp8SegmentInfo[] segmentInfos; - - /// - /// Contextual macroblock infos. - /// - private readonly Vp8MacroBlockInfo[] mbInfo; - - /// - /// Probabilities. - /// - private readonly Vp8EncProba proba; - private readonly Vp8RdLevel rdOptLevel; - private int dqY1Dc; - - private int dqY2Dc; - - private int dqY2Ac; - - private int dqUvDc; - - private int dqUvAc; - private int maxI4HeaderBits; /// @@ -149,41 +99,40 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy : Vp8RdLevel.RdOptNone; var pixelCount = width * height; - this.mbw = (width + 15) >> 4; - this.mbh = (height + 15) >> 4; + this.Mbw = (width + 15) >> 4; + this.Mbh = (height + 15) >> 4; var uvSize = ((width + 1) >> 1) * ((height + 1) >> 1); this.Y = this.memoryAllocator.Allocate(pixelCount); this.U = this.memoryAllocator.Allocate(uvSize); this.V = this.memoryAllocator.Allocate(uvSize); - this.YTop = new byte[this.mbw * 16]; - this.UvTop = new byte[this.mbw * 16 * 2]; - this.Nz = new uint[this.mbw + 1]; - this.MbHeaderLimit = 256 * 510 * 8 * 1024 / (this.mbw * this.mbh); - this.TopDerr = new sbyte[this.mbw * 4]; + this.YTop = new byte[this.Mbw * 16]; + this.UvTop = new byte[this.Mbw * 16 * 2]; + this.Nz = new uint[this.Mbw + 1]; + this.MbHeaderLimit = 256 * 510 * 8 * 1024 / (this.Mbw * this.Mbh); + this.TopDerr = new sbyte[this.Mbw * 4]; // TODO: make partition_limit configurable? int limit = 100; // original code: limit = 100 - config->partition_limit; this.maxI4HeaderBits = - 256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block - (limit * limit) / (100 * 100); // ... modulated with a quadratic curve. + 256 * 16 * 16 * limit * limit / (100 * 100); // ... modulated with a quadratic curve. - this.mbInfo = new Vp8MacroBlockInfo[this.mbw * this.mbh]; - for (int i = 0; i < this.mbInfo.Length; i++) + this.MbInfo = new Vp8MacroBlockInfo[this.Mbw * this.Mbh]; + for (int i = 0; i < this.MbInfo.Length; i++) { - this.mbInfo[i] = new Vp8MacroBlockInfo(); + this.MbInfo[i] = new Vp8MacroBlockInfo(); } - this.segmentInfos = new Vp8SegmentInfo[4]; + this.SegmentInfos = new Vp8SegmentInfo[4]; for (int i = 0; i < 4; i++) { - this.segmentInfos[i] = new Vp8SegmentInfo(); + this.SegmentInfos[i] = new Vp8SegmentInfo(); } - this.filterHeader = new Vp8FilterHeader(); - int predSize = (((4 * this.mbw) + 1) * ((4 * this.mbh) + 1)) + this.predsWidth + 1; - this.predsWidth = (4 * this.mbw) + 1; - this.proba = new Vp8EncProba(); - this.Preds = new byte[predSize + this.predsWidth + this.mbw]; + this.FilterHeader = new Vp8FilterHeader(); + int predSize = (((4 * this.Mbw) + 1) * ((4 * this.Mbh) + 1)) + this.PredsWidth + 1; + this.PredsWidth = (4 * this.Mbw) + 1; + this.Proba = new Vp8EncProba(); + this.Preds = new byte[predSize + this.PredsWidth + this.Mbw]; // Initialize with default values, which the reference c implementation uses, // to be able to compare to the original and spot differences. @@ -198,42 +147,27 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy /// /// Gets the probabilities. /// - public Vp8EncProba Proba - { - get => this.proba; - } + public Vp8EncProba Proba { get; private set; } /// /// Gets the segment features. /// - public Vp8EncSegmentHeader SegmentHeader - { - get => this.segmentHeader; - } + public Vp8EncSegmentHeader SegmentHeader { get; private set; } /// /// Gets the segment infos. /// - public Vp8SegmentInfo[] SegmentInfos - { - get => this.segmentInfos; - } + public Vp8SegmentInfo[] SegmentInfos { get; private set; } /// /// Gets the macro block info's. /// - public Vp8MacroBlockInfo[] MbInfo - { - get => this.mbInfo; - } + public Vp8MacroBlockInfo[] MbInfo { get; private set; } /// /// Gets the filter header. /// - public Vp8FilterHeader FilterHeader - { - get => this.filterHeader; - } + public Vp8FilterHeader FilterHeader { get; private set; } /// /// Gets or sets the global susceptibility. @@ -250,45 +184,30 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy /// public int Height { get; } - public int PredsWidth - { - get => this.predsWidth; - } + /// + /// Gets the stride of the prediction plane (=4*mb_w + 1) + /// + public int PredsWidth { get; } - public int Mbw - { - get => this.mbw; - } + /// + /// Gets the macroblock width. + /// + public int Mbw { get; } - public int Mbh - { - get => this.mbh; - } + /// + /// Gets the macroblock height. + /// + public int Mbh { get; } - public int DqY1Dc - { - get => this.dqY1Dc; - } + public int DqY1Dc { get; private set; } - public int DqY2Ac - { - get => this.dqY2Ac; - } + public int DqY2Ac { get; private set; } - public int DqY2Dc - { - get => this.dqY2Dc; - } + public int DqY2Dc { get; private set; } - public int DqUvAc - { - get => this.dqUvAc; - } + public int DqUvAc { get; private set; } - public int DqUvDc - { - get => this.dqUvDc; - } + public int DqUvDc { get; private set; } /// /// Gets the luma component. @@ -354,21 +273,21 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy int yStride = width; int uvStride = (yStride + 1) >> 1; - var it = new Vp8EncIterator(this.YTop, this.UvTop, this.Nz, this.mbInfo, this.Preds, this.TopDerr, this.mbw, this.mbh); + var it = new Vp8EncIterator(this.YTop, this.UvTop, this.Nz, this.MbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); var alphas = new int[WebpConstants.MaxAlpha + 1]; this.alpha = this.MacroBlockAnalysis(width, height, it, y, u, v, yStride, uvStride, alphas, out this.uvAlpha); - int totalMb = this.mbw * this.mbw; + int totalMb = this.Mbw * this.Mbw; this.alpha /= totalMb; this.uvAlpha /= totalMb; // Analysis is done, proceed to actual encoding. - this.segmentHeader = new Vp8EncSegmentHeader(4); + this.SegmentHeader = new Vp8EncSegmentHeader(4); this.AssignSegments(alphas); this.SetLoopParams(this.quality); // Initialize the bitwriter. int averageBytesPerMacroBlock = this.averageBytesPerMb[this.BaseQuant >> 4]; - int expectedSize = this.mbw * this.mbh * averageBytesPerMacroBlock; + int expectedSize = this.Mbw * this.Mbh * averageBytesPerMacroBlock; this.bitWriter = new Vp8BitWriter(expectedSize, this); // TODO: EncodeAlpha(); @@ -426,10 +345,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy bool fastProbe = (this.method == 0 || this.method == 3) && !doSearch; int numPassLeft = this.entropyPasses; Vp8RdLevel rdOpt = (this.method >= 3 || doSearch) ? Vp8RdLevel.RdOptBasic : Vp8RdLevel.RdOptNone; - int nbMbs = this.mbw * this.mbh; + int nbMbs = this.Mbw * this.Mbh; var stats = new PassStats(targetSize, targetPsnr, QMin, QMax, this.quality); - this.proba.ResetTokenStats(); + this.Proba.ResetTokenStats(); // Fast mode: quick analysis pass over few mbs. Better than nothing. if (fastProbe) @@ -480,11 +399,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy if (!doSearch || !stats.DoSizeSearch) { // Need to finalize probas now, since it wasn't done during the search. - this.proba.FinalizeSkipProba(this.mbw, this.mbh); - this.proba.FinalizeTokenProbas(); + this.Proba.FinalizeSkipProba(this.Mbw, this.Mbh); + this.Proba.FinalizeTokenProbas(); } - this.proba.CalculateLevelCosts(); // Finalize costs. + this.Proba.CalculateLevelCosts(); // Finalize costs. } private long OneStatPass(int width, int height, int yStride, int uvStride, Vp8RdLevel rdOpt, int nbMbs, PassStats stats) @@ -492,7 +411,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy Span y = this.Y.GetSpan(); Span u = this.U.GetSpan(); Span v = this.V.GetSpan(); - var it = new Vp8EncIterator(this.YTop, this.UvTop, this.Nz, this.mbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); + var it = new Vp8EncIterator(this.YTop, this.UvTop, this.Nz, this.MbInfo, this.Preds, this.TopDerr, this.Mbw, this.Mbh); long size = 0; long sizeP0 = 0; long distortion = 0; @@ -506,7 +425,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy if (this.Decimate(it, info, rdOpt)) { // Just record the number of skips and act like skipProba is not used. - ++this.proba.NbSkip; + ++this.Proba.NbSkip; } this.RecordResiduals(it, info); @@ -518,11 +437,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy } while (it.Next()); - sizeP0 += this.segmentHeader.Size; + sizeP0 += this.SegmentHeader.Size; if (stats.DoSizeSearch) { - size += this.proba.FinalizeSkipProba(this.mbw, this.mbh); - size += this.proba.FinalizeTokenProbas(); + size += this.Proba.FinalizeSkipProba(this.Mbw, this.Mbh); + size += this.Proba.FinalizeTokenProbas(); size = ((size + sizeP0 + 1024) >> 11) + HeaderSizeEstimate; stats.Value = size; } @@ -556,7 +475,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy // this '>> 3' accounts for some inverse WHT scaling int delta = (dqm.MaxEdge * dqm.Y2.Q[1]) >> 3; - int level = this.FilterStrengthFromDelta(this.filterHeader.Sharpness, delta); + int level = this.FilterStrengthFromDelta(this.FilterHeader.Sharpness, delta); if (level > dqm.FStrength) { dqm.FStrength = level; @@ -568,28 +487,28 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy } } - this.filterHeader.FilterLevel = maxLevel; + this.FilterHeader.FilterLevel = maxLevel; } } private void ResetBoundaryPredictions() { Span top = this.Preds.AsSpan(); // original source top starts at: enc->preds_ - enc->preds_w_ - Span left = this.Preds.AsSpan(this.predsWidth - 1); - for (int i = 0; i < 4 * this.mbw; ++i) + Span left = this.Preds.AsSpan(this.PredsWidth - 1); + for (int i = 0; i < 4 * this.Mbw; ++i) { top[i] = (int)IntraPredictionMode.DcPrediction; } - for (int i = 0; i < 4 * this.mbh; ++i) + for (int i = 0; i < 4 * this.Mbh; ++i) { - left[i * this.predsWidth] = (int)IntraPredictionMode.DcPrediction; + left[i * this.PredsWidth] = (int)IntraPredictionMode.DcPrediction; } - int predsW = (4 * this.mbw) + 1; - int predsH = (4 * this.mbh) + 1; + int predsW = (4 * this.Mbw) + 1; + int predsH = (4 * this.Mbh) + 1; int predsSize = predsW * predsH; - this.Preds.AsSpan(predsSize + this.predsWidth - 4, 4).Fill(0); + this.Preds.AsSpan(predsSize + this.PredsWidth - 4, 4).Fill(0); this.Nz[0] = 0; // constant } @@ -597,7 +516,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy // Simplified k-Means, to assign Nb segments based on alpha-histogram. private void AssignSegments(int[] alphas) { - int nb = (this.segmentHeader.NumSegments < NumMbSegments) ? this.segmentHeader.NumSegments : NumMbSegments; + int nb = (this.SegmentHeader.NumSegments < NumMbSegments) ? this.SegmentHeader.NumSegments : NumMbSegments; var centers = new int[NumMbSegments]; int weightedAverage = 0; var map = new int[WebpConstants.MaxAlpha + 1]; @@ -677,9 +596,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy } // Map each original value to the closest centroid - for (n = 0; n < this.mbw * this.mbh; ++n) + for (n = 0; n < this.Mbw * this.Mbh; ++n) { - Vp8MacroBlockInfo mb = this.mbInfo[n]; + Vp8MacroBlockInfo mb = this.MbInfo[n]; int alpha = mb.Alpha; mb.Segment = map[alpha]; mb.Alpha = centers[map[alpha]]; // for the record. @@ -691,8 +610,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy private void SetSegmentAlphas(int[] centers, int mid) { - int nb = this.segmentHeader.NumSegments; - Vp8SegmentInfo[] dqm = this.segmentInfos; + int nb = this.SegmentHeader.NumSegments; + Vp8SegmentInfo[] dqm = this.SegmentInfos; int min = centers[0], max = centers[0]; int n; @@ -728,7 +647,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy private void SetSegmentParams(float quality) { - int nb = this.segmentHeader.NumSegments; + int nb = this.SegmentHeader.NumSegments; Vp8SegmentInfo[] dqm = this.SegmentInfos; int snsStrength = 50; // TODO: Spatial Noise Shaping, hardcoded for now. double amp = WebpConstants.SnsToDq * snsStrength / 100.0d / 128.0d; @@ -749,23 +668,23 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy // uvAlpha is normally spread around ~60. The useful range is // typically ~30 (quite bad) to ~100 (ok to decimate UV more). // We map it to the safe maximal range of MAX/MIN_DQ_UV for dq_uv. - this.dqUvAc = (this.uvAlpha - WebpConstants.QuantEncMidAlpha) * (WebpConstants.QuantEncMaxDqUv - WebpConstants.QuantEncMinDqUv) / (WebpConstants.QuantEncMaxAlpha - WebpConstants.QuantEncMinAlpha); + this.DqUvAc = (this.uvAlpha - WebpConstants.QuantEncMidAlpha) * (WebpConstants.QuantEncMaxDqUv - WebpConstants.QuantEncMinDqUv) / (WebpConstants.QuantEncMaxAlpha - WebpConstants.QuantEncMinAlpha); // We rescale by the user-defined strength of adaptation. - this.dqUvAc = this.dqUvAc * snsStrength / 100; + this.DqUvAc = this.DqUvAc * snsStrength / 100; // and make it safe. - this.dqUvAc = Clip(this.dqUvAc, WebpConstants.QuantEncMinDqUv, WebpConstants.QuantEncMaxDqUv); + this.DqUvAc = Clip(this.DqUvAc, WebpConstants.QuantEncMinDqUv, WebpConstants.QuantEncMaxDqUv); // We also boost the dc-uv-quant a little, based on sns-strength, since // U/V channels are quite more reactive to high quants (flat DC-blocks // tend to appear, and are unpleasant). - this.dqUvDc = -4 * snsStrength / 100; - this.dqUvDc = Clip(this.dqUvDc, -15, 15); // 4bit-signed max allowed + this.DqUvDc = -4 * snsStrength / 100; + this.DqUvDc = Clip(this.DqUvDc, -15, 15); // 4bit-signed max allowed - this.dqY1Dc = 0; - this.dqY2Dc = 0; - this.dqY2Ac = 0; + this.DqY1Dc = 0; + this.DqY2Dc = 0; + this.DqY2Ac = 0; // Initialize segments' filtering this.SetupFilterStrength(); @@ -786,7 +705,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy // We focus on the quantization of AC coeffs. int qstep = WebpLookupTables.AcTable[Clip(m.Quant, 0, 127)] >> 2; - int baseStrength = this.FilterStrengthFromDelta(this.filterHeader.Sharpness, qstep); + int baseStrength = this.FilterStrengthFromDelta(this.FilterHeader.Sharpness, qstep); // Segments with lower complexity ('beta') will be less filtered. int f = baseStrength * level0 / (256 + m.Beta); @@ -794,9 +713,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy } // We record the initial strength (mainly for the case of 1-segment only). - this.filterHeader.FilterLevel = this.SegmentInfos[0].FStrength; - this.filterHeader.Simple = filterType == 0; - this.filterHeader.Sharpness = filterSharpness; + this.FilterHeader.FilterLevel = this.SegmentInfos[0].FStrength; + this.FilterHeader.Simple = filterType == 0; + this.FilterHeader.Sharpness = filterSharpness; } private void SetSegmentProbas() @@ -804,49 +723,49 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy var p = new int[NumMbSegments]; int n; - for (n = 0; n < this.mbw * this.mbh; ++n) + for (n = 0; n < this.Mbw * this.Mbh; ++n) { - Vp8MacroBlockInfo mb = this.mbInfo[n]; + Vp8MacroBlockInfo mb = this.MbInfo[n]; ++p[mb.Segment]; } - if (this.segmentHeader.NumSegments > 1) + if (this.SegmentHeader.NumSegments > 1) { - byte[] probas = this.proba.Segments; + byte[] probas = this.Proba.Segments; probas[0] = (byte)GetProba(p[0] + p[1], p[2] + p[3]); probas[1] = (byte)GetProba(p[0], p[1]); probas[2] = (byte)GetProba(p[2], p[3]); - this.segmentHeader.UpdateMap = (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); - if (!this.segmentHeader.UpdateMap) + this.SegmentHeader.UpdateMap = (probas[0] != 255) || (probas[1] != 255) || (probas[2] != 255); + if (!this.SegmentHeader.UpdateMap) { this.ResetSegments(); } - this.segmentHeader.Size = (p[0] * (LossyUtils.Vp8BitCost(0, probas[0]) + LossyUtils.Vp8BitCost(0, probas[1]))) + + this.SegmentHeader.Size = (p[0] * (LossyUtils.Vp8BitCost(0, probas[0]) + LossyUtils.Vp8BitCost(0, probas[1]))) + (p[1] * (LossyUtils.Vp8BitCost(0, probas[0]) + LossyUtils.Vp8BitCost(1, probas[1]))) + (p[2] * (LossyUtils.Vp8BitCost(1, probas[0]) + LossyUtils.Vp8BitCost(0, probas[2]))) + (p[3] * (LossyUtils.Vp8BitCost(1, probas[0]) + LossyUtils.Vp8BitCost(1, probas[2]))); } else { - this.segmentHeader.UpdateMap = false; - this.segmentHeader.Size = 0; + this.SegmentHeader.UpdateMap = false; + this.SegmentHeader.Size = 0; } } private void ResetSegments() { int n; - for (n = 0; n < this.mbw * this.mbh; ++n) + for (n = 0; n < this.Mbw * this.Mbh; ++n) { - this.mbInfo[n].Segment = 0; + this.MbInfo[n].Segment = 0; } } private void ResetStats() { - Vp8EncProba proba = this.proba; + Vp8EncProba proba = this.Proba; proba.CalculateLevelCosts(); proba.NbSkip = 0; } @@ -868,8 +787,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy m.Y2.Q[0] = (ushort)(WebpLookupTables.DcTable[Clip(q, 0, 127)] * 2); m.Y2.Q[1] = WebpLookupTables.AcTable2[Clip(q, 0, 127)]; - m.Uv.Q[0] = WebpLookupTables.DcTable[Clip(q + this.dqUvDc, 0, 117)]; - m.Uv.Q[1] = WebpLookupTables.AcTable[Clip(q + this.dqUvAc, 0, 127)]; + m.Uv.Q[0] = WebpLookupTables.DcTable[Clip(q + this.DqUvDc, 0, 117)]; + m.Uv.Q[1] = WebpLookupTables.AcTable[Clip(q + this.DqUvAc, 0, 127)]; var qi4 = m.Y1.Expand(0); m.Y2.Expand(1); // qi16 @@ -954,7 +873,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy int nz = 0; int mode; bool isI16 = tryBothModes || (it.CurrentMacroBlockInfo.MacroBlockType == Vp8MacroBlockType.I16X16); - Vp8SegmentInfo dqm = this.segmentInfos[it.CurrentMacroBlockInfo.Segment]; + Vp8SegmentInfo dqm = this.SegmentInfos[it.CurrentMacroBlockInfo.Segment]; // Some empiric constants, of approximate order of magnitude. int lambdaDi16 = 106; @@ -1100,15 +1019,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy int pos1 = this.bitWriter.NumBytes(); if (i16) { - residual.Init(0, 1, this.proba); + residual.Init(0, 1, this.Proba); residual.SetCoeffs(rd.YDcLevels); int res = this.bitWriter.PutCoeffs(it.TopNz[8] + it.LeftNz[8], residual); it.TopNz[8] = it.LeftNz[8] = res; - residual.Init(1, 0, this.proba); + residual.Init(1, 0, this.Proba); } else { - residual.Init(0, 3, this.proba); + residual.Init(0, 3, this.Proba); } // luma-AC @@ -1127,7 +1046,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy int pos2 = this.bitWriter.NumBytes(); // U/V - residual.Init(0, 2, this.proba); + residual.Init(0, 2, this.Proba); for (ch = 0; ch <= 2; ch += 2) { for (y = 0; y < 2; ++y) @@ -1165,16 +1084,16 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy if (i16) { // i16x16 - residual.Init(0, 1, this.proba); + residual.Init(0, 1, this.Proba); residual.SetCoeffs(rd.YDcLevels); var res = residual.RecordCoeffs(it.TopNz[8] + it.LeftNz[8]); it.TopNz[8] = res; it.LeftNz[8] = res; - residual.Init(1, 0, this.proba); + residual.Init(1, 0, this.Proba); } else { - residual.Init(0, 3, this.proba); + residual.Init(0, 3, this.Proba); } // luma-AC @@ -1192,7 +1111,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy } // U/V - residual.Init(0, 2, this.proba); + residual.Init(0, 2, this.Proba); for (ch = 0; ch <= 2; ch += 2) { for (y = 0; y < 2; ++y) @@ -1352,27 +1271,15 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Webp.Lossy } [MethodImpl(InliningOptions.ShortMethod)] - private static int Clip(int v, int min, int max) - { - return (v < min) ? min : (v > max) ? max : v; - } + private static int Clip(int v, int min, int max) => (v < min) ? min : (v > max) ? max : v; [MethodImpl(InliningOptions.ShortMethod)] - private static int Vp8Sse16X16(Span a, Span b) - { - return GetSse(a, b, 16, 16); - } + private static int Vp8Sse16X16(Span a, Span b) => GetSse(a, b, 16, 16); - private static int Vp8Sse16X8(Span a, Span b) - { - return GetSse(a, b, 16, 8); - } + private static int Vp8Sse16X8(Span a, Span b) => GetSse(a, b, 16, 8); [MethodImpl(InliningOptions.ShortMethod)] - private static int Vp8Sse4X4(Span a, Span b) - { - return GetSse(a, b, 4, 4); - } + private static int Vp8Sse4X4(Span a, Span b) => GetSse(a, b, 4, 4); [MethodImpl(InliningOptions.ShortMethod)] private static int GetSse(Span a, Span b, int w, int h)