/// <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); }
/// <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); } }
/// <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; }
/// <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; }
/// <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; }
/// <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; }
public static unsafe BufferPointer <T> Slice <T>(this PinnedBuffer <T> buffer) where T : struct { return(new BufferPointer <T>(buffer.Array, (void *)buffer.Pointer)); }
/// <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)) { }