Images
Logos, product photos and signatures in merged documents usually come from the data, not from the template. The template contains a placeholder image with a name; during the merge, MailMerge replaces it with the image data of the same name and keeps its size and position. You create such placeholders, merge image data from JSON and files, handle placeholders without data and change the merged images in code.
Inserting and positioning images in general is described in Images in Document Processing. The examples extend the invoice data of Simple Mail Merge with a logo.
How Image Placeholders Work
An image placeholder is an ordinary image in the template whose name matches a field of the data. During the merge, MailMerge replaces the placeholder with the image from the data:
- Size. The merged image is scaled to the width of the placeholder.
- Layout. The position and the text flow of the placeholder, such as an image anchored at the right of a paragraph, are kept.
- Data. The value of the field can be image data as a byte array or a
System.Drawing.Image, a Base64 string, a hexadecimal string that starts withX', the name of an image file or SVG markup as plain XML text. - Missing data. A placeholder without data stays in the document, unless RemoveEmptyImages is
true.
Images in merge blocks are merged for each record, so a product table can show a photo in every row. The names of placeholders follow the same rules as the names of merge fields, including dot notation for related data. In a merge block, the name starts at the table of the block and can pass through several related tables: in the sample database of TX Text Control Words, a placeholder in the order line block Sales_SalesOrderDetail named Production_Product.Production_ProductProductPhoto.Production_ProductPhoto.ThumbNailPhoto receives the thumbnail photo of the product of each order line. Merge Fields describes the tables of this example.


JSON data carries images as Base64 strings, which makes the data self-contained. Add a Logo property with the Base64 data of a PNG image to the invoice in data.json:
[
{
"InvoiceNumber": "INV-2025-001",
"Logo": "iVBORw0KGgoAAAANSUhEUgAA...",
"Customer": {
"CustomerName": "Acme Corporation"
}
}
]
The value is shortened here; use the complete Base64 string of your image.
Create a Template With an Image Placeholder
In code, a placeholder is an image with a Name. The following program inserts a placeholder image named Logo and saves the template:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
byte[] placeholderData = File.ReadAllBytes("Documents/placeholder.png");
// The stream must be publicly visible for the Image class
using (MemoryStream stream = new MemoryStream(placeholderData, 0, placeholderData.Length, false, true))
{
Image placeholder = new Image(stream);
tx.Images.Add(placeholder, -1);
// The name connects the placeholder with the data
placeholder.Name = "Logo";
}
tx.Selection.Text = "\r\nInvoice ";
tx.Save("image-template.tx", StreamType.InternalUnicodeFormat);
}
The code works as follows:
- The Image constructor with a
MemoryStreamreads the image data, so the template contains the image itself and not a reference to a file. - ImageCollection.Add with
-1inserts the image inline at the input position. - The template is saved in the TX Text Control format, which the samples of Text Control use for image placeholders.
The size you give the placeholder is the width of every image merged into it. Images in Document Processing shows how to anchor the image or place it at a fixed position.
In the Document Editor, a placeholder is created the same way from JavaScript: insert an image and give it a name with setName, as Images in the Document Editor section describes.
Merge Images From Data
The following program merges the invoice data with the logo into the template, removes placeholders without data and sets the alternative text of the merged logo:
using TXTextControl;
using TXTextControl.DocumentServer;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
tx.Load("image-template.tx", StreamType.InternalUnicodeFormat);
using (MailMerge mailMerge = new MailMerge
{
TextComponent = tx,
RemoveEmptyImages = true
})
{
mailMerge.ImageMerged += (sender, e) =>
{
// Alternative text for accessible PDF documents
if (e.Merged && e.Name == "Logo")
{
e.DescriptiveText = "Company logo";
}
};
mailMerge.MergeJsonData(File.ReadAllText("data.json"));
}
tx.Save("invoice-with-logo.pdf", StreamType.AdobePDF);
}
The code works as follows:
RemoveEmptyImagesremoves a placeholder when the data has no image for it. By default, the placeholder image stays in the document.- The ImageMerged event occurs when an image has been merged. Its arguments contain the Name of the image, whether it was Merged and the MergeBlockName of an image in a merge block.
- DescriptiveText replaces the descriptive text of the image, which accessible PDF documents use as alternative text. Image gives access to the merged image: a byte array with the Core engine, a
System.Drawing.Imagewith the Classic engine.
The online demo Merging images merges a Base64 logo into a template in the same way.
Merge Images From Files
When the data contains file names instead of image data, such as "Logo": "logo.png", MailMerge looks for the files in the folder that MailMerge.SearchPath sets. Without a search path, it uses the root directory:
using (MailMerge mailMerge = new MailMerge
{
TextComponent = tx,
// Image files are searched in this folder
SearchPath = Path.Combine(AppContext.BaseDirectory, "Images")
})
{
mailMerge.MergeJsonData(File.ReadAllText("data.json"));
}
Merge SVG Images
Placeholders can also receive SVG images. The SVG markup is the value of the field as plain XML text, not Base64 encoded. In a PDF, SVG images are stored as vector graphics. The blog article Service Pack 3: MailMerge Supports SVG Images shows an example.
Image Merge Fields
Before named placeholders were introduced, images were merged into merge fields whose name starts with image:, such as image:Logo. MailMerge still merges such fields as images, and the ImageFieldMerged event gives access to the merged image as a TXTextControl.Image that your code can replace. Named image placeholders, which came later, also keep the size and layout of the placeholder in the template.
Next Steps
- Barcodes: merge values into barcode placeholders the same way.
- Merge Blocks: repeat images for each record.
- Images in Document Processing: insert and position images in code.
- Data Sources: the data that carries the images.