AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.29k stars 2.19k forks source link

To show AV_PIX_FMT_BGR24 format (format in FFmpeg context) image #10612

Open mail2mhossain opened 1 year ago

mail2mhossain commented 1 year ago

Is there any way to show AV_PIX_FMT_BGR24 format (format in FFmpeg context) image in Avalonia App

mail2mhossain commented 1 year ago

Should following code work:

using Avalonia.Controls; using Avalonia.Media.Imaging; using SIPSorceryMedia.Abstractions;

public static Bitmap Convert_AV_PIX_FMT_BGR24(RawImage rawImage) { // Create a new Bitmap from the raw image. var bitmap = new Bitmap( PixelFormat.Bgra8888, AlphaFormat.Premul, rawImage.Sample, new PixelSize(rawImage.Width, rawImage.Height), new Vector(96, 96), rawImage.Stride ); return bitmap;
}

jmacato commented 1 year ago

@mail2mhossain No sadly you need to at least get AV_PIX_FMT_BGRA format from ffmpeg so that it maps with Avalonia's Bgra8888 format.

danwalmsley commented 1 year ago

@jmacato we can add sensible pixel formats, we already implement transcoding since:

https://github.com/AvaloniaUI/Avalonia/pull/10120

mail2mhossain commented 1 year ago

Solution:

First, you need to install the SixLabors.ImageSharp NuGet package to your project
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;
}

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