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);
/// <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); }
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); }