iron-software / IronSoftware.System.Drawing

An open-source System.Drawing.Common replacement for .NET 5 and above on all platforms. Bringing together System.Drawing, Maui, and ImageSharp's Bitmap, Image, Font, and Shape types via an agnostic free NuGet package.
Other
114 stars 18 forks source link

How to create a Bitmap from RGB buffer data? #29

Closed pzs7602 closed 1 year ago

pzs7602 commented 1 year ago

I want to implement a method: AnyBitmap GetBitmapFromRGBBuffer(byte[] buffer, int width, int height) The buffer is image RGB data(length=widthheight3) Thanks in advance.

iron-production-team commented 1 year ago

Is there a similar method, constructor or factory in System.Drawing.Bitmap which you would use to achieve this in the past? https://learn.microsoft.com/en-us/dotnet/api/system.drawing.bitmap?view=windowsdesktop-7.0

pzs7602 commented 1 year ago

The method would be implemented in macOS/Linux/Windows, so System.Drawing.Bitmap is not the right way, that's why I choose to use AnyBitmap.

michael-ironsoftware commented 1 year ago

@pzs7602 Please provide the equivalent method that existed in System.Drawing.Bitmap

pzs7602 commented 1 year ago
        // buffer size = width*height*3
        public static Avalonia.Media.Imaging.Bitmap GetBitmapFromRGBBuffer(byte[] buffer, int width, int height)
        {
            System.Drawing.Bitmap b = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            System.Drawing.Rectangle BoundsRect = new System.Drawing.Rectangle();
            BoundsRect.Width = width;
            BoundsRect.Height = height;

            BitmapData bmpData = b.LockBits(BoundsRect, ImageLockMode.WriteOnly, b.PixelFormat);

            IntPtr ptr = bmpData.Scan0;

            // add back dummy bytes between lines, make each line be a multiple of 4 bytes
            int skipByte = bmpData.Stride - width*3;
            byte[] newBuff = new byte[buffer.Length + skipByte*height];
            for (int j = 0; j < height; j++)
            {
                Buffer.BlockCopy(buffer, j * width * 3, newBuff, j * (width * 3 + skipByte), width * 3);
            }

            // fill in rgbValues
            Marshal.Copy(newBuff, 0, ptr, newBuff.Length);
            b.UnlockBits(bmpData);
            return ConvertToAvaloniaBitmap(b);
        }
        // conversion between System.Drawing.Bitmap and Avalonia.Media.Imaging.Bitmap
        public static Avalonia.Media.Imaging.Bitmap ConvertToAvaloniaBitmap(System.Drawing.Bitmap bitmap)
        {
            if (bitmap == null)
                return null;
            System.Drawing.Bitmap bitmapTmp = bitmap;
            var bitmapdata = bitmapTmp.LockBits(new Rectangle(0, 0, bitmapTmp.Width, bitmapTmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
            Avalonia.Media.Imaging.Bitmap bitmap1 = new Avalonia.Media.Imaging.Bitmap(Avalonia.Platform.PixelFormat.Bgra8888, Avalonia.Platform.AlphaFormat.Premul, bitmapdata.Scan0, new Avalonia.PixelSize(bitmapdata.Width, bitmapdata.Height), new Avalonia.Vector(96, 96), bitmapdata.Stride);
            bitmapTmp.UnlockBits(bitmapdata);
            bitmapTmp.Dispose();
            return bitmap1;
        }
        //  conversion between Avalonia.Media.Imaging.Bitmap and IronSoftware.Drawing.AnyBitmap
        public static Avalonia.Media.Imaging.Bitmap ConvertToAvaloniaBitmap(AnyBitmap bitmap)
        {
            if (bitmap == null)
                return null;
            var bitmapdata = bitmap.ToStream();
            bitmapdata.Position = 0;
            Avalonia.Media.Imaging.Bitmap bitmap1 = new Avalonia.Media.Imaging.Bitmap(bitmapdata);
            return bitmap1;
        }
michael-ironsoftware commented 1 year ago

@pzs7602 This is fixed in the latest release.