Lxman.PdfLibrary.Rendering.SkiaSharp 1.1.0

The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Lxman.PdfLibrary.Rendering.SkiaSharp --version 1.1.0
                    
NuGet\Install-Package Lxman.PdfLibrary.Rendering.SkiaSharp -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Lxman.PdfLibrary.Rendering.SkiaSharp" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Lxman.PdfLibrary.Rendering.SkiaSharp" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Lxman.PdfLibrary.Rendering.SkiaSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Lxman.PdfLibrary.Rendering.SkiaSharp --version 1.1.0
                    
#r "nuget: Lxman.PdfLibrary.Rendering.SkiaSharp, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Lxman.PdfLibrary.Rendering.SkiaSharp@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Lxman.PdfLibrary.Rendering.SkiaSharp&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Lxman.PdfLibrary.Rendering.SkiaSharp&version=1.1.0
                    
Install as a Cake Tool

PdfLibrary

License: MIT .NET

A comprehensive .NET library for parsing, rendering, creating, editing, and optimizing PDF documents. Built with C# and multi-targeting .NET 8, 9, and 10.

Features

PDF Rendering

  • Full PDF 1.x and 2.0 parsing support
  • High-quality rendering using SkiaSharp with optimized glyph and path caching
  • Support for complex graphics operations (paths, clipping, transparency)
  • Memory-efficient image processing using ArrayPool<byte> and pre-allocated buffers
  • Comprehensive color space support (DeviceRGB, DeviceCMYK, DeviceGray, ICCBased, Separation, Lab)
  • Image handling with custom high-performance decompressors:
    • JPEG (in-house JpegCodec — baseline and progressive)
    • JPEG2000 (JP2/J2K via in-house Jp2Codec)
    • CCITT Group 3 and Group 4 fax compression
    • JBIG2 monochrome compression
    • LZW compression
    • FlateDecode (zlib/PNG) with optimized predictor functions
    • RunLength, ASCII85, ASCIIHex encoding
  • Font rendering (Type1, TrueType, CID, embedded fonts) with optimized glyph path extraction
  • Text extraction and positioning

PDF Creation (Fluent Builder API)

  • Intuitive fluent API for document creation
  • Text with full styling (fonts, colors, spacing)
  • Vector graphics (rectangles, circles, lines, paths)
  • Image embedding (JPEG, PNG)
  • Interactive forms (text fields, checkboxes, radio buttons, dropdowns)
  • Annotations (links, notes, highlights)
  • Bookmarks/Outlines with hierarchical navigation
  • Page labels (custom numbering schemes)
  • Layers (Optional Content Groups)
  • Encryption (RC4, AES-128, AES-256)
  • Custom font embedding (TrueType, OpenType)

PDF Editing

  • Edit a loaded document via PdfDocument.Edit()PdfDocumentEditor
  • Page operations: rotate, reorder, delete, insert blank pages
  • Merge multiple PDFs, split out page ranges, import/duplicate pages
  • Deleting a page cleans up bookmarks, named destinations, and links that pointed at it
  • Importing a page brings its interactive form fields across
  • Full-rewrite save (classic xref or object streams) with automatic garbage collection

PDF Optimization

  • Optimize a loaded document via PdfOptimizer.Optimize()
  • Lossless by default: Flate-compress uncompressed streams, drop unused objects, pack into object streams
  • Opt-in lossy passes: re-encode images as JPEG (with optional downsampling), subset embedded fonts (TrueType and CFF) to the glyphs actually used
  • Encrypted input is decrypted and written out unencrypted

Project Structure

PDF/
├── 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
│   ├── Editing/                      # Edit/mutate loaded documents (pages, merge, split)
│   ├── Optimization/                 # Optimize/compress loaded documents
│   ├── 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

Quick Start

Rendering a PDF

using PdfLibrary.Structure;
using PdfLibrary.Document;
using PdfLibrary.Rendering.SkiaSharp;

// Load a PDF document
using var doc = PdfDocument.Load("document.pdf");
var page = doc.GetPage(0)!;   // 0-based index

// Render to a file (format inferred from the extension)
page.RenderTo()
    .WithScale(1.0)  // 1.0 = 72 DPI
    .ToFile("output.png");

// Or render to an SKImage for further processing
using var image = page.RenderTo()
    .WithDpi(144)    // 2x resolution
    .ToImage();

Creating a PDF

using PdfLibrary.Builder;

PdfDocumentBuilder.Create()
    .WithMetadata(meta => meta
        .SetTitle("My Document")
        .SetAuthor("John Doe"))
    .AddPage(page =>
    {
        page.AddText("Hello, World!", 100, 750)
            .Font("Helvetica-Bold", 24)
            .Color(PdfColor.Blue);
        page.AddRectangle(100, 650, 200, 30,
            fillColor: PdfColor.LightGray, strokeColor: PdfColor.Black);
    })
    .AddPage(page => page.AddText("Page 2", 100, 700, "Helvetica", 12))
    .AddBookmark("Page 1", 0)
    .AddBookmark("Page 2", 1)
    .Save("output.pdf");

Creating a Form

PdfDocumentBuilder.Create()
    .AddPage(page =>
    {
        page.AddText("Registration Form", 100, 750, "Helvetica-Bold", 18);
        page.AddText("Name:", 100, 700, "Helvetica", 12);
        page.AddTextField("name", 170, 695, 200, 25).Required();
        page.AddText("Email:", 100, 660, "Helvetica", 12);
        page.AddTextField("email", 170, 655, 200, 25);
        page.AddText("I agree to terms:", 100, 620, "Helvetica", 12);
        page.AddCheckbox("agree", 220, 618, 18);   // name, x, y, size
    })
    .WithAcroForm(form => form.SetNeedAppearances(true))
    .Save("form.pdf");

Advanced Rendering Options

// Transparent background (for PNG with alpha) instead of the default white
using var image = page.RenderTo()
    .WithTransparentBackground()
    .ToImage();

// Encode straight to PNG bytes at a chosen DPI
byte[] png = page.RenderTo()
    .WithDpi(300)   // high resolution for printing
    .ToBytes();

Text Extraction

// Extract all text from a page
var page = doc.GetPage(0)!;
string textContent = page.ExtractText();

// Extract text with positioning information
var (text, fragments) = page.ExtractTextWithFragments();
foreach (var f in fragments)
{
    Console.WriteLine($"Text: {f.Text}");
    Console.WriteLine($"Position: ({f.X}, {f.Y})");
    Console.WriteLine($"Font: {f.FontName}, Size: {f.FontSize}");
}

Editing an Existing PDF

using PdfLibrary.Structure;
using PdfLibrary.Editing;

using var doc = PdfDocument.Load("input.pdf");
var edit = doc.Edit();

edit.Pages.RemoveAt(2);       // delete the 3rd page
edit.Pages.Rotate(0, 90);     // rotate the 1st page 90°
edit.Pages.Move(4, 0);        // move the 5th page to the front

edit.Save("edited.pdf");

// Merge several PDFs into one
using var a = PdfDocument.Load("part1.pdf");
using var b = PdfDocument.Load("part2.pdf");
using PdfDocument merged = PdfDocumentEditor.Merge([a, b]);
merged.Save("combined.pdf");

See the Complete Guide for the full surface.

Optimizing a PDF

using PdfLibrary.Structure;
using PdfLibrary.Optimization;

using var doc = PdfDocument.Load("input.pdf");
using var output = File.Create("optimized.pdf");

// Lossless by default (Flate + object streams + unused-object GC)
PdfOptimizationResult result = PdfOptimizer.Optimize(doc, output);
Console.WriteLine($"Removed {result.ObjectsRemoved} objects; wrote {result.OutputBytes} bytes");

// Opt in to lossy size reductions
PdfOptimizer.Optimize(doc, output, new PdfOptimizationOptions
{
    RecompressImages = true,   // lossy: re-encode images as JPEG
    SubsetFonts      = true,   // discard unused glyphs in embedded fonts
});

Thread Safety

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.

Supported pattern (do this)

// 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
}

Constraints (don't do this)

  • Do not share one 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.
  • Do not share a 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.

Image Decompression Architecture

PdfLibrary uses custom-built, high-performance decompression libraries for all PDF image formats. These are pure C# implementations with no external dependencies:

Custom Decompressors

  • JpegCodec - DCTDecode filter (in-house, baseline + progressive JPEG, encode + decode)
  • Jp2Codec - JPXDecode filter, in-house JPEG 2000 decoder (decode only)
  • CcittCodec - CCITTFaxDecode filter (Group 3 1D/2D and Group 4)
  • Jbig2Decoder - JBIG2Decode filter for monochrome document compression (ITU-T T.88, used directly by PdfLibrary.Filters.Jbig2DecodeFilter)
  • LzwCodec - LZWDecode filter with Early Change support
  • PdfLibrary.Filters.FlateDecodeFilter - FlateDecode (DEFLATE) using System.IO.Compression

Integration

PDF 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).

Requirements

  • .NET 8.0, 9.0, or 10.0
  • SkiaSharp (for rendering - separate PdfLibrary.Rendering.SkiaSharp package)

Core Dependencies

  • Serilog - Structured logging
  • Unicolour - Advanced color space transformations
  • In-tree codec libraries (all pure C#, no third-party codec dependencies):
    • ImageLibrary/JpegCodec - JPEG (DCTDecode) baseline and progressive
    • ImageLibrary/Jp2Codec - JPEG 2000 (JPXDecode), decode only
    • ImageLibrary/LzwCodec - LZW (LZWDecode) with Early Change support
    • ImageLibrary/CcittCodec - CCITT (CCITTFaxDecode) Group 3 1D/2D and Group 4
    • ImageLibrary/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.

Building

# Clone the repository
git clone https://github.com/lxman/PdfLibrary.git
cd PdfLibrary

# 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).

Documentation

  • Complete Guide - Loading, reading, rendering, creating, editing, and optimizing PDFs
  • Architecture - Technical architecture overview

Supported PDF Features

Content Streams

  • Graphics state operators (q, Q, cm, w, J, j, M, d, ri, i, gs)
  • Path operators (m, l, c, v, y, h, re, S, s, f, F, f*, B, B*, b, b*, n, W, W*)
  • Text operators (BT, ET, Tc, Tw, Tz, TL, Tf, Tr, Ts, Td, TD, Tm, T*, Tj, TJ, ', ")
  • Color operators (CS, cs, SC, SCN, sc, scn, G, g, RG, rg, K, k)
  • XObject operators (Do)
  • Inline image operators (BI, ID, EI)
  • Marked content operators (MP, DP, BMC, BDC, EMC)

Color Spaces

  • DeviceGray, DeviceRGB, DeviceCMYK
  • CalGray, CalRGB, Lab
  • ICCBased
  • Indexed
  • Separation, DeviceN
  • Pattern (tiling and shading)

Fonts

  • Type1, Type1C (CFF)
  • TrueType
  • Type0 (CID fonts)
  • Type3
  • Embedded and system fonts

Images

  • DCTDecode (JPEG)
  • FlateDecode (PNG/zlib)
  • LZWDecode
  • CCITTFaxDecode (Group 3 and 4)
  • JBIG2Decode
  • JPXDecode (JPEG2000)
  • RunLengthDecode
  • ASCII85Decode, ASCIIHexDecode

Security

  • RC4 40-bit and 128-bit encryption
  • AES 128-bit and 256-bit encryption
  • Permission flags

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

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.

Development Setup

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Code Style

  • Follow C# coding conventions
  • Use meaningful variable and method names
  • Add XML documentation for public APIs
  • Include unit tests for new features

Acknowledgments

Core Library

  • SkiaSharp - 2D graphics library for PDF rendering
  • Serilog - Structured logging framework
  • Unicolour - Advanced color space handling and transformations

Test-time references

  • Melville.CSJ2K - Used only by ImageLibrary/Jp2Codec.Tests as a differential reference for in-house JPEG 2000 conformance testing; not a runtime dependency of PdfLibrary.
Product Compatible and additional computed target framework versions.
.NET 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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
Loading failed