internal static unsafe Bitmap To32bppArgbSystemDrawingBitmap <TPixel>(Image <TPixel> image)
            where TPixel : struct, IPixel <TPixel>
        {
            int w = image.Width;
            int h = image.Height;

            var        resultBitmap = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            var        fullRect     = new Rectangle(0, 0, w, h);
            BitmapData data         = resultBitmap.LockBits(fullRect, ImageLockMode.ReadWrite, resultBitmap.PixelFormat);
            byte *     destPtrBase  = (byte *)data.Scan0;

            long destRowByteCount   = data.Stride;
            long sourceRowByteCount = w * sizeof(Bgra32);

            using (IMemoryOwner <Bgra32> workBuffer = image.GetConfiguration().MemoryAllocator.Allocate <Bgra32>(w))
            {
                fixed(Bgra32 *sourcePtr = &workBuffer.GetReference())
                {
                    for (int y = 0; y < h; y++)
                    {
                        Span <TPixel> row = image.Frames.RootFrame.GetPixelRowSpan(y);
                        PixelOperations <TPixel> .Instance.ToBgra32(row, workBuffer.GetSpan(), row.Length);

                        byte *destPtr = destPtrBase + (data.Stride * y);

                        Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
                    }
                }
            }

            resultBitmap.UnlockBits(data);

            return(resultBitmap);
        }
        /// <inheritdoc/>
        protected override void OnFrameApply(ImageFrame <TPixel> source)
        {
            int brushSize = this.definition.BrushSize;

            if (brushSize <= 0 || brushSize > source.Height || brushSize > source.Width)
            {
                throw new ArgumentOutOfRangeException(nameof(brushSize));
            }

            int startY = this.SourceRectangle.Y;
            int endY   = this.SourceRectangle.Bottom;
            int startX = this.SourceRectangle.X;
            int endX   = this.SourceRectangle.Right;
            int maxY   = endY - 1;
            int maxX   = endX - 1;

            int radius         = brushSize >> 1;
            int levels         = this.definition.Levels;
            int rowWidth       = source.Width;
            int rectangleWidth = this.SourceRectangle.Width;

            Configuration configuration = this.Configuration;

            using Buffer2D <TPixel> targetPixels = this.Configuration.MemoryAllocator.Allocate2D <TPixel>(source.Size());
            source.CopyTo(targetPixels);

            var workingRect = Rectangle.FromLTRB(startX, startY, endX, endY);

            ParallelHelper.IterateRows(
                workingRect,
                this.Configuration,
                (rows) =>
            {
                /* Allocate the two temporary Vector4 buffers, one for the source row and one for the target row.
                 * The ParallelHelper.IterateRowsWithTempBuffers overload is not used in this case because
                 * the two allocated buffers have a length equal to the width of the source image,
                 * and not just equal to the width of the target rectangle to process.
                 * Furthermore, there are two buffers being allocated in this case, so using that overload would
                 * have still required the explicit allocation of the secondary buffer.
                 * Similarly, one temporary float buffer is also allocated from the pool, and that is used
                 * to create the target bins for all the color channels being processed.
                 * This buffer is only rented once outside of the main processing loop, and its contents
                 * are cleared for each loop iteration, to avoid the repeated allocation for each processed pixel. */
                using (IMemoryOwner <Vector4> sourceRowBuffer = configuration.MemoryAllocator.Allocate <Vector4>(rowWidth))
                    using (IMemoryOwner <Vector4> targetRowBuffer = configuration.MemoryAllocator.Allocate <Vector4>(rowWidth))
                        using (IMemoryOwner <float> bins = configuration.MemoryAllocator.Allocate <float>(levels * 4))
                        {
                            Span <Vector4> sourceRowVector4Span     = sourceRowBuffer.Memory.Span;
                            Span <Vector4> sourceRowAreaVector4Span = sourceRowVector4Span.Slice(startX, rectangleWidth);

                            Span <Vector4> targetRowVector4Span     = targetRowBuffer.Memory.Span;
                            Span <Vector4> targetRowAreaVector4Span = targetRowVector4Span.Slice(startX, rectangleWidth);

                            ref float binsRef       = ref bins.GetReference();
                            ref int intensityBinRef = ref Unsafe.As <float, int>(ref binsRef);
                            ref float redBinRef     = ref Unsafe.Add(ref binsRef, levels);
Example #3
0
        /// <summary>
        /// Returns an image from the given System.Drawing bitmap.
        /// </summary>
        /// <typeparam name="TPixel">The pixel format.</typeparam>
        /// <param name="bmp">The input bitmap.</param>
        /// <exception cref="ArgumentException">Thrown if the image pixel format is not of type <see cref="PixelFormat.Format32bppArgb"/></exception>
        internal static unsafe Image <TPixel> From32bppArgbSystemDrawingBitmap <TPixel>(Bitmap bmp)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            int w = bmp.Width;
            int h = bmp.Height;

            var fullRect = new System.Drawing.Rectangle(0, 0, w, h);

            if (bmp.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ArgumentException(
                          $"{nameof(From32bppArgbSystemDrawingBitmap)} : pixel format should be {PixelFormat.Format32bppArgb}!",
                          nameof(bmp));
            }

            BitmapData data  = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
            var        image = new Image <TPixel>(w, h);

            try
            {
                byte *sourcePtrBase = (byte *)data.Scan0;

                long sourceRowByteCount = data.Stride;
                long destRowByteCount   = w * sizeof(Bgra32);

                Configuration configuration = image.GetConfiguration();

                using (IMemoryOwner <Bgra32> workBuffer = Configuration.Default.MemoryAllocator.Allocate <Bgra32>(w))
                {
                    fixed(Bgra32 *destPtr = &workBuffer.GetReference())
                    {
                        for (int y = 0; y < h; y++)
                        {
                            Span <TPixel> row = image.Frames.RootFrame.GetPixelRowSpan(y);

                            byte *sourcePtr = sourcePtrBase + (data.Stride * y);

                            Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
                            PixelOperations <TPixel> .Instance.FromBgra32(
                                configuration,
                                workBuffer.GetSpan().Slice(0, w),
                                row);
                        }
                    }
                }
            }
            finally
            {
                bmp.UnlockBits(data);
            }

            return(image);
        }
Example #4
0
        internal static unsafe Bitmap To32bppArgbSystemDrawingBitmap <TPixel>(Image <TPixel> image)
            where TPixel : unmanaged, IPixel <TPixel>
        {
            Configuration configuration = image.GetConfiguration();
            int           w             = image.Width;
            int           h             = image.Height;

            var        resultBitmap = new Bitmap(w, h, PixelFormat.Format32bppArgb);
            var        fullRect     = new System.Drawing.Rectangle(0, 0, w, h);
            BitmapData data         = resultBitmap.LockBits(fullRect, ImageLockMode.ReadWrite, resultBitmap.PixelFormat);

            try
            {
                byte *destPtrBase = (byte *)data.Scan0;

                long destRowByteCount   = data.Stride;
                long sourceRowByteCount = w * sizeof(Bgra32);
                image.ProcessPixelRows(accessor =>
                {
                    using IMemoryOwner <Bgra32> workBuffer = image.GetConfiguration().MemoryAllocator.Allocate <Bgra32>(w);
                    fixed(Bgra32 * sourcePtr = &workBuffer.GetReference())
                    {
                        for (int y = 0; y < h; y++)
                        {
                            Span <TPixel> row = accessor.GetRowSpan(y);
                            PixelOperations <TPixel> .Instance.ToBgra32(configuration, row, workBuffer.GetSpan());
                            byte *destPtr = destPtrBase + (data.Stride * y);

                            Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
                        }
                    }
                });
            }
            finally
            {
                resultBitmap.UnlockBits(data);
            }

            return(resultBitmap);
        }