OfficeIMO.Pdf
3.0.0
Prefix Reserved
See the version list below for details.
dotnet add package OfficeIMO.Pdf --version 3.0.0
NuGet\Install-Package OfficeIMO.Pdf -Version 3.0.0
<PackageReference Include="OfficeIMO.Pdf" Version="3.0.0" />
<PackageVersion Include="OfficeIMO.Pdf" Version="3.0.0" />
<PackageReference Include="OfficeIMO.Pdf" />
paket add OfficeIMO.Pdf --version 3.0.0
#r "nuget: OfficeIMO.Pdf, 3.0.0"
#:package OfficeIMO.Pdf@3.0.0
#addin nuget:?package=OfficeIMO.Pdf&version=3.0.0
#tool nuget:?package=OfficeIMO.Pdf&version=3.0.0
OfficeIMO.Pdf - First-party PDF engine
OfficeIMO.Pdf is the first-party PDF package for OfficeIMO. It creates, reads, inspects, edits, merges, splits, stamps, exports, signs, and validates PDFs. PDF mechanics and rendering remain first-party; CMS, RFC 3161, and X.509 operations route through the neutral OfficeIMO.Security package.
If OfficeIMO saves you time, please consider supporting the work through GitHub Sponsors or PayPal. PowerShell users should use PSWriteOffice for the PowerShell-facing experience.
Install
dotnet add package OfficeIMO.Pdf
Quick start
using OfficeIMO.Pdf;
PdfDocument.Create(new PdfOptions {
DefaultFont = PdfStandardFont.Helvetica,
DefaultFontSize = 11
})
.Meta(title: "Hello PDF", author: "OfficeIMO")
.H1("OfficeIMO.Pdf")
.Paragraph(p => p
.Text("A first-party PDF builder with ")
.Bold("rich text")
.Text(", links, tables, images, and document operations."))
.Table(new[] {
new[] { "Area", "Status" },
new[] { "Security engine", "OfficeIMO.Security" },
new[] { "License", "MIT" }
})
.Save("hello.pdf");
What it does
- Creates PDFs with page setup, headings, paragraphs, rich text, links, lists, mixed inline images and boxes, dictionary-driven hyphenation, styled multipage containers, balanced block-flow columns, conditional/replayable flow, position capture, sections, generated TOCs, optional-content layers, tables, images, vector drawing, headers, footers, watermarks, metadata, portfolios, and form primitives.
- Reads and inspects PDFs through text extraction, logical document objects, page metadata, links, images, attachments, portfolios, outlines, forms, bounded immutable raw-structure views, active-content diagnostics, and security/revision markers.
- Manipulates existing PDFs with page extraction, split, merge, delete, duplicate, move, rotate, metadata editing, stamps, watermarks, and complete-page overlay/underlay while preserving source PDF header versions on shared rewrite paths.
- Renders supported embedded TrueType and OpenType/CFF fonts with stable-glyph subsetting. Built-in shaping remains dependency-free, while the shared
OfficeIMO.Drawing.IOfficeTextShapingProvidercontract can supply positioned glyph advances and offsets for scripts that need a host-owned shaping engine. - Shares managed CMYK, Lab, XYZ, calibrated-color conversion, vector tiling fills, standard blend modes, and alpha/luminosity soft masks with
OfficeIMO.Drawing. - Bounds completed page/effect content and serialized-object retention with separate memory limits, temporary-file spillover, direct large-stream spooling, and chunked final assembly during stream saves. Per-page metadata and the authored block model remain proportional to document size, and
ToBytes()buffers the final artifact. - Provides conversion reports, grouped warning summaries, and diagnostics so adapters can expose unsupported or simplified source content honestly.
- Provides reusable conversion proof snapshots for generated PDFs, artifact hashes, required page counts, page sizes, document metadata, outline titles, URI links, form fields, named destinations, page labels, attachments, output intents, optional-content/layer metadata, catalog/viewer metadata, XMP/tagged metadata, text markers, logical readback signals, expected and accepted warning contracts, and post-processing hand-off. Compliance proof records bind external validator name, version, profile, result, warnings, SHA-256, byte length, and validation time to the exact artifact.
- Provides reusable rewrite-preservation proof for page geometry, metadata, navigation, catalog/viewer/action state, optional content, tagged content, security signatures, document versions, and source-structure markers such as incremental updates, xref streams, and object streams.
- Provides a reusable rewrite-preservation matrix for classifying named manipulation scenarios as rewrite-safe, preservation-failed, blocked by safety checks, or operation-failed, including optional-content/layer drift, targeted form-fill preservation, form/tagged/active-content/signature blockers, and fluent
PdfDocumenthelpers for normal document rewrite operations. - Serves as the shared engine for Word, Excel, PowerPoint, Markdown, HTML, RTF, OneNote, AsciiDoc, and LaTeX PDF adapters.
Existing PDF workflows
using OfficeIMO.Pdf;
PdfDocument.Open("input.pdf")
.Pages.Extract("1-2,4")
.MergeWith("appendix.pdf")
.UpdateMetadata(title: "Merged report")
.Stamp.Text("Reviewed")
.Save("output.pdf");
string text = PdfDocument.Open("output.pdf").Read.Text();
Open(...) is the one entry point for byte arrays, files, and streams. It
enforces the same PdfReadOptions limits before buffering, snapshots caller
input once, and reuses one parsed document across read, inspection, preflight,
diagnostic, optimization, signature, and compliance operations.
For a single health and capability view:
PdfAnalysisReport analysis = PdfDocument
.Open("incoming.pdf")
.Analyze(PdfComplianceProfile.PdfA2B);
Console.WriteLine($"Pages: {analysis.Info.PageCount}");
Console.WriteLine($"Readable: {analysis.CanRead}");
Console.WriteLine($"Rewrite safe: {analysis.CanRewrite}");
Console.WriteLine($"Healthy: {analysis.IsHealthy}");
foreach (PdfDiagnosticFinding finding in analysis.Diagnostics.Findings) {
Console.WriteLine($"{finding.Severity}: {finding.Code} — {finding.Message}");
}
Migrating to the unified API
The unified API intentionally narrows the public surface around the fluent
PdfDocument facade:
- Replace
PdfDocument.Load(...)andPdfReadDocument.Load(...)withPdfDocument.Open(...)orPdfReadDocument.Open(...). - Seekable PDF input streams are now consistently read from the beginning and restored to their original position. Non-seekable streams are read forward from their current position.
- Keep one opened
PdfDocumentand reuse it forRead,Inspect,Preflight,Analyze, compliance, and manipulation work. The source snapshot and canonical parse are cached for that document. - Use
PdfDocument.Analyze(...)when a workflow needs the combined health, rewrite-safety, diagnostics, optimization, signature, repair, and compliance view. - Use
CreateComplianceArtifact(...)instead of separately rendering bytes and passing them back toAssessComplianceProof(...). The returned immutable snapshot keeps exact output bytes and matching readiness evidence together, including for randomized encrypted output. - Use the fluent
Pages,Forms,Attachments,Bookmarks,Annotations,Stamp,Security, and metadata operations instead of the former public static engine classes. Those implementation engines are now internal so there is one supported route for each operation. Save(...),SaveAsync(...), and every typed adapterSaveAsPdf(...)now returnPdfSaveResult. It carries output path/length, conversion warnings, and an immutablePipelinewith create/open, mutation, hash, page-count, execution-mode, timing, and final-output evidence.TrySave(...)keeps the same result shape while capturing exceptions instead of throwing.
The target-framework support remains netstandard2.0, net8.0, and
net10.0; the API cleanup itself is a deliberate source-breaking change.
Examples
Export PDF pages as images
using OfficeIMO.Drawing;
using OfficeIMO.Pdf;
PdfReadDocument pdf = PdfReadDocument.Open("input.pdf");
pdf.Pages[0]
.ToImage()
.AtDpi(144)
.AsThumbnail(800)
.AsPng()
.Save("preview.png");
pdf.ToImages()
.Pages("1-3,last")
.WithMaximumRasterPixels(20_000_000)
.AsWebp()
.Save("page-images");
PNG, JPEG, TIFF, SVG, and WebP use the same OfficeImageExportResult contract and Drawing-owned encoders. Allocation limits are resolved before a raster buffer is created. Unsupported or simplified PDF operators and resources remain visible as typed image diagnostics.
Any adapter that returns PdfDocumentConversionResult can use the same paged-image bridge without adding another renderer:
IReadOnlyList<OfficeImageExportResult> pages = markdown
.ToPdfDocumentResult()
.ToImages()
.AsPng()
.Export();
Source conversion warnings are copied into every page result. Use PdfReadPage.ToDrawing() only when an intermediate OfficeDrawing is needed.
Write a generated PDF
using OfficeIMO.Pdf;
PdfDocument.Create(new PdfOptions {
PageSize = PageSizes.A4,
Margins = PageMargins.UniformCentimeters(1.6),
DefaultFont = PdfStandardFont.Helvetica,
DefaultFontSize = 10
})
.Meta(
title: "Service report",
author: "OfficeIMO",
subject: "Generated PDF")
.Header(h => h.AlignCenter().Text("Service report"))
.Footer(f => f.AlignRight().Text("Page {page} of {pages}"))
.H1("Service report")
.Paragraph(p => p
.Text("Generated ")
.Bold(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm 'UTC'"))
.Text(" with first-party PDF primitives."))
.Table(new[] {
new[] { "System", "Status", "Owner" },
new[] { "Identity", "Green", "Operations" },
new[] { "Messaging", "Yellow", "Exchange" }
})
.Save("service-report.pdf");
Rich report layout
PdfDocument.Create()
.H1("Operational summary")
.Paragraph(p => p
.Text("Generated ")
.Bold(DateTime.Today.ToString("yyyy-MM-dd"))
.Text(" with links, lists, panels, and tables."))
.Bullets(list => list
.Item("No runtime package dependencies")
.Item("Word-like document flow")
.Item("Reusable PDF primitives for adapters"))
.Panel(panel => panel
.H2("Review note")
.Paragraph(p => p.Text("Keep polished report designs in samples; keep reusable primitives in the engine.")))
.Table(new[] {
new[] { "Area", "Status" },
new[] { "Layout", "Ready" },
new[] { "Reading", "Evolving" }
})
.Save("summary.pdf");
Hyphenation and inline visuals
byte[] statusIcon = File.ReadAllBytes("status.png");
var hyphenation = new PdfHyphenationLexicon(new[] {
"auto-ma-tion",
"ty-pog-ra-phy",
"re-port-ing"
});
PdfDocument.Create(new PdfOptions()
.UseTextHyphenationDictionary(hyphenation))
.Paragraph(paragraph => paragraph
.Text("Automation status ")
.InlineImage(statusIcon, 12, 12, alternativeText: "Healthy")
.Text(" remains available during long reporting runs."))
.Save("inline-status.pdf");
Inline elements participate in normal line wrapping. In tagged output, image and box alternative text is carried into the structure tree.
Sections, generated navigation, and bounded stream output
var options = new PdfOptions {
PageContentMemoryLimitBytes = 4 * 1024 * 1024,
ObjectBufferMemoryLimitBytes = 8 * 1024 * 1024
};
PdfDocument.Create(options)
.TableOfContents()
.Section("Summary", section => section
.Container(content => content
.Paragraph(p => p.Text("A styled, keep-together summary."))))
.Section("Details", section => section
.Columns(columns => {
columns.Paragraph(p => p.Text("First column"));
columns.ColumnBreak();
columns.Paragraph(p => p.Text("Second column"));
}, new PdfMultiColumnOptions { ColumnCount = 2, Gap = 18 }))
.Save("navigable-report.pdf");
Read text, Markdown, tables, images, and attachments
using OfficeIMO.Pdf;
PdfDocument pdf = PdfDocument.Open("statement.pdf");
string text = pdf.Read.Text();
string firstPages = pdf.Read.Text("1-2");
PdfOperationResult<string> safeFirstPages = pdf.Read.TryText("1-2");
string markdown = pdf.Read.Markdown();
IReadOnlyList<string> pages = pdf.Read.TextByPage();
PdfLogicalDocument logical = pdf.Read.Logical();
PdfMetadata metadata = pdf.Read.Metadata();
PdfDocumentSecurityInfo security = pdf.Read.Security();
IReadOnlyList<PdfPageInfo> pageInfo = pdf.Read.Pages();
PdfXmpMetadataInfo? xmp = pdf.Read.XmpMetadata();
IReadOnlyList<PdfOutputIntentInfo> outputIntents = pdf.Read.OutputIntents();
PdfTaggedContentInfo? taggedContent = pdf.Read.TaggedContent();
PdfOptionalContentProperties? optionalContent = pdf.Read.OptionalContent();
PdfOperationResult<PdfDocumentInfo> safeInfo = pdf.Read.TryDocumentInfo();
foreach (var table in logical.Tables) {
Console.WriteLine($"Table on page {table.PageNumber}: {table.Rows.Count} rows");
}
string markdownTables = PdfLogicalTableTextExportExtensions.ExtractMarkdownTables("statement.pdf");
IReadOnlyList<PdfExtractedImage> images = pdf.Read.Images();
IReadOnlyList<PdfExtractedImage> firstPageImages = pdf.Read.Images("1");
PdfOperationResult<IReadOnlyList<PdfExtractedImage>> safeImages = pdf.Read.TryImages("1-2");
IReadOnlyList<PdfImagePlacement> imageGeometry = pdf.Read.ImagePlacements("1-2");
IReadOnlyList<PdfOutlineItem> outlines = pdf.Read.Outlines();
IReadOnlyList<PdfLogicalLinkAnnotation> links = pdf.Read.Links();
IReadOnlyList<PdfLogicalLinkAnnotation> supportLinks = pdf.Read.LinksByUri("https://example.com/support");
PdfOperationResult<IReadOnlyList<PdfNamedDestination>> safeDestinations = pdf.Read.TryNamedDestinations();
IReadOnlyList<PdfAnnotation> annotations = pdf.Read.Annotations();
IReadOnlyList<PdfAnnotation> freeTextNotes = pdf.Read.AnnotationsBySubtype("FreeText");
PdfOperationResult<IReadOnlyList<PdfAnnotation>> safeAnnotations = pdf.Read.TryAnnotations();
IReadOnlyList<PdfCatalogAction> catalogActions = pdf.Read.CatalogActions();
IReadOnlyList<PdfPageAction> pageActions = pdf.Read.PageActions();
PdfOperationResult<IReadOnlyList<PdfPageAction>> safePageActions = pdf.Read.TryPageActions();
IReadOnlyList<PdfFormField> formFields = pdf.Read.FormFields();
IReadOnlyList<PdfLogicalFormWidget> formWidgets = pdf.Read.FormWidgets("Person.Name");
PdfOperationResult<IReadOnlyList<PdfFormField>> safeFormFields = pdf.Read.TryFormFields();
IReadOnlyList<PdfAttachmentInfo> attachmentMetadata = pdf.Read.AttachmentMetadata();
IReadOnlyList<PdfExtractedAttachment> attachments = pdf.Read.Attachments();
PdfOperationResult<IReadOnlyList<PdfExtractedAttachment>> safeAttachments = pdf.Read.TryAttachments();
Split and extract pages
using OfficeIMO.Pdf;
PdfDocument source = PdfDocument.Open("packet.pdf");
source.Pages.Extract("1-3")
.Save("cover-and-summary.pdf");
IReadOnlyList<PdfDocument> singlePageDocuments = source.Pages.Split();
for (int index = 0; index < singlePageDocuments.Count; index++) {
singlePageDocuments[index].Save($"packet-page-{index + 1:000}.pdf");
}
IReadOnlyList<PdfDocument> selectedRanges = source.Pages.Split("1-2,5-6");
selectedRanges[0].Save("packet-front.pdf");
selectedRanges[1].Save("packet-evidence.pdf");
Merge, reorder, delete, duplicate, move, and rotate
using OfficeIMO.Pdf;
PdfDocument.Open("packet.pdf")
.MergeWith("appendix.pdf")
.Pages.Delete("2,5-6")
.Pages.Duplicate("1")
.Pages.Move(insertBeforePageNumber: 3, pageRanges: "7-8")
.Pages.Rotate(90, "4")
.UpdateMetadata(title: "Cleaned packet")
.Save("packet-clean.pdf");
Stamp and watermark an existing PDF
using OfficeIMO.Pdf;
PdfDocument.Open("contract.pdf")
.Stamp.Text("Reviewed", new PdfTextStampOptions {
X = 72,
Y = 720,
FontSize = 18,
Color = PdfColor.FromRgb(180, 30, 30)
})
.Stamp.TextWatermark("CONFIDENTIAL", new PdfTextStampOptions {
FontSize = 54,
Color = PdfColor.Gray,
RotationDegrees = -35
})
.Save("contract-reviewed.pdf");
Import a complete source page above or below selected target pages without rasterizing it:
PdfDocument.Open("contract.pdf")
.Stamp.OverlayPage("letterhead.pdf", new PdfPageOverlayOptions {
SourcePageNumber = 1,
TargetPages = PdfPageSelector.Parse("all,!last"),
Fit = PdfPageOverlayFit.Contain,
Opacity = 0.9
})
.Save("contract-with-letterhead.pdf");
Fill and flatten a PDF form
using OfficeIMO.Pdf;
PdfDocument.Open("application-form.pdf")
.Forms.FillAndFlatten(new Dictionary<string, string> {
["Applicant.Name"] = "Adele Vance",
["Applicant.Email"] = "adele@example.com",
["Approval.Status"] = "Approved"
})
.Save("application-form-filled.pdf");
Generate and assess validator-backed PDF/A
using OfficeIMO.Pdf;
byte[] fontBytes = File.ReadAllBytes("SourceSerif4-Regular.otf");
var options = new PdfOptions()
.UsePdfA(PdfComplianceProfile.PdfA2B)
.EmbedStandardFont(PdfStandardFont.Helvetica, fontBytes, "Source Serif 4")
.RequireCompliance(PdfComplianceProfile.PdfA2B);
PdfComplianceArtifact artifact = PdfDocument.Create(options)
.Meta(title: "Archive copy")
.Paragraph(paragraph => paragraph.Text("This artifact is ready for external validation."))
.CreateComplianceArtifact(PdfComplianceProfile.PdfA2B);
byte[] pdf = artifact.ToBytes();
File.WriteAllBytes("archive.pdf", pdf);
// Create this result from the validator invocation in your build or release lane.
PdfExternalValidationResult validation = PdfExternalValidationResult.PassedForArtifact(
PdfExternalValidatorKind.VeraPdf,
"veraPDF",
"1.30.2",
"PDF/A-2b validation passed.",
pdf,
"PDF/A-2b");
PdfComplianceProofReport proof = artifact.AssessProof(new[] { validation });
if (!proof.CanClaimConformance) {
throw new InvalidOperationException(proof.ExternalProofSummary);
}
Formal generation gates are available for PDF/A-2b, PDF/A-3b, PDF/UA-1, Factur-X, and ZUGFeRD. RequireCompliance(...) rejects incomplete generation settings. A conformance claim still requires a passing external result for the same profile, SHA-256, and byte length; validators are build-time tools and are not runtime dependencies of OfficeIMO.Pdf.
Choose converter-friendly text fallbacks
using OfficeIMO.Pdf;
using OfficeIMO.Word;
using OfficeIMO.Word.Pdf;
using var document = WordDocument.Load("proposal.docx");
var options = new PdfSaveOptions {
TextFallbacks = PdfTextFallbackFeatures.Default,
ResourcePolicy = PdfResourcePolicy.CreateTrustedHost()
}.UseProfile(PdfExportProfile.PrintReady);
var result = document.ToPdfDocumentResult(options);
result.Report.RequireNoErrorWarnings();
result.Save("proposal.pdf");
The Word, Excel, PowerPoint, Markdown, HTML, RTF, OneNote, AsciiDoc, and LaTeX PDF adapters use one PdfResourcePolicy; semantic-projection adapters expose it through their nested Markdown PDF options. The balanced default enables installed fonts and bounded data URI/package resources for document fidelity while denying arbitrary local files and remote resolver calls. Use PdfResourcePolicy.CreatePortableDeterministic() for reproducible or untrusted conversion, and CreateTrustedHost() only when both source and host are trusted. Profiles never grant resource access.
The text-capable adapters also expose TextFallbacks. PdfTextFallbackFeatures.Default enables document, monospace, symbol, and emoji groups. Add PdfTextFallbackFeatures.MultilingualFonts for CJK, Arabic, and other non-Latin family candidates; OneNote adds that candidate group unless fallbacks are None. Candidate selection does not read installed fonts unless the resource policy allows it.
Generate a formal e-invoice carrier
using OfficeIMO.Pdf;
byte[] invoiceXml = File.ReadAllBytes("factur-x.xml");
byte[] fontBytes = File.ReadAllBytes("SourceSerif4-Regular.otf");
PdfDocument.Create(new PdfOptions()
.UseFacturX(
invoiceXml,
relationship: PdfAssociatedFileRelationship.Alternative,
textFallbacks: PdfTextFallbackFeatures.None)
.EmbedStandardFont(PdfStandardFont.Helvetica, fontBytes, "Source Serif 4")
.RequireCompliance(PdfComplianceProfile.FacturX))
.Paragraph("Invoice preview")
.Save("invoice.pdf");
The XML must be a valid EN 16931 CrossIndustryInvoice payload. The formal carrier gate checks the PDF/A-3 attachment, metadata, font, Unicode, and invoice rules before writing; exact-artifact PDF/A and invoice-validator results are still required before claiming conformance.
Page setup, watermarks, and metadata
PdfDocument.Create(new PdfOptions {
PageSize = PageSize.FromCentimeters(21, 29.7).Portrait(),
Margins = PageMargins.UniformCentimeters(1.5),
TextWatermark = new PdfTextWatermark("DRAFT") {
Opacity = 0.12,
RotationAngle = -35
}
})
.Meta(title: "Draft report", author: "OfficeIMO")
.H1("Draft report")
.Paragraph("This document uses page-level options instead of post-processing.")
.Save("draft.pdf");
Inspect and preflight before rewriting
using OfficeIMO.Pdf;
byte[] bytes = File.ReadAllBytes("incoming.pdf");
PdfDocument pdf = PdfDocument.Open(bytes);
PdfDocumentPreflight preflight = pdf.Preflight();
if (!preflight.Can(PdfPreflightCapability.ManipulatePages)) {
foreach (string diagnostic in preflight.GetCapabilityDiagnostics(PdfPreflightCapability.ManipulatePages)) {
Console.WriteLine(diagnostic);
}
}
var result = pdf.Pages.TryExtract("1-2");
if (result.Succeeded) {
result.RequireValue().Save("incoming-first-pages.pdf");
}
Inspect before automating
PdfDocument pdf = PdfDocument.Open("incoming.pdf");
var inspection = pdf.Inspect();
Console.WriteLine($"Pages: {inspection.PageCount}");
Console.WriteLine($"Links: {inspection.LinkAnnotationCount}");
Console.WriteLine($"Forms: {inspection.FormFields.Count}");
Console.WriteLine($"Active content: {inspection.HasActiveContent}");
foreach (var page in inspection.Pages) {
Console.WriteLine($"{page.PageNumber}: {page.Width} x {page.Height}");
}
Convert PDFs through adapter packages
using OfficeIMO.Excel.Pdf;
using OfficeIMO.Html.Pdf;
using OfficeIMO.Pdf;
using OfficeIMO.Word;
using OfficeIMO.Word.Pdf;
using var word = WordDocument.Load("proposal.docx");
word.SaveAsPdf("proposal.pdf");
PdfLogicalDocument statement = PdfLogicalDocument.Load("bank-statement.pdf");
PdfExcelTableImportReport tableReport = statement.SaveTablesAsExcel(
"bank-statement-tables.xlsx");
Console.WriteLine($"Non-table page content detected: {tableReport.HasOmittedPageContent}");
PdfHtmlConverterExtensions.SaveAsHtml(
"proposal.pdf",
"proposal-review.html",
new PdfHtmlSaveOptions {
Profile = PdfHtmlProfile.PositionedReview,
IncludeLinkAnnotations = true,
IncludeFormWidgets = true
});
Conversion adapters
| Package | Role |
|---|---|
| OfficeIMO.Word.Pdf | Maps Word documents into PDF primitives. |
| OfficeIMO.Excel.Pdf | Maps Excel workbooks into PDF primitives. |
| OfficeIMO.Markdown.Pdf | Maps Markdown documents into PDF primitives. |
| OfficeIMO.PowerPoint.Pdf | Maps PowerPoint slides into PDF primitives. |
| OfficeIMO.Html.Pdf | Bridges HTML to PDF and PDF to HTML. |
| OfficeIMO.Rtf.Pdf | Maps semantic RTF into PDF and logical PDF content back to RTF. |
| OfficeIMO.OneNote.Pdf | Explicitly projects offline OneNote hierarchy into a semantic PDF document with loss diagnostics. |
| OfficeIMO.AsciiDoc.Pdf | Projects native AsciiDoc through the loss-aware Markdown bridge and combines parser, projection, and PDF diagnostics. |
| OfficeIMO.Latex.Pdf | Projects the bounded LaTeX profile through the loss-aware Markdown bridge without executing TeX. |
The canonical catalog records OpenDocument as manual loss-aware composition and formats that are intentionally not advertised as direct conversion yet: email, EPUB, and Visio. See Docs/pdf-conversion-scenarios.json.
Boundaries
- PDF parsing, layout, writing, and rendering stay first-party. CMS/DER/X.509 belongs in
OfficeIMO.Security; rasterizers, visual comparison tools, and external renderers remain test or development tooling. - Polished invoice, report, and statement examples belong in samples and visual fixtures, not as special engine concepts.
- Adapter-specific mapping belongs in the source adapter packages. Shared PDF layout, reading, and manipulation behavior belongs here.
- Current-state inventories belong in Docs/officeimo.pdf.current-state.md, not in this NuGet README.
Repository validation
The repository keeps the public contract, target frameworks, package dependency shape, performance budgets, compliance proof, and rendered output under separate gates:
dotnet test OfficeIMO.Pdf.Tests/OfficeIMO.Pdf.Tests.csproj -c Release -f net8.0
dotnet test OfficeIMO.Pdf.Tests/OfficeIMO.Pdf.Tests.csproj -c Release -f net10.0
dotnet run --project OfficeIMO.Pdf.Benchmarks/OfficeIMO.Pdf.Benchmarks.csproj -c Release -f net8.0 -- --verify-budgets
dotnet run --project OfficeIMO.Pdf.Benchmarks/OfficeIMO.Pdf.Benchmarks.csproj -c Release -f net10.0 -- --verify-budgets
Build/Export-PdfComplianceProof.ps1 -Configuration Release -Framework net8.0
Build/Export-PdfVisualReviewGallery.ps1 -Configuration Release -Framework net8.0
The checked-in interoperability gate uses hash-pinned Open Preservation Foundation and veraPDF fixtures with explicit provenance. The performance gate uses a deterministic 60-page mixed corpus and checks cold and cached analysis, SVG rendering, PNG rendering, output integrity, and allocation/time budgets.
Pixel baselines are strict when the installed Poppler major/minor version matches the recorded renderer. A different renderer version still runs semantic and page-count checks in ordinary local runs. Required-rasterizer and CI visual gates fail on a version mismatch; release investigations can deliberately opt into a cross-version comparison.
Current state
The PDF engine is useful and broad, but it is still evolving. It has strong first-party coverage for common generated business documents, reusable Unicode line breaking and Latin ligatures, host-provided complex-script shaping, conservative read/manipulation workflows, password security, shared Security-backed certificate signing/validation, standards-compliant Fast Web View output, and bounded-payload stream saves. Built-in full complex-script shaping, difficult producer-specific preservation, broader transparency/pattern edge cases, and fully forward-only layout remain deeper roadmap areas.
For the full capability inventory and roadmap, read Docs/officeimo.pdf.current-state.md.
Targets and license
- Targets:
netstandard2.0,net8.0,net10.0. - License: MIT.
- Repository: EvotecIT/OfficeIMO
Dependency footprint
- External:
BouncyCastle.Cryptography, owned and hidden behindOfficeIMO.Security; no third-party PDF parser, writer, or renderer. - OfficeIMO:
OfficeIMO.DrawingandOfficeIMO.Security. PDF parsing, writing, logical recovery, manipulation, forms, diagnostics, and preservation analysis are first-party.
See the complete OfficeIMO package map for related formats and conversion paths.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 is compatible. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- OfficeIMO.Drawing (>= 3.0.0)
- OfficeIMO.Security (>= 3.0.0)
-
.NETStandard 2.0
- OfficeIMO.Drawing (>= 3.0.0)
- OfficeIMO.Security (>= 3.0.0)
-
net10.0
- OfficeIMO.Drawing (>= 3.0.0)
- OfficeIMO.Security (>= 3.0.0)
-
net8.0
- OfficeIMO.Drawing (>= 3.0.0)
- OfficeIMO.Security (>= 3.0.0)
NuGet packages (9)
Showing the top 5 NuGet packages that depend on OfficeIMO.Pdf:
| Package | Downloads |
|---|---|
|
OfficeIMO.Reader
Unified, read-only document extraction facade for OfficeIMO (Word/Excel/PowerPoint/Markdown/PDF) intended for AI ingestion. |
|
|
OfficeIMO.Word.Pdf
PDF converter for OfficeIMO.Word - Export Word documents to PDF using the first-party OfficeIMO.Pdf engine. |
|
|
OfficeIMO.Reader.Pdf
PDF reader and normalized PDF projection bridge for OfficeIMO.Reader. |
|
|
OfficeIMO.Markdown.Pdf
PDF converter for OfficeIMO.Markdown - Export Markdown documents to PDF using the first-party OfficeIMO.Pdf engine. |
|
|
OfficeIMO.PowerPoint.Pdf
PDF converter for OfficeIMO.PowerPoint - Export PowerPoint presentations to PDF using the first-party OfficeIMO.Pdf engine. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.3 | 2,343 | 7/27/2026 |
| 3.0.2 | 584 | 7/26/2026 |
| 3.0.1 | 830 | 7/26/2026 |
| 3.0.0 | 984 | 7/20/2026 |
| 2.0.1 | 1,444 | 7/14/2026 |
| 2.0.0 | 1,076 | 7/14/2026 |
| 0.1.50 | 1,117 | 7/9/2026 |
| 0.1.49 | 1,030 | 7/8/2026 |
| 0.1.48 | 1,217 | 7/5/2026 |
| 0.1.47 | 962 | 7/4/2026 |
| 0.1.46 | 2,038 | 6/27/2026 |
| 0.1.45 | 894 | 6/27/2026 |
| 0.1.44 | 1,172 | 6/24/2026 |
| 0.1.43 | 908 | 6/23/2026 |
| 0.1.42 | 1,067 | 6/21/2026 |
| 0.1.41 | 1,032 | 6/16/2026 |
| 0.1.40 | 1,046 | 6/16/2026 |
| 0.1.39 | 1,356 | 6/15/2026 |
| 0.1.38 | 871 | 6/13/2026 |
| 0.1.37 | 860 | 6/12/2026 |