Ejemplo n.º 1
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor> source, Rectangle sourceRectangle)
        {
            float brightness = this.Value / 100F;

            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;
            }

            using (PixelAccessor <TColor> 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;

                        // TODO: Check this with other formats.
                        Vector4 vector      = sourcePixels[offsetX, offsetY].ToVector4().Expand();
                        Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z) + new Vector3(brightness);
                        vector = new Vector4(transformed, vector.W);

                        TColor packed = default(TColor);
                        packed.PackFromVector4(vector.Compress());

                        sourcePixels[offsetX, offsetY] = packed;
                    }
                });
            }
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            float contrast = (100F + this.Value) / 100F;

            int     startY         = sourceRectangle.Y;
            int     endY           = sourceRectangle.Bottom;
            int     startX         = sourceRectangle.X;
            int     endX           = sourceRectangle.Right;
            Vector4 contrastVector = new Vector4(contrast, contrast, contrast, 1);
            Vector4 shiftVector    = new Vector4(.5F, .5F, .5F, 1);

            // 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;
            }

            using (PixelAccessor <TPixel> 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 vector = sourcePixels[offsetX, offsetY].ToVector4().Expand();
                        vector        -= shiftVector;
                        vector        *= contrastVector;
                        vector        += shiftVector;
                        TPixel packed  = default(TPixel);
                        packed.PackFromVector4(vector.Compress());
                        sourcePixels[offsetX, offsetY] = packed;
                    }
                });
            }
        }
Ejemplo n.º 3
0
        /// <inheritdoc/>
        protected override void OnApply(ImageFrame <TPixel> source, Rectangle sourceRectangle, Configuration configuration)
        {
            float contrast = (100F + this.Value) / 100F;

            int startY         = sourceRectangle.Y;
            int endY           = sourceRectangle.Bottom;
            int startX         = sourceRectangle.X;
            int endX           = sourceRectangle.Right;
            var contrastVector = new Vector4(contrast, contrast, contrast, 1);
            var shiftVector    = new Vector4(.5F, .5F, .5F, 1);

            // 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;
            }

            Parallel.For(
                minY,
                maxY,
                configuration.ParallelOptions,
                y =>
            {
                Span <TPixel> row = source.GetPixelRowSpan(y - startY);

                for (int x = minX; x < maxX; x++)
                {
                    ref TPixel pixel = ref row[x - startX];

                    Vector4 vector = pixel.ToVector4().Expand();
                    vector        -= shiftVector;
                    vector        *= contrastVector;
                    vector        += shiftVector;

                    pixel.PackFromVector4(vector.Compress());
                }
            });
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Applies the color matrix against the given color.
        /// </summary>
        /// <param name="color">The source color.</param>
        /// <param name="matrix">The matrix.</param>
        /// <param name="compand">Whether to compand the color during processing.</param>
        /// <returns>
        /// The <see cref="Color"/>.
        /// </returns>
        private TColor ApplyMatrix(TColor color, Matrix4x4 matrix, bool compand)
        {
            Vector4 vector = color.ToVector4();

            if (compand)
            {
                vector = vector.Expand();
            }

            vector = Vector4.Transform(vector, matrix);
            TColor packed = default(TColor);

            packed.PackFromVector4(compand ? vector.Compress() : vector);
            return(packed);
        }
Ejemplo n.º 5
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TPixel> source, Rectangle sourceRectangle)
        {
            float brightness = this.Value / 100F;

            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;
            }

            Parallel.For(
                minY,
                maxY,
                this.ParallelOptions,
                y =>
            {
                Span <TPixel> row = source.GetRowSpan(y - startY);

                for (int x = minX; x < maxX; x++)
                {
                    ref TPixel pixel = ref row[x - startX];

                    // TODO: Check this with other formats.
                    Vector4 vector      = pixel.ToVector4().Expand();
                    Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z) + new Vector3(brightness);
                    vector = new Vector4(transformed, vector.W);

                    pixel.PackFromVector4(vector.Compress());
                }
            });
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Applies the color matrix against the given color.
        /// </summary>
        /// <param name="color">The source color.</param>
        /// <param name="matrix">The matrix.</param>
        /// <param name="compand">Whether to compand the color during processing.</param>
        /// <returns>
        /// The <see cref="Color"/>.
        /// </returns>
        private TColor ApplyMatrix(TColor color, Matrix4x4 matrix, bool compand)
        {
            Vector4 vector = color.ToVector4();

            if (compand)
            {
                vector = vector.Expand();
            }

            Vector3 transformed = Vector3.Transform(new Vector3(vector.X, vector.Y, vector.Z), matrix);

            vector = new Vector4(transformed, vector.W);
            TColor packed = default(TColor);

            packed.PackFromVector4(compand ? vector.Compress() : vector);
            return(packed);
        }
Ejemplo n.º 7
0
        /// <inheritdoc/>
        protected override void OnApply(ImageBase <TColor> source, Rectangle sourceRectangle)
        {
            // Jump out, we'll deal with that later.
            if (source.Width == this.Width && source.Height == this.Height && sourceRectangle == this.ResizeRectangle)
            {
                return;
            }

            int width  = this.Width;
            int height = this.Height;
            int startY = this.ResizeRectangle.Y;
            int endY   = this.ResizeRectangle.Bottom;
            int startX = this.ResizeRectangle.X;
            int endX   = this.ResizeRectangle.Right;

            int minX = Math.Max(0, startX);
            int maxX = Math.Min(width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(height, endY);

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

            if (this.Sampler is NearestNeighborResampler)
            {
                // Scaling factors
                float widthFactor  = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
                float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;

                using (PixelAccessor <TColor> sourcePixels = source.Lock())
                    using (PixelAccessor <TColor> targetPixels = target.Lock <TColor>(width, height))
                    {
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            // Y coordinates of source points
                            int originY = (int)((y - startY) * heightFactor);

                            for (int x = minX; x < maxX; x++)
                            {
                                // X coordinates of source points
                                targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY];
                            }
                        });
                    }

                // Break out now.
                source.SetPixels(width, height, target);
                return;
            }

            // Interpolate the image using the calculated weights.
            // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
            // First process the columns. Since we are not using multiple threads startY and endY
            // are the upper and lower bounds of the source rectangle.
            TColor[] firstPass = new TColor[width * source.Height];
            using (PixelAccessor <TColor> sourcePixels = source.Lock())
                using (PixelAccessor <TColor> firstPassPixels = firstPass.Lock <TColor>(width, source.Height))
                    using (PixelAccessor <TColor> targetPixels = target.Lock <TColor>(width, height))
                    {
                        Parallel.For(
                            0,
                            sourceRectangle.Height,
                            this.ParallelOptions,
                            y =>
                        {
                            for (int x = minX; x < maxX; x++)
                            {
                                // Ensure offsets are normalised for cropping and padding.
                                Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;

                                // Destination color components
                                Vector4 destination = Vector4.Zero;

                                for (int i = 0; i < horizontalValues.Length; i++)
                                {
                                    Weight xw    = horizontalValues[i];
                                    destination += sourcePixels[xw.Index, y].ToVector4().Expand() * xw.Value;
                                }

                                TColor d = default(TColor);
                                d.PackFromVector4(destination.Compress());
                                firstPassPixels[x, y] = d;
                            }
                        });

                        // Now process the rows.
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            // Ensure offsets are normalised for cropping and padding.
                            Weight[] verticalValues = this.VerticalWeights[y - startY].Values;

                            for (int x = 0; x < width; x++)
                            {
                                // Destination color components
                                Vector4 destination = Vector4.Zero;

                                for (int i = 0; i < verticalValues.Length; i++)
                                {
                                    Weight yw    = verticalValues[i];
                                    destination += firstPassPixels[x, yw.Index].ToVector4().Expand() * yw.Value;
                                }

                                TColor d = default(TColor);
                                d.PackFromVector4(destination.Compress());
                                targetPixels[x, y] = d;
                            }
                        });
                    }

            source.SetPixels(width, height, target);
        }
Ejemplo n.º 8
0
        /// <inheritdoc/>
        protected override unsafe void OnApply(ImageFrame <TPixel> source, ImageFrame <TPixel> cloned, Rectangle sourceRectangle, Configuration configuration)
        {
            // Jump out, we'll deal with that later.
            if (source.Width == cloned.Width && source.Height == cloned.Height && sourceRectangle == this.ResizeRectangle)
            {
                // the cloned will be blank here copy all the pixel data over
                source.GetPixelSpan().CopyTo(cloned.GetPixelSpan());
                return;
            }

            int width   = this.Width;
            int height  = this.Height;
            int sourceX = sourceRectangle.X;
            int sourceY = sourceRectangle.Y;
            int startY  = this.ResizeRectangle.Y;
            int endY    = this.ResizeRectangle.Bottom;
            int startX  = this.ResizeRectangle.X;
            int endX    = this.ResizeRectangle.Right;

            int minX = Math.Max(0, startX);
            int maxX = Math.Min(width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(height, endY);

            if (this.Sampler is NearestNeighborResampler)
            {
                // Scaling factors
                float widthFactor  = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
                float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;

                Parallel.For(
                    minY,
                    maxY,
                    configuration.ParallelOptions,
                    y =>
                {
                    // Y coordinates of source points
                    Span <TPixel> sourceRow = source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY));
                    Span <TPixel> targetRow = cloned.GetPixelRowSpan(y);

                    for (int x = minX; x < maxX; x++)
                    {
                        // X coordinates of source points
                        targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)];
                    }
                });

                return;
            }

            // Interpolate the image using the calculated weights.
            // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
            // First process the columns. Since we are not using multiple threads startY and endY
            // are the upper and lower bounds of the source rectangle.
            // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed!
            using (var firstPassPixels = new Buffer2D <Vector4>(width, source.Height))
            {
                firstPassPixels.Clear();

                Parallel.For(
                    0,
                    sourceRectangle.Bottom,
                    configuration.ParallelOptions,
                    y =>
                {
                    // TODO: Without Parallel.For() this buffer object could be reused:
                    using (var tempRowBuffer = new Buffer <Vector4>(source.Width))
                    {
                        Span <Vector4> firstPassRow = firstPassPixels.GetRowSpan(y);
                        Span <TPixel> sourceRow     = source.GetPixelRowSpan(y);
                        PixelOperations <TPixel> .Instance.ToVector4(sourceRow, tempRowBuffer, sourceRow.Length);

                        if (this.Compand)
                        {
                            for (int x = minX; x < maxX; x++)
                            {
                                WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
                                firstPassRow[x]      = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX);
                            }
                        }
                        else
                        {
                            for (int x = minX; x < maxX; x++)
                            {
                                WeightsWindow window = this.HorizontalWeights.Weights[x - startX];
                                firstPassRow[x]      = window.ComputeWeightedRowSum(tempRowBuffer, sourceX);
                            }
                        }
                    }
                });

                // Now process the rows.
                Parallel.For(
                    minY,
                    maxY,
                    configuration.ParallelOptions,
                    y =>
                {
                    // Ensure offsets are normalised for cropping and padding.
                    WeightsWindow window    = this.VerticalWeights.Weights[y - startY];
                    Span <TPixel> targetRow = cloned.GetPixelRowSpan(y);

                    if (this.Compand)
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // Destination color components
                            Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY);
                            destination         = destination.Compress();

                            ref TPixel pixel = ref targetRow[x];
                            pixel.PackFromVector4(destination);
                        }
                    }
                    else
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // Destination color components
                            Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY);

                            ref TPixel pixel = ref targetRow[x];
                            pixel.PackFromVector4(destination);
                        }
                    }
                });
Ejemplo n.º 9
0
        /// <inheritdoc/>
        protected override unsafe void OnApply(ImageBase <TColor> source, Rectangle sourceRectangle)
        {
            // Jump out, we'll deal with that later.
            if (source.Width == this.Width && source.Height == this.Height && sourceRectangle == this.ResizeRectangle)
            {
                return;
            }

            int width   = this.Width;
            int height  = this.Height;
            int sourceX = sourceRectangle.X;
            int sourceY = sourceRectangle.Y;
            int startY  = this.ResizeRectangle.Y;
            int endY    = this.ResizeRectangle.Bottom;
            int startX  = this.ResizeRectangle.X;
            int endX    = this.ResizeRectangle.Right;

            int minX = Math.Max(0, startX);
            int maxX = Math.Min(width, endX);
            int minY = Math.Max(0, startY);
            int maxY = Math.Min(height, endY);

            if (this.Sampler is NearestNeighborResampler)
            {
                // Scaling factors
                float widthFactor  = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
                float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;

                using (PixelAccessor <TColor> targetPixels = new PixelAccessor <TColor>(width, height))
                {
                    using (PixelAccessor <TColor> sourcePixels = source.Lock())
                    {
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            // Y coordinates of source points
                            int originY = (int)(((y - startY) * heightFactor) + sourceY);

                            for (int x = minX; x < maxX; x++)
                            {
                                // X coordinates of source points
                                targetPixels[x, y] = sourcePixels[(int)(((x - startX) * widthFactor) + sourceX), originY];
                            }
                        });
                    }

                    // Break out now.
                    source.SwapPixelsBuffers(targetPixels);
                    return;
                }
            }

            // Interpolate the image using the calculated weights.
            // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
            // First process the columns. Since we are not using multiple threads startY and endY
            // are the upper and lower bounds of the source rectangle.

            // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed!
            using (PixelAccessor <TColor> targetPixels = new PixelAccessor <TColor>(width, height))
            {
                using (PixelAccessor <TColor> sourcePixels = source.Lock())
                    using (Buffer2D <Vector4> firstPassPixels = new Buffer2D <Vector4>(width, source.Height))
                    {
                        firstPassPixels.Clear();

                        Parallel.For(
                            0,
                            sourceRectangle.Bottom,
                            this.ParallelOptions,
                            y =>
                        {
                            // TODO: Without Parallel.For() this buffer object could be reused:
                            using (Buffer <Vector4> tempRowBuffer = new Buffer <Vector4>(sourcePixels.Width))
                            {
                                BufferSpan <TColor> sourceRow = sourcePixels.GetRowSpan(y);

                                BulkPixelOperations <TColor> .Instance.ToVector4(
                                    sourceRow,
                                    tempRowBuffer,
                                    sourceRow.Length);

                                if (this.Compand)
                                {
                                    for (int x = minX; x < maxX; x++)
                                    {
                                        WeightsWindow window  = this.HorizontalWeights.Weights[x - startX];
                                        firstPassPixels[x, y] = window.ComputeExpandedWeightedRowSum(tempRowBuffer);
                                    }
                                }
                                else
                                {
                                    for (int x = minX; x < maxX; x++)
                                    {
                                        WeightsWindow window  = this.HorizontalWeights.Weights[x - startX];
                                        firstPassPixels[x, y] = window.ComputeWeightedRowSum(tempRowBuffer);
                                    }
                                }
                            }
                        });

                        // Now process the rows.
                        Parallel.For(
                            minY,
                            maxY,
                            this.ParallelOptions,
                            y =>
                        {
                            // Ensure offsets are normalised for cropping and padding.
                            WeightsWindow window = this.VerticalWeights.Weights[y - startY];

                            if (this.Compand)
                            {
                                for (int x = 0; x < width; x++)
                                {
                                    // Destination color components
                                    Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x);
                                    destination         = destination.Compress();
                                    TColor d            = default(TColor);
                                    d.PackFromVector4(destination);
                                    targetPixels[x, y] = d;
                                }
                            }
                            else
                            {
                                for (int x = 0; x < width; x++)
                                {
                                    // Destination color components
                                    Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x);

                                    TColor d = default(TColor);
                                    d.PackFromVector4(destination);
                                    targetPixels[x, y] = d;
                                }
                            }
                        });
                    }

                source.SwapPixelsBuffers(targetPixels);
            }
        }