Пример #1
0
        private void RestoreToBackground(ImageBase <TColor, TPacked> frame)
        {
            if (this.restoreArea == null)
            {
                return;
            }

            // Optimization for when the size of the frame is the same as the image size.
            if (this.restoreArea.Value.Width == this.decodedImage.Width &&
                this.restoreArea.Value.Height == this.decodedImage.Height)
            {
                using (PixelAccessor <TColor, TPacked> pixelAccessor = frame.Lock())
                {
                    pixelAccessor.Reset();
                }
            }
            else
            {
                using (PixelArea <TColor, TPacked> emptyRow = new PixelArea <TColor, TPacked>(this.restoreArea.Value.Width, ComponentOrder.XYZW))
                {
                    using (PixelAccessor <TColor, TPacked> pixelAccessor = frame.Lock())
                    {
                        for (int y = this.restoreArea.Value.Top; y < this.restoreArea.Value.Top + this.restoreArea.Value.Height; y++)
                        {
                            pixelAccessor.CopyFrom(emptyRow, y, this.restoreArea.Value.Left);
                        }
                    }
                }
            }

            this.restoreArea = null;
        }
Пример #2
0
        /// <summary>
        /// Collects the true color pixel data.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="image">The image to encode.</param>
        private void CollectColorBytes <TColor, TPacked>(ImageBase <TColor, TPacked> image)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            // Copy the pixels across from the image.
            // TODO: This could be sped up more if we add a method to PixelAccessor that does this by row directly to a byte array.
            this.pixelData = new byte[this.width * this.height * this.bytesPerPixel];
            int stride = this.width * this.bytesPerPixel;

            using (PixelAccessor <TColor, TPacked> pixels = image.Lock())
            {
                int bpp = this.bytesPerPixel;
                Parallel.For(
                    0,
                    this.height,
                    Bootstrapper.Instance.ParallelOptions,
                    y =>
                {
                    for (int x = 0; x < this.width; x++)
                    {
                        int dataOffset = (y * stride) + (x * this.bytesPerPixel);
                        pixels[x, y].ToBytes(this.pixelData, dataOffset, bpp == 4 ? ComponentOrder.XYZW : ComponentOrder.XYZ);
                    }
                });
            }
        }
Пример #3
0
        /// <inheritdoc/>
        public override void Apply(ImageBase <TColor, TPacked> target, ImageBase <TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
        {
            if (this.OptimizedApply(target, source))
            {
                return;
            }

            int       height = target.Height;
            int       width  = target.Width;
            Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix);

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            Point transformedPoint = Point.Rotate(new Point(x, y), matrix);
                            if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y))
                            {
                                targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y];
                            }
                        }
                    });
                }
        }
Пример #4
0
        /// <summary>
        /// Rotates the image 90 degrees clockwise at the centre point.
        /// </summary>
        /// <param name="target">The target image.</param>
        /// <param name="source">The source image.</param>
        private void Rotate90(ImageBase <TColor, TPacked> target, ImageBase <TColor, TPacked> source)
        {
            int width  = source.Width;
            int height = source.Height;
            Image <TColor, TPacked> temp = new Image <TColor, TPacked>(height, width);

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> tempPixels = temp.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newX            = height - y - 1;
                            tempPixels[newX, x] = sourcePixels[x, y];
                        }
                    });
                }

            target.SetPixels(height, width, temp.Pixels);
        }
Пример #5
0
        /// <summary>
        /// Swaps the image at the X-axis, which goes horizontally through the middle
        /// at half the height of the image.
        /// </summary>
        /// <param name="target">Target image to apply the process to.</param>
        private void FlipX(ImageBase <T, TP> target)
        {
            int           width      = target.Width;
            int           height     = target.Height;
            int           halfHeight = (int)Math.Ceiling(target.Height * .5F);
            Image <T, TP> temp       = new Image <T, TP>(width, height);

            temp.ClonePixels(width, height, target.Pixels);

            using (IPixelAccessor <T, TP> targetPixels = target.Lock())
                using (IPixelAccessor <T, TP> tempPixels = temp.Lock())
                {
                    Parallel.For(
                        0,
                        halfHeight,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newY              = height - y - 1;
                            targetPixels[x, y]    = tempPixels[x, newY];
                            targetPixels[x, newY] = tempPixels[x, y];
                        }

                        this.OnRowProcessed();
                    });
                }
        }
Пример #6
0
        /// <inheritdoc/>
        public override void Apply(ImageBase <TColor, TPacked> target, ImageBase <TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
        {
            // Jump out, we'll deal with that later.
            if (source.Bounds == target.Bounds)
            {
                return;
            }

            int targetY      = this.cropRectangle.Y;
            int targetBottom = this.cropRectangle.Bottom;
            int startX       = this.cropRectangle.X;
            int endX         = this.cropRectangle.Right;

            int minY = Math.Max(targetY, startY);
            int maxY = Math.Min(targetBottom, endY);

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock())
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = startX; x < endX; x++)
                        {
                            targetPixels[x - startX, y - targetY] = sourcePixels[x, y];
                        }
                    });
                }
        }
Пример #7
0
        /// <summary>
        /// Swaps the image at the Y-axis, which goes vertically through the middle
        /// at half of the width of the image.
        /// </summary>
        /// <param name="source">The source image to apply the process to.</param>
        private void FlipY(ImageBase <TColor> source)
        {
            int width     = source.Width;
            int height    = source.Height;
            int halfWidth = (int)Math.Ceiling(width * .5F);

            using (PixelAccessor <TColor> targetPixels = new PixelAccessor <TColor>(width, height))
            {
                using (PixelAccessor <TColor> sourcePixels = source.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < halfWidth; x++)
                        {
                            int newX              = width - x - 1;
                            targetPixels[x, y]    = sourcePixels[newX, y];
                            targetPixels[newX, y] = sourcePixels[x, y];
                        }
                    });
                }

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Пример #8
0
        /// <inheritdoc/>
        public override void Apply(ImageBase <TColor, TPacked> target, ImageBase <TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
        {
            int startX  = targetRectangle.X;
            int endX    = targetRectangle.Right;
            int sourceX = sourceRectangle.X;
            int sourceY = sourceRectangle.Y;

            Guard.MustBeGreaterThanOrEqualTo(startX, sourceX, nameof(targetRectangle));
            Guard.MustBeGreaterThanOrEqualTo(startY, sourceY, nameof(targetRectangle));
            Guard.MustBeLessThanOrEqualTo(endX, sourceRectangle.Right, nameof(targetRectangle));
            Guard.MustBeLessThanOrEqualTo(endY, sourceRectangle.Bottom, nameof(targetRectangle));

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock())
                {
                    Parallel.For(
                        startY,
                        endY,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = startX; x < endX; x++)
                        {
                            targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY];
                        }
                    });
                }
        }
Пример #9
0
        /// <summary>
        /// Swaps the image at the Y-axis, which goes vertically through the middle
        /// at half of the width of the image.
        /// </summary>
        /// <param name="source">The source image to apply the process to.</param>
        private void FlipY(ImageBase <TColor, TPacked> source)
        {
            int width     = source.Width;
            int height    = source.Height;
            int halfWidth = (int)Math.Ceiling(width * .5F);

            TColor[] target = new TColor[width * height];

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock <TColor, TPacked>(width, height))
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < halfWidth; x++)
                        {
                            int newX              = width - x - 1;
                            targetPixels[x, y]    = sourcePixels[newX, y];
                            targetPixels[newX, y] = sourcePixels[x, y];
                        }
                    });
                }

            source.SetPixels(width, height, target);
        }
Пример #10
0
        /// <summary>
        /// Collects the true color pixel data.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="image">The image to encode.</param>
        private void CollectColorBytes <TColor, TPacked>(ImageBase <TColor, TPacked> image)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            // Copy the pixels across from the image.
            this.pixelData = new byte[this.width * this.height * this.bytesPerPixel];
            int stride = this.width * this.bytesPerPixel;

            using (PixelAccessor <TColor, TPacked> pixels = image.Lock())
            {
                Parallel.For(
                    0,
                    this.height,
                    Bootstrapper.Instance.ParallelOptions,
                    y =>
                {
                    for (int x = 0; x < this.width; x++)
                    {
                        int dataOffset = (y * stride) + (x * this.bytesPerPixel);
                        Color source   = new Color(pixels[x, y].ToVector4());

                        this.pixelData[dataOffset]     = source.R;
                        this.pixelData[dataOffset + 1] = source.G;
                        this.pixelData[dataOffset + 2] = source.B;
                        if (this.bytesPerPixel == 4)
                        {
                            this.pixelData[dataOffset + 3] = source.A;
                        }
                    }
                });
            }
        }
Пример #11
0
        /// <summary>
        /// Rotates the image 180 degrees clockwise at the centre point.
        /// </summary>
        /// <param name="target">The target image.</param>
        /// <param name="source">The source image.</param>
        private void Rotate180(ImageBase <T, TP> target, ImageBase <T, TP> source)
        {
            int width  = source.Width;
            int height = source.Height;

            using (IPixelAccessor <T, TP> sourcePixels = source.Lock())
                using (IPixelAccessor <T, TP> targetPixels = target.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newX = width - x - 1;
                            int newY = height - y - 1;
                            targetPixels[newX, newY] = sourcePixels[x, y];
                        }

                        this.OnRowProcessed();
                    });
                }
        }
Пример #12
0
        /// <summary>
        /// Rotates the image 270 degrees clockwise at the centre point.
        /// </summary>
        /// <param name="target">The target image.</param>
        /// <param name="source">The source image.</param>
        private void Rotate270(ImageBase <T, TP> target, ImageBase <T, TP> source)
        {
            int           width  = source.Width;
            int           height = source.Height;
            Image <T, TP> temp   = new Image <T, TP>(height, width);

            using (IPixelAccessor <T, TP> sourcePixels = source.Lock())
                using (IPixelAccessor <T, TP> tempPixels = temp.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newX = height - y - 1;
                            newX     = height - newX - 1;
                            int newY = width - x - 1;
                            tempPixels[newX, newY] = sourcePixels[x, y];
                        }

                        this.OnRowProcessed();
                    });
                }

            target.SetPixels(height, width, temp.Pixels);
        }
Пример #13
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor> source, Rectangle sourceRectangle)
        {
            if (this.CropRectangle == sourceRectangle)
            {
                return;
            }

            int minY = Math.Max(this.CropRectangle.Y, sourceRectangle.Y);
            int maxY = Math.Min(this.CropRectangle.Bottom, sourceRectangle.Bottom);
            int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X);
            int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right);

            TColor[] target = new TColor[this.CropRectangle.Width * this.CropRectangle.Height];

            using (PixelAccessor <TColor> sourcePixels = source.Lock())
                using (PixelAccessor <TColor> targetPixels = target.Lock <TColor>(this.CropRectangle.Width, this.CropRectangle.Height))
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = minX; x < maxX; x++)
                        {
                            targetPixels[x - minX, y - minY] = sourcePixels[x, y];
                        }
                    });
                }

            source.SetPixels(this.CropRectangle.Width, this.CropRectangle.Height, target);
        }
Пример #14
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            int       height = this.CanvasRectangle.Height;
            int       width  = this.CanvasRectangle.Width;
            Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix);

            TColor[] target = new TColor[width * height];

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock <TColor, TPacked>(width, height))
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            Point transformedPoint = Point.Skew(new Point(x, y), matrix);
                            if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y))
                            {
                                targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y];
                            }
                        }
                    });
                }

            source.SetPixels(width, height, target);
        }
Пример #15
0
        /// <summary>
        /// Swaps the image at the X-axis, which goes horizontally through the middle
        /// at half the height of the image.
        /// </summary>
        /// <param name="source">The source image to apply the process to.</param>
        private void FlipX(ImageBase <TColor> source)
        {
            int width      = source.Width;
            int height     = source.Height;
            int halfHeight = (int)Math.Ceiling(source.Height * .5F);

            TColor[] target = new TColor[width * height];

            using (PixelAccessor <TColor> sourcePixels = source.Lock())
                using (PixelAccessor <TColor> targetPixels = target.Lock <TColor>(width, height))
                {
                    Parallel.For(
                        0,
                        halfHeight,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newY              = height - y - 1;
                            targetPixels[x, y]    = sourcePixels[x, newY];
                            targetPixels[x, newY] = sourcePixels[x, y];
                        }
                    });
                }

            source.SetPixels(width, height, target);
        }
Пример #16
0
        /// <inheritdoc/>
        protected override void Apply(ImageBase <T, TP> target, ImageBase <T, TP> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
        {
            int       height = target.Height;
            int       width  = target.Width;
            Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix);

            using (IPixelAccessor <T, TP> sourcePixels = source.Lock())
                using (IPixelAccessor <T, TP> targetPixels = target.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            Point transformedPoint = Point.Skew(new Point(x, y), matrix);
                            if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y))
                            {
                                targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y];
                            }
                        }

                        OnRowProcessed();
                    });
                }
        }
Пример #17
0
        /// <summary>
        /// Collects the true color pixel data.
        /// </summary>
        /// <typeparam name="T">The pixel format.</typeparam>
        /// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
        /// <param name="image">The image to encode.</param>
        private void CollectColorBytes <T, TP>(ImageBase <T, TP> image)
            where T : IPackedVector <TP>
            where TP : struct
        {
            // Copy the pixels across from the image.
            this.pixelData = new byte[this.width * this.height * this.bytesPerPixel];
            int stride = this.width * this.bytesPerPixel;

            using (IPixelAccessor <T, TP> pixels = image.Lock())
            {
                Parallel.For(
                    0,
                    this.height,
                    Bootstrapper.Instance.ParallelOptions,
                    y =>
                {
                    // Color data is stored in r -> g -> b -> a order
                    for (int x = 0; x < this.width; x++)
                    {
                        int dataOffset = (y * stride) + (x * this.bytesPerPixel);
                        byte[] source  = pixels[x, y].ToBytes();

                        for (int i = 0; i < this.bytesPerPixel; i++)
                        {
                            this.pixelData[dataOffset + i] = source[i];
                        }
                    }
                });
            }
        }
Пример #18
0
        /// <summary>
        /// Collects the grayscale pixel data.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
        /// <param name="image">The image to encode.</param>
        private void CollectGrayscaleBytes <TColor, TPacked>(ImageBase <TColor, TPacked> image)
            where TColor : struct, IPackedPixel <TPacked>
            where TPacked : struct
        {
            // Copy the pixels across from the image.
            this.pixelData = new byte[this.width * this.height * this.bytesPerPixel];
            int stride = this.width * this.bytesPerPixel;

            byte[] bytes = new byte[4];
            using (PixelAccessor <TColor, TPacked> pixels = image.Lock())
            {
                for (int y = 0; y < this.height; y++)
                {
                    for (int x = 0; x < this.width; x++)
                    {
                        // Convert the color to YCbCr and store the luminance
                        // Optionally store the original color alpha.
                        int dataOffset = (y * stride) + (x * this.bytesPerPixel);
                        pixels[x, y].ToBytes(bytes, 0, ComponentOrder.XYZW);
                        YCbCr luminance = new Color(bytes[0], bytes[1], bytes[2], bytes[3]);
                        for (int i = 0; i < this.bytesPerPixel; i++)
                        {
                            if (i == 0)
                            {
                                this.pixelData[dataOffset] = (byte)luminance.Y;
                            }
                            else
                            {
                                this.pixelData[dataOffset + i] = bytes[3];
                            }
                        }
                    }
                }
            }
        }
Пример #19
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            int     startY      = sourceRectangle.Y;
            int     endY        = sourceRectangle.Bottom;
            int     startX      = sourceRectangle.X;
            int     endX        = sourceRectangle.Right;
            TPixel  glowColor   = this.GlowColor;
            Vector2 centre      = Rectangle.Center(sourceRectangle).ToVector2();
            float   maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            if (minY > 0)
            {
                startY = 0;
            }

            int width = maxX - minX;

            using (Buffer <TPixel> rowColors = new Buffer <TPixel>(width))
                using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                {
                    for (int i = 0; i < width; i++)
                    {
                        rowColors[i] = glowColor;
                    }

                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        using (Buffer <float> amounts = new Buffer <float>(width))
                        {
                            int offsetY = y - startY;
                            int offsetX = minX - startX;
                            for (int i = 0; i < width; i++)
                            {
                                float distance = Vector2.Distance(centre, new Vector2(i + offsetX, offsetY));
                                amounts[i]     = (this.options.BlendPercentage * (1 - (.95F * (distance / maxDistance)))).Clamp(0, 1);
                            }

                            Span <TPixel> destination = sourcePixels.GetRowSpan(offsetY).Slice(offsetX, width);

                            this.blender.Blend(destination, destination, rowColors, amounts);
                        }
                    });
                }
        }
Пример #20
0
        /// <inheritdoc/>
        public virtual QuantizedImage <TColor> Quantize(ImageBase <TColor> image, int maxColors)
        {
            Guard.NotNull(image, nameof(image));

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

            byte[]   quantizedPixels = new byte[width * height];
            TColor[] palette;

            using (PixelAccessor <TColor> pixels = image.Lock())
            {
                // 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(pixels, width, height);
                }

                // Get the palette
                palette = this.GetPalette();

                this.SecondPass(pixels, quantizedPixels, width, height);
            }

            return(new QuantizedImage <TColor>(width, height, palette, quantizedPixels));
        }
Пример #21
0
        /// <inheritdoc/>
        protected override void Apply(ImageBase <T, TP> target, ImageBase <T, TP> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
        {
            int startX  = targetRectangle.X;
            int endX    = targetRectangle.Right;
            int sourceX = sourceRectangle.X;
            int sourceY = sourceRectangle.Y;

            using (IPixelAccessor <T, TP> sourcePixels = source.Lock())
                using (IPixelAccessor <T, TP> targetPixels = target.Lock())
                {
                    Parallel.For(
                        startY,
                        endY,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = startX; x < endX; x++)
                        {
                            targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY];
                        }

                        this.OnRowProcessed();
                    });
                }
        }
Пример #22
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            if (this.OptimizedApply(source))
            {
                return;
            }

            int       height = this.CanvasRectangle.Height;
            int       width  = this.CanvasRectangle.Width;
            Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix);

            using (PixelAccessor <TPixel> targetPixels = new PixelAccessor <TPixel>(width, height))
            {
                using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            Point transformedPoint = Point.Rotate(new Point(x, y), matrix);
                            if (source.Bounds.Contains(transformedPoint.X, transformedPoint.Y))
                            {
                                targetPixels[x, y] = sourcePixels[transformedPoint.X, transformedPoint.Y];
                            }
                        }
                    });
                }

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Пример #23
0
        /// <summary>
        /// Rotates the image 270 degrees clockwise at the centre point.
        /// </summary>
        /// <param name="source">The source image.</param>
        private void Rotate270(ImageBase <TPixel> source)
        {
            int width  = source.Width;
            int height = source.Height;

            using (var targetPixels = new PixelAccessor <TPixel>(height, width))
            {
                using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newX = height - y - 1;
                            newX     = height - newX - 1;
                            int newY = width - x - 1;
                            targetPixels[newX, newY] = sourcePixels[x, y];
                        }
                    });
                }

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Пример #24
0
        /// <summary>
        /// Swaps the image at the X-axis, which goes horizontally through the middle
        /// at half the height of the image.
        /// </summary>
        /// <param name="source">The source image to apply the process to.</param>
        private void FlipX(ImageBase <TPixel> source)
        {
            int width      = source.Width;
            int height     = source.Height;
            int halfHeight = (int)Math.Ceiling(source.Height * .5F);

            using (PixelAccessor <TPixel> targetPixels = new PixelAccessor <TPixel>(width, height))
            {
                using (PixelAccessor <TPixel> sourcePixels = source.Lock())
                {
                    Parallel.For(
                        0,
                        halfHeight,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newY              = height - y - 1;
                            targetPixels[x, y]    = sourcePixels[x, newY];
                            targetPixels[x, newY] = sourcePixels[x, y];
                        }
                    });
                }

                source.SwapPixelsBuffers(targetPixels);
            }
        }
Пример #25
0
        /// <summary>
        /// Swaps the image at the Y-axis, which goes vertically through the middle
        /// at half of the width of the image.
        /// </summary>
        /// <param name="target">Target image to apply the process to.</param>
        private void FlipY(ImageBase <TColor, TPacked> target)
        {
            int width     = target.Width;
            int height    = target.Height;
            int halfWidth = (int)Math.Ceiling(width * .5F);
            Image <TColor, TPacked> temp = new Image <TColor, TPacked>(width, height);

            temp.ClonePixels(width, height, target.Pixels);

            using (PixelAccessor <TColor, TPacked> targetPixels = target.Lock())
                using (PixelAccessor <TColor, TPacked> tempPixels = temp.Lock())
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < halfWidth; x++)
                        {
                            int newX              = width - x - 1;
                            targetPixels[x, y]    = tempPixels[newX, y];
                            targetPixels[newX, y] = tempPixels[x, y];
                        }
                    });
                }
        }
Пример #26
0
        /// <summary>
        /// Rotates the image 90 degrees clockwise at the centre point.
        /// </summary>
        /// <param name="source">The source image.</param>
        private void Rotate90(ImageBase <TColor> source)
        {
            int width  = source.Width;
            int height = source.Height;

            TColor[] target = new TColor[width * height];

            using (PixelAccessor <TColor> sourcePixels = source.Lock())
                using (PixelAccessor <TColor> targetPixels = target.Lock <TColor>(height, width))
                {
                    Parallel.For(
                        0,
                        height,
                        this.ParallelOptions,
                        y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            int newX = height - y - 1;
                            targetPixels[newX, x] = sourcePixels[x, y];
                        }
                    });
                }

            source.SetPixels(height, width, target);
        }
Пример #27
0
        /// <inheritdoc/>
        protected override void Apply(ImageBase <T, TP> target, ImageBase <T, TP> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
        {
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            if (minY > 0)
            {
                startY = 0;
            }

            Vector4 backgroundColor = this.Value.ToVector4();

            using (IPixelAccessor <T, TP> sourcePixels = source.Lock())
                using (IPixelAccessor <T, TP> targetPixels = target.Lock())
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY = y - startY;
                        for (int x = minX; x < maxX; x++)
                        {
                            int offsetX   = x - startX;
                            Vector4 color = sourcePixels[offsetX, offsetY].ToVector4();
                            float a       = color.W;

                            if (a < 1 && a > 0)
                            {
                                color = Vector4.Lerp(color, backgroundColor, .5F);
                            }

                            if (Math.Abs(a) < Epsilon)
                            {
                                color = backgroundColor;
                            }

                            T packed = default(T);
                            packed.PackFromVector4(color);
                            targetPixels[offsetX, offsetY] = packed;
                        }

                        this.OnRowProcessed();
                    });
                }
        }
Пример #28
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;
            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            if (minY > 0)
            {
                startY = 0;
            }

            // we could possibly do some optermising by having knowledge about the individual brushes operate
            // for example If brush is SolidBrush<TColor, TPacked> then we could just get the color upfront
            // and skip using the IBrushApplicator<TColor, TPacked>?.
            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                using (IBrushApplicator <TColor, TPacked> applicator = this.brush.CreateApplicator(sourceRectangle))
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY = y - startY;

                        Vector2 currentPoint = default(Vector2);
                        for (int x = minX; x < maxX; x++)
                        {
                            int offsetX      = x - startX;
                            int offsetColorX = x - minX;
                            currentPoint.X   = offsetX;
                            currentPoint.Y   = offsetY;

                            Vector4 backgroundVector = sourcePixels[offsetX, offsetY].ToVector4();
                            Vector4 sourceVector     = applicator.GetColor(currentPoint).ToVector4();

                            var finalColor = Vector4BlendTransforms.PremultipliedLerp(backgroundVector, sourceVector, 1);

                            TColor packed = default(TColor);
                            packed.PackFromVector4(finalColor);
                            sourcePixels[offsetX, offsetY] = packed;
                        }
                    });
                }
        }
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle)
        {
            int startY = sourceRectangle.Y;
            int endY   = sourceRectangle.Bottom;
            int startX = sourceRectangle.X;
            int endX   = sourceRectangle.Right;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            if (minY > 0)
            {
                startY = 0;
            }

            Vector4 backgroundColor = this.Value.ToVector4();

            using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
            {
                Parallel.For(
                    minY,
                    maxY,
                    this.ParallelOptions,
                    y =>
                {
                    int offsetY = y - startY;
                    for (int x = minX; x < maxX; x++)
                    {
                        int offsetX   = x - startX;
                        Vector4 color = sourcePixels[offsetX, offsetY].ToVector4();
                        float a       = color.W;

                        if (a < 1 && a > 0)
                        {
                            color = Vector4BlendTransforms.PremultipliedLerp(backgroundColor, color, .5F);
                        }

                        if (Math.Abs(a) < Epsilon)
                        {
                            color = backgroundColor;
                        }

                        TColor packed = default(TColor);
                        packed.PackFromVector4(color);
                        sourcePixels[offsetX, offsetY] = packed;
                    }
                });
            }
        }
Пример #30
0
        /// <inheritdoc/>
        protected override void Apply(ImageBase <TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
        {
            int       startX = sourceRectangle.X;
            int       endX   = sourceRectangle.Right;
            Rectangle bounds = this.blend.Bounds;

            // Align start/end positions.
            int minX = Math.Max(0, startX);
            int maxX = Math.Min(source.Width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(source.Height, endY);

            // Reset offset if necessary.
            if (minX > 0)
            {
                startX = 0;
            }

            if (minY > 0)
            {
                startY = 0;
            }

            float alpha = this.Value / 100F;

            using (PixelAccessor <TColor, TPacked> toBlendPixels = this.blend.Lock())
                using (PixelAccessor <TColor, TPacked> sourcePixels = source.Lock())
                {
                    Parallel.For(
                        minY,
                        maxY,
                        this.ParallelOptions,
                        y =>
                    {
                        int offsetY = y - startY;
                        for (int x = minX; x < maxX; x++)
                        {
                            int offsetX   = x - startX;
                            Vector4 color = sourcePixels[offsetX, offsetY].ToVector4();

                            if (bounds.Contains(offsetX, offsetY))
                            {
                                Vector4 blendedColor = toBlendPixels[offsetX, offsetY].ToVector4();

                                if (blendedColor.W > 0)
                                {
                                    // Lerping colors is dependent on the alpha of the blended color
                                    color = Vector4.Lerp(color, blendedColor, alpha > 0 ? alpha : blendedColor.W);
                                }
                            }

                            TColor packed = default(TColor);
                            packed.PackFromVector4(color);
                            sourcePixels[offsetX, offsetY] = packed;
                        }
                    });
                }
        }
Пример #31
0
 public QuantizedImage Quantize(ImageBase image, int maxColors)
 {
     if (image == null){
         throw new ArgumentNullException();
     }
     int colorCount = NumUtils.Clamp(maxColors,1, 256);
     Clear();
     using (IPixelAccessor imagePixels = image.Lock()){
         Build3DHistogram(imagePixels);
         Get3DMoments();
         Box[] cube;
         BuildCube(out cube, ref colorCount);
         return GenerateResult(imagePixels, colorCount, cube);
     }
 }
Пример #32
0
 public void Encode(ImageBase image, Stream stream, int quality, JpegSubsample sample)
 {
     if (image == null || stream == null){
         throw new ArgumentNullException();
     }
     ushort max = JpegConstants.MaxLength;
     if (image.Width >= max || image.Height >= max){
         throw new Exception($"Image is too large to encode at {image.Width}x{image.Height}.");
     }
     outputStream = stream;
     subsample = sample;
     for (int i = 0; i < theHuffmanSpec.Length; i++){
         theHuffmanLut[i] = new HuffmanLut(theHuffmanSpec[i]);
     }
     for (int i = 0; i < nQuantIndex; i++){
         quant[i] = new byte[Block.blockSize];
     }
     if (quality < 1){
         quality = 1;
     }
     if (quality > 100){
         quality = 100;
     }
     int scale;
     if (quality < 50){
         scale = 5000/quality;
     } else{
         scale = 200 - quality*2;
     }
     for (int i = 0; i < nQuantIndex; i++){
         for (int j = 0; j < Block.blockSize; j++){
             int x = unscaledQuant[i, j];
             x = (x*scale + 50)/100;
             if (x < 1){
                 x = 1;
             }
             if (x > 255){
                 x = 255;
             }
             quant[i][j] = (byte) x;
         }
     }
     int componentCount = 3;
     double densityX = ((Image2) image).HorizontalResolution;
     double densityY = ((Image2) image).VerticalResolution;
     WriteApplicationHeader((short) densityX, (short) densityY);
     WriteDqt();
     WriteSof0(image.Width, image.Height, componentCount);
     WriteDht(componentCount);
     using (IPixelAccessor pixels = image.Lock()){
         WriteSos(pixels);
     }
     buffer[0] = 0xff;
     buffer[1] = 0xd9;
     stream.Write(buffer, 0, 2);
     stream.Flush();
 }
Пример #33
0
 private void WriteImage(EndianBinaryWriter writer, ImageBase image)
 {
     // TODO: Add more compression formats.
     int amount = (image.Width*(int) bmpBitsPerPixel)%4;
     if (amount != 0){
         amount = 4 - amount;
     }
     using (IPixelAccessor pixels = image.Lock()){
         switch (bmpBitsPerPixel){
             case BmpBitsPerPixel.Pixel32:
                 Write32bit(writer, pixels, amount);
                 break;
             case BmpBitsPerPixel.Pixel24:
                 Write24bit(writer, pixels, amount);
                 break;
         }
     }
 }