Exemplo n.º 1
0
        public void Indexer(int width, int height, int x, int y)
        {
            using (PinnedImageBuffer <Foo> buffer = new PinnedImageBuffer <Foo>(width, height))
            {
                Foo[] array = buffer.Array;

                ref Foo actual = ref buffer[x, y];

                ref Foo expected = ref array[y * width + x];
Exemplo n.º 2
0
 public void Construct(int width, int height)
 {
     using (PinnedImageBuffer <Foo> buffer = new PinnedImageBuffer <Foo>(width, height))
     {
         Assert.Equal(width, buffer.Width);
         Assert.Equal(height, buffer.Height);
         Assert.Equal(width * height, buffer.Length);
     }
 }
Exemplo n.º 3
0
 public void Construct_FromExternalArray(int width, int height)
 {
     Foo[] array = new Foo[width * height + 10];
     using (PinnedImageBuffer <Foo> buffer = new PinnedImageBuffer <Foo>(array, width, height))
     {
         Assert.Equal(width, buffer.Width);
         Assert.Equal(height, buffer.Height);
         Assert.Equal(width * height, buffer.Length);
     }
 }
Exemplo n.º 4
0
        public void GetRowSpanXY(int width, int height, int x, int y)
        {
            using (PinnedImageBuffer <Foo> buffer = new PinnedImageBuffer <Foo>(width, height))
            {
                BufferSpan <Foo> span = buffer.GetRowSpan(x, y);

                Assert.Equal(width * y + x, span.Start);
                Assert.Equal(width - x, span.Length);
                Assert.Equal(buffer.Pointer + sizeof(Foo) * (width * y + x), span.PointerAtOffset);
            }
        }
Exemplo n.º 5
0
 public void CreateClean()
 {
     for (int i = 0; i < 100; i++)
     {
         using (PinnedImageBuffer <int> buffer = PinnedImageBuffer <int> .CreateClean(42, 42))
         {
             for (int j = 0; j < buffer.Length; j++)
             {
                 Assert.Equal(0, buffer.Array[j]);
                 buffer.Array[j] = 666;
             }
         }
     }
 }
            public Vector4 ComputeWeightedColumnSum(PinnedImageBuffer <Vector4> firstPassPixels, int x)
            {
                float *verticalValues = this.Ptr;
                int    left           = this.Left;

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

                for (int i = 0; i < this.Length; i++)
                {
                    float yw    = verticalValues[i];
                    int   index = left + i;
                    result += firstPassPixels[x, index] * yw;
                }

                return(result);
            }
            /// <summary>
            /// Initializes a new instance of the <see cref="WeightsBuffer"/> class.
            /// </summary>
            /// <param name="sourceSize">The size of the source window</param>
            /// <param name="destinationSize">The size of the destination window</param>
            public WeightsBuffer(int sourceSize, int destinationSize)
            {
                this.dataBuffer = PinnedImageBuffer <float> .CreateClean(sourceSize, destinationSize);

                this.Weights = new WeightsWindow[destinationSize];
            }
Exemplo n.º 8
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 (PinnedImageBuffer <Vector4> firstPassPixels = new PinnedImageBuffer <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 (PinnedBuffer <Vector4> tempRowBuffer = new PinnedBuffer <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);
            }
        }