Customizing Image Loading in Markdown
The Markdown
control supports custom image loading via the ImageLoader
property. This allows you to handle image formats such as SVG, remote images, or any custom logic for image resolution.
Example: Loading SVG Images
Required Packages
To use the custom image loader example above, you need to install the following NuGet packages:
dotnet add package Avalonia.Svg.Skia
Implementation
Below is an example of a custom image loader that supports SVG images:
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Avalonia.Svg.Skia;
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
public class CustomImageLoader : MarkdownImageLoader
{
public override async Task<IImage?> LoadImageAsync(string url)
{
IImage? image = null;
if (Uri.TryCreate(url, UriKind.Absolute, out var uri))
{
Stream? stream = null;
if (uri.Scheme == "http" || uri.Scheme == "https")
{
stream = await DownloadImage(uri);
}
else if (uri.Scheme == "file" && File.Exists(uri.LocalPath))
{
stream = File.OpenRead(uri.LocalPath);
}
if (stream is null)
{
return null;
}
using (stream)
{
if (IsSvgFile(stream))
{
var svg = new SvgImage
{
Source = SvgSource.LoadFromStream(stream)
};
image = svg;
}
else
{
image = new Bitmap(stream);
}
}
}
return image;
}
private static async Task<Stream> DownloadImage(Uri url)
{
using var client = new HttpClient();
using var response = await client.GetAsync(url).ConfigureAwait(false);
using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
memoryStream.Position = 0;
return memoryStream;
}
private static bool IsSvgFile(Stream stream)
{
if (stream == null || stream.Length == 0)
return false;
try
{
const int bufferSize = 512;
byte[] buffer = new byte[Math.Min(bufferSize, stream.Length)];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
string header = Encoding.UTF8.GetString(buffer, 0, bytesRead);
return header.Contains("<svg", StringComparison.OrdinalIgnoreCase);
}
catch
{
return false;
}
finally
{
stream.Position = 0;
}
}
}
Usage
Assign your custom loader to the ImageLoader
property:
var markdown = new Markdown
{
Text = "",
ImageLoader = new CustomImageLoader()
};
When to Use
- To support SVG images in Markdown
- To implement custom caching or authentication for images