/// <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; }
/// <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); }
/// <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(); }
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); }
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); }