Пример #1
0
        public static Image2 Quantize(this Image2 source, IQuantizer quantizer, int maxColors)
        {
            QuantizedImage quantizedImage = quantizer.Quantize(source, maxColors);

            source.SetPixels(source.Width, source.Height, quantizedImage.ToImage().Pixels);
            return(source);
        }
Пример #2
0
        /// <summary>
        /// Applies quantization to the image.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="quantizer">The quantizer to apply to perform the operation.</param>
        /// <param name="maxColors">The maximum number of colors to return.</param>
        /// <returns>The <see cref="Image{TPixel}"/>.</returns>
        public static IImageProcessingContext <TPixel> Quantize <TPixel>(this IImageProcessingContext <TPixel> source, IQuantizer <TPixel> quantizer, int maxColors)
            where TPixel : struct, IPixel <TPixel>
        {
            return(source.Apply(img =>
            {
                // TODO : move helper logic into the processor
                QuantizedImage <TPixel> quantized = quantizer.Quantize(img.Frames.RootFrame, maxColors);
                int palleteCount = quantized.Palette.Length - 1;

                using (var pixels = new PixelAccessor <TPixel>(quantized.Width, quantized.Height))
                {
                    Parallel.For(
                        0,
                        pixels.Height,
                        img.GetConfiguration().ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < pixels.Width; x++)
                        {
                            int i = x + (y * pixels.Width);
                            TPixel color = quantized.Palette[Math.Min(palleteCount, quantized.Pixels[i])];
                            pixels[x, y] = color;
                        }
                    });

                    img.Frames[0].SwapPixelsBuffers(pixels);
                }
            }));
        }
Пример #3
0
        /// <summary>
        /// Applies quantization to the image.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="quantizer">The quantizer to apply to perform the operation.</param>
        /// <param name="maxColors">The maximum number of colors to return.</param>
        /// <returns>The <see cref="Image{TColor}"/>.</returns>
        public static Image <TColor> Quantize <TColor>(this Image <TColor> source, IQuantizer <TColor> quantizer, int maxColors)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            QuantizedImage <TColor> quantized = quantizer.Quantize(source, maxColors);

            int pixelCount   = quantized.Pixels.Length;
            int palleteCount = quantized.Palette.Length - 1;

            using (PixelAccessor <TColor> pixels = new PixelAccessor <TColor>(quantized.Width, quantized.Height))
            {
                Parallel.For(
                    0,
                    pixels.Height,
                    source.Configuration.ParallelOptions,
                    y =>
                {
                    for (var x = 0; x < pixels.Width; x++)
                    {
                        var i        = x + (y * pixels.Width);
                        TColor color = quantized.Palette[Math.Min(palleteCount, quantized.Pixels[i])];
                        pixels[x, y] = color;
                    }
                });

                source.SwapPixelsBuffers(pixels);
                return(source);
            }
        }
Пример #4
0
        /// <summary>
        /// Applies quantization to the image.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="quantizer">The quantizer to apply to perform the operation.</param>
        /// <param name="maxColors">The maximum number of colors to return.</param>
        /// <returns>The <see cref="Image{TPixel}"/>.</returns>
        public static IImageProcessingContext <TPixel> Quantize <TPixel>(this IImageProcessingContext <TPixel> source, IQuantizer <TPixel> quantizer, int maxColors)
            where TPixel : struct, IPixel <TPixel>
        {
            return(source.Apply(img =>
            {
                // TODO : move helper logic into the processor
                QuantizedImage <TPixel> quantized = quantizer.Quantize(img.Frames.RootFrame, maxColors);
                int palleteCount = quantized.Palette.Length - 1;

                using (Buffer2D <TPixel> pixels = source.MemoryManager.Allocate2D <TPixel>(quantized.Width, quantized.Height))
                {
                    Parallel.For(
                        0,
                        pixels.Height,
                        img.GetConfiguration().ParallelOptions,
                        y =>
                    {
                        Span <TPixel> row = pixels.GetRowSpan(y);
                        int yy = y * pixels.Width;
                        for (int x = 0; x < pixels.Width; x++)
                        {
                            int i = x + yy;
                            TPixel color = quantized.Palette[Math.Min(palleteCount, quantized.Pixels[i])];
                            row[x] = color;
                        }
                    });

                    Buffer2D <TPixel> .SwapContents(img.Frames[0].PixelBuffer, pixels);
                }
            }));
        }
Пример #5
0
        /// <summary>
        /// Applies quantization to the image.
        /// </summary>
        /// <typeparam name="T">The pixel format.</typeparam>
        /// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="quantizer">The quantizer to apply to perform the operation.</param>
        /// <param name="maxColors">The maximum number of colors to return.</param>
        /// <returns>The <see cref="Image{T,TP}"/>.</returns>
        public static Image <T, TP> Quantize <T, TP>(this Image <T, TP> source, IQuantizer <T, TP> quantizer, int maxColors)
            where T : IPackedVector <TP>
            where TP : struct
        {
            QuantizedImage <T, TP> quantizedImage = quantizer.Quantize(source, maxColors);

            source.SetPixels(source.Width, source.Height, quantizedImage.ToImage().Pixels);
            return(source);
        }
Пример #6
0
        /// <summary>
        /// Applies quantization to the image.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="quantizer">The quantizer to apply to perform the operation.</param>
        /// <param name="maxColors">The maximum number of colors to return.</param>
        /// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
        public static Image <TColor, TPacked> Quantize <TColor, TPacked>(this Image <TColor, TPacked> source, IQuantizer <TColor, TPacked> quantizer, int maxColors)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct, IEquatable <TPacked>
        {
            QuantizedImage <TColor, TPacked> quantizedImage = quantizer.Quantize(source, maxColors);

            source.SetPixels(source.Width, source.Height, quantizedImage.ToImage().Pixels);
            return(source);
        }
Пример #7
0
        private void TestQuantizer(string path, IQuantizer quantizer)
        {
            var image = new Mat(path, LoadImageType.Grayscale);

            Assert.NotNull(image);

            var w = new Stopwatch();

            w.Start();
            var quantized = quantizer.Quantize(image);

            w.Stop();

            Debug.Write(w.ElapsedMilliseconds);

            Assert.NotNull(quantized);
        }
Пример #8
0
        public void Step(Action <Mat> showImage = null, Action <Mat> showProcessedImage = null)
        {
            // get image as photo of the gameboy screen (input)
            Mat      image = Capture();
            TimeSpan time  = Clock.Time;

            // process image
            Mat processed = Quantizer.Quantize(image);

            showImage?.Invoke(image);

            if (_messages.Count > 0)
            {
                // send messages to agent
                Agent.Send(PopAllMessages());
            }

            if (Play)
            {
                IScreenshot screenshot = new EmguScreenshot(processed, time);
                screenshot.OriginalImage = image;

                try
                {
                    // extracts the game state
                    Agent.Extract(screenshot);

                    processed = Agent.Visualize(processed);
                    showProcessedImage?.Invoke(processed);

                    // presses the buttons
                    Agent.Play(Executor);
                }
                catch (GameOverException)
                {
                    OnGameOver();
                }
            }
            else
            {
                showProcessedImage?.Invoke(processed);
            }

            OnAfterStep();
        }
Пример #9
0
        /// <summary>
        /// Applies quantization to the image.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="source">The image this method extends.</param>
        /// <param name="quantizer">The quantizer to apply to perform the operation.</param>
        /// <param name="maxColors">The maximum number of colors to return.</param>
        /// <returns>The <see cref="Image{TColor}"/>.</returns>
        public static Image <TColor> Quantize <TColor>(this Image <TColor> source, IQuantizer <TColor> quantizer, int maxColors)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            QuantizedImage <TColor> quantized = quantizer.Quantize(source, maxColors);

            int pixelCount   = quantized.Pixels.Length;
            int palleteCount = quantized.Palette.Length - 1;

            TColor[] pixels = new TColor[pixelCount];

            Parallel.For(
                0,
                pixelCount,
                source.Configuration.ParallelOptions,
                i =>
            {
                TColor color = quantized.Palette[Math.Min(palleteCount, quantized.Pixels[i])];
                pixels[i]    = color;
            });

            source.SetPixels(source.Width, source.Height, pixels);
            return(source);
        }
Пример #10
0
 public static Image2 Quantize(this Image2 source, IQuantizer quantizer, int maxColors)
 {
     QuantizedImage quantizedImage = quantizer.Quantize(source, maxColors);
     source.SetPixels(source.Width, source.Height, quantizedImage.ToImage().Pixels);
     return source;
 }
Пример #11
0
        /// <summary>
        /// Encodes the image to the specified stream from the <see cref="Image{TPixel}"/>.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
        /// <param name="stream">The <see cref="Stream"/> to encode the image data to.</param>
        public void Encode <TPixel>(Image <TPixel> image, Stream stream)
            where TPixel : struct, IPixel <TPixel>
        {
            Guard.NotNull(image, nameof(image));
            Guard.NotNull(stream, nameof(stream));

            this.Quantizer = this.options.Quantizer ?? new OctreeQuantizer <TPixel>();

            // Do not use IDisposable pattern here as we want to preserve the stream.
            EndianBinaryWriter writer = new EndianBinaryWriter(Endianness.LittleEndian, stream);

            // Ensure that quality can be set but has a fallback.
            int quality = this.options.Quality > 0 ? this.options.Quality : image.MetaData.Quality;

            quality = quality > 0 ? quality.Clamp(1, 256) : 256;

            // Get the number of bits.
            this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quality);

            // Quantize the image returning a palette.
            this.hasFrames = image.Frames.Any();

            // Dithering when animating gifs is a bad idea as we introduce pixel tearing across frames.
            IQuantizer <TPixel> ditheredQuantizer = (IQuantizer <TPixel>) this.Quantizer;

            ditheredQuantizer.Dither = !this.hasFrames;

            QuantizedImage <TPixel> quantized = ditheredQuantizer.Quantize(image, quality);

            int index = this.GetTransparentIndex(quantized);

            // Write the header.
            this.WriteHeader(writer);

            // Write the LSD. We'll use local color tables for now.
            this.WriteLogicalScreenDescriptor(image, writer, index);

            // Write the first frame.
            this.WriteGraphicalControlExtension(image, writer, index);
            this.WriteComments(image, writer);
            this.WriteImageDescriptor(image, writer);
            this.WriteColorTable(quantized, writer);
            this.WriteImageData(quantized, writer);

            // Write additional frames.
            if (this.hasFrames)
            {
                this.WriteApplicationExtension(writer, image.MetaData.RepeatCount, image.Frames.Count);

                // ReSharper disable once ForCanBeConvertedToForeach
                for (int i = 0; i < image.Frames.Count; i++)
                {
                    ImageFrame <TPixel>     frame          = image.Frames[i];
                    QuantizedImage <TPixel> quantizedFrame = ditheredQuantizer.Quantize(frame, quality);

                    this.WriteGraphicalControlExtension(frame, writer, this.GetTransparentIndex(quantizedFrame));
                    this.WriteImageDescriptor(frame, writer);
                    this.WriteColorTable(quantizedFrame, writer);
                    this.WriteImageData(quantizedFrame, writer);
                }
            }

            // TODO: Write extension etc
            writer.Write(GifConstants.EndIntroducer);
        }