Ejemplo n.º 1
0
        private long OneStatPass(int width, int height, int yStride, int uvStride, Vp8RdLevel rdOpt, int nbMbs, PassStats stats)
        {
            Span <byte> y          = this.Y.GetSpan();
            Span <byte> u          = this.U.GetSpan();
            Span <byte> v          = this.V.GetSpan();
            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;
            long        pixelCount = nbMbs * 384;

            it.Init();
            this.SetLoopParams(stats.Q);
            var info = new Vp8ModeScore();

            do
            {
                info.Clear();
                it.Import(y, u, v, yStride, uvStride, width, height, false);
                if (this.Decimate(it, ref info, rdOpt))
                {
                    // Just record the number of skips and act like skipProba is not used.
                    ++this.Proba.NbSkip;
                }

                this.RecordResiduals(it, info);
                size       += info.R + info.H;
                sizeP0     += info.H;
                distortion += info.D;

                it.SaveBoundary();
            }while (it.Next() && --nbMbs > 0);

            sizeP0 += this.SegmentHeader.Size;
            if (stats.DoSizeSearch)
            {
                size       += this.Proba.FinalizeSkipProba(this.Mbw, this.Mbh);
                size       += this.Proba.FinalizeTokenProbas();
                size        = ((size + sizeP0 + 1024) >> 11) + HeaderSizeEstimate;
                stats.Value = size;
            }
            else
            {
                stats.Value = GetPsnr(distortion, pixelCount);
            }

            return(sizeP0);
        }
Ejemplo n.º 2
0
        private int MacroBlockAnalysis(int width, int height, Vp8EncIterator it, Span <byte> y, Span <byte> u, Span <byte> v, int yStride, int uvStride, int[] alphas, out int uvAlpha)
        {
            int alpha = 0;

            uvAlpha = 0;
            if (!it.IsDone())
            {
                do
                {
                    it.Import(y, u, v, yStride, uvStride, width, height, true);
                    int bestAlpha = this.MbAnalyze(it, alphas, out int bestUvAlpha);

                    // Accumulate for later complexity analysis.
                    alpha   += bestAlpha;
                    uvAlpha += bestUvAlpha;
                }while (it.Next());
            }

            return(alpha);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
        /// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
        public void Encode <TPixel>(Image <TPixel> image, Stream stream)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            int         width  = image.Width;
            int         height = image.Height;
            Span <byte> y      = this.Y.GetSpan();
            Span <byte> u      = this.U.GetSpan();
            Span <byte> v      = this.V.GetSpan();

            YuvConversion.ConvertRgbToYuv(image, this.configuration, this.memoryAllocator, y, u, v);

            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);

            int[] 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;

            this.alpha   /= totalMb;
            this.uvAlpha /= totalMb;

            // Analysis is done, proceed to actual encoding.
            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;

            this.bitWriter = new Vp8BitWriter(expectedSize, this);

            // TODO: EncodeAlpha();
            bool hasAlpha = false;

            // Stats-collection loop.
            this.StatLoop(width, height, yStride, uvStride);
            it.Init();
            it.InitFilter();
            var info     = new Vp8ModeScore();
            var residual = new Vp8Residual();

            do
            {
                bool dontUseSkip = !this.Proba.UseSkipProba;
                info.Clear();
                it.Import(y, u, v, yStride, uvStride, width, height, false);

                // Warning! order is important: first call VP8Decimate() and
                // *then* decide how to code the skip decision if there's one.
                if (!this.Decimate(it, ref info, this.rdOptLevel) || dontUseSkip)
                {
                    this.CodeResiduals(it, info, residual);
                }
                else
                {
                    it.ResetAfterSkip();
                }

                it.SaveBoundary();
            }while (it.Next());

            // Store filter stats.
            this.AdjustFilterStrength();

            // Write bytes from the bitwriter buffer to the stream.
            image.Metadata.SyncProfiles();
            this.bitWriter.WriteEncodedImageToStream(stream, image.Metadata.ExifProfile, (uint)width, (uint)height, hasAlpha);
        }