# Images

> Insert PNG, JPG and SVG images with ServerTextControl from files or byte arrays: inline, anchored or fixed, then scale, find, remove, compress and extract them.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Document Processing > Images
- **5882 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/images/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/images/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/images/llms-full.txt

---

Logos, product photos and diagrams reach a document as images. `ServerTextControl` inserts them from files and byte arrays, inline with the text, anchored to a paragraph or at a fixed position on a page. Your code then scales, finds and removes them, decides how they're saved and extracts the images of documents you load.

Templates whose image placeholders are filled from your data are the subject of [Images](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/images/llms-full.txt) in Mail Merge and Reporting. The console programs below read a *logo.png* and a *logo.svg* from the *Documents* folder.

### How Images Are Placed

[ServerTextControl.Images](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/images-property/llms-full.txt) returns the [ImageCollection](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/imagecollection/llms-full.txt) of the main text. Headers, footers and text frames have their own collections, such as [HeaderFooter.Images](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/headerfooter/images-property/llms-full.txt). An image is placed in one of three ways:

| Placement | Behavior | Location measured from |
|---|---|---|
| Inline | Treated like a single character of the text | — |
| Anchored to a paragraph | Moves with its paragraph; the text flows around it or it lies above or below the text | The top-left corner of the paragraph |
| Fixed position | Stays where it is when the text changes | The top-left corner of a page, or of the whole document |

The [Add](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/imagecollection/add-method/llms-full.txt) method you call decides the placement. Locations are measured in twips, 1/1440 inch, and a text position of `-1` stands for the current input position. `Add` without parameters opens a file dialog box and isn't meant for the server.

### Supported Image Formats

The [Image](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/llms-full.txt) class loads the image formats BMP, TIF, WMF, PNG, JPG, GIF, EMF and SVG. When you create an image from a file, the [constructor](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/constructor/llms-full.txt) takes the file name and the index of the import filter:

| Filter index | Format |
|---|---|
| 1 | BMP |
| 2 | TIF |
| 3 | WMF |
| 4 | PNG |
| 5 | JPG, JPEG |
| 6 | GIF |
| 7 | EMF |
| 8 | SVG |

- **SVG** follows SVG 1.1 (Second Edition), without external images or style sheets, interactivity and animation, advanced text transformations, patterns, masking, compositing and filter effects. When a document is saved as PDF, SVG images become vector graphics.
- **EMF** is available in the Core engine since version 34.0, so applications on Linux can use EMF images.

### Insert an Image From a File

The following program writes a line of text and inserts a logo behind it, inline with the text:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Selection.Text = "Invoice INV-2025-001 ";

    // 4 is the import filter for PNG
    Image logo = new Image("Documents/logo.png", 4);

    // -1 inserts the image inline at the current input position
    tx.Images.Add(logo, -1);

    logo.Name = "logo";
    logo.DescriptiveText = "Company logo";

    tx.Save("inline-image.pdf", StreamType.AdobePDF);
}
```

The code works as follows:

- `new Image("Documents/logo.png", 4)` creates the image from the file with the PNG filter. For *logo.svg*, the filter index is 8.
- `tx.Images.Add(logo, -1)` inserts the image inline and returns `true` if it was added.
- [Name](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/name-property/llms-full.txt) gives the image a name your code can find it by later.
- [DescriptiveText](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/descriptivetext-property/llms-full.txt) is the alternative text of the image in accessible PDF documents, described in [PDF/UA](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/pdf-ua/llms-full.txt).

### Insert an Image From a Byte Array

Images from a database, cloud storage or an upload arrive as bytes. Wrap the bytes in a `MemoryStream` and pass it to the `Image` constructor. The buffer of the stream must be publicly visible, which the `Image` class needs to read it, and the image is added while the stream is open:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    byte[] data = File.ReadAllBytes("Documents/logo.png");

    // A read-only stream whose buffer is publicly visible
    using (MemoryStream stream = new MemoryStream(data, 0, data.Length, false, true))
    {
        Image image = new Image(stream);
        bool added = tx.Images.Add(image, -1);

        Console.WriteLine($"Image added: {added}");
    }

    tx.Save("image-from-bytes.docx", StreamType.WordprocessingML);
}
```

The fifth argument of the `MemoryStream` constructor, `publiclyVisible`, is `true`. The stream constructor doesn't need a filter index.

### Position an Image on the Page

The other `Add` overloads anchor an image to a paragraph or place it at a fixed position. Their last parameter is a value of [ImageInsertionMode](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/imageinsertionmode/enumeration/llms-full.txt) that sets how the text flows around the image. `Add` accepts four values:

| Value | The text |
|---|---|
| `DisplaceText` | Flows around the image and fills the space left and right of it |
| `DisplaceCompleteLines` | Stops above the image and continues below it |
| `AboveTheText` | Is covered by the image |
| `BelowTheText` | Covers the image |

An image in a header or a footer that has to stay at the same place on every page takes `FixedOnPage` in addition to its text flow, as `FixedOnPage | BelowTheText` in [Watermarks](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/watermarks/llms-full.txt). The header then keeps its height, whatever the position of the image.

The following program anchors a logo at the right edge of a paragraph and places an SVG image on the first page, 1 inch from its top-left corner, behind the text:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "TX Text Control .NET Server License. Priority Support - 12 Months. " +
              "The text of this paragraph flows around the logo on the right.";

    // Anchored to the paragraph at the input position, aligned right
    Image logo = new Image("Documents/logo.png", 4);
    tx.Images.Add(logo, HorizontalAlignment.Right, -1, ImageInsertionMode.DisplaceText);

    // Fixed on page 1, 1440 twips (1 inch) from the left and top edge of the page
    Image stamp = new Image("Documents/logo.svg", 8);
    tx.Images.Add(stamp, 1, new System.Drawing.Point(1440, 1440), ImageInsertionMode.BelowTheText);

    tx.Save("positioned-images.pdf", StreamType.AdobePDF);
}
```

The code works as follows:

- `Add(image, alignment, textPosition, insertionMode)` anchors the image to the paragraph that contains the text position. The alignment is `Left`, `Right` or `Center`. Another overload takes a `System.Drawing.Point` relative to the paragraph instead.
- `Add(image, pageNumber, location, insertionMode)` places the image on a page, numbered from 1, at a location relative to the top-left corner of the page.
- `Add(image, location, insertionMode)`, without a page number, measures the location from the top-left corner of the whole document. The vertical value includes every page above and the gaps between the pages, starting with the gap above the first page.
- [Location](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/location-property/llms-full.txt) of an image at a fixed position is always relative to the whole document, whichever of the two overloads inserted it. For an anchored image, it's relative to the paragraph, and it's zero for an inline image or an image with a horizontal alignment.
- [Alignment](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/alignment-property/llms-full.txt) applies to anchored images only. Inline images and images at a fixed position have no horizontal alignment.
- [TextDistances](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/textdistances-property/llms-full.txt) sets the distance between the image and the surrounding text, and [ChangeZOrder](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/changezorder-method/llms-full.txt) moves an image in front of or behind other objects.

### Find, Change and Remove Images

The images of a loaded document are in the same collection. The following program prints the name, size and position of each image in the main text of *Documents/sample.docx*, scales all images to half their size and removes the image named "logo":

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/sample.docx", StreamType.WordprocessingML);

    Console.WriteLine($"Images in the main text: {tx.Images.Count}");

    foreach (Image image in tx.Images)
    {
        Console.WriteLine($"'{image.Name}': {image.Size.Width} x {image.Size.Height} twips, text position {image.TextPosition}");

        // Scaling factors in percent
        image.HorizontalScaling = 50;
        image.VerticalScaling = 50;
    }

    // null if no image has this name
    Image logo = tx.Images.GetItem("logo");

    if (logo != null)
    {
        tx.Images.Remove(logo);
    }

    tx.Save("sample-images-changed.docx", StreamType.WordprocessingML);
}
```

The code works as follows:

- [Size](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/size-property/llms-full.txt) returns the size of an image in twips. For images, it's read only: change the size with [HorizontalScaling](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/horizontalscaling-property/llms-full.txt) and [VerticalScaling](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/verticalscaling-property/llms-full.txt), which are percentages.
- [TextPosition](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/textposition-property/llms-full.txt) is the one-based text position of the image.
- [GetItem](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/imagecollection/getitem-method/llms-full.txt) returns the image with a name or an [ID](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebase/id-property/llms-full.txt), or `null` if there is none.
- [Remove](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/imagecollection/remove-method/llms-full.txt) removes an image from the document, and [Clear](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/framebasecollection/clear-method/llms-full.txt) removes all images of the collection.

While a document is loaded, `ServerTextControl` raises the [ImageCreated](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/imagecreated-event/llms-full.txt) event for each image it contains. [ServerTextControl.Frames](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/frames-property/llms-full.txt) contains the images together with the text frames, charts and barcodes of a document, which [Text Frames and Shapes](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/text-frames-shapes/llms-full.txt) and [Charts and Barcodes](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/charts-barcodes/llms-full.txt) describe.

### Add a Logo to a Header

A logo that appears on every page belongs in the header. Add the image to the header's own collection:

```csharp
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();

    tx.Text = "This document has a logo in its header.";

    tx.HeadersAndFooters.Add(HeaderFooterType.Header);
    HeaderFooter header = tx.HeadersAndFooters.GetItem(HeaderFooterType.Header);

    // Anchored at the right edge of the header's first paragraph
    Image logo = new Image("Documents/logo.png", 4);
    header.Images.Add(logo, HorizontalAlignment.Right, 0, ImageInsertionMode.DisplaceText);

    header.Selection.Text = "Invoice INV-2025-001";

    tx.Save("header-logo.pdf", StreamType.AdobePDF);
}
```

[Headers and Footers](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/headers-footers/llms-full.txt) describes headers and footers, and [Watermarks](https://docs.textcontrol.com/tx-text-control-dotnet-server/pdf/watermarks/llms-full.txt) images that lie behind the text of every page.

### Control How Images Are Saved

An image that you add from a file is saved with a reference to that file, its name including the absolute path. Images without a file reference are saved with their data, in their original format. On a server, where the document usually leaves the machine, save the data with the document:

```csharp
SaveSettings saveSettings = new SaveSettings()
{
    // Save the images with their data instead of references to image files
    ImageSaveMode = ImageSaveMode.SaveAsData
};

tx.Save("document.docx", StreamType.WordprocessingML, saveSettings);
```

The [SaveSettings](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/savesettings/llms-full.txt) class has more options for images:

| Property | Sets |
|---|---|
| [ImageSaveMode](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/savesettings/imagesavemode-property/llms-full.txt) | `Auto` (a file reference when one exists, otherwise the data), `SaveAsData` or `SaveAsFileReference`. [Image.SaveMode](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/savemode-property/llms-full.txt) sets it for a single image |
| [ImageSavePath](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/savesettings/imagesavepath-property/llms-full.txt) | The folder in which image files are created when images are saved as file references |
| [ImageExportFilterIndex](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/savesettings/imageexportfilterindex-property/llms-full.txt) | The format images are saved in, with export filter indexes that differ from the import filters: 1 BMP, 2 WMF, 3 PNG, 4 JPG, 5 EMF, 6 TIF and 7 GIF; 0 keeps the original format |
| [ImageCompressionQuality](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/savesettings/imagecompressionquality-property/llms-full.txt) | The quality of lossy compression, from 1 to 100 |
| [ImageMaxResolution](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/savesettings/imagemaxresolution-property/llms-full.txt) | The maximum resolution in DPI; larger images are reduced |

[Image.ExportFilterIndex](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/exportfilterindex-property/llms-full.txt) sets the format of a single image with the same export filter indexes. A value of 0 keeps the format the image was loaded in, which [Image.FilterIndex](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/filterindex-property/llms-full.txt) returns. [ImageCollection.ExportFilters](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/imagecollection/exportfilters-property/llms-full.txt) lists the export filters as a string, in the order of their numbers.

#### Image Formats per Document Format

Not every document format can hold every image format. When the format you request isn't possible in the format of the document, the image is saved in the default image format of that document format, the first one in each row:

| Document format | Image formats, default first |
|---|---|
| RTF | PNG, BMP, WMF, JPG, EMF |
| DOC | WMF, BMP, PNG, JPG, EMF, TIF |
| DOCX | PNG, BMP, WMF, JPG, EMF, TIF, GIF, SVG |
| HTML | PNG, BMP, JPG, GIF |
| PDF | BMP, JPG; the vector formats EMF, WMF and SVG are written as vector graphics |
| TX Text Control format | WMF, BMP, PNG, JPG, EMF, TIF, GIF, SVG |

#### File Names of Saved Images

Images saved as file references in another format than their original one are written to new image files. Their folder and names follow these rules:

- **Folder.** The folder is `ImageSavePath`. Without it, the image files go to a subfolder of the document's folder, named after the document with `_Images` appended: for *C:\\Documents\\sample.rtf*, this is *C:\\Documents\\sample\_Images*.
- **File name.** [Image.ExportFileName](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/image/exportfilename-property/llms-full.txt) sets the file name of an image. Without it, the original file name is used, with the extension of the export format.
- **Numbered names.** An image without a file name gets the name of the document followed by an underscore and a number: *sample\_1.bmp*, *sample\_2.bmp* and so on for images saved as BMP.

With `ImageSaveMode.SaveAsFileReference`, an image that has no file yet is written to a new file by these rules.

When you load a document whose images are file references, [LoadSettings.ImageSearchPath](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/loadsettings/imagesearchpath-property/llms-full.txt) sets a folder that replaces their absolute paths. An image that isn't found is shown as a rectangle with its file name.

For PDF files, the blog article [Best Practices for Image Compression when Exporting to PDF in .NET C#](https://www.textcontrol.com/blog/2025/08/22/best-practices-for-image-compression-when-exporting-to-pdf-in-dotnet-csharp/) compares compression qualities and resolutions.

### Extract the Images of a Document

There is no method that saves a single image to a file. To get the images of a document, save it as HTML with the image data embedded and decode the `data:` URLs of its `img` elements:

```csharp
using System.Text.RegularExpressions;
using TXTextControl;

using (ServerTextControl tx = new ServerTextControl())
{
    tx.Create();
    tx.Load("Documents/sample.docx", StreamType.WordprocessingML);

    // Embed the images as Base64 data in the HTML
    SaveSettings saveSettings = new SaveSettings()
    {
        ImageSaveMode = ImageSaveMode.SaveAsData
    };

    string html;
    tx.Save(out html, StringStreamType.HTMLFormat, saveSettings);

    Regex imageData = new Regex(
        "<img[^>]+?src=[\"']data:image/(?<format>[^;]+);base64,(?<data>[^\"']+)[\"']",
        RegexOptions.IgnoreCase);

    Directory.CreateDirectory("Images");
    int number = 0;

    foreach (Match match in imageData.Matches(html))
    {
        string extension = match.Groups["format"].Value.ToLowerInvariant() switch
        {
            "jpeg" => ".jpg",
            "svg+xml" => ".svg",
            string format => "." + format
        };

        number++;
        byte[] bytes = Convert.FromBase64String(match.Groups["data"].Value);
        File.WriteAllBytes(Path.Combine("Images", $"image{number}{extension}"), bytes);
    }

    Console.WriteLine($"Images extracted: {number}");
}
```

The blog article [Extracting Images from MS Word Documents in C#](https://www.textcontrol.com/blog/2024/06/11/extracting-images-from-ms-word-documents-in-csharp/) describes this approach for DOCX, DOC, RTF and PDF documents.

### Next Steps

- [Images](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/images/llms-full.txt) in Mail Merge and Reporting: fill image placeholders of a template with data.
- [Headers and Footers](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/headers-footers/llms-full.txt): repeat images and text on every page.
- [Saving and Converting Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/saving-converting/llms-full.txt): save documents with their images in other formats.
- [Images](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/images/llms-full.txt) in the Document Editor: insert and change images from JavaScript.

---

## Nearby

- **Previous:** [Tables](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/tables/llms-full.txt)
- **Next:** [Text Frames and Shapes](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/text-frames-shapes/llms-full.txt)
