![]() |
VOOZH | about |
dotnet add package Lxman.PdfLibrary.Rendering.SkiaSharp --version 1.0.0-rc.5
NuGet\Install-Package Lxman.PdfLibrary.Rendering.SkiaSharp -Version 1.0.0-rc.5
<PackageReference Include="Lxman.PdfLibrary.Rendering.SkiaSharp" Version="1.0.0-rc.5" />
<PackageVersion Include="Lxman.PdfLibrary.Rendering.SkiaSharp" Version="1.0.0-rc.5" />Directory.Packages.props
<PackageReference Include="Lxman.PdfLibrary.Rendering.SkiaSharp" />Project file
paket add Lxman.PdfLibrary.Rendering.SkiaSharp --version 1.0.0-rc.5
#r "nuget: Lxman.PdfLibrary.Rendering.SkiaSharp, 1.0.0-rc.5"
#:package Lxman.PdfLibrary.Rendering.SkiaSharp@1.0.0-rc.5
#addin nuget:?package=Lxman.PdfLibrary.Rendering.SkiaSharp&version=1.0.0-rc.5&prereleaseInstall as a Cake Addin
#tool nuget:?package=Lxman.PdfLibrary.Rendering.SkiaSharp&version=1.0.0-rc.5&prereleaseInstall as a Cake Tool
A comprehensive .NET library for parsing, rendering, and creating PDF documents. Built with C# and targeting .NET 10.
ArrayPool<byte> and pre-allocated buffersPDF/
├── PdfLibrary/ # Core library
│ ├── Document/ # PDF document model
│ ├── Structure/ # PDF structure (xref, trailer, objects)
│ ├── Parsing/ # PDF lexer/parser
│ ├── Content/ # Content stream processing
│ ├── Filters/ # Stream decode filters (Flate, JBIG2Decode, etc.)
│ ├── Rendering/ # Rendering pipeline
│ ├── Builder/ # Fluent API for PDF creation
│ ├── Fonts/ # Font handling
│ ├── Functions/ # PDF function objects
│ ├── Fixups/ # Per-document corrective passes
│ ├── Core/ # Primitive types
│ └── Security/ # Encryption/decryption
├── PdfLibrary.Rendering.SkiaSharp/ # SkiaSharp render target
├── PdfLibrary.Tests/ # Unit tests
├── PdfLibrary.Integration/ # Integration tests
├── PdfLibrary.Wpf.Viewer/ # WPF PDF viewer application
├── PdfLibrary.Utilities/ # Utility applications
│ └── ImageUtility/ # Image format viewer with codec system
├── PdfLibrary.Examples/ # Standalone usage samples
├── ImageLibrary/ # Pure-C# image format library — one project per codec
│ ├── CcittCodec/ # CCITT Group 3 (1D/2D) and Group 4 fax
│ ├── LzwCodec/ # LZW compression (with Early Change support)
│ ├── JpegCodec/ # JPEG (baseline + progressive, encode + decode)
│ ├── Jbig2Decoder/ # JBIG2 decoder (ITU-T T.88)
│ ├── BmpCodec/ # BMP container
│ ├── GifCodec/ # GIF container (with LZW)
│ ├── PngCodec/ # PNG container
│ ├── TgaCodec/ # TGA container
│ ├── TiffCodec/ # TIFF container (uses CcittCodec + LzwCodec)
│ ├── CcittCodec.Tests/
│ ├── LzwCodec.Tests/
│ ├── JpegCodec.Tests/
│ ├── Jbig2Decoder.Tests/
│ ├── BmpCodec.Tests/
│ ├── GifCodec.Tests/
│ ├── PngCodec.Tests/
│ ├── TgaCodec.Tests/
│ └── ImageLibrary.IntegrationTests/
├── FontParser/ # TrueType/OpenType parsing
├── Logging/ # Logging infrastructure
└── Docs/ # Documentation
using PdfLibrary.Structure;
using PdfLibrary.Rendering.SkiaSharp;
// Load a PDF document
using var stream = File.OpenRead("document.pdf");
var document = PdfDocument.Load(stream);
// Get the page to render
var page = document.GetPage(0); // 0-based index
// Render to file using the fluent API
page.Render(document)
.WithScale(1.0) // 1.0 = 72 DPI
.ToFile("output.png");
// Or render to SKImage for further processing
using var image = page.Render(document)
.WithDpi(144) // 2x resolution
.ToImage();
using PdfLibrary.Builder;
PdfDocumentBuilder.Create()
.WithMetadata(meta => meta
.Title("My Document")
.Author("John Doe"))
.AddPage(page => page
.AddText("Hello, World!", 100, 700)
.WithFont("Helvetica-Bold")
.WithSize(24)
.WithColor(PdfColor.Blue)
.AddRectangle(100, 650, 200, 30)
.Fill(PdfColor.LightGray)
.Stroke(PdfColor.Black))
.AddPage(page => page
.AddText("Page 2", 100, 700))
.AddBookmark("Page 1", 0)
.AddBookmark("Page 2", 1)
.Save("output.pdf");
PdfDocumentBuilder.Create()
.AddPage(page => page
.AddText("Registration Form", 100, 750)
.WithSize(18)
.Bold()
.AddText("Name:", 100, 700)
.AddTextField("name", 170, 695, 200, 25)
.Required()
.AddText("Email:", 100, 660)
.AddTextField("email", 170, 655, 200, 25)
.AddText("I agree to terms:", 100, 620)
.AddCheckbox("agree", 220, 618, 18, 18))
.WithAcroForm(form => form.SetNeedAppearances(true))
.Save("form.pdf");
// Render with custom background color
using var image = page.Render(document)
.WithDpi(300) // High resolution for printing
.WithBackgroundColor(new SKColor(255, 250, 240)) // Antique white
.ToImage();
// Render specific region of page
using var cropImage = page.Render(document)
.WithScale(2.0)
.WithCropBox(100, 100, 400, 600) // x, y, width, height
.ToImage();
// Extract all text from a page
var page = document.GetPage(0);
var textContent = page.ExtractText(document);
// Extract text with positioning information
var textBlocks = page.ExtractTextBlocks(document);
foreach (var block in textBlocks)
{
Console.WriteLine($"Text: {block.Text}");
Console.WriteLine($"Position: ({block.X}, {block.Y})");
Console.WriteLine($"Font: {block.FontName}, Size: {block.FontSize}");
}
PdfLibrary supports concurrent rendering using the one-document-per-thread model — the standard pattern for ASP.NET Core and other multi-threaded servers. Each request loads its own PdfDocument, renders it on its own render target, and disposes both. Under this model the library is thread-safe: the process-wide caches and lookup tables shared across renders (glyph-path cache, system-font/typeface resolver, built-in ICC profiles, codec registry, font lookup tables) are synchronized, and CFF/Type1 glyph decoding uses per-parse state.
This is verified by a stress harness that renders a corpus concurrently at 2× core count and compares every page's output pixel-for-pixel against a single-threaded baseline — zero divergence, with managed memory bounded across thousands of renders. No process-wide render lock is required; throughput scales with cores.
// Per request/thread: load → render → dispose. No shared state, no global lock.
public async Task<byte[]> RenderFirstPageAsync(string pdfPath)
{
using var document = PdfDocument.Load(pdfPath);
return document.GetPage(0)! // 0-based
.RenderTo()
.WithDpi(150)
.ToBytes(); // PNG bytes
}
PdfDocument across threads. It lazy-loads objects by mutating internal state and seeking a shared Stream; concurrent access to a single instance is unsafe. Load one per request instead.SkiaSharpRenderTarget (or render into one) from multiple threads. A render target wraps a single SKCanvas, which is not thread-safe by design. Use one render target per render.PdfDocumentBuilder is not thread-safe during construction — build a document on a single thread.If the same PDFs are rendered repeatedly, caching the rendered output at the HTTP layer is still worthwhile — but as an optimization, not a correctness requirement.
PdfLibrary uses custom-built, high-performance decompression libraries for all PDF image formats. These are pure C# implementations with no external dependencies:
PdfLibrary.Filters.Jbig2DecodeFilter)System.IO.CompressionPDF stream filters in PdfLibrary/Filters/ are thin adapters: each maps PDF filter parameters onto the underlying codec library and returns decoded bytes in the layout the renderer expects. Image containers (BMP/GIF/PNG/TGA/TIFF/PBM) live in their own per-codec projects under ImageLibrary/ and are used by the standalone ImageUtility application; PDF rendering only consumes the codec layer (JpegCodec, Jp2Codec, LzwCodec, CcittCodec, Jbig2Decoder).
ImageLibrary/JpegCodec - JPEG (DCTDecode) baseline and progressiveImageLibrary/Jp2Codec - JPEG 2000 (JPXDecode), decode onlyImageLibrary/LzwCodec - LZW (LZWDecode) with Early Change supportImageLibrary/CcittCodec - CCITT (CCITTFaxDecode) Group 3 1D/2D and Group 4ImageLibrary/Jbig2Decoder - JBIG2 (JBIG2Decode, ITU-T T.88)Note: PdfLibrary has no third-party image-format dependencies. All image handling is backed by in-tree codecs.
# Clone the repository
git clone https://github.com/lxman/PDF.git
cd PDF
# Build the solution
dotnet build PdfLibrary.slnx
# Run tests
dotnet test PdfLibrary.Tests/PdfLibrary.Tests.csproj
All codec implementations are in-tree (no git submodules required).
This project is licensed under the MIT License - see the file for details.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)ImageLibrary/Jp2Codec.Tests as a differential reference for in-house JPEG 2000 conformance testing; not a runtime dependency of PdfLibrary.| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-rc.5 | 41 | 6/12/2026 |
| 1.0.0-rc.4 | 58 | 6/10/2026 |
| 1.0.0-rc.3 | 61 | 6/7/2026 |
| 1.0.0-rc.2 | 52 | 6/7/2026 |
| 1.0.0-rc.1 | 48 | 6/7/2026 |
| 0.5.0-beta | 54 | 5/21/2026 |
| 0.4.0-beta | 58 | 5/14/2026 |
| 0.3.0-beta | 56 | 5/13/2026 |
| 0.2.0-beta | 54 | 5/11/2026 |
| 0.1.0-beta | 60 | 5/10/2026 |
| 0.0.10-beta | 151 | 12/13/2025 |
| 0.0.9-beta | 124 | 12/12/2025 |
| 0.0.8-beta | 414 | 12/9/2025 |
| 0.0.6-beta | 333 | 12/8/2025 |
| 0.0.5-beta | 332 | 12/8/2025 |
| 0.0.4-beta | 198 | 12/7/2025 |
| 0.0.3-beta | 117 | 12/6/2025 |
| 0.0.2-beta | 109 | 11/29/2025 |