Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Converting SIPSorceryMedia.Abstractions.RawImage to IronSoftware.Drawing.AnyBitmap #47

Open
mail2mhossain opened this issue Dec 13, 2022 · 3 comments

Comments

@mail2mhossain
Copy link

It is possible to convert SIPSorceryMedia.Abstractions.RawImage to System.Drawing.Bitmap as follows:

System.Drawing.Bitmap bmpImage = new System.Drawing.Bitmap(rawImage.Width, rawImage.Height, rawImage.Stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, rawImage.Sample);

Now I want to convert SIPSorceryMedia.Abstractions.RawImage to IronSoftware.Drawing.AnyBitmap.

Any help in this regard.

@ChristopheI
Copy link
Collaborator

SIPSorceryMedia.Abstractions.RawImage contains all necessary info about an image in AV_PIX_FMT_BGR24 format (format in FFmpeg context)

So 8 bits for B, 8 bits for G, 8 bits for R (=> 24 bits for one pixel), it's size (width and height) and it's stride

As an example, This AV_PIX_FMT_BGR24 format is the same as this one PixelFormat.Format24bppRgb in
System.Drawing.Imaging context.

According the library, you must use an equivalent:

  • use 8 bits for each colors
  • no alpha
  • necessary to specify width, height and stride

About stride, read this: https://learn.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.-ctor?view=dotnet-plat-ext-7.0#system-drawing-bitmap-ctor(system-int32-system-int32-system-int32-system-drawing-imaging-pixelformat-system-intptr)

@mail2mhossain
Copy link
Author

mail2mhossain commented Feb 13, 2023

Trying to convert AV_PIX_FMT_BGR24 to 32-bit color with the format BGRA:

        AnyBitmap anyImage;
        int width = rawImage.Width;
        int height = rawImage.Height;
    int stride = rawImage.Stride;

        byte[] bgr24 = rawImage.GetBuffer(); 
        byte[] bgra32 = new byte[width * height * 4]; 

        for (int y = 0; y < height; y++)
        {
            int bgr24RowIndex = y * stride;
            int bgra32RowIndex = y * width * 4;

            for (int x = 0; x < width; x++)
            {
                int bgr24Index = bgr24RowIndex + x * 3;
                int bgra32Index = bgra32RowIndex + x * 4;

                bgra32[bgra32Index] = bgr24[bgr24Index + 2]; // blue channel
                bgra32[bgra32Index + 1] = bgr24[bgr24Index + 1]; // green channel
                bgra32[bgra32Index + 2] = bgr24[bgr24Index]; // red channel
                bgra32[bgra32Index + 3] = 255; // alpha channel (fully opaque)
            }
        }

        SKImageInfo info = new SKImageInfo(rawImage.Width, rawImage.Height, SKColorType.Bgra8888);	
		
        using (SKData data = SKData.CreateCopy(bgra32))
        {
            using (SKImage image = SKImage.FromPixels(info, data, rawImage.Width * 4))
            {
                using (SKBitmap bitmap = SKBitmap.FromImage(image))
                {
                    anyImage = bitmap;
                }
            }
        }

But getting blueish color in image and taking to long to convert too.

Any suggestions please.

@mail2mhossain
Copy link
Author

mail2mhossain commented May 3, 2023

Solution:

  1. First, you need to install the SixLabors.ImageSharp NuGet package to your project
  2. Then, you can use the following code to convert the RawImage object to a SixLabors.ImageSharp.Image:

public static unsafe Image ConvertRawImageToImageSharp (SIPSorceryMedia.Abstractions.RawImage rawImage)
{
int expectedStride = rawImage.Width * 3; // 3 bytes per pixel for Bgr24 format
if (rawImage.Stride != expectedStride)
{
throw new InvalidOperationException("Stride of the raw image does not match the expected stride for ImageSharp Bgr24 format.");
}

		// Create a new memory span from the rawImage Sample pointer
		var pixelDataSpan = new Span<byte>(rawImage.Sample.ToPointer(), rawImage.Height * rawImage.Stride);

		// Load the pixel data from the span
		var image = Image.LoadPixelData<Bgr24>(pixelDataSpan, rawImage.Width, rawImage.Height);

		return image;
	}
  1. Now convert the ImageSharp Image to an Avalonia Bitmap:
    public static Bitmap ConvertImageSharpToAvaloniaBitmap (Image image)
    {
    // Create a new WriteableBitmap with the same dimensions as the ImageSharp image
    var writeableBitmap = new WriteableBitmap(new PixelSize(image.Width, image.Height), new Vector(96, 96), Avalonia.Platform.PixelFormat.Rgba8888, Avalonia.Platform.AlphaFormat.Opaque);

     	// Lock the WriteableBitmap's pixel buffer for direct access
     	using (var buffer = writeableBitmap.Lock())
     	{
     		// Copy the pixel data from the ImageSharp image to the WriteableBitmap
     		for (int y = 0; y < image.Height; y++)
     		{
     			Span<Bgr24> pixelRowSpan = image.GetPixelRowSpan(y);
     			IntPtr pixelRowPtr = buffer.Address + y * buffer.RowBytes;
    
     			for (int x = 0; x < pixelRowSpan.Length; x++)
     			{
     				Bgr24 pixel = pixelRowSpan[x];
     				byte[] rgbaPixel = { pixel.R, pixel.G, pixel.B, 255 };
     				Marshal.Copy(rgbaPixel, 0, pixelRowPtr + x * 4, 4);
     			}
     		}
     	}
    
     	return writeableBitmap;
     }
    

Thanks to ChatGPT-4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants