How to save Html callback images and custom fonts in C# and .NET


In today's world of document processing and web formatting, many tasks arise related to converting various data types — from text documents to images and fonts. One such challenge is preserving callback images and custom fonts when converting RTF or Word documents to HTML. In this article, we'll look at how to implement this in C# and .NET, using the powerful component RTF TO HTML .NET from SautinSoft library.

In many cases, documents contain images or fonts specific to a user or project. When converting to HTML, these components must be preserved to maintain the visual integrity and readability of the document.

  • Callback images are images that are not directly embedded but inserted dynamically, for example, when loading data or via JavaScript.
  • Custom fonts enable unique styles within a document, which is especially important for design, branding, or special display requirements.

Failure to preserve these components can result in the resulting HTML document losing its original appearance, becoming less readable, and missing important information.
Final recommendations and interesting aspects:

  • Before starting work, it's important to clearly define which resources you need to save (images, fonts) – this is what determines proper configuration.
  • Don't forget about the compatibility of supported formats and checking the resulting HTML.
  • For complex documents, it's recommended to test the conversion on different documents to achieve optimal results.
  • The library allows you to manage paths, resource names, and their embedding, providing flexible control over export.

Complete code

using SkiaSharp;
using System.Collections.Generic;
using System.IO;


namespace SautinSoft
{
    class SaveImage : RtfToHtml.IHtmlImageSavingCallback
    {
        public Dictionary<string, byte[]> Images = new Dictionary<string, byte[]>();

        public void ImageSaving(RtfToHtml.HtmlImageSavingArgs args)
        {
            if (!Images.ContainsKey(args.ImageFileName))
            {
                SKBitmap bitmap = SKBitmap.Decode(args.ImageStream);
                var ms = new MemoryStream();
                bitmap.Encode(ms, SKEncodedImageFormat.Png, 100);
                ms.Position = 0;
                Images.Add(args.ImageFileName, ms.ToArray());
            }
        }
    }

    class SaveFont : RtfToHtml.IHtmlFontSavingCallback
    {
        public Dictionary<string, byte[]> Fonts = new Dictionary<string, byte[]>();

        public void FontSaving(RtfToHtml.HtmlFontSavingArgs args)
        {
            if (!Fonts.ContainsKey(args.FontFileName))
            {
                var ms = new MemoryStream();
                args.FontStream.CopyTo(ms);
                ms.Position = 0;
                Fonts.Add(args.FontFileName, ms.ToArray());
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Get your free trial key here:   
            // https://sautinsoft.com/start-for-free/

            Convert();
        }

        /// <summary>
        /// Creates a new Html document using custom fonts in the source document 
        /// and placing fonts and images in separate folders.
        /// </summary>
        /// <remarks>
        /// Details: 
        /// </remarks>
        public static void Convert()
        {
            string inpFile = @"..\..\..\text.docx";
            string outFile = Path.ChangeExtension(inpFile, ".html");
            var rth = new RtfToHtml();
            var a = new RtfToHtml.HtmlFixedSaveOptions();
            a.FontsDirectoryPath = Path.GetDirectoryName(outFile) + "\\fonts";
            a.ImagesDirectoryPath = Path.GetDirectoryName(outFile) + "\\images";
            a.ImageSavingCallback = new SaveImage();
            a.FontSavingCallback = new SaveFont();
            var ms = new MemoryStream();
            var inp = File.OpenRead(inpFile);
            rth.Convert(inp, ms, a);
            var images = (a.ImageSavingCallback as SaveImage).Images;
            var fonts = (a.FontSavingCallback as SaveFont).Fonts;
            ms.Position = 0;
            File.WriteAllBytes(outFile, ms.ToArray());
            foreach (var image in images)
            {
                if (!Directory.Exists(a.ImagesDirectoryPath)) Directory.CreateDirectory(a.ImagesDirectoryPath);
                File.WriteAllBytes(a.ImagesDirectoryPath + "\\" + image.Key + ".png", image.Value);
            }
            foreach (var font in fonts)
            {
                if (!Directory.Exists(a.FontsDirectoryPath)) Directory.CreateDirectory(a.FontsDirectoryPath);
                File.WriteAllBytes(a.FontsDirectoryPath + "\\" + font.Key + ".ttf", font.Value);
            }
            System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(outFile) { UseShellExecute = true });
        }
    }
}

Download

Option Infer On

Imports SkiaSharp
Imports SautinSoft
Imports System.IO

Namespace SautinSoft
    Friend Class SaveImage
        Implements RtfToHtml.IHtmlImageSavingCallback

        Public Images As New Dictionary(Of String, Byte())()

        Public Sub ImageSaving(args As RtfToHtml.HtmlImageSavingArgs) Implements RtfToHtml.IHtmlImageSavingCallback.ImageSaving
            If Not Images.ContainsKey(args.ImageFileName) Then
                Dim bitmap As SKBitmap = SKBitmap.Decode(args.ImageStream)
                Dim ms = New MemoryStream()
                bitmap.Encode(ms, SKEncodedImageFormat.Png, 100)
                ms.Position = 0
                Images.Add(args.ImageFileName, ms.ToArray())
            End If
        End Sub
    End Class

    Friend Class SaveFont
        Implements RtfToHtml.IHtmlFontSavingCallback

        Public Fonts As New Dictionary(Of String, Byte())()

        Public Sub FontSaving(args As RtfToHtml.HtmlFontSavingArgs) Implements RtfToHtml.IHtmlFontSavingCallback.FontSaving
            If Not Fonts.ContainsKey(args.FontFileName) Then
                Dim ms = New MemoryStream()
                args.FontStream.CopyTo(ms)
                ms.Position = 0
                Fonts.Add(args.FontFileName, ms.ToArray())
            End If
        End Sub
    End Class

    Friend Class Program
        Shared Sub Main(ByVal args() As String)
            ' Get your free trial key here:   
            ' https://sautinsoft.com/start-for-free/

            Convert()
        End Sub

        ''' <summary>
        ''' Creates a new Html document using custom fonts in the source document 
        ''' and placing fonts and images in separate folders.
        ''' </summary>
        ''' <remarks>
        ''' Details: 
        ''' </remarks>
        Public Shared Sub Convert()
            Dim inpFile As String = "..\..\..\text.docx"
            Dim outFile As String = Path.ChangeExtension(inpFile, ".html")
            Dim rth = New RtfToHtml()
            Dim a = New RtfToHtml.HtmlFixedSaveOptions()
            a.FontsDirectoryPath = Path.GetDirectoryName(outFile) & "\fonts"
            a.ImagesDirectoryPath = Path.GetDirectoryName(outFile) & "\images"
            a.ImageSavingCallback = New SaveImage()
            a.FontSavingCallback = New SaveFont()
            Dim ms = New MemoryStream()
            Dim inp = File.OpenRead(inpFile)
            rth.Convert(inp, ms, a)
            Dim images = (TryCast(a.ImageSavingCallback, SaveImage)).Images
            Dim fonts = (TryCast(a.FontSavingCallback, SaveFont)).Fonts
            ms.Position = 0
            File.WriteAllBytes(outFile, ms.ToArray())
            For Each image In images
                If Not Directory.Exists(a.ImagesDirectoryPath) Then
                    Directory.CreateDirectory(a.ImagesDirectoryPath)
                End If
                File.WriteAllBytes(a.ImagesDirectoryPath & "\" & image.Key & ".png", image.Value)
            Next image
            For Each font In fonts
                If Not Directory.Exists(a.FontsDirectoryPath) Then
                    Directory.CreateDirectory(a.FontsDirectoryPath)
                End If
                File.WriteAllBytes(a.FontsDirectoryPath & "\" & font.Key & ".ttf", font.Value)
            Next font
            System.Diagnostics.Process.Start(New System.Diagnostics.ProcessStartInfo(outFile) With {.UseShellExecute = True})
        End Sub
    End Class
End Namespace

Download


If you need a new code example or have a question: email us at support@sautinsoft.com or ask at Online Chat (right-bottom corner of this page) or use the Form below:


Captcha

Questions and suggestions from you are always welcome!

We are developing .Net components since 2002. We know PDF, DOCX, RTF, HTML, XLSX and Images formats. If you need any assistance with creating, modifying or converting documents in various formats, we can help you. We will write any code example for you absolutely free.