Tutorial: Image Processing — Blazor
IsabyteImageAnalysis for client-side edge detection (Sobel, Canny,
Contour, Skeleton) and IsabyteAnimationEffect for GPU-accelerated
visuals. Everything runs in the browser — your server never sees the
image data. Package: Isabyte.PowerTools.Blazor.
Part 1 — IsabyteImageAnalysis (image-analysis)
Step 1 — Render an Image with Detection Layers
The component renders an <img>, then overlays one or more detection
layers on top — each independently toggleable with its own parameters,
painted on its own stacked <canvas>.
@using Isabyte.PowerTools.Components.Image
@using Isabyte.PowerTools.Components.Animation
<IsabyteImageAnalysis Src="/images/sample.jpg"
Width="640px"
LineDetectEnabled="true"
LineDetectSensitivity="60"
LineDetectColor="#00ff88" />
That single line turns on the Sobel-based line detector ("LineDetect"). Sensitivity is a 0–100 threshold — lower values pick up faint edges, higher values keep only the strongest ones.
Step 2 — Pick the Right Detector
| Algorithm | What it finds | Speed | Best for |
|---|---|---|---|
| LineDetect (Sobel) | Strong gradients. | Fastest. | General-purpose edge highlighting. |
| CannyEdgeDetect | Single-pixel-wide edges. | Slower; 3 thresholds. | Document/OCR preprocessing. |
| ContourFinder | Closed shapes. | Medium. | Shape recognition, ROI extraction. |
| Skeletonize | One-pixel skeleton. | Medium-slow. | Handwriting, road centerlines. |
All four can be enabled simultaneously, each in its own color — the basis of the live demo.
Step 3 — Canny in Depth
<IsabyteImageAnalysis Src="@_imageSrc"
CannyEdgeDetectEnabled="true"
CannyEdgeDetectSigma="2.0f"
CannyEdgeDetectLowThreshold="15"
CannyEdgeDetectHighThreshold="40"
CannyEdgeDetectColor="#ff00ff"
CannyEdgeDetectAntiAlias="3" />
CannyEdgeDetectSigma is the Gaussian standard deviation applied before
edge detection (default 1.4) — bump to 2.0–2.5 for noisy/scanned input.
Low/High thresholds seed and extend edges (hysteresis); the high
threshold is usually 2–3× the low one.
Step 4 — Capturing Snapshots
<IsabyteImageAnalysis Src="@_src"
ContourFinderEnabled="true"
OnPatternSnapshot="OnSnapshot" />
@code {
private string? _capturedDataUrl;
private void OnSnapshot(AnalysisPatternSnapshotData data)
{
_capturedDataUrl = data.DataUrl;
}
}
OnPatternSnapshot hands you the rendered overlay as a base64 data URL.
It fires when a pattern is saved or a blueprint exported — from the
component's own buttons or from the matching method — not on every
render.
Part 2 — IsabyteAnimationEffect (animation-effect)
Step 5 — GPU-Accelerated Visuals
A single component whose effects are selected via the Effect enum,
wrapping a ChildContent fragment.
Step 6 — A Water-Ripple Hero
<IsabyteAnimationEffect Effect="IsabyteEffect.WaterRipple"
Width="100%"
Height="400px"
Color="rgba(120, 180, 255, 0.35)"
Speed="2.5"
Spread="80">
<div class="hero-content">
<h1>Welcome aboard</h1>
<p>Sign in to continue.</p>
</div>
</IsabyteAnimationEffect>
ChildContent renders on top of the effect canvas and stays interactive.
Color tints the effect, Speed scales the animation rate, Spread
controls ripple radius.
Step 7 — WebGL with a Canvas 2D Fallback
Three effects are WebGL-backed — Water Ripple, Sea Water and Rain. Those try WebGL first and fall back to a Canvas 2D version automatically, with no fallback code required. Every other effect, Refraction and Perspective included, is Canvas/CSS-based and has no WebGL path to lose.
Step 8 — Composing Detection + Animation
<IsabyteAnimationEffect Effect="IsabyteEffect.Refraction" Speed="1.5">
<IsabyteImageAnalysis Src="@_src"
LineDetectEnabled="true"
CannyEdgeDetectEnabled="true" />
</IsabyteAnimationEffect>
Common Gotchas
- CORS on image sources. A cross-origin
Srcblocks pixel reads — host same-origin or serve withAccess-Control-Allow-Origin: *. - Anti-alias above 4 starts to dissolve thin features — lower it first if you're losing structure.
- Animation on low-power devices. WaterRipple/SeaWater are GPU-bound;
the 2D fallback is automatic, but consider disabling effects on
low-memory devices via JS interop (
navigator.deviceMemory).