The PdfDocument class lets you build a PDF from scratch and add content elements through a small object-oriented API.
Images are represented by EvoPdf.NextPdfImageElement. An instance is added to the current page with PdfDocumentAddImage(PdfImageElement). Configure position, sizing, alignment and rotation before the call. The call returns a EvoPdf.NextPdfImageRenderInfo that describes where the image was drawn.
An image element needs either an image file path or raw image bytes. The steps below show how to build one and render it on a PDF page.
A EvoPdf.NextPdfImageElement can be created either from a file path or from raw image bytes. The file path form is the most common.
The element also exposes X and Y properties that position the image relative to the top-left of the page content area. Page margins are excluded from these coordinates. Both default to zero.
PdfImageElement pdfImage = new PdfImageElement(imagePath)
{
X = crtXPos,
Y = crtYPos
};Supported image formats are PNG (including transparency), JPEG and WebP.
The X and Y properties give the location of the image relative to the top-left of the page content area. Page margins do not affect these coordinates.
Specify either Width or Height to scale the image while preserving its aspect ratio. Specify both to force a precise rectangle. The aspect ratio is then lost.
The PdfImageElementScaleDownToFit and PdfImageElementEnlargeToFit properties offer finer control over auto-resize behaviour. They let you cap the image to its natural size while still shrinking it to fit a constrained area.
string imagesPath = GetDemoImagesPath();
// Add a transparent PNG image with a custom width
PdfImageElement pdfPngImage = new PdfImageElement(
Path.Combine(imagesPath, "transparent.png"))
{
X = crtXPos,
Y = crtYPos,
Width = 150
};The PdfImageElementHorizontalAlign and PdfImageElementVerticalAlign properties control where the image sits within the available content area. When set to a value other than None they override the X and Y properties. This is useful when the page geometry can vary because the engine computes the position based on the actual page dimensions.
Render the image on the current page with PdfDocumentAddImage(PdfImageElement). The call returns a EvoPdf.NextPdfImageRenderInfo that carries the actual rendered geometry.
PdfImageRenderInfo imageRenderInfo = pdfDocument.AddImage(pdfPngImage);
// Use the rendered geometry to position the next element
crtYPos = imageRenderInfo.BoundingBox.Bottom + ySeparator;The BoundingBox is the axis-aligned rectangle that contains the rendered image. For rotated images the QuadPoints give the four corners that follow the actual orientation.
Use RotationDegrees together with RotationPivot to rotate the image around one of the standard pivot points (TopLeft, TopCenter, Center and so on). Positive values rotate counter-clockwise. Negative values rotate clockwise.
After rendering the BoundingBox is the tight axis-aligned rectangle that contains the rotated image. The QuadPoints give the four rotated corners. Use the BoundingBox to draw an axis-aligned outline and the QuadPoints to outline the rotated shape exactly.
Transparency is controlled by the Opacity property. The value range is 0 (fully transparent) to 1 (fully opaque). The default is 1.
When the target document standard is PDF/UA-1, PDF/UA-2 or PDF/A-2a, every meaningful image should carry an alternative description. Set Accessibility.AlternateText to a short text that describes the image content. Screen readers announce this text to the user.
Decorative images that carry no semantic content should be tagged with Accessibility.StructureType set to PdfStructureTypeArtifact so they are excluded from the reading order.
using System.IO;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using EvoPdf_Next_AspNetDemo.Models;
using EvoPdf_Next_AspNetDemo.Models.PDF_Creator;
// Use EVO PDF Namespace
using EvoPdf.Next;
namespace EvoPdf_Next_AspNetDemo.Controllers.PDF_Creator
{
public class Create_PDF_Documents_with_ImagesController : Controller
{
private readonly IWebHostEnvironment m_hostingEnvironment;
public Create_PDF_Documents_with_ImagesController(IWebHostEnvironment hostingEnvironment)
{
m_hostingEnvironment = hostingEnvironment;
}
public IActionResult Index()
{
var model = new Create_PDF_Documents_with_Images_ViewModel();
return View(model);
}
[HttpPost]
public ActionResult CreatePdf(Create_PDF_Documents_with_Images_ViewModel model)
{
if (!ModelState.IsValid)
{
var errorMessage = ModelStateHelper.GetModelErrors(ModelState);
throw new ValidationException(errorMessage);
}
// Set the license key received after purchase to use the library in licensed mode; leave it commented for demo mode
// Licensing.LicenseKey = "your-license-key";
PdfDocumentCreateSettings pdfCreateSettings = new PdfDocumentCreateSettings()
{
PageSize = PdfPageSize.A4,
PageOrientation = PdfPageOrientation.Portrait,
Margins = new PdfMargins(36, 36, 36, 36),
PdfStandard = model.PdfStandard,
Language = "en-US"
};
using PdfDocument pdfDocument = new PdfDocument(pdfCreateSettings);
pdfDocument.PdfDocumentInfo.Title = "PDF Image Demo";
string fontsPath = GetDemoFontsPath();
string fontFilePath = Path.Combine(fontsPath, "DejaVuSerif.ttf");
PdfBaseFont baseFont = PdfFontManager.CreateBaseFont(fontFilePath);
PdfFont titleFont = PdfFontManager.CreateFont(baseFont, 18f,
PdfFontStyle.Bold | PdfFontStyle.Underline, PdfColor.Black);
PdfFont sectionFont = PdfFontManager.CreateFont(baseFont, 14f,
PdfFontStyle.Bold, PdfColor.DarkBlue);
PdfFont smallFont = PdfFontManager.CreateFont(baseFont, 9f,
PdfFontStyle.Normal, PdfColor.DarkGray);
const int xLeft = 0;
const int ySeparator = 10;
int crtYPos = 0;
string imagesPath = GetDemoImagesPath();
string transparentPngPath = Path.Combine(imagesPath, "transparent.png");
string jpegPath = Path.Combine(imagesPath, "image.jpg");
// ===== Title =====
PdfTextElement titleElement = new PdfTextElement(
"PDF Image Demo", titleFont)
{
X = xLeft,
Y = crtYPos,
Alignment = PdfTextAlignment.Center,
Width = pdfDocument.ContentWidth
};
titleElement.Accessibility.StructureType = PdfStructureType.Heading1;
crtYPos = (int)pdfDocument.AddText(titleElement).LastPageRectangle.Bounds.Bottom + ySeparator * 2;
// ===== Section 1: PNG with custom width, ScaleDownToFit =====
crtYPos = AddSectionLabel(pdfDocument, sectionFont,
"1. PNG with custom Width (ScaleDownToFit, EnlargeToFit)", xLeft, crtYPos, ySeparator);
PdfImageElement pngImage = new PdfImageElement(transparentPngPath)
{
X = xLeft,
Y = crtYPos,
Width = 150,
ScaleDownToFit = true,
EnlargeToFit = false,
Opacity = 0.85f
};
pngImage.Accessibility.AlternateText = "Transparent glass globe";
PdfImageRenderInfo pngInfo = pdfDocument.AddImage(pngImage);
crtYPos = (int)pngInfo.BoundingBox.Bottom + ySeparator * 2;
// ===== Section 2: JPEG with alignment =====
EnsureSpaceOnPage(ref crtYPos, 220, pdfDocument);
crtYPos = AddSectionLabel(pdfDocument, sectionFont,
"2. JPEG aligned Center horizontally", xLeft, crtYPos, ySeparator);
PdfImageElement jpgCentered = new PdfImageElement(jpegPath)
{
Y = crtYPos,
Height = 120,
HorizontalAlign = PdfElementHorizontalAlign.Center
};
jpgCentered.Accessibility.AlternateText = "Wooden house on a river";
PdfImageRenderInfo jpgInfo = pdfDocument.AddImage(jpgCentered);
crtYPos = (int)jpgInfo.BoundingBox.Bottom + ySeparator * 2;
// ===== Section 3: Rotated image with QuadPoints-based outline =====
EnsureSpaceOnPage(ref crtYPos, 280, pdfDocument);
crtYPos = AddSectionLabel(pdfDocument, sectionFont,
"3. Rotated 30 degrees clockwise - Bounding Box (red) vs Rotated Rectangle (blue)", xLeft, crtYPos, ySeparator);
PdfImageElement rotatedJpg = new PdfImageElement(jpegPath)
{
X = xLeft + 80,
Y = crtYPos + 10,
Width = 200,
Height = 150,
RotationDegrees = -30,
RotationPivot = PdfRotationPivot.TopLeft,
Opacity = 0.95f
};
rotatedJpg.Accessibility.AlternateText = "Wooden house rotated 30 degrees clockwise";
PdfImageRenderInfo rotatedInfo = pdfDocument.AddImage(rotatedJpg);
// Outline the axis-aligned Bounds (red).
var aabb = rotatedInfo.BoundingBox;
pdfDocument.AddRectangle(new PdfRectangleElement(aabb.X, aabb.Y, aabb.Width, aabb.Height)
{
FillColor = null,
BorderColor = PdfColor.Red,
Border = new PdfLineStyle { LineWidth = 1f, DashStyle = PdfLineDashStyle.Dotted }
});
// Outline the rotated QuadPoints (blue) using a polygon through the four corners.
var q = rotatedInfo.QuadPoints;
pdfDocument.AddPolygon(new PdfPolygonElement(q.TopLeft, q.TopRight, q.BottomRight, q.BottomLeft)
{
FillColor = null,
BorderColor = PdfColor.Blue,
Border = new PdfLineStyle { LineWidth = 1.5f }
});
// Annotate with VisibleBounds info using the actual AABB bottom.
string visibleSummary = rotatedInfo.VisibleBounds == null
? "VisibleBounds: image fully outside the page"
: $"VisibleBounds=({rotatedInfo.VisibleBounds.X:F0}, {rotatedInfo.VisibleBounds.Y:F0}, " +
$"{rotatedInfo.VisibleBounds.Width:F0}x{rotatedInfo.VisibleBounds.Height:F0}) on page " +
$"{rotatedInfo.Page} ({rotatedInfo.PageWidth:F0}x{rotatedInfo.PageHeight:F0})";
PdfTextElement visibleLabel = new PdfTextElement(visibleSummary, smallFont)
{
X = xLeft,
Y = (int)aabb.Bottom + ySeparator,
Width = pdfDocument.ContentWidth
};
visibleLabel.Accessibility.StructureType = PdfStructureType.Artifact;
crtYPos = (int)pdfDocument.AddText(visibleLabel).LastPageRectangle.Bounds.Bottom + ySeparator * 2;
// ===== Section 4: Different rotation pivots =====
pdfDocument.AddPage();
crtYPos = 0;
crtYPos = AddSectionLabel(pdfDocument, sectionFont,
"4. Same image rotated 45 degrees around four different pivots", xLeft, crtYPos, ySeparator);
PdfRotationPivot[] pivots = new[]
{
PdfRotationPivot.TopLeft, PdfRotationPivot.TopRight,
PdfRotationPivot.BottomLeft, PdfRotationPivot.Center
};
const int cellW = 220;
const int cellH = 220;
int imgW = 100, imgH = 75;
for (int i = 0; i < pivots.Length; i++)
{
int col = i % 2;
int row = i / 2;
int cellX = xLeft + col * cellW;
int cellY = crtYPos + row * cellH;
// Draw the cell as a dashed reference frame.
pdfDocument.AddRectangle(new PdfRectangleElement(cellX, cellY, cellW - 10, cellH - 10)
{
FillColor = null,
BorderColor = PdfColor.LightGray,
Border = new PdfLineStyle { LineWidth = 0.5f, DashStyle = PdfLineDashStyle.Dashed }
});
// Center the image inside the cell, then rotate by 45 around the chosen pivot.
int imgX = cellX + (cellW - 10 - imgW) / 2;
int imgY = cellY + (cellH - 10 - imgH) / 2 + 10;
PdfImageElement img = new PdfImageElement(jpegPath)
{
X = imgX,
Y = imgY,
Width = imgW,
Height = imgH,
RotationDegrees = 45,
RotationPivot = pivots[i]
};
img.Accessibility.AlternateText = $"Sample image rotated 45 degrees around {pivots[i]}";
PdfImageRenderInfo info = pdfDocument.AddImage(img);
// Trace the rotated quad.
var rq = info.QuadPoints;
pdfDocument.AddPolygon(new PdfPolygonElement(rq.TopLeft, rq.TopRight, rq.BottomRight, rq.BottomLeft)
{
FillColor = null,
BorderColor = PdfColor.Blue,
Border = new PdfLineStyle { LineWidth = 1f }
});
// Label.
PdfTextElement pivotLabel = new PdfTextElement(pivots[i].ToString(), smallFont)
{ X = cellX + 4, Y = cellY + 2, Width = cellW - 14 };
pivotLabel.Accessibility.StructureType = PdfStructureType.Artifact;
pdfDocument.AddText(pivotLabel);
}
byte[] outPdfBuffer = pdfDocument.Save();
FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
fileResult.FileDownloadName = "PdfImageDemo.pdf";
return fileResult;
}
private int AddSectionLabel(PdfDocument doc, PdfFont sectionFont,
string label, int x, int y, int separator)
{
PdfTextElement section = new PdfTextElement(label, sectionFont)
{ X = x, Y = y };
section.Accessibility.StructureType = PdfStructureType.Heading2;
var info = doc.AddText(section);
return (int)info.LastPageRectangle.Bounds.Bottom + separator;
}
private void EnsureSpaceOnPage(ref int crtYPos, int requestedHeight, PdfDocument pdfDocument)
{
if (crtYPos + requestedHeight > pdfDocument.ContentHeight)
{
pdfDocument.AddPage();
crtYPos = 0;
}
}
private string GetDemoFilesPath() => m_hostingEnvironment.ContentRootPath + "/wwwroot" + "/DemoAppFiles/Input/";
private string GetDemoImagesPath() => Path.Combine(GetDemoFilesPath(), "Image_Files");
private string GetDemoFontsPath() => Path.Combine(GetDemoFilesPath(), "Font_Files");
private string GetDemoTextsPath() => Path.Combine(GetDemoFilesPath(), "Text_Files");
}
}