SIPSorceryMedia.FFmpeg
SIPSorceryMedia.FFmpeg copied to clipboard
Converting SIPSorceryMedia.Abstractions.RawImage to IronSoftware.Drawing.AnyBitmap
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.
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)
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.
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<Bgr24> 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<Bgr24> 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