Skip to content

ImageProcessing

Olivier Nizet edited this page Oct 10, 2024 · 6 revisions

The image are automatically downloaded and inserted inside the word document as embedded resources. You can also provide your own mechanism to retrieve the image or provide credentials to read the data.

Supported Formats

Those image formats are natively supported by OpenXml: bmp, emf, gif, ico, jp2, jpe, jpeg, pcx, png, svg, tif, tiff, wmf.

Inline (base 64)

The library support the data URI format as specified by the IETF. More detailed information available on wikipedia.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA
AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO
9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot" />

Unsupported format

Other extension such as webP must be first transformed to a supported format. You can achieve this by shipping your own implementation of HtmlToOpenXml.IO.IWebRequest or inherits from HtmlToOpenXml.IO.DefaultWebRequest.

Example with nuget package SixLabors.ImageSharp

class WebPWebRequest : DefaultWebRequest
{
    protected override async Task<Resource> DownloadHttpFile(Uri requestUri, CancellationToken cancellationToken)
    {
        var resource = await base.DownloadHttpFile(requestUri, cancellationToken);
        if (resource.Content is not null &&
            requestUri.OriginalString.EndsWith(".webp", StringComparison.OrdinalIgnoreCase))
        {
            using var img = await Image.LoadAsync(resource.Content, cancellationToken);

            var convertedStream = new System.IO.MemoryStream();
            await img.SaveAsPngAsync(convertedStream, cancellationToken);
            convertedStream.Position = 0L;
            resource.Content.Dispose();
            resource.Content = convertedStream;
        }
        return resource;
    }
}


HtmlConverter converter = new HtmlConverter(mainPart, new WebPWebRequest());
await converter.ParseBody(@"<img src='https://www.gstatic.com/webp/gallery/1.webp'>");

Download of external images

Any download of images are delegated to HtmlToOpenXml.IO.IWebRequest.

The default implementation will handle both remote file (http(s)) and local files. Remove files are downloaded via a static instance of System.Net.Http.HttpClient. If you need to provide your own credentials, you can instantiate HtmlToOpenXml.IO.DefaultWebRequest and providing your own version of HttpClient.

You can resolve relative urls by providing the base image context in DefaultWebRequest.BaseImageUrl.

HtmlConverter converter = new(mainPart, new HtmlToOpenXml.IO.DefaultWebRequest() {
    BaseImageUrl = "http://web.site/path/"
})

Alternatively, you are free to either override the existing implementation HtmlToOpenXml.IO.DefaultWebRequest or rolling out your own HtmlToOpenXml.IO.IWebRequest.

Border support

The border, border-style, border-width and border-color style attributes are interpreted. border-style could take these values: dotted, dashed, solid, double, inset, outset or none. border-width only support px units or these reserved keywords: medium, thick or thin.

Legend

You can add a legend above or below an image.

The synthax is similarly to the <figcaption> tag included in Html5:

<figure>
  <img src="img_pulpit.jpg" width="304" height="228" />
  <figcaption>A view of the pulpit rock in Norway</figcaption>
</figure>

or inverse the line <figcaption> and <img> to display the legend above.

SVG

The converter will embed SVG as an image resource in those case:

  • inlined <svg> tag
  • <img> with a svg source

Please note that MacOS Pages doesn't support svg format.

If the SVG contain the title or description element, they will be used for the description of the image in Word.

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 width="612px" height="502.174px" viewBox="0 65.326 612 502.174" enable-background="new 0 65.326 612 502.174"
	 xml:space="preserve">
	<title>
		Illustration of a Kiwi
	</title>
	<desc>
		Kiwi (/ˈkiːwiː/ KEE-wee)[4] are flightless birds endemic to New Zealand of the order Apterygiformes.
	</desc>
        [...]
</svg>

Specify the dimension of an image

The converter take care of the width and height attributes on the <img> tag. The size should be in pixels (px).

If no dimension is specified, the image size is automatically detected through HtmlToOpenXml.ImageHeader.GetDimensions(). This class give you the image size without reading the entire file. This code was found on stackoverflow forum

If only one of the two attributes is specified, the image is resized regarding the aspect ratio.


Legacy documentation based on version prior to 2.2

Automatic Download

The automatic download uses a classic System.Net.WebClient in anonymous mode. Since v1.4, you can specify your credentials and/or the proxy or still handling the ProvisionImage event.

converter.WebProxy.Credentials = new NetworkCredential("john", "123456", "codeplex");
converter.WebProxy.Proxy = new System.Net.WebProxy("http://proxy-isa:8080");

Manually download image

HtmlToOpenXml automatically download the image. However, you can either ignore any <img> tag or manually read the image from a data cache or provide some credentials to grab them. You can set the property that control this behavior like this:

converter.ImageProcessing = ImageProcessing.ManualProvisioning;
converter.ProvisionImage += converter_ProvisionImage;

...

private void converter_ProvisionImage(object sender, ProvisionImageEventArgs e)
{
       // Read the image from the file system:
        e.Data = File.ReadAllBytes(@"c:\inetpub\wwwroot\mysite\images\" + e.ImageUrl);
}

You can set manually the image size or leave empty (0,0) to let the converter detects the image size.

e.ImageSize = new System.Drawing.Size(50, 50);

Resolve relative image link

If you let the default image processing to "AutomaticDownload", the converter will not be able to resolve url like : "/_layouts/images/pic.gif". These images will be ignored unless you set the property:

converter.BaseImageUrl = new Uri("http://myserver:8080/");

It's possible to work with local images

converter.BaseImageUrl = new Uri("C:\inetpub\wwwroot\static-assets\");