Example #1
0
        /// <summary>
        /// Returns a slice that is expected to be within the bounds of a single buffer.
        /// Otherwise <see cref="ArgumentOutOfRangeException"/> is thrown.
        /// </summary>
        internal static Memory <T> GetBoundedSlice <T>(this IMemoryGroup <T> group, long start, int length)
            where T : struct
        {
            Guard.NotNull(group, nameof(group));
            Guard.IsTrue(group.IsValid, nameof(group), "Group must be valid!");
            Guard.MustBeGreaterThanOrEqualTo(length, 0, nameof(length));
            Guard.MustBeLessThan(start, group.TotalLength, nameof(start));

            int bufferIdx = (int)(start / group.BufferLength);

            if (bufferIdx >= group.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }

            int        bufferStart = (int)(start % group.BufferLength);
            int        bufferEnd   = bufferStart + length;
            Memory <T> memory      = group[bufferIdx];

            if (bufferEnd > memory.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return(memory.Slice(bufferStart, length));
        }
Example #2
0
            public override void Dispose()
            {
                ImageFrame <TImageSharpPixel>?image = _image;

                if (image is null)
                {
                    return;
                }
                IMemoryGroup <TImageSharpPixel> memoryGroup = image.GetPixelMemoryGroup();
                long totalLength = memoryGroup.TotalLength;

                // Copy pixels into this column
                int width    = image.Width;
                int start    = _start;
                int end      = start + _length;
                int colIndex = _colIndex;
                int index    = 0;
                Span <TImageSharpPixel> sourceSpan = MemoryMarshal.Cast <byte, TImageSharpPixel>(_buffer.AsSpan(0, _length * Unsafe.SizeOf <TTiffPixel>()));

                for (int rowIndex = start; rowIndex < end; rowIndex++)
                {
                    GetBoundedSlice(memoryGroup, totalLength, rowIndex * (long)width, width)[colIndex] = sourceSpan[index++];
                }

                _image = null;
                if (_parent != null)
                {
                    ImageSharpPixelBufferWriter <TImageSharpPixel, TTiffPixel> parent = _parent;
                    _parent = null;
                    if (Interlocked.CompareExchange(ref parent._cachedColHandle, this, null) != null)
                    {
                        ReleaseBuffer();
                    }
                }
            }
Example #3
0
            internal static Span <T> GetBoundedSlice <T>(IMemoryGroup <T> group, long totalLength, long start, int length) where T : struct
            {
                Debug.Assert(!(group is null));
                Debug.Assert(group !.IsValid);
                Debug.Assert(length >= 0);
                Debug.Assert(start <= group.TotalLength);
                Debug.Assert(totalLength == group.TotalLength);

                int bufferIdx = (int)(start / totalLength);

                if (bufferIdx >= group.Count)
                {
                    throw new ArgumentOutOfRangeException(nameof(start));
                }

                int        bufferStart = (int)(start % totalLength);
                int        bufferEnd   = bufferStart + length;
                Memory <T> memory      = group[bufferIdx];

                if (bufferEnd > memory.Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(length));
                }

                return(memory.Span.Slice(bufferStart, length));
            }
Example #4
0
 /// <summary>
 /// Creates a new <see cref="Thread"/>
 /// </summary>
 /// <param name="name">The name of the thread.</param>
 /// <param name="capabilities">A collection of capabilities that the <see cref="Thread"/> has to run certain <see cref="ICommand"/> commands.</param>
 /// <param name="pointer">The <see cref="ThreadPointer"/> contains information about the <see cref="ICommand"/>s that will be run on the <see cref="Thread"/>.</param>
 /// <param name="context">Memory context, such as static type information, specific to the environment where the <see cref="Thread"/> is executing.</param>
 public Thread(string name, CapabilitiesCollection capabilities, ThreadPointer pointer, IMemoryGroup context)
 {
     Name         = name;
     Capabilities = capabilities;
     Pointer      = pointer;
     Context      = context;
 }
Example #5
0
        public Image <TPixel> Decode <TPixel>(Configuration configuration, Stream stream)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            using var magickImage = new MagickImage(stream);
            var result = new Image <TPixel>(configuration, magickImage.Width, magickImage.Height);
            IMemoryGroup <TPixel> resultPixels = result.GetRootFramePixelBuffer().FastMemoryGroup;

            using (IPixelCollection pixels = magickImage.GetPixelsUnsafe())
            {
                if (magickImage.Depth == 8)
                {
                    byte[] data = pixels.ToByteArray(PixelMapping.RGBA);

                    FromRgba32Bytes(configuration, data, resultPixels);
                }
                else if (magickImage.Depth == 16)
                {
                    ushort[]    data  = pixels.ToShortArray(PixelMapping.RGBA);
                    Span <byte> bytes = MemoryMarshal.Cast <ushort, byte>(data.AsSpan());
                    FromRgba64Bytes(configuration, bytes, resultPixels);
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }

            return(result);
        }
Example #6
0
        internal static void CopyTo <T>(this IMemoryGroup <T> source, IMemoryGroup <T> target)
            where T : struct
        {
            Guard.NotNull(source, nameof(source));
            Guard.NotNull(target, nameof(target));
            Guard.IsTrue(source.IsValid, nameof(source), "Source group must be valid.");
            Guard.IsTrue(target.IsValid, nameof(target), "Target group must be valid.");
            Guard.MustBeLessThanOrEqualTo(source.TotalLength, target.TotalLength, "Destination buffer too short!");

            if (source.IsEmpty())
            {
                return;
            }

            long position = 0;
            var  srcCur   = new MemoryGroupCursor <T>(source);
            var  trgCur   = new MemoryGroupCursor <T>(target);

            while (position < source.TotalLength)
            {
                int      fwd     = Math.Min(srcCur.LookAhead(), trgCur.LookAhead());
                Span <T> srcSpan = srcCur.GetSpan(fwd);
                Span <T> trgSpan = trgCur.GetSpan(fwd);
                srcSpan.CopyTo(trgSpan);

                srcCur.Forward(fwd);
                trgCur.Forward(fwd);
                position += fwd;
            }
        }
Example #7
0
 public static MemoryGroupIndex MaxIndex <T>(this IMemoryGroup <T> group)
     where T : struct
 {
     return(group.Count == 0
         ? new MemoryGroupIndex(group.BufferLength, 0, 0)
         : new MemoryGroupIndex(group.BufferLength, group.Count - 1, group[group.Count - 1].Length));
 }
Example #8
0
 internal static void Fill <T>(this IMemoryGroup <T> group, T value)
     where T : struct
 {
     foreach (Memory <T> memory in group)
     {
         memory.Span.Fill(value);
     }
 }
Example #9
0
 internal static void Clear <T>(this IMemoryGroup <T> group)
     where T : struct
 {
     foreach (Memory <T> memory in group)
     {
         memory.Span.Clear();
     }
 }
Example #10
0
 internal static void TransformInplace <T>(
     this IMemoryGroup <T> memoryGroup,
     TransformItemsInplaceDelegate <T> transform)
     where T : struct
 {
     foreach (Memory <T> memory in memoryGroup)
     {
         transform(memory.Span);
     }
 }
Example #11
0
        /// <summary>
        /// Gets the representation of the pixels as a <see cref="Span{T}"/> in the source image's pixel format
        /// stored in row major order, if the backing buffer is contiguous.
        /// </summary>
        /// <param name="span">The <see cref="Span{T}"/>.</param>
        /// <returns>The <see cref="bool"/>.</returns>
        public bool TryGetSinglePixelSpan(out Span <TPixel> span)
        {
            IMemoryGroup <TPixel> mg = this.GetPixelMemoryGroup();

            if (mg.Count > 1)
            {
                span = default;
                return(false);
            }

            span = mg.Single().Span;
            return(true);
        }
Example #12
0
        /// <summary>
        /// Gets the representation of the pixels as a <see cref="Memory{T}"/> in the source image's pixel format
        /// stored in row major order, if the backing buffer is contiguous.
        /// <para />
        /// To ensure the memory is contiguous, <see cref="Configuration.PreferContiguousImageBuffers"/> should be set
        /// to true, preferably on a non-global configuration instance (not <see cref="Configuration.Default"/>).
        /// <para />
        /// WARNING: Disposing or leaking the underlying image while still working with the <paramref name="memory"/>'s <see cref="Span{T}"/>
        /// might lead to memory corruption.
        /// </summary>
        /// <param name="memory">The <see cref="Memory{T}"/> referencing the image buffer.</param>
        /// <returns>The <see cref="bool"/> indicating the success.</returns>
        public bool DangerousTryGetSinglePixelMemory(out Memory <TPixel> memory)
        {
            IMemoryGroup <TPixel> mg = this.GetPixelMemoryGroup();

            if (mg.Count > 1)
            {
                memory = default;
                return(false);
            }

            memory = mg.Single();
            return(true);
        }
Example #13
0
            public void OwnedMemory_PixelDataIsCorrect <TPixel>(TestImageProvider <TPixel> provider)
                where TPixel : unmanaged, IPixel <TPixel>
            {
                provider.LimitAllocatorBufferCapacity().InPixelsSqrt(200);

                using Image <TPixel> image = provider.GetImage();

                // Act:
                IMemoryGroup <TPixel> memoryGroup = image.GetPixelMemoryGroup();

                // Assert:
                VerifyMemoryGroupDataMatchesTestPattern(provider, memoryGroup, image.Size());
            }
Example #14
0
            public void OwnedMemory_DestructiveMutate_ShouldInvalidateMemoryGroup <TPixel>(TestImageProvider <TPixel> provider)
                where TPixel : unmanaged, IPixel <TPixel>
            {
                using Image <TPixel> image = provider.GetImage();

                IMemoryGroup <TPixel> memoryGroup = image.GetPixelMemoryGroup();
                Memory <TPixel>       memory      = memoryGroup.Single();

                image.Mutate(c => c.Resize(8, 8));

                Assert.False(memoryGroup.IsValid);
                Assert.ThrowsAny <InvalidMemoryOperationException>(() => _ = memoryGroup.First());
                Assert.ThrowsAny <InvalidMemoryOperationException>(() => _ = memory.Span);
            }
        public static Span <TPixel> GetPixelSpan <TPixel>(this ImageFrame <TPixel> source)
            where TPixel : struct, IPixel <TPixel>
        {
            Guard.NotNull(source, nameof(source));

            IMemoryGroup <TPixel> mg = source.GetPixelMemoryGroup();

            if (mg.Count > 1)
            {
                throw new InvalidOperationException($"GetPixelSpan is invalid, since the backing buffer of this {source.Width}x{source.Height} sized image is discontiguous!");
            }

            return(mg.Single().Span);
        }
Example #16
0
        internal static void CopyTo <T>(this ReadOnlySpan <T> source, IMemoryGroup <T> target)
            where T : struct
        {
            Guard.NotNull(target, nameof(target));
            Guard.MustBeGreaterThanOrEqualTo(target.TotalLength, source.Length, nameof(target));

            var cur = new MemoryGroupCursor <T>(target);

            while (!source.IsEmpty)
            {
                int fwd = Math.Min(cur.LookAhead(), source.Length);
                source.Slice(0, fwd).CopyTo(cur.GetSpan(fwd));
                cur.Forward(fwd);
                source = source.Slice(fwd);
            }
        }
Example #17
0
 /// <inheritdoc/>
 public bool Push(IMemoryGroup memoryGroup)
 {
     if (new List <IMemoryGroup>(Layers)
     {
         memoryGroup
     }.CanLink())
     {
         Layers.Add(memoryGroup);
         WritableLayer = memoryGroup as IWritableMemoryGroup;
         return(true);
     }
     else
     {
         return(false);
     }
 }
Example #18
0
        /// <summary>
        /// Starts the execution of a thread at a specific <see cref="ICommand"/> with a memory context in the form of an <see cref="IMemoryStack"/> and an input <see cref="IWritableMemoryGroup"/>.
        /// </summary>
        /// <param name="me">The owning <see cref="DataObject"/>, which executes the commands and provides bound .NET objects.</param>
        /// <param name="inputs">Memory context in the form of local variables such as inputs or scoped variables.</param>
        /// <returns>A <see cref="DataObject"/> representing the context at the point the <see cref="Thread"/> completed execution (this value may be null).</returns>
        public async Task <DataObject> RunThreadAsync(DataObject me, IMemoryGroup inputs)
        {
            ////Initializes memory.
            MemoryStack = new MemoryStack();
            MemoryStack.Push(Context);
            MemoryStack.Push(me.MemoryStack);
            MemoryStack.Push(inputs);
            MemoryStack.Push();

            IMemoryGroup commandContext = null;

            while (!Pointer.IsStopped)
            {
                commandContext = await Pointer.CurrentCommand.ExecuteCommandAsync(this, me, commandContext);

                Pointer.Next();
            }
            return(commandContext as DataObject);
        }
Example #19
0
        internal static void CopyTo <T>(this IMemoryGroup <T> source, Span <T> target)
            where T : struct
        {
            Guard.NotNull(source, nameof(source));
            Guard.MustBeGreaterThanOrEqualTo(target.Length, source.TotalLength, nameof(target));

            var  cur      = new MemoryGroupCursor <T>(source);
            long position = 0;

            while (position < source.TotalLength)
            {
                int fwd = Math.Min(cur.LookAhead(), target.Length);
                cur.GetSpan(fwd).CopyTo(target);

                cur.Forward(fwd);
                target    = target.Slice(fwd);
                position += fwd;
            }
        }
Example #20
0
        /// <summary>
        /// Returns the slice of the buffer starting at global index <paramref name="start"/> that goes until the end of the buffer.
        /// </summary>
        internal static Memory <T> GetRemainingSliceOfBuffer <T>(this IMemoryGroup <T> group, long start)
            where T : struct
        {
            Guard.NotNull(group, nameof(group));
            Guard.IsTrue(group.IsValid, nameof(group), "Group must be valid!");
            Guard.MustBeLessThan(start, group.TotalLength, nameof(start));

            int bufferIdx = (int)(start / group.BufferLength);

            // if (bufferIdx < 0 || bufferIdx >= group.Count)
            if ((uint)bufferIdx >= group.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }

            int bufferStart = (int)(start % group.BufferLength);

            Memory <T> memory = group[bufferIdx];

            return(memory.Slice(bufferStart));
        }
Example #21
0
            private static void VerifyMemoryGroupDataMatchesTestPattern <TPixel>(
                TestImageProvider <TPixel> provider,
                IMemoryGroup <TPixel> memoryGroup,
                Size size)
                where TPixel : unmanaged, IPixel <TPixel>
            {
                Assert.True(memoryGroup.IsValid);
                Assert.Equal(size.Width * size.Height, memoryGroup.TotalLength);
                Assert.True(memoryGroup.BufferLength % size.Width == 0);

                int cnt = 0;

                for (MemoryGroupIndex i = memoryGroup.MaxIndex(); i < memoryGroup.MaxIndex(); i += 1, cnt++)
                {
                    int y = cnt / size.Width;
                    int x = cnt % size.Width;

                    TPixel expected = provider.GetExpectedBasicTestPatternPixelAt(x, y);
                    TPixel actual   = memoryGroup.GetElementAt(i);
                    Assert.Equal(expected, actual);
                }
            }
Example #22
0
        private static void FromRgba64Bytes <TPixel>(Configuration configuration, Span <byte> rgbaBytes, IMemoryGroup <TPixel> destinationGroup)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            foreach (Memory <TPixel> m in destinationGroup)
            {
                Span <TPixel> destBuffer = m.Span;
                PixelOperations <TPixel> .Instance.FromRgba64Bytes(
                    configuration,
                    rgbaBytes,
                    destBuffer,
                    destBuffer.Length);

                rgbaBytes = rgbaBytes.Slice(destBuffer.Length * 8);
            }
        }
Example #23
0
 internal static bool IsEmpty <T>(this IMemoryGroup <T> group)
     where T : struct
 => group.Count == 0;
Example #24
0
 public static void SetElementAt <T>(this IMemoryGroup <T> group, MemoryGroupIndex idx, T value)
     where T : struct
 {
     group[idx.BufferIndex].Span[idx.ElementIndex] = value;
 }
Example #25
0
 public static MemoryGroupIndex MinIndex <T>(this IMemoryGroup <T> group)
     where T : struct
 {
     return(new MemoryGroupIndex(group.BufferLength, 0, 0));
 }
Example #26
0
 public static T GetElementAt <T>(this IMemoryGroup <T> group, MemoryGroupIndex idx)
     where T : struct
 {
     return(group[idx.BufferIndex].Span[idx.ElementIndex]);
 }
 internal MemoryGroupEnumerator(MemoryGroupView <T> memoryGroup)
 {
     this.memoryGroup = memoryGroup;
     this.count       = memoryGroup.Count;
     this.index       = -1;
 }
 internal MemoryGroupEnumerator(MemoryGroup <T> .Consumed memoryGroup)
 {
     this.memoryGroup = memoryGroup;
     this.count       = memoryGroup.Count;
     this.index       = -1;
 }
Example #29
0
 public MemoryGroupCursor(IMemoryGroup <T> memoryGroup)
 {
     this.memoryGroup  = memoryGroup;
     this.bufferIndex  = 0;
     this.elementIndex = 0;
 }
Example #30
0
 internal static void CopyTo <T>(this Span <T> source, IMemoryGroup <T> target)
     where T : struct
 => CopyTo((ReadOnlySpan <T>)source, target);