Beispiel #1
0
        public void SRgbCompanding_IsCorrect()
        {
            const float input = .667F;
            float       e     = SRgbCompanding.Expand(input);
            float       c     = SRgbCompanding.Compress(e);

            CompandingIsCorrectImpl(e, c, .40242353F, input);
        }
Beispiel #2
0
        public void SRgbCompanding_Compress_VectorSpan(int length)
        {
            var rnd = new Random(42);

            Vector4[] source   = rnd.GenerateRandomVectorArray(length, 0, 1);
            Vector4[] expected = source.Select(v => SRgbCompanding.Compress(v)).ToArray();

            SRgbCompanding.Compress(source);

            Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f));
        }
Beispiel #3
0
        internal static void ApplyBackwardConversionModifiers(Span <Vector4> vectors, PixelConversionModifiers modifiers)
        {
            if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
            {
                Vector4Utilities.UnPremultiply(vectors);
            }

            if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))
            {
                SRgbCompanding.Compress(vectors);
            }
        }
Beispiel #4
0
        internal static void ApplyBackwardConversionModifiers(Span <Vector4> vectors, PixelConversionModifiers modifiers)
        {
            if (modifiers.HasFlag(PixelConversionModifiers.Premultiply))
            {
                Numeric.UnPremultiply(vectors);
            }

            if (modifiers.HasFlag(PixelConversionModifiers.SRgbCompand))
            {
                SRgbCompanding.Compress(vectors);
            }
        }
Beispiel #5
0
        internal static void ApplyForwardConversionModifiers(Span <Vector4> vectors, PixelConversionModifiers modifiers)
        {
            if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))
            {
                SRgbCompanding.Expand(vectors);
            }

            if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
            {
                Numerics.Premultiply(vectors);
            }
        }
Beispiel #6
0
        public void SRgbCompanding_Expand_VectorSpan(int length)
        {
            var rnd = new Random(42);

            Vector4[] source   = rnd.GenerateRandomVectorArray(length, 0, 1);
            var       expected = new Vector4[source.Length];

            for (int i = 0; i < source.Length; i++)
            {
                Vector4     s = source[i];
                ref Vector4 e = ref expected[i];
                SRgbCompanding.Expand(ref s);
                e = s;
            }
Beispiel #7
0
 public override float Expand(float channel) => SRgbCompanding.Expand(channel);
Beispiel #8
0
 public override float Compress(float channel) => SRgbCompanding.Compress(channel);
Beispiel #9
0
        /// <inheritdoc/>
        protected override void OnFrameApply(ImageFrame <TPixel> source, ImageFrame <TPixel> destination, Rectangle sourceRectangle, Configuration configuration)
        {
            // Handle resize dimensions identical to the original
            if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.ResizeRectangle)
            {
                // The cloned will be blank here copy all the pixel data over
                source.GetPixelSpan().CopyTo(destination.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)
            {
                var workingRect = Rectangle.FromLTRB(minX, minY, maxX, maxY);

                // Scaling factors
                float widthFactor  = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
                float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;

                ParallelHelper.IterateRows(
                    workingRect,
                    configuration,
                    rows =>
                {
                    for (int y = rows.Min; y < rows.Max; y++)
                    {
                        // Y coordinates of source points
                        Span <TPixel> sourceRow =
                            source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY));
                        Span <TPixel> targetRow = destination.GetPixelRowSpan(y);

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

                return;
            }

            int sourceHeight = source.Height;

            // 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.
            using (Buffer2D <Vector4> firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D <Vector4>(sourceHeight, width))
            {
                firstPassPixelsTransposed.MemorySource.Clear();

                var processColsRect = new Rectangle(0, 0, source.Width, sourceRectangle.Bottom);

                ParallelHelper.IterateRowsWithTempBuffer <Vector4>(
                    processColsRect,
                    configuration,
                    (rows, tempRowBuffer) =>
                {
                    for (int y = rows.Min; y < rows.Max; y++)
                    {
                        Span <TPixel> sourceRow    = source.GetPixelRowSpan(y);
                        Span <Vector4> tempRowSpan = tempRowBuffer.Span;

                        PixelOperations <TPixel> .Instance.ToVector4(sourceRow, tempRowSpan, sourceRow.Length);
                        Vector4Utils.Premultiply(tempRowSpan);

                        ref Vector4 firstPassBaseRef = ref firstPassPixelsTransposed.Span[y];

                        if (this.Compand)
                        {
                            SRgbCompanding.Expand(tempRowSpan);
                        }

                        for (int x = minX; x < maxX; x++)
                        {
                            ResizeKernel window = this.horizontalKernelMap.Kernels[x - startX];
                            Unsafe.Add(ref firstPassBaseRef, x * sourceHeight) =
                                window.Convolve(tempRowSpan, sourceX);
                        }
                    }
                });

                var processRowsRect = Rectangle.FromLTRB(0, minY, width, maxY);

                // Now process the rows.
                ParallelHelper.IterateRowsWithTempBuffer <Vector4>(
                    processRowsRect,
                    configuration,
                    (rows, tempRowBuffer) =>
                {
                    Span <Vector4> tempRowSpan = tempRowBuffer.Span;

                    for (int y = rows.Min; y < rows.Max; y++)
                    {
                        // Ensure offsets are normalized for cropping and padding.
                        ResizeKernel window = this.verticalKernelMap.Kernels[y - startY];

                        ref Vector4 tempRowBase = ref MemoryMarshal.GetReference(tempRowSpan);

                        for (int x = 0; x < width; x++)
                        {
                            Span <Vector4> firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x);

                            // Destination color components
                            Unsafe.Add(ref tempRowBase, x) = window.Convolve(firstPassColumn, sourceY);
                        }

                        Vector4Utils.UnPremultiply(tempRowSpan);

                        if (this.Compand)
                        {
                            SRgbCompanding.Compress(tempRowSpan);
                        }

                        Span <TPixel> targetRowSpan = destination.GetPixelRowSpan(y);
                        PixelOperations <TPixel> .Instance.PackFromVector4(tempRowSpan, targetRowSpan, tempRowSpan.Length);
                    }
                });
            }
        }