ImageSharp.Drawing

High-performance canvas-based 2D drawing for ImageSharp with paths, brushes, text, composition, retained scenes, and WebGPU output.

ImageSharp.Drawing adds canvas drawing, vector geometry, image composition, and rich text rendering to ImageSharp, whether you are generating social cards, overlays, charts, labels, diagrams, badges, watermarks, or custom graphics in code.

Built for generated graphics

ImageSharp.Drawing extends ImageSharp with canvas-based vector, image composition, and text APIs that fit naturally into the same load, process, compose, and save workflow your application already uses.

It is a strong fit for web apps, background services, containers, cloud workloads, desktop tools, and device or edge scenarios on .NET 8+.

dotnet add package SixLabors.ImageSharp.Drawing

Paths, brushes, and composition

Fill and stroke primitives, shapes, paths, polygons, and custom geometry with the canvas API, using a clean brush-and-pen model that stays readable even as compositions become more dynamic.

Save and restore drawing state, clip with paths, apply transforms and blend modes, isolate work in compositing layers with SaveLayer(...), draw into local-coordinate regions with CreateRegion(...), and run any ImageSharp processor over a rectangle or path with Apply(...).

When the same artwork is replayed over and over, capture it once with CreateScene() and dispatch it through RenderScene(...) to skip command preparation on every frame.

using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

using Image<Rgba32> image = new(1200, 630, Color.White);

RectangularPolygon card = new(60, 60, 1080, 510);
Star badge = new(1040, 140, 12, 40, 72);

image.Mutate(x => x.Paint(canvas =>
{
    canvas.Fill(Brushes.Solid(Color.WhiteSmoke), card);
    canvas.Draw(Pens.Solid(Color.DeepPink, 6), card);
    canvas.Fill(Brushes.Horizontal(Color.Orange, Color.Gold), badge);
    canvas.Draw(Pens.Solid(Color.Black, 4), badge);
}));

image.Save("launch-card.png");

Typography that belongs in real products

Text rendering in ImageSharp.Drawing is powered by SixLabors.Fonts, bringing the same shaping, layout, fallback, and color-font support into generated graphics.

Measure and draw text through the same canvas API, with wrapping, alignment, fallback fonts, decorations, vertical layout, bidirectional text, and brush or pen styling for assets that need to look deliberate in every language and format.

  • Render headlines, labels, captions, callouts, and overlays directly into your image pipeline.
  • Drive layout from a single MeasureText(...) pass that returns logical advance, ink bounds, renderable bounds, per-character entries, and per-line metrics.
  • Mix text with vector shapes, fills, outlines, color fonts, path text, source images, masks, and image processing in one consistent workflow.
  • Generate polished assets for dashboards, certificates, reports, social cards, marketing automation, and localized media.
using SixLabors.Fonts;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Drawing.Processing;

Font font = SystemFonts.CreateFont("Segoe UI", 48, FontStyle.Bold);

RichTextOptions textOptions = new(font)
{
    Origin = new PointF(80, 120),
    WrappingLength = 1040,
    TextRuns = new[]
    {
        new RichTextRun
        {
            Start = 0,
            End = 6,
            TextDecorations = TextDecorations.Underline
        }
    }
};

using Image<Rgba32> image = new(1200, 630, Color.White);

image.Mutate(x => x.Paint(canvas =>
{
    canvas.Fill(Brushes.Solid(Color.White));
    canvas.DrawText(textOptions, "Launch assets generated in code.", Brushes.Solid(Color.Black), pen: null);
}));

image.Save("headline-card.png");

Images, masks, and local effects

Real generated graphics often mix source imagery, vector masks, text, and local processing. ImageSharp.Drawing keeps those operations on the same ordered canvas timeline.

Draw images into destination rectangles, fill arbitrary paths with image brushes, clip portraits into shapes, blur or color-adjust only the pixels inside a region, and keep source images alive until the deferred canvas replay has completed.

  • Use DrawImage(...) for rectangular placement, crop, and scale operations.
  • Use image brushes when a source image should fill a path, text shape, mask, or repeated decorative element.
  • Use Apply(...) as a replay barrier when normal ImageSharp processors must affect only earlier drawing inside a rectangle or path.
  • Use SaveLayer(...) when several commands need to composite back to the parent as one group.
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

using Image<Rgba32> photo = Image.Load<Rgba32>("portrait.jpg");
using Image<Rgba32> image = new(900, 500, Color.White);

EllipsePolygon avatar = new(new PointF(220, 250), new SizeF(280, 280));
Rectangle source = new(80, 20, 420, 420);
RectangleF target = new(80, 110, 280, 280);

image.Mutate(x => x.Paint(canvas =>
{
    DrawingOptions clip = new()
    {
        ShapeOptions = new() { BooleanOperation = BooleanOperation.Intersection }
    };

    _ = canvas.Save(clip, avatar);
    canvas.DrawImage(photo, source, target, KnownResamplers.Bicubic);
    canvas.Restore();

    // Apply runs an ImageSharp processor over only the clipped region.
    canvas.Apply(avatar, region => region.GaussianBlur(1.5F));
    canvas.Draw(Pens.Solid(Color.White, 8), avatar);
}));

GPU-native rendering with WebGPU

The optional SixLabors.ImageSharp.Drawing.WebGPU package renders the same canvas model into GPU-native windows, offscreen render targets, or surfaces owned by an existing UI framework, so interactive applications can keep one drawing API across CPU and GPU output.

Pair WebGPU with retained scenes for editors, diagramming tools, map and chart viewers, dashboards, creative apps, and live previews where most of the scene is stable from frame to frame and only a small portion changes.

  • Drive a native window with WebGPUWindow, attach to a host-owned drawable through WebGPUExternalSurface, or render offscreen into a texture with WebGPURenderTarget.
  • Probe support up front through WebGPUEnvironment.ProbeAvailability() and ProbeComputePipelineSupport() before constructing any target.
  • Target common WebGPU texture formats and read GPU output back into a managed Image<TPixel> when offline rendering needs to encode to PNG, JPEG, or WebP.
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Drawing.Processing.Backends;

using WebGPUWindow window = new(new WebGPUWindowOptions
{
    Title = "ImageSharp.Drawing WebGPU",
    Size = new Size(960, 540),
    PresentMode = WebGPUPresentMode.Fifo,
});

window.Run(frame =>
{
    DrawingCanvas canvas = frame.Canvas;
    canvas.Clear(Brushes.Solid(Color.White));

    canvas.Fill(
        Brushes.Solid(Color.CornflowerBlue),
        new EllipsePolygon(
            new PointF(480, 270),
            new SizeF(280, 180)));

    canvas.Draw(
        Pens.Solid(Color.MidnightBlue, 6),
        new RectangularPolygon(40, 40, 880, 460));
});