uno
uno copied to clipboard
BitmapImage returns 0 for decoded and pixel dimensions
Current behavior
Using the following code, you can capture and "create" a Bitmap image to use as source for an image for example:
var captureUI = new CameraCaptureUI();
var photo = await captureUI.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (photo == null)
{
return;
}
var source = new BitmapImage(new Uri(photo.Path));
ImageViewer.Source = source;
However source.PixelHeight
, source.PixelWidth
, source.DecodePixelHeight
and source.DecodePixelWidth
are 0.
Expected behavior
These properties should be not 0 and usable, e.g. to use them to size correctly or convert a bytestream into a different image object.
How to reproduce it (as minimally and precisely as possible)
See code example above.
Workaround
No workarounds found so far. A possible workaround would have been to use GetImagePropertiesAsync to get the necessary information, unfortunately this isn't implemented yet.
Environment
Nuget Package:
- [x] Uno.UI / Uno.UI.WebAssembly / Uno.UI.Skia
- [ ] Uno.WinUI / Uno.WinUI.WebAssembly / Uno.WinUI.Skia
- [ ] Uno.SourceGenerationTasks
- [ ] Uno.UI.RemoteControl / Uno.WinUI.RemoteControl
- [x] Uno.Core
Nuget Package Version(s): Uno.UI: 3.5.0 Uno.Core: 2.1.0 Affected platform(s):
- [ ] iOS
- [x] Android
- [ ] WebAssembly
- [ ] WebAssembly renderers for Xamarin.Forms
- [ ] macOS
- [ ] Skia
- [ ] WPF
- [ ] GTK (Linux)
- [ ] Tizen
- [ ] Windows
- [ ] Build tasks
- [ ] Solution Templates
IDE:
- [ ] Visual Studio 2017 (version: )
- [x] Visual Studio 2019 (version: 16.8.5)
- [ ] Visual Studio for Mac (version: )
- [ ] Rider Windows (version: )
- [ ] Rider macOS (version: )
- [ ] Visual Studio Code (version: )
Relevant plugins:
- [ ] Resharper (version: )
Anything else we need to know?
Found while trying to create a RGBLuminanceSource to use for QR code scanning.
Hello guys, I'm thinking in implementing the method GetImagePropertiesAsync that was suggestion on workaround. https://docs.microsoft.com/en-us/uwp/api/windows.storage.fileproperties.imageproperties?view=winrt-19041 Would this be the best way?
Provides access to the image-related properties of an item (like a file or folder).
You will not be able to use this API to get image properties, as images may come from network sources, local files, local streams, or from computed images.
Each platform has its own ways to get image sizes, depending on what's done in all ImageSource.*.cs
implementations in https://github.com/unoplatform/uno/blob/2a76c3be2e5ff5325e37e50f4fb54b7724359906/src/Uno.UI/UI/Xaml/Media.
GitHub
Build Mobile, Desktop and WebAssembly apps with C# and XAML. Today. Open source and professionally supported. - uno/src/Uno.UI/UI/Xaml/Media at 2a76c3be2e5ff5325e37e50f4fb54b7724359906 · unoplatfor...
Hey @CesarRabelo,
Taking into account what @jeromelaban mentioned, I think you could take the following approach:
- Reproduce the reported issue
- Check the existing Android implementation and why it does not add values to the properties.
- Check the appropriate way to provide those values on the Android platform.
It affects wasm as well. No workaround means it is a show-stopper for now.
I'm about to implement a workaround by creating an HtmlImage
and set the src
manually. However, the class is not found, and when I write new UIElement("img")
, the compiler complains there is no such constructor. Checking the source, everything is public so they should be accessible. Am I missing anything? Thanks!
HtmlImage
is not meant to be used directly and is hidden from the public APIs accessible from the apps, but you can create your own control based on img
if you need to.
Why do you need the size of the image, out of curiosity? On WebAssembly, since Uno is giving Urls directly to the control, we don't really have a way to get the image size in the same way UWP does. The Image
control gets the size once the image has been loaded, but can't get it before that.
I need it to compute scale informations to control zoom and scaling. I cant use scroller viewer becoz scrollerviewer's scale in wasm isnt working 😅.
In js, we can instantiate Image
and set src to force it to load and grab size there, and I think we can do similar things with HtmlImage
. Long term, bitmap source should use similar implementation (better yet, implement BitmapEncoder
and use it in bitmap source), so others can get the size easily. I dont mind submiting PRs to fix, but being unable to workaround this for now is a show stopper.
I might try calling js using wasm runtime js interop but it is really not ideal. Being able to use wasm specific class like HtmlImage
directly is better. What is the reasoning behind hiding implementation specific class? Users would need to guard such code use with #if
anyways.
For those who are affected by this issue and is on wasm, you can use this workaround to get image size:
#if __WASM__
var result = await WebAssemblyRuntime.InvokeAsync("(async () => {"
+ "var promise = new Promise((resolve) => {"
+ "var i = new Image();"
+ "i.onload = function() { resolve(\"\" + i.width + \",\" + i.height); };"
+ $"i.src = \"{_imageSource.Uri}\";"
+ "});"
+ "return await promise;"
+ "})()");
var sizes = result.Split(",");
if (sizes.Length != 2)
{
throw new InvalidOperationException($"Failed to get image size via js interop. Result: {result}");
}
const int widthIndex = 0;
const int heightIndex = 1;
Width = uint.Parse(sizes[widthIndex]);
Height = uint.Parse(sizes[heightIndex]);
I think BitmapSource
etc should get the image size accordingly before ImageOpened
is called. Should I submit a PR? @jeromelaban
Possible fixes:
- Fix all
BitmapSource
by getting image size using method above. - Implement
BitmapEncoder
, at least getting image size, using method above. Then, fix allBitmapSource
by usingBitmapEncoder
to get size.
Engineering wise I think (2) is a better solution, but I reckon it might not be feasible due to API surface concerns, etc. Please lemme know which works for Uno so I can proceed to work on either one of these (I'd like to omit this workaround in my codebase). If I should open a new issue for the implementation, please lemme know. Thanks!
@roxk There is a bigger refactoring in progress for ImageSource
and related classes inside the SVG PR I have open so I suggest waiting for it to be merged before submitting this change, but it definitely would be great if you were able to contribute it afterwards 🚀 !
This is done and merged in 4x