Image Features Demo

This report demonstrates every image method in the library. All SVG is generated inline — no external files or image-processing libraries are required for the SVG sections.

Generated: 2026-02-27 17:44:22 Methods: AddSvg · AddImage(bytes) · AddImage(stream) · AddImageFromUrl Self-contained: Yes (SVG & base64)

Inline SVG — AddSvg()

The most efficient way to embed vector graphics. The SVG markup is written directly into the HTML — no encoding overhead, fully self-contained, and scales perfectly at every zoom level.

CDS.FluentHtmlReports Image Features Demo Inline SVG · Base64 · Stream · URL · Alignment · Captions
A gradient banner generated in C# without any image library

Inline SVG: maxWidthPercent

The same SVG constrained to different widths via the optional maxWidthPercent parameter:

Build Pipeline Checkout Build Unit Tests ~ Integration Deploy
100% width (full container)
Build Pipeline Checkout Build Unit Tests ~ Integration Deploy
60% width, centered
Build Pipeline Checkout Build Unit Tests ~ Integration Deploy
40% width, left-aligned

Alignment — left, center, right

All image methods accept an optional alignment parameter. Here the same SVG badge is placed at each of the three positions:

Left-aligned image
Centered image
Right-aligned image

Captions — figure + figcaption

Pass a caption string to any image method to wrap the image in a semantic HTML5 <figure>/<figcaption> element:

Weekly Active Users 810 380
Figure 1 — Weekly active users for the past 7 days

Base64 Embedding — AddImage(byte[]) and AddImage(Stream)

When you have image data as a byte array or Stream — for example from a cross-platform image library — use these overloads. The image is base64-encoded into the HTML, keeping the report self-contained.

Purple badge
AddImage(byte[], mimeType) — SVG bytes embedded as base64
Teal badge
AddImage(Stream, mimeType) — read from a MemoryStream

Cross-platform image sources (macOS / Linux / Windows)

This library has zero dependencies and does not ship an image-processing package. To produce bitmap data from code, use one of these cross-platform libraries:

// ── SkiaSharp (recommended cross-platform) ──────────────────────────────
// NuGet: SkiaSharp

using SkiaSharp;

using var surface = SKSurface.Create(new SKImageInfo(400, 200));
var canvas = surface.Canvas;
canvas.Clear(SKColors.White);
// ... draw on canvas ...
using var image = surface.Snapshot();
using var data = image.Encode(SKEncodedImageFormat.Png, 100);

// Option A — byte array
report.AddImage(data.ToArray(), "image/png", "My chart");

// Option B — stream (avoids the extra byte[] allocation)
using var stream = data.AsStream();
report.AddImage(stream, "image/png", "My chart");
// ── SixLabors.ImageSharp (cross-platform) ──────────────────────────────
// NuGet: SixLabors.ImageSharp

using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;

using var img = new Image<Rgba32>(400, 200);
// ... draw on img ...
using var ms = new MemoryStream();
img.Save(ms, new PngEncoder());
ms.Position = 0;
report.AddImage(ms, "image/png", caption: "Figure 1");
// ── System.Drawing.Bitmap (Windows only) ───────────────────────────────
// Note: System.Drawing.Common is Windows-only on .NET 6+.
// Throws PlatformNotSupportedException on macOS and Linux.

using var bmp = new System.Drawing.Bitmap(400, 200);
// ... draw on bmp ...
using var ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
report.AddImage(ms.ToArray(), "image/png");
ℹ️ Tip: for purely vector output, AddSvg() requires no image library at all. Build an SVG string in C# and embed it directly — fully self-contained and resolution-independent.

SkiaSharp: Real Cross-Platform Image Processing

The ConsoleTest project references SkiaSharp (NuGet: SkiaSharp 3.x). The three images below are produced by the private helper methods in this class — they load the sample PNG from disk and apply real pixel operations.

ℹ️ The library itself (CDS.FluentHtmlReports) has zero dependencies. SkiaSharp is referenced only by this demo project, showing how any caller can integrate a cross-platform image library on Windows, macOS, and Linux.
Source image: docs/images/example-report.png
Dimensions: 923 × 1187 px

1. Load and re-encode — SKBitmap.Decode + SKImage.Encode

The original file is decoded into an SKBitmap, then re-encoded to PNG bytes and embedded via AddImage(byte[]):

Original image loaded with SkiaSharp
Original — SKBitmap.Decode() → SKImage.Encode() → AddImage(byte[], "image/png")
using var bitmap = SKBitmap.Decode(sampleImagePath);
using var image  = SKImage.FromBitmap(bitmap);
using var data   = image.Encode(SKEncodedImageFormat.Png, quality: 90);

report.AddImage(data.ToArray(), "image/png", alt: "My image");

2. Resize to thumbnail — SKBitmap.Resize

The image is scaled down to 280 px wide using Mitchell cubic resampling, then embedded at 35% of the report width:

Thumbnail created with SkiaSharp
Thumbnail (280 px wide) — SKBitmap.Resize() with SKCubicResampler.Mitchell
using var original = SKBitmap.Decode(sampleImagePath);
int targetWidth  = 280;
int targetHeight = (int)((float)original.Height / original.Width * targetWidth);

using var resized = original.Resize(
    new SKImageInfo(targetWidth, targetHeight),
    new SKSamplingOptions(SKCubicResampler.Mitchell));

using var image = SKImage.FromBitmap(resized!);
using var data  = image.Encode(SKEncodedImageFormat.Png, 90);

report.AddImage(data.ToArray(), "image/png",
    maxWidthPercent: 35, alignment: ImageAlignment.Left);

3. Watermark — SKCanvas compositing

An SKSurface is created at the original dimensions, the bitmap is drawn onto it, then a diagonal semi-transparent "DRAFT" text is composited using SKCanvas:

Watermarked image produced by SkiaSharp
Watermarked — SKSurface + SKCanvas.DrawBitmap + SKCanvas.DrawText
using var bitmap  = SKBitmap.Decode(sampleImagePath);
using var surface = SKSurface.Create(new SKImageInfo(bitmap.Width, bitmap.Height));
var canvas = surface.Canvas;

canvas.DrawBitmap(bitmap, 0, 0);

using var font  = new SKFont(SKTypeface.Default, size: 72);
using var paint = new SKPaint { Color = new SKColor(200, 30, 30, 140), IsAntialias = true };
float textWidth = font.MeasureText("DRAFT");

canvas.Save();
canvas.Translate(bitmap.Width / 2f, bitmap.Height / 2f);
canvas.RotateDegrees(-35);
canvas.DrawText("DRAFT", -textWidth / 2f, font.Size / 3f, font, paint);
canvas.Restore();

using var image = surface.Snapshot();
using var data  = image.Encode(SKEncodedImageFormat.Png, 90);

report.AddImage(data.ToArray(), "image/png");

URL-referenced Images — AddImageFromUrl()

Instead of embedding image data, this overload emits a standard <img src="url"> tag. The report file stays small, but the image is only visible when the viewer has network access.

⚠️ URL images are NOT self-contained. They require network access at viewing time. Do not use them for emailed attachments or fully offline reports.
Placeholder image loaded from an external URL
Loaded from picsum.photos — requires internet access
// Suitable for: intranet dashboards, stable CDN assets, live reports.
// Not suitable for: email attachments, fully offline reports.

report.AddImageFromUrl(
    "https://example.com/company-logo.png",
    alt: "Company logo",
    maxWidthPercent: 30,
    alignment: ImageAlignment.Left,
    caption: "Our logo");

Images inside the Columns layout

Images work inside BeginColumns/EndColumns for side-by-side comparisons:

CPU Usage % 90 45
CPU usage — last 7 intervals
Memory MB 240 210
Memory usage — last 7 intervals