unoplatform / uno

Open-source platform for building cross-platform native Mobile, Web, Desktop and Embedded apps quickly. Create rich, C#/XAML, single-codebase apps from any IDE. Hot Reload included! 90m+ NuGet Downloads!!
https://platform.uno
Apache License 2.0
8.94k stars 724 forks source link

[WASM] Support for image of type "`blob:`" #10772

Open carldebilly opened 1 year ago

carldebilly commented 1 year ago

Support for image uri of type "blob:"

In JavaScript, when the image is already available as binary blob, it is possible to use the URL.createObjectUrl() method to get a blob uri (an URI like that: blob:null/8e17eac9-a052-436e-8ab7-7c0c13c8a0b0).

The code in JavaScript is the following:

  const blob = new Blob([1, 2, 3, 4]); // suppose that's a valid Blob containing an image
  const blobUri = URL.createObjectURL(blob); // output with "blob" scheme like that: blob:null/8e17eac9-a052-436e-8ab7-7c0c13c8a0b0
  document.getElementById("my-img").src = blobUri; // Display

  [... later]
  URL.revokeObjectURL(blobUri);

The equivalent in C# should be the following:

  var blobUri = GetBlobUriFromJavaScript(); // suppose we're getting the blob uri from JavaScript here
  img.Source = new BitmapImage(blobUri);

The problem

It's not working because the BitmapImage is hard-coded to considered as empty any non-locally resolved absolute uri not using the http or https scheme. The code doing that is here.

    if (uri.IsAbsoluteUri)
    {
        if (uri.Scheme.Equals("http", StringComparison.OrdinalIgnoreCase) ||
            uri.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
        {
            return ImageData.FromUrl(uri, source);
        }

        // TODO: Implement ms-appdata
        return ImageData.Empty;
    }

Why is this needed:

The only alternative for now is to encode the image as base64 and set it as a data uri. This is CPU EXPENSIVE.

For which Platform:

Anything else we need to know?

Yep. Overalls are cool. But it won't help you solving this problem ;-)

EvarDion commented 1 year ago

I would like to second this proposal.

The a similar problem is when you are loading media files (images etc) from disk and you call BitmapImage.SetSourceAsync() and pass in a stream created from either a byte array or a storage file.

A classic example would be a photo editing app: For 4MB JPG photos, this can take 8 seconds to load per image and it blocks the UI thread while it is loading/decoding even if you call BitmapImage.SetSourceAsync() from a background thread.

So if we had a function where you could pass in a stream or byte array and it created the blob and gave you back the BlobURI then it would be very useful indeed.

One way to get around the above problem is to encode the File Bytes as Base64 on background threads and then set the .src tag directly via JavaScript, but as mentioned it is quite CPU intensive so you need to run multiple background threads if you want to load a bunch of images, and even then it is much slower than native.