Results 1 to 2 of 2

Thread: WPF supports only PBGRA format

  1. #1
    Registered User
    Join Date
    Jun 2017
    Location
    Olomouc
    Posts
    1

    WPF supports only PBGRA format

    Hello,

    when working with WPF.SendContainer, you are not converting the format of the rendered bitmap. As we can see in this code
    Code:
    targetBitmap = new RenderTargetBitmap(xres, yres, 96, 96, PixelFormats.Pbgra32);
    targetBitmap.Render(this.Child);
    You can't render your UIElements (like grid or canvas) in other format than PGBRA32. Microsoft programmed it this way unfortunatelly. As long as you are receiving in WPF, it doesn't matter. But I haven't met a commeracial receiver made in c#.
    Since the desired format for sending video is just BGRA, in WPF you gotta unmultiply it yourself. Like this

    Code:
    private void ToBgra(int xres, int yres, byte[] buffer)
            {
                for (int y = 0; y < yres; y++)
                {
                    for (int x = 0; x < xres; x++)
                    {
                        // Calculate array offset for this pixel
                        int offset = y * _stride + x * 4;
                        int alpha = buffer[offset + 3];
    
                        //Optimizaion for fully transparent pixel
                        if (alpha == 255)
                        {
                            continue;
                        }
    
                        // Extract individual color channels from pixel value
                        int b = buffer[offset];
                        int g = buffer[offset + 1];
                        int r = buffer[offset + 2];
    
    
                        // Remove premultiplication
                        if (alpha > 0)
                        {
                            r = r * 255 / alpha;
                            g = g * 255 / alpha;
                            b = b * 255 / alpha;
                        }
    
                        // Write color channels in desired order
                        buffer[offset] = (byte)b;
                        buffer[offset + 1] = (byte)g;
                        buffer[offset + 2] = (byte)r;
                    }
                }
            }
    It would be good to at least have this function in the SDK for others starting to avoid confusion. If possible, could you add some support to your c++ libraries for faster processing? Or am I missing something?
    Last edited by Korhak; 05-10-2018 at 10:30 AM.

  2. #2
    You're 100% correct on this. I'll be changing the example to include something similar.

    I've made it optional because there is overhead in changing so many pixels one at a time and I took a slightly different approach so that we might gain a bit of speed from Microsoft's implementation.

    If you don't need the alpha or if you have no partially transparent areas, you could leave UnPremultiply set to false and save a few CPU cycles.

    Code:
    if (UnPremultiply)
    {
        FormatConvertedBitmap fmtConvertedBmp = new FormatConvertedBitmap();
        fmtConvertedBmp.BeginInit();
        fmtConvertedBmp.Source = targetBitmap;
        fmtConvertedBmp.DestinationFormat = PixelFormats.Bgra32;
        fmtConvertedBmp.EndInit();
    
        fmtConvertedBmp.CopyPixels(new Int32Rect(0, 0, xres, yres), bufferPtr, bufferSize, stride);
    }
    else
    {
        // copy the pixels into the buffer
        targetBitmap.CopyPixels(new Int32Rect(0, 0, xres, yres), bufferPtr, bufferSize, stride);
    }
    Thanks, that was a good find.
    John Perkins
    Software Engineer

    "No, it's my natural color..."

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •