예제 #1
0
        public void OrderedDitherEquality()
        {
            IDither       dither  = KnownDitherings.Bayer2x2;
            OrderedDither dither2 = OrderedDither.Bayer2x2;
            OrderedDither dither3 = OrderedDither.Bayer2x2;

            Assert.True(dither == dither2);
            Assert.True(dither2 == dither);
            Assert.False(dither != dither2);
            Assert.False(dither2 != dither);
            Assert.Equal(dither, dither2);
            Assert.Equal(dither, (object)dither2);
            Assert.Equal(dither.GetHashCode(), dither2.GetHashCode());

            dither = null;
            Assert.False(dither == dither2);
            Assert.False(dither2 == dither);
            Assert.True(dither != dither2);
            Assert.True(dither2 != dither);
            Assert.NotEqual(dither, dither2);
            Assert.NotEqual(dither, (object)dither2);
            Assert.NotEqual(dither?.GetHashCode(), dither2.GetHashCode());

            Assert.True(dither2 == dither3);
            Assert.True(dither3 == dither2);
            Assert.False(dither2 != dither3);
            Assert.False(dither3 != dither2);
            Assert.Equal(dither2, dither3);
            Assert.Equal(dither2, (object)dither3);
            Assert.Equal(dither2.GetHashCode(), dither3.GetHashCode());
        }
예제 #2
0
        public void ErrorDitherEquality()
        {
            IDither     dither  = KnownDitherings.FloydSteinberg;
            ErrorDither dither2 = ErrorDither.FloydSteinberg;
            ErrorDither dither3 = ErrorDither.FloydSteinberg;

            Assert.True(dither == dither2);
            Assert.True(dither2 == dither);
            Assert.False(dither != dither2);
            Assert.False(dither2 != dither);
            Assert.Equal(dither, dither2);
            Assert.Equal(dither, (object)dither2);
            Assert.Equal(dither.GetHashCode(), dither2.GetHashCode());

            dither = null;
            Assert.False(dither == dither2);
            Assert.False(dither2 == dither);
            Assert.True(dither != dither2);
            Assert.True(dither2 != dither);
            Assert.NotEqual(dither, dither2);
            Assert.NotEqual(dither, (object)dither2);
            Assert.NotEqual(dither?.GetHashCode(), dither2.GetHashCode());

            Assert.True(dither2 == dither3);
            Assert.True(dither3 == dither2);
            Assert.False(dither2 != dither3);
            Assert.False(dither3 != dither2);
            Assert.Equal(dither2, dither3);
            Assert.Equal(dither2, (object)dither3);
            Assert.Equal(dither2.GetHashCode(), dither3.GetHashCode());
        }
예제 #3
0
 /// <summary>
 /// Dithers the image reducing it to the given palette using ordered dithering.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="ditherScale">The dithering scale used to adjust the amount of dither.</param>
 /// <param name="palette">The palette to select substitute colors from.</param>
 /// <param name="rectangle">
 /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
 /// </param>
 /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
 public static IImageProcessingContext Dither(
     this IImageProcessingContext source,
     IDither dither,
     float ditherScale,
     ReadOnlyMemory <Color> palette,
     Rectangle rectangle) =>
 source.ApplyProcessor(new PaletteDitherProcessor(dither, ditherScale, palette), rectangle);
예제 #4
0
 /// <summary>
 /// Dithers the image reducing it to two colors using ordered dithering.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="upperColor">The color to use for pixels that are above the threshold.</param>
 /// <param name="lowerColor">The color to use for pixels that are below the threshold</param>
 /// <param name="rectangle">
 /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
 /// </param>
 /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
 public static IImageProcessingContext BinaryDither(
     this IImageProcessingContext source,
     IDither dither,
     Color upperColor,
     Color lowerColor,
     Rectangle rectangle) =>
 source.ApplyProcessor(new PaletteDitherProcessor(dither, new[] { upperColor, lowerColor }), rectangle);
예제 #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PaletteDitherProcessor"/> class.
 /// </summary>
 /// <param name="dither">The dithering algorithm.</param>
 /// <param name="ditherScale">The dithering scale used to adjust the amount of dither.</param>
 /// <param name="palette">The palette to select substitute colors from.</param>
 public PaletteDitherProcessor(IDither dither, float ditherScale, ReadOnlyMemory <Color> palette)
 {
     Guard.MustBeGreaterThan(palette.Length, 0, nameof(palette));
     Guard.NotNull(dither, nameof(dither));
     this.Dither      = dither;
     this.DitherScale = ditherScale.Clamp(QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale);
     this.Palette     = palette;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="PaletteDitherProcessor{TPixel}"/> class.
 /// </summary>
 /// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
 /// <param name="definition">The <see cref="PaletteDitherProcessor"/> defining the processor parameters.</param>
 /// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param>
 /// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
 public PaletteDitherProcessor(Configuration configuration, PaletteDitherProcessor definition, Image <TPixel> source, Rectangle sourceRectangle)
     : base(configuration, source, sourceRectangle)
 {
     this.paletteLength = definition.Palette.Span.Length;
     this.dither        = definition.Dither;
     this.ditherScale   = definition.DitherScale;
     this.sourcePalette = definition.Palette;
 }
예제 #7
0
        public void ShouldThrowForDefaultDitherInstance(IDither dither)
        {
            void Command()
            {
                using var image = new Image <Rgba32>(10, 10);
                image.Mutate(x => x.Dither(dither));
            }

            Assert.Throws <ImageProcessingException>(Command);
        }
예제 #8
0
        public void ShouldThrowForDefaultDitherInstance(IDither dither)
        {
            void Command()
            {
                using var image = new Image <Rgba32>(10, 10);
                var quantizer = new WebSafePaletteQuantizer();

                quantizer.Options.Dither = dither;
                image.Mutate(x => x.Quantize(quantizer));
            }

            Assert.Throws <ImageProcessingException>(Command);
        }
예제 #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PaletteDitherProcessor{TPixel}"/> class.
        /// </summary>
        /// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
        /// <param name="definition">The <see cref="PaletteDitherProcessor"/> defining the processor parameters.</param>
        /// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param>
        /// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
        public PaletteDitherProcessor(Configuration configuration, PaletteDitherProcessor definition, Image <TPixel> source, Rectangle sourceRectangle)
            : base(configuration, source, sourceRectangle)
        {
            this.dither = definition.Dither;

            ReadOnlySpan <Color> sourcePalette = definition.Palette.Span;

            this.paletteOwner = this.Configuration.MemoryAllocator.Allocate <TPixel>(sourcePalette.Length);
            Color.ToPixel(this.Configuration, sourcePalette, this.paletteOwner.Memory.Span);

            this.ditherProcessor = new DitherProcessor(
                this.Configuration,
                this.paletteOwner.Memory,
                definition.DitherScale);
        }
예제 #10
0
        public void CommonDitherers_WorkWithDiscoBuffers <TPixel>(
            TestImageProvider <TPixel> provider,
            string name)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            IDither dither = TestUtils.GetDither(name);

            if (SkipAllDitherTests)
            {
                return;
            }

            provider.RunBufferCapacityLimitProcessorTest(
                41,
                c => c.Dither(dither),
                name);
        }
예제 #11
0
        public void DitherFilter_WorksWithAllDitherers <TPixel>(
            TestImageProvider <TPixel> provider,
            IDither ditherer,
            string name)
            where TPixel : struct, IPixel <TPixel>
        {
            if (SkipAllDitherTests)
            {
                return;
            }

            provider.RunValidatingProcessorTest(
                x => x.Dither(ditherer),
                testOutputDetails: name,
                comparer: ValidatorComparer,
                appendPixelTypeToFileName: false);
        }
예제 #12
0
        public void CommonDitherers_WorkWithDiscoBuffers <TPixel>(
            TestImageProvider <TPixel> provider,
            string name)
            where TPixel : struct, IPixel <TPixel>
        {
            IDither dither = TestUtils.GetDither(name);

            if (SkipAllDitherTests)
            {
                return;
            }

            provider.RunBufferCapacityLimitProcessorTest(
                41,
                c => c.Dither(dither),
                name,
                ImageComparer.TolerantPercentage(0.001f));
        }
        public static IDither CreateDither(DitherAlgorithm ditherAlgorithm)
        {
            Initialize();

            IDither dither = null;

            var attribute = _enumLinks.Where(l => l.EnumValue == (int)ditherAlgorithm);

            if (attribute.Any())
            {
                var foundAttribute = attribute.First();
                dither = (IDither)Activator.CreateInstance(foundAttribute.Type);
            }
            else
            {
                throw new NotSupportedException(ditherAlgorithm.ToString() + " is not supported");
            }

            return(dither);
        }
예제 #14
0
        private static void SecondPass <TFrameQuantizer, TPixel>(
            ref TFrameQuantizer quantizer,
            ImageFrame <TPixel> source,
            Rectangle bounds,
            Memory <byte> output,
            ReadOnlyMemory <TPixel> palette)
            where TFrameQuantizer : struct, IFrameQuantizer <TPixel>
            where TPixel : unmanaged, IPixel <TPixel>
        {
            IDither dither = quantizer.Options.Dither;

            if (dither is null)
            {
                var operation = new RowIntervalOperation <TFrameQuantizer, TPixel>(quantizer, source, output, bounds, palette);
                ParallelRowIterator.IterateRowIntervals(
                    quantizer.Configuration,
                    bounds,
                    in operation);

                return;
            }

            dither.ApplyQuantizationDither(ref quantizer, palette, source, output, bounds);
        }
예제 #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PaletteDitherProcessor"/> class.
 /// </summary>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="ditherScale">The dithering scale used to adjust the amount of dither.</param>
 public PaletteDitherProcessor(IDither dither, float ditherScale)
     : this(dither, ditherScale, Color.WebSafePalette)
 {
 }
예제 #16
0
        public bool TwoColor()
        {
            var Folder    = Config.InputFolder;
            var files     = Directory.EnumerateFiles(Folder, "*.png");
            var filenames = files.ToArray();

            MathUtils.NumericalSort(filenames);

            var contrast = Config.Contrast;

            IDither DitheringType = null;

            switch (Config.DitheringMode)
            {
            case 0:
                break;

            case 1:
                DitheringType = KnownDitherings.Bayer8x8;
                break;

            case 2:
                DitheringType = KnownDitherings.Bayer4x4;
                break;

            case 3:
                DitheringType = KnownDitherings.Bayer2x2;
                break;

            case 4:
                DitheringType = KnownDitherings.FloydSteinberg;
                break;

            case 5:
                DitheringType = KnownDitherings.Atkinson;
                break;

            case 6:
                DitheringType = KnownDitherings.Burks;
                break;

            case 7:
                DitheringType = KnownDitherings.JarvisJudiceNinke;
                break;

            case 8:
                DitheringType = KnownDitherings.StevensonArce;
                break;

            case 9:
                DitheringType = KnownDitherings.Sierra2;
                break;

            case 10:
                DitheringType = KnownDitherings.Sierra3;
                break;

            case 11:
                DitheringType = KnownDitherings.SierraLite;
                break;

            case 12:
                DitheringType = KnownDitherings.Stucki;
                break;

            case 13:
                DitheringType = KnownDitherings.Ordered3x3;
                break;

            default:
                //this one is my favorite :)
                DitheringType = KnownDitherings.Bayer8x8;
                break;
            }

            List <Color> colors = new List <Color>();

            for (int i = 0; i < filenames.Length; i++)
            {
                using (Image <Rgba32> image = (Image <Rgba32>)Image.Load(filenames[i]))
                {
                    image.Mutate(x =>
                    {
                        if (contrast != 0)
                        {
                            x.Contrast(contrast);
                        }
                        if (DitheringType == null)
                        {
                            x.AdaptiveThreshold();
                        }
                        else
                        {
                            x.BinaryDither(DitheringType);
                        }
                    });
                    image.SaveAsPng($"{Folder}/frame_{i}.png");
                    image.Dispose();
                }
            }
            return(true);
        }
예제 #17
0
        public bool FullColor()
        {
            var Folder    = Config.InputFolder;
            var files     = Directory.EnumerateFiles(Folder, "*.png");
            var filenames = files.ToArray();

            MathUtils.NumericalSort(filenames);

            var contrast = Config.Contrast;

            IDither DitheringType = null;

            switch (Config.DitheringMode)
            {
            case 1:
                DitheringType = KnownDitherings.Bayer8x8;
                break;

            case 2:
                DitheringType = KnownDitherings.Bayer4x4;
                break;

            case 3:
                DitheringType = KnownDitherings.Bayer2x2;
                break;

            case 4:
                DitheringType = KnownDitherings.FloydSteinberg;
                break;

            case 5:
                DitheringType = KnownDitherings.Atkinson;
                break;

            case 6:
                DitheringType = KnownDitherings.Burks;
                break;

            case 7:
                DitheringType = KnownDitherings.JarvisJudiceNinke;
                break;

            case 8:
                DitheringType = KnownDitherings.StevensonArce;
                break;

            case 9:
                DitheringType = KnownDitherings.Sierra2;
                break;

            case 10:
                DitheringType = KnownDitherings.Sierra3;
                break;

            case 11:
                DitheringType = KnownDitherings.SierraLite;
                break;

            case 12:
                DitheringType = KnownDitherings.Stucki;
                break;

            case 13:
                DitheringType = KnownDitherings.Ordered3x3;
                break;

            default:
                DitheringType = null;
                break;
            }

            List <Color> colors = new List <Color>();

            colors.Add(Color.Red);
            colors.Add(Color.Black);
            colors.Add(Color.White);
            colors.Add(Color.Blue);
            if (DitheringType != null)
            {
                for (int i = 0; i < filenames.Length; i++)
                {
                    Directory.CreateDirectory("tmp");
                    using (Image <Rgba32> image = (Image <Rgba32>)Image.Load(filenames[i]))
                    {
                        Image <Rgba32> bw = image.Clone();
                        bw.Mutate(x =>
                        {
                            if (contrast != 0)
                            {
                                x.Contrast(contrast);
                            }
                            x.BinaryDither(DitheringType);
                        });
                        bw.Save($"tmp/frame_{i}.png");
                        bw.Dispose();

                        image.Mutate(x =>
                        {
                            if (contrast != 0)
                            {
                                x.Contrast(contrast);
                            }
                            //x.BinaryDither(DitheringType);
                            var Palette = new ReadOnlyMemory <Color>(colors.ToArray());

                            x.Dither(DitheringType, Palette);
                        });

                        image.SaveAsPng($"frames/frame_{i}.png");
                        image.Dispose();
                    }
                }
            }

            return(true);
        }
예제 #18
0
 /// <summary>
 /// Dithers the image reducing it to two colors using ordered dithering.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="rectangle">
 /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
 /// </param>
 /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
 public static IImageProcessingContext BinaryDither(
     this IImageProcessingContext source,
     IDither dither,
     Rectangle rectangle) =>
 BinaryDither(source, dither, Color.White, Color.Black, rectangle);
예제 #19
0
 /// <summary>
 /// Dithers the image reducing it to a web-safe palette using ordered dithering.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="ditherScale">The dithering scale used to adjust the amount of dither.</param>
 /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
 public static IImageProcessingContext Dither(
     this IImageProcessingContext source,
     IDither dither,
     float ditherScale) =>
 source.ApplyProcessor(new PaletteDitherProcessor(dither, ditherScale));
예제 #20
0
 /// <summary>
 /// Dithers the image reducing it to the given palette using ordered dithering.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="palette">The palette to select substitute colors from.</param>
 /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
 public static IImageProcessingContext Dither(
     this IImageProcessingContext source,
     IDither dither,
     ReadOnlyMemory <Color> palette) =>
 source.ApplyProcessor(new PaletteDitherProcessor(dither, palette));
예제 #21
0
 BinaryDither(this IImageProcessingContext source, IDither dither) =>
 BinaryDither(source, dither, Color.White, Color.Black);
예제 #22
0
 public DitherTest()
 {
     this.orderedDither = KnownDitherings.Bayer4x4;
     this.errorDiffuser = KnownDitherings.FloydSteinberg;
 }
예제 #23
0
 /// <summary>
 /// Dithers the image reducing it to a web-safe palette using ordered dithering.
 /// </summary>
 /// <param name="source">The image this method extends.</param>
 /// <param name="dither">The ordered ditherer.</param>
 /// <param name="rectangle">
 /// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
 /// </param>
 /// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
 public static IImageProcessingContext Dither(
     this IImageProcessingContext source,
     IDither dither,
     Rectangle rectangle) =>
 source.ApplyProcessor(new PaletteDitherProcessor(dither), rectangle);
예제 #24
0
 public void BinaryDitherFilter_WorksWithAllDitherers <TPixel>(TestImageProvider <TPixel> provider, string name, IDither ditherer)
     where TPixel : struct, IPixel <TPixel>
 {
     using (Image <TPixel> image = provider.GetImage())
     {
         image.Mutate(x => x.BinaryDither(ditherer));
         image.DebugSave(provider, name);
     }
 }
예제 #25
0
 public void DiffusionFilter_WorksWithAllErrorDiffusers <TPixel>(TestImageProvider <TPixel> provider, string name, IDither diffuser)
     where TPixel : unmanaged, IPixel <TPixel>
 {
     using (Image <TPixel> image = provider.GetImage())
     {
         image.Mutate(x => x.BinaryDither(diffuser));
         image.DebugSave(provider, name);
     }
 }
예제 #26
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PaletteDitherProcessor"/> class.
 /// </summary>
 /// <param name="dither">The ordered ditherer.</param>
 public PaletteDitherProcessor(IDither dither)
     : this(dither, QuantizerConstants.MaxDitherScale)
 {
 }
예제 #27
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PaletteDitherProcessor"/> class.
 /// </summary>
 /// <param name="dither">The dithering algorithm.</param>
 /// <param name="palette">The palette to select substitute colors from.</param>
 public PaletteDitherProcessor(IDither dither, ReadOnlyMemory <Color> palette)
     : this(dither, QuantizerConstants.MaxDitherScale, palette)
 {
 }
예제 #28
0
 /// <inheritdoc/>
 public bool Equals(IDither other)
 => this.Equals((object)other);