mono / SkiaSharp

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's Skia Graphics Library. It provides a comprehensive 2D API that can be used across mobile, server and desktop models to render images.
MIT License
4.51k stars 538 forks source link

Can image in AV_PIX_FMT_BGR24 format (format in FFmpeg context) be ported to SKBitmap #2384

Open mail2mhossain opened 1 year ago

mail2mhossain commented 1 year ago

To port AV_PIX_FMT_BGR24 format (format in FFmpeg context), we need to consider

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, we must use an equivalent:

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

mail2mhossain commented 1 year ago

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.

m7md7sien commented 1 year ago

The result image is blueish because you swap blue and red channels. Either don't swap the channels: bgra32[bgra32Index] = bgr24[bgr24Index]; // blue channel bgra32[bgra32Index + 1] = bgr24[bgr24Index + 1]; // green channel bgra32[bgra32Index + 2] = bgr24[bgr24Index + 2]; // red channel bgra32[bgra32Index + 3] = 255; // alpha channel (fully opaque)

Or use RGB color type (like SKColorType.Rgba8888) instead of BGR (SKColorType.Bgra8888).