/// <inheritdoc/>
        protected override void OnFrameApply(ImageFrame <TPixel> source)
        {
            byte threshold   = (byte)MathF.Round(this.Definition.Threshold * 255F);
            bool isAlphaOnly = typeof(TPixel) == typeof(Alpha8);

            var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
            int startY   = interest.Y;
            int endY     = interest.Bottom;
            int startX   = interest.X;
            int endX     = interest.Right;

            // Collect the values before looping so we can reduce our calculation count for identical sibling pixels
            TPixel             sourcePixel   = source[startX, startY];
            TPixel             previousPixel = sourcePixel;
            PixelPair <TPixel> pair          = this.GetClosestPixelPair(ref sourcePixel);
            Rgba32             rgba          = default;

            sourcePixel.ToRgba32(ref rgba);

            // Convert to grayscale using ITU-R Recommendation BT.709 if required
            byte luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);

            for (int y = startY; y < endY; y++)
            {
                Span <TPixel> row = source.GetPixelRowSpan(y);

                for (int x = startX; x < endX; x++)
                {
                    sourcePixel = row[x];

                    // Check if this is the same as the last pixel. If so use that value
                    // rather than calculating it again. This is an inexpensive optimization.
                    if (!previousPixel.Equals(sourcePixel))
                    {
                        pair = this.GetClosestPixelPair(ref sourcePixel);

                        // No error to spread, exact match.
                        if (sourcePixel.Equals(pair.First))
                        {
                            continue;
                        }

                        sourcePixel.ToRgba32(ref rgba);
                        luminance = isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);

                        // Setup the previous pointer
                        previousPixel = sourcePixel;
                    }

                    TPixel transformedPixel = luminance >= threshold ? pair.Second : pair.First;
                    this.Definition.Diffuser.Dither(source, sourcePixel, transformedPixel, x, y, startX, startY, endX, endY);
                }
            }
        }
Пример #2
0
        /// <inheritdoc/>
        protected override void OnFrameApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration)
        {
            Rgba32 rgba        = default;
            bool   isAlphaOnly = typeof(TPixel) == typeof(Alpha8);

            var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
            int startY   = interest.Y;
            int endY     = interest.Bottom;
            int startX   = interest.X;
            int endX     = interest.Right;

            // Collect the values before looping so we can reduce our calculation count for identical sibling pixels
            TPixel             sourcePixel   = source[startX, startY];
            TPixel             previousPixel = sourcePixel;
            PixelPair <TPixel> pair          = this.GetClosestPixelPair(ref sourcePixel);

            sourcePixel.ToRgba32(ref rgba);

            // Convert to grayscale using ITU-R Recommendation BT.709 if required
            float luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);

            for (int y = startY; y < endY; y++)
            {
                Span <TPixel> row = source.GetPixelRowSpan(y);

                for (int x = startX; x < endX; x++)
                {
                    sourcePixel = row[x];

                    // Check if this is the same as the last pixel. If so use that value
                    // rather than calculating it again. This is an inexpensive optimization.
                    if (!previousPixel.Equals(sourcePixel))
                    {
                        pair = this.GetClosestPixelPair(ref sourcePixel);

                        // No error to spread, exact match.
                        if (sourcePixel.Equals(pair.First))
                        {
                            continue;
                        }

                        sourcePixel.ToRgba32(ref rgba);
                        luminance = isAlphaOnly ? rgba.A : (.2126F * rgba.R) + (.7152F * rgba.G) + (.0722F * rgba.B);

                        // Setup the previous pointer
                        previousPixel = sourcePixel;
                    }

                    this.Dither.Dither(source, sourcePixel, pair.Second, pair.First, luminance, x, y);
                }
            }
        }
Пример #3
0
 /// <inheritdoc/>
 public bool Equals(PixelPair <TPixel> other)
 => this.First.Equals(other.First) && this.Second.Equals(other.Second);