예제 #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="WebpEncoderCore"/> class.
 /// </summary>
 /// <param name="options">The encoder options.</param>
 /// <param name="memoryAllocator">The memory manager.</param>
 public WebpEncoderCore(IWebpEncoderOptions options, MemoryAllocator memoryAllocator)
 {
     this.memoryAllocator      = memoryAllocator;
     this.alphaCompression     = options.UseAlphaCompression;
     this.fileFormat           = options.FileFormat;
     this.quality              = options.Quality;
     this.method               = options.Method;
     this.entropyPasses        = options.EntropyPasses;
     this.spatialNoiseShaping  = options.SpatialNoiseShaping;
     this.filterStrength       = options.FilterStrength;
     this.transparentColorMode = options.TransparentColorMode;
     this.nearLossless         = options.NearLossless;
     this.nearLosslessQuality  = options.NearLosslessQuality;
 }
예제 #2
0
        /// <summary>
        /// Encodes the alpha channel data.
        /// Data is either compressed as lossless webp image or uncompressed.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="image">The <see cref="ImageFrame{TPixel}"/> to encode from.</param>
        /// <param name="configuration">The global configuration.</param>
        /// <param name="memoryAllocator">The memory manager.</param>
        /// <param name="compress">Indicates, if the data should be compressed with the lossless webp compression.</param>
        /// <param name="size">The size in bytes of the alpha data.</param>
        /// <returns>The encoded alpha data.</returns>
        public IMemoryOwner <byte> EncodeAlpha <TPixel>(Image <TPixel> image, Configuration configuration, MemoryAllocator memoryAllocator, bool compress, out int size)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            int width  = image.Width;
            int height = image.Height;

            this.alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator);

            if (compress)
            {
                WebpEncodingMethod effort = WebpEncodingMethod.Default;
                int quality = 8 * (int)effort;
                using var lossLessEncoder = new Vp8LEncoder(
                          memoryAllocator,
                          configuration,
                          width,
                          height,
                          quality,
                          effort,
                          WebpTransparentColorMode.Preserve,
                          false,
                          0);

                // The transparency information will be stored in the green channel of the ARGB quadruplet.
                // The green channel is allowed extra transformation steps in the specification -- unlike the other channels,
                // that can improve compression.
                using Image <Rgba32> alphaAsImage = DispatchAlphaToGreen(image, this.alphaData.GetSpan());

                size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, this.alphaData);

                return(this.alphaData);
            }

            size = width * height;
            return(this.alphaData);
        }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Vp8Encoder" /> class.
        /// </summary>
        /// <param name="memoryAllocator">The memory allocator.</param>
        /// <param name="configuration">The global configuration.</param>
        /// <param name="width">The width of the input image.</param>
        /// <param name="height">The height of the input image.</param>
        /// <param name="quality">The encoding quality.</param>
        /// <param name="method">Quality/speed trade-off (0=fast, 6=slower-better).</param>
        /// <param name="entropyPasses">Number of entropy-analysis passes (in [1..10]).</param>
        /// <param name="filterStrength">The filter the strength of the deblocking filter, between 0 (no filtering) and 100 (maximum filtering).</param>
        /// <param name="spatialNoiseShaping">The spatial noise shaping. 0=off, 100=maximum.</param>
        public Vp8Encoder(
            MemoryAllocator memoryAllocator,
            Configuration configuration,
            int width,
            int height,
            int quality,
            WebpEncodingMethod method,
            int entropyPasses,
            int filterStrength,
            int spatialNoiseShaping)
        {
            this.memoryAllocator     = memoryAllocator;
            this.configuration       = configuration;
            this.Width               = width;
            this.Height              = height;
            this.quality             = Numerics.Clamp(quality, 0, 100);
            this.method              = method;
            this.entropyPasses       = Numerics.Clamp(entropyPasses, 1, 10);
            this.filterStrength      = Numerics.Clamp(filterStrength, 0, 100);
            this.spatialNoiseShaping = Numerics.Clamp(spatialNoiseShaping, 0, 100);
            this.rdOptLevel          = method is WebpEncodingMethod.BestQuality ? Vp8RdLevel.RdOptTrellisAll
                : method >= WebpEncodingMethod.Level5 ? Vp8RdLevel.RdOptTrellis
                : method >= WebpEncodingMethod.Level3 ? Vp8RdLevel.RdOptBasic
                : Vp8RdLevel.RdOptNone;

            int pixelCount = width * height;

            this.Mbw = (width + 15) >> 4;
            this.Mbh = (height + 15) >> 4;
            int uvSize = ((width + 1) >> 1) * ((height + 1) >> 1);

            this.Y             = this.memoryAllocator.Allocate <byte>(pixelCount);
            this.U             = this.memoryAllocator.Allocate <byte>(uvSize);
            this.V             = this.memoryAllocator.Allocate <byte>(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];

            // TODO: make partition_limit configurable?
            int limit = 100; // original code: limit = 100 - config->partition_limit;

            this.maxI4HeaderBits =
                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[i] = new Vp8MacroBlockInfo();
            }

            this.SegmentInfos = new Vp8SegmentInfo[4];
            for (int i = 0; i < 4; i++)
            {
                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];

            // Initialize with default values, which the reference c implementation uses,
            // to be able to compare to the original and spot differences.
            this.Preds.AsSpan().Fill(205);
            this.Nz.AsSpan().Fill(3452816845);

            this.ResetBoundaryPredictions();
        }
예제 #4
0
        public void Encode_Lossless_WithDifferentMethodAndQuality_Works <TPixel>(TestImageProvider <TPixel> provider, WebpEncodingMethod method, int quality)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            var encoder = new WebpEncoder()
            {
                FileFormat = WebpFileFormatType.Lossless,
                Method     = method,
                Quality    = quality
            };

            using Image <TPixel> image = provider.GetImage();
            string testOutputDetails   = string.Concat("lossless", "_m", method, "_q", quality);

            image.VerifyEncoder(provider, "webp", testOutputDetails, encoder);
        }
예제 #5
0
        public void Encode_Lossless_WithPreserveTransparentColor_Works <TPixel>(TestImageProvider <TPixel> provider, WebpEncodingMethod method)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            var encoder = new WebpEncoder()
            {
                FileFormat           = WebpFileFormatType.Lossless,
                Method               = method,
                TransparentColorMode = WebpTransparentColorMode.Preserve
            };

            using Image <TPixel> image = provider.GetImage();
            string testOutputDetails   = string.Concat("lossless", "_m", method);

            image.VerifyEncoder(provider, "webp", testOutputDetails, encoder);
        }