Search code examples
windows-runtimewinui-3

convert system.windows.media.imaging.bitmapsource to microsoft.ui.xaml.media.imaging.bitmapsource


I thought this would be easy (and built-in) but alas not. Does anyone know of a simply way to convert this ?

I'm getting the thumbnail of files/folders and using this code (from WPF, now using WinUI 3 for desktop). I can't use the WinRT Windows.Storage.FileProperties.StorageItemThumbnail because of the threading model it uses with the RunTimeBroker.

using var shellFolder = ShellFileSystemFolder.FromFolderPath(this.Path);
shellFolder.Thumbnail.CurrentSize = new Size(requestedSize, requestedSize);
result = shellFolder.Thumbnail.BitmapSource;
result.Freeze();

Solution

  • Here is a C# code that convert from WPF's BitmapSource to WinUI3 BitmapSource, using bitmap's pixels copy from one to the other.

    public static async Task<Microsoft.UI.Xaml.Media.Imaging.SoftwareBitmapSource> GetWinUI3BitmapSourceFromWpfBitmapSource(System.Windows.Media.Imaging.BitmapSource bitmapSource)
    {
        if (bitmapSource == null)
            return null;
    
        // get pixels as an array of bytes
        var stride = bitmapSource.PixelWidth * bitmapSource.Format.BitsPerPixel / 8;
        var bytes = new byte[stride * bitmapSource.PixelHeight];
        bitmapSource.CopyPixels(bytes, stride, 0);
    
        // get WinRT SoftwareBitmap
        var softwareBitmap = new Windows.Graphics.Imaging.SoftwareBitmap(
            Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8,
            bitmapSource.PixelWidth,
            bitmapSource.PixelHeight,
            Windows.Graphics.Imaging.BitmapAlphaMode.Premultiplied);
        softwareBitmap.CopyFromBuffer(bytes.AsBuffer());
    
        // build WinUI3 SoftwareBitmapSource
        var source = new Microsoft.UI.Xaml.Media.Imaging.SoftwareBitmapSource();
        await source.SetBitmapAsync(softwareBitmap);
        return source;
    }
    

    Note that depending on how you got the "bitmap" (whatever format that is, GDI, WPF, etc), there may be smarter ways as this is allocating usually a 4 * width * height byte array for the whole bitmap.

    Also, it would probably be good to review your threading issues, using WinRT all along is probably better.