namespace ImageSharp.Tests.TestUtilities.ReferenceCodecs { using System; using System.Drawing.Imaging; using ImageSharp.Memory; using ImageSharp.PixelFormats; public static class SystemDrawingBridge { // TODO: It would be nice to have this method in PixelOperations private static void ToArgb32(Span source, Span dest) where TPixel : struct, IPixel { int length = source.Length; Guard.MustBeSizedAtLeast(dest, length, nameof(dest)); using (var rgbaBuffer = new Buffer(length)) { PixelOperations.Instance.ToRgba32(source, rgbaBuffer, length); for (int i = 0; i < length; i++) { ref Rgba32 s = ref rgbaBuffer[i]; ref Argb32 d = ref dest[i]; d.PackFromRgba32(s); } } } private static void FromArgb32(Span source, Span dest) where TPixel : struct, IPixel { int length = source.Length; Guard.MustBeSizedAtLeast(dest, length, nameof(dest)); using (var rgbaBuffer = new Buffer(length)) { PixelOperations.Instance.ToRgba32(source, rgbaBuffer, length); for (int i = 0; i < length; i++) { ref Rgba32 s = ref rgbaBuffer[i]; ref TPixel d = ref dest[i]; d.PackFromRgba32(s); } } } internal static unsafe Image FromSystemDrawingBitmap(System.Drawing.Bitmap bmp) where TPixel : struct, IPixel { 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("FromSystemDrawingBitmap(): pixel format not supported", nameof(bmp)); } BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); byte* sourcePtrBase = (byte*)data.Scan0; long sourceRowByteCount = data.Stride; long destRowByteCount = w * sizeof(Argb32); var image = new Image(w, h); using (var workBuffer = new Buffer(w)) { var destPtr = (Argb32*)workBuffer.Pin(); for (int y = 0; y < h; y++) { Span row = image.GetRowSpan(y); byte* sourcePtr = sourcePtrBase + data.Stride * y; Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); FromArgb32(workBuffer, row); } } return image; } internal static unsafe System.Drawing.Bitmap ToSystemDrawingBitmap(Image image) where TPixel : struct, IPixel { int w = image.Width; int h = image.Height; var resultBitmap = new System.Drawing.Bitmap(w, h, PixelFormat.Format32bppArgb); var fullRect = new System.Drawing.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(Argb32); using (var workBuffer = new Buffer(w)) { var sourcePtr = (Argb32*) workBuffer.Pin(); for (int y = 0; y < h; y++) { Span row = image.GetRowSpan(y); ToArgb32(row, workBuffer); byte* destPtr = destPtrBase + data.Stride * y; Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount); } } resultBitmap.UnlockBits(data); return resultBitmap; } } }