maui
maui copied to clipboard
SVG Image loaded with ImageSource.FromStream() not displayed
Description
I'm loading PNG and SVG images stored in a database. I have gotten this to work correctly in the Xamarin version of the application, using FFImageLoading Nuget, using the SVGImageSource class.
PNG files work fine, but SVG are not displayed.
This is how it was on Xamarin:
//ImageFormat is a string that contains the value of FileResult.ContentType, to know if it is PNG or SVG
if (image.ImageFormat != null && image.ImageFormat.ToLower().Contains("svg"))
{
imageSource = SvgImageSource.FromStream(() => new MemoryStream(image.ImageData));
}
else
{
imageSource = ImageSource.FromStream(() => new MemoryStream(image.ImageData));
}
MAUI:
imageSource = ImageSource.FromStream(() => new MemoryStream(image.ImageData));
The documentation inticates that ImageSource.FromStream can load SVG and also animated .GIF, so, no need to check if its PNG or SVG. Anyway, i haven't found anything similar to SvgImageSource.
Steps to Reproduce
- Load a SVG File (PNG works fine)
FileResult fileData = await MediaPicker.PickPhotoAsync(options);
- Read data from the file
var imageData = await fileData.OpenReadAsync();
- Get byte[] from imageData
byte[] imageByteArray = new byte[imageData.Length];
await imageData.ReadAsync(imageByteArray, 0, (int)imageData.Length);
ImageData = imageByteArray;
- Get ImageSource from byte[] to bind it to an Image Control
//If you try to get an ImageSource from this byte[] the image is not displayed if is an SVG image
ImageSource ImageData = ImageSource.FromStream(() => new MemoryStream(item.ImageData));
- Bind the control on the view to the ImageData Property
<Image Source="{Binding ImageData }" WidthRequest="64" HeightRequest="64" Margin="4,0"/>
Link to public reproduction project repository
https://github.com/drossoft/SVGImageLoadSample
Version with bug
7.0 (current)
Last version that worked well
Unknown/Other
Affected platforms
Android, Windows, I was not able test on other platforms
Affected platform versions
Windows SDK 10.0.19041.0, Android 11
Did you find any workaround?
Not yet
Relevant log output
Microsoft.Maui.StreamImageSourceService: Warning: Unable to load image stream.
System.Runtime.InteropServices.COMException (0x88982F50): The component cannot be found. (0x88982F50)
at Microsoft.Maui.StreamImageSourceService.GetImageSourceAsync(IStreamImageSource imageSource, Single scale, CancellationToken cancellationToken)
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.
Is there any workaround? Can't upgrade my app without loading SVG Image from byte[].
Any news?
No, and I haven't found any workaround yet
We're running into this issue with an maui app build on .NET 7.0.103, android. Not only with SVG, also with Jpg and similar image types.
Our workaround is to cache the image in file and using ImageSource FromFile. It's not nice but works like a charm.
Yes, that seems to be the best option, I will try that as well. Thanks!
Any news?
I've tried caching the image in the file and loading it using ImageSource.FromFile, but it still doesn't work for SVG files.
string localPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); string imagesPath = Path.Combine(localPath, "Images");
string imageFullPath = Path.Combine(imagesPath, "image_test.svg");
File.WriteAllBytes(imageFullPath, imageBytes); //imageBytes is the byte[] read from database image = ImageSource.FromFile(imageFullPath);
I see that the image is correctly saved to the file when I open it in File Explorer, and the variable "image" is an ImageSource pointing to the file, but it doesn't show up when I bind it in my view.
@daDomas, have you checked that SVG images work with your solution or only JPG images?
For anyone having trouble with this, I have found a solution. I have implemented a method using SkiaSharp to get an ImageSource from a byte[] (with the help of ChatGPT).
You need these nugets:
- SkiaSharp.Svg (1.60.0)
- SkiaSharp.Views.Maui.Core (2.88.3)
using SkiaSharp;
public ImageSource ConvertSvgToImageSource(byte[] svgData)
{
using (var stream = new MemoryStream(svgData))
{
var svgDocument = new SkiaSharp.Extended.Svg.SKSvg();
svgDocument.Load(stream);
var bitmap = new SKBitmap((int)svgDocument.Picture.CullRect.Width, (int)svgDocument.Picture.CullRect.Height);
using (var surface = SKSurface.Create(new SKImageInfo(bitmap.Width, bitmap.Height)))
{
var canvas = surface.Canvas;
canvas.Clear(SKColors.Transparent);
canvas.DrawPicture(svgDocument.Picture);
surface.Canvas.Flush();
var image = surface.Snapshot();
bitmap = SKBitmap.FromImage(image);
var data = bitmap.Encode(SKEncodedImageFormat.Png, 100);
var imageStream = new MemoryStream(data.ToArray());
var imageSource = ImageSource.FromStream(() => imageStream);
return imageSource;
}
}
}
@drossoft your workarround dont work well when we have a svg with gradients.
Yes, we've noticed, but that's the best we've come up with for now.