Ejemplo n.º 1
0
        /// <inheritdoc/>
        public virtual QuantizedFrame <TPixel> QuantizeFrame(ImageFrame <TPixel> image)
        {
            Guard.NotNull(image, nameof(image));

            // Get the size of the source image
            int height = image.Height;
            int width  = image.Width;

            // Call the FirstPass function if not a single pass algorithm.
            // For something like an Octree quantizer, this will run through
            // all image pixels, build a data structure, and create a palette.
            if (!this.singlePass)
            {
                this.FirstPass(image, width, height);
            }

            // Collect the palette. Required before the second pass runs.
            TPixel[] palette = this.GetPalette();
            this.paletteVector = new Vector4[palette.Length];
            PixelOperations <TPixel> .Instance.ToVector4(image.Configuration, (ReadOnlySpan <TPixel>) palette, (Span <Vector4>) this.paletteVector, PixelConversionModifiers.Scale);

            var quantizedFrame = new QuantizedFrame <TPixel>(image.MemoryAllocator, width, height, palette);

            if (this.Dither)
            {
                // We clone the image as we don't want to alter the original via dithering.
                using (ImageFrame <TPixel> clone = image.Clone())
                {
                    this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette, width, height);
                }
            }
            else
            {
                this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette, width, height);
            }

            return(quantizedFrame);
        }
Ejemplo n.º 2
0
        /// <inheritdoc />
        protected override void OnFrameApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration)
        {
            using (IFrameQuantizer <TPixel> executor = this.quantizer.CreateFrameQuantizer <TPixel>(configuration))
                using (QuantizedFrame <TPixel> quantized = executor.QuantizeFrame(source))
                {
                    int paletteCount = quantized.Palette.Length - 1;

                    // Not parallel to remove "quantized" closure allocation.
                    // We can operate directly on the source here as we've already read it to get the
                    // quantized result
                    for (int y = 0; y < source.Height; y++)
                    {
                        Span <TPixel>       row = source.GetPixelRowSpan(y);
                        ReadOnlySpan <byte> quantizedPixelSpan = quantized.GetPixelSpan();
                        int yy = y * source.Width;

                        for (int x = 0; x < source.Width; x++)
                        {
                            int i = x + yy;
                            row[x] = quantized.Palette[Math.Min(paletteCount, quantizedPixelSpan[i])];
                        }
                    }
                }
        }