예제 #1
0
        /// <summary>
        /// Creates a clean instance of <see cref="PinnedBuffer{T}"/> initializing it's elements with 'default(T)'.
        /// </summary>
        /// <param name="count">The desired count of elements. (Minimum size for <see cref="Array"/>)</param>
        /// <returns>The <see cref="PinnedBuffer{T}"/> instance</returns>
        public static PinnedBuffer <T> CreateClean(int count)
        {
            PinnedBuffer <T> buffer = new PinnedBuffer <T>(count);

            buffer.Clear();
            return(buffer);
        }
예제 #2
0
            /// <summary>
            /// SIMD optimized bulk implementation of <see cref="IPixel.PackFromVector4(Vector4)"/>
            /// that works only with `count` divisible by <see cref="Vector{UInt32}.Count"/>.
            /// </summary>
            /// <param name="sourceColors">The <see cref="BufferSpan{T}"/> to the source colors.</param>
            /// <param name="destVectors">The <see cref="BufferSpan{T}"/> to the dstination vectors.</param>
            /// <param name="count">The number of pixels to convert.</param>
            /// <remarks>
            /// Implementation adapted from:
            /// <see>
            ///     <cref>http://stackoverflow.com/a/5362789</cref>
            /// </see>
            /// TODO: We can replace this implementation in the future using new Vector API-s:
            /// <see>
            ///     <cref>https://github.com/dotnet/corefx/issues/15957</cref>
            /// </see>
            /// </remarks>
            internal static unsafe void ToVector4SimdAligned(
                BufferSpan <Color> sourceColors,
                BufferSpan <Vector4> destVectors,
                int count)
            {
                if (!Vector.IsHardwareAccelerated)
                {
                    throw new InvalidOperationException(
                              "Color.BulkOperations.ToVector4SimdAligned() should not be called when Vector.IsHardwareAccelerated == false!");
                }

                int vecSize = Vector <uint> .Count;

                DebugGuard.IsTrue(
                    count % vecSize == 0,
                    nameof(count),
                    "Argument 'count' should divisible by Vector<uint>.Count!");

                Vector <float> bVec       = new Vector <float>(256.0f / 255.0f);
                Vector <float> magicFloat = new Vector <float>(32768.0f);
                Vector <uint>  magicInt   = new Vector <uint>(1191182336); // reinterpreded value of 32768.0f
                Vector <uint>  mask       = new Vector <uint>(255);

                int unpackedRawCount = count * 4;

                uint *src    = (uint *)sourceColors.PointerAtOffset;
                uint *srcEnd = src + count;

                using (PinnedBuffer <uint> tempBuf = new PinnedBuffer <uint>(
                           unpackedRawCount + Vector <uint> .Count))
                {
                    uint *        tPtr  = (uint *)tempBuf.Pointer;
                    uint[]        temp  = tempBuf.Array;
                    float[]       fTemp = Unsafe.As <float[]>(temp);
                    UnpackedRGBA *dst   = (UnpackedRGBA *)tPtr;

                    for (; src < srcEnd; src++, dst++)
                    {
                        // This call is the bottleneck now:
                        dst->Load(*src);
                    }

                    for (int i = 0; i < unpackedRawCount; i += vecSize)
                    {
                        Vector <uint> vi = new Vector <uint>(temp, i);

                        vi &= mask;
                        vi |= magicInt;

                        Vector <float> vf = Vector.AsVectorSingle(vi);
                        vf = (vf - magicFloat) * bVec;
                        vf.CopyTo(fTemp, i);
                    }

                    BufferSpan.Copy <uint>(tempBuf, (BufferSpan <byte>)destVectors, unpackedRawCount);
                }
            }
예제 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PixelAccessor{TColor}" /> class.
        /// </summary>
        /// <param name="width">The width of the image represented by the pixel buffer.</param>
        /// <param name="height">The height of the image represented by the pixel buffer.</param>
        /// <param name="pixels">The pixel buffer.</param>
        private PixelAccessor(int width, int height, PinnedBuffer <TColor> pixels)
        {
            Guard.NotNull(pixels, nameof(pixels));
            Guard.MustBeGreaterThan(width, 0, nameof(width));
            Guard.MustBeGreaterThan(height, 0, nameof(height));

            this.SetPixelBufferUnsafe(width, height, pixels);

            this.ParallelOptions = Configuration.Default.ParallelOptions;
        }
예제 #4
0
        /// <summary>
        /// Sets the pixel buffer in an unsafe manor this should not be used unless you know what its doing!!!
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="pixels">The pixel buffer</param>
        private void SetPixelBufferUnsafe(int width, int height, PinnedBuffer <TColor> pixels)
        {
            this.pixelBuffer = pixels;
            this.pixelsBase  = (byte *)pixels.Pointer;

            this.Width     = width;
            this.Height    = height;
            this.PixelSize = Unsafe.SizeOf <TColor>();
            this.RowStride = this.Width * this.PixelSize;
        }
예제 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PixelArea{TColor}"/> class.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="componentOrder">The component order.</param>
        /// <param name="padding">The number of bytes to pad each row.</param>
        public PixelArea(int width, int height, ComponentOrder componentOrder, int padding)
        {
            this.Width          = width;
            this.Height         = height;
            this.ComponentOrder = componentOrder;
            this.RowStride      = (width * GetComponentCount(componentOrder)) + padding;
            this.Length         = this.RowStride * height;

            this.byteBuffer = new PinnedBuffer <byte>(this.Length);
            this.PixelBase  = (byte *)this.byteBuffer.Pointer;
        }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PixelArea{TColor}"/> class.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="bytes">The bytes.</param>
        /// <param name="componentOrder">The component order.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown if <paramref name="bytes"></paramref> is the incorrect length.
        /// </exception>
        public PixelArea(int width, int height, byte[] bytes, ComponentOrder componentOrder)
        {
            this.CheckBytesLength(width, height, bytes, componentOrder);

            this.Width          = width;
            this.Height         = height;
            this.ComponentOrder = componentOrder;
            this.RowStride      = width * GetComponentCount(componentOrder);
            this.Length         = bytes.Length; // TODO: Is this the right value for Length?

            this.byteBuffer = new PinnedBuffer <byte>(bytes);
            this.PixelBase  = (byte *)this.byteBuffer.Pointer;
        }
예제 #7
0
 public static unsafe BufferPointer <T> Slice <T>(this PinnedBuffer <T> buffer)
     where T : struct
 {
     return(new BufferPointer <T>(buffer.Array, (void *)buffer.Pointer));
 }
예제 #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PixelAccessor{TColor}"/> class.
 /// </summary>
 /// <param name="width">The width of the image represented by the pixel buffer.</param>
 /// <param name="height">The height of the image represented by the pixel buffer.</param>
 public PixelAccessor(int width, int height)
     : this(width, height, PinnedBuffer <TColor> .CreateClean(width * height))
 {
 }