
Syncfusion Blazor Image Editor
- 241 installs
- 4 repo stars
- Updated July 28, 2026
- syncfusion/blazor-ui-components-skills
Use syncfusion-blazor-image-editor for development tasks
About
syncfusion-blazor-image-editor: A skill for development. This provides functionality for development workflows.
- syncfusion-blazor-image-editor
Syncfusion Blazor Image Editor by the numbers
- 241 all-time installs (skills.sh)
- +13 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,620 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/blazor-ui-components-skills --skill syncfusion-blazor-image-editorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 241 |
|---|---|
| repo stars | ★ 4 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/blazor-ui-components-skills ↗ |
What it does
Use syncfusion-blazor-image-editor for development tasks
Files
Implementing the Syncfusion Blazor Image Editor Component
The Syncfusion Blazor Image Editor is a powerful, feature-rich component for building image editing capabilities into your Blazor applications. It provides a complete toolkit for image manipulation, annotation, transformation, and export with an intuitive UI and extensive API.
Navigation Guide
Getting Started
📄 Read: references/getting-started.md
- Installation of NuGet packages (Syncfusion.Blazor.ImageEditor, Syncfusion.Blazor.Themes)
- Blazor WebAssembly and Web App setup
- Import namespaces and register services
- Add stylesheet and script references
- Render the basic component
- NEW: Component properties (AllowUndoRedo, IsReadOnly, Enabled, Theme, CssClass, EnableImageSmoothing)
Core Operations
📄 Read: references/core-operations.md
- Open/load images from file explorer
- NEW: Complete OpenAsync signature with all 6 parameters (resetChanges, fillColor, width, height, isAspectRatio)
- Save and export images (PNG, JPEG, SVG, WEBP formats)
- Image quality settings for JPEG export
- Undo and redo operations with keyboard shortcuts (CanUndoAsync, CanRedoAsync)
- Reset image to original state
- NEW: Apply and Discard changes, Clear image, Get image data methods
Image Transformations
📄 Read: references/image-transformations.md
- Crop images with custom, circle, square, or ratio selections
- Rotate left, right, and arbitrary angles
- Flip horizontally and vertically
- Straighten images with slider control
- NEW: StraightenImageAsync method for precise angle adjustment (-45 to +45 degrees)
- Resize images to specific dimensions
- Pan images within the canvas
Annotations
📄 Read: references/annotations.md
- Add text annotations with customization (font, size, color, bold, italic, underline, strikethrough)
- NEW: Complete DrawTextAsync with underline and strikethrough parameters
- Create multiline text annotations
- Enable freehand drawing with stroke control
- Draw shapes (rectangles, ellipses, arrows, paths, lines)
- Insert image annotations (watermarks, logos, decorative elements)
- NEW: Annotation z-order management (BringToFrontAsync, SendToBackAsync, BringForwardAsync, SendBackwardAsync)
- NEW: Clone annotations with CloneShapeAsync
- NEW: Enable/disable annotation modes (EnableActiveAnnotationAsync, DisableActiveAnnotationAsync)
- NEW: Enable text editing mode
- Delete and manage annotations using ShapeSettings and IDs
Annotation Styling
📄 Read: references/annotation-styling.md
- Customize stroke width, color, and fill colors
- Apply font styling for text annotations
- Use ShapeChanging event for dynamic customization
- Configure default stroke colors and styles
- Work with ShapeSettings properties
Adjustments, Filters & Effects
📄 Read: references/adjustments-filters-effects.md
- Apply fine-tuning adjustments (brightness, contrast, saturation, hue, blur, etc.)
- Use slider controls for adjustment preview
- Apply filters to images (predefined effects)
- Add frame effects to images
- Commit or preview changes before applying
Redaction
📄 Read: references/redaction.md NEW
- Draw redactions with blur or pixelate effects
- RedactType enum (Blur, Pixelate)
- Control blur intensity and pixel size
- Get, select, update, and delete redactions
- RedactSettings class properties
- Privacy protection and GDPR compliance use cases
Frames
📄 Read: references/frames.md NEW
- Apply decorative frames to images
- FrameType enum (Mat, Bevel, Line, Inset, Hook)
- Customize frame colors, gradients, sizes
- FrameLineStyle for Line frames (Solid, Dashed, Dotted)
- Configure inset, offset, border radius, and line count
- Professional photo presentation examples
Events Reference
📄 Read: references/events-reference.md NEW
- Complete ImageEditorEvents documentation
- Lifecycle events (Created, Destroyed)
- File operation events (FileOpened, Saving)
- Transformation events (Cropping/Cropped, Rotating/Rotated, Flipping/Flipped)
- Shape events (ShapeChanging/ShapeChanged, resize/drag start/end)
- Adjustment events (ImageFiltering/Filtered, FinetuneValueChanging/Changed, FrameChanging/Changed)
- User interaction events (Zooming/Zoomed, OnPanStart/End, Clicked)
- Toolbar events (ToolbarUpdating, ToolbarItemClicked, QuickAccessToolbarOpening)
- History events (HistoryChanged)
- Event arguments reference for all events
Toolbar Customization
📄 Read: references/toolbar-customization.md
- Reference of built-in toolbar items (Open, Crop, Rotate, Annotation, Filters, etc.)
- Add custom toolbar items and buttons
- Show/hide entire toolbar or specific items
- Enable/disable toolbar items conditionally
- Customize contextual toolbars using ToolbarUpdating event
- Create custom toolbar templates
User Interactions
📄 Read: references/user-interactions.md
- Zoom methods (toolbar buttons, pinch gesture, mouse wheel, keyboard shortcuts)
- Pan/move images across the canvas
- Selection types for cropping
- Get image dimensions and coordinates
- Keyboard shortcuts reference (Ctrl+Z, Ctrl+Y, Ctrl+S, etc.)
Accessibility & Localization
📄 Read: references/accessibility-localization.md
- WCAG compliance and accessibility features
- Keyboard navigation support
- Screen reader compatibility
- ARIA attributes
- Color contrast standards
- Localization and RTL support
Setup Modes & Deployment
📄 Read: references/setup-modes.md
- WebAssembly app setup (Visual Studio, VS Code, .NET CLI)
- Web App setup with interactive render modes (Auto, WebAssembly, Server)
- Theme configuration (Bootstrap5, Fluent2, Material3, Tailwind3)
- Static Web Assets vs CDN references
- Script references and dependencies
Quick Start Example
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Width="100%">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
// Load an image when component is ready
await ImageEditor.OpenAsync("path/to/image.png");
}
}Setup steps: 1. Install NuGet packages: Syncfusion.Blazor.ImageEditor and Syncfusion.Blazor.Themes 2. Add imports in _Imports.razor: @using Syncfusion.Blazor.ImageEditor 3. Register service in Program.cs: builder.Services.AddSyncfusionBlazor(); 4. Add theme stylesheet to index.html or App.razor 5. Add the component and load an image in the Created event
Key Capabilities
| Feature | Purpose | Reference |
|---|---|---|
| Image Loading | Open JPEG, PNG, JPG, WEBP, BMP files | core-operations.md |
| Text Annotations | Add labels, captions, watermarks with underline/strikethrough | annotations.md |
| Shape Annotations | Draw rectangles, ellipses, arrows, paths with z-order control | annotations.md |
| Freehand Drawing | Sketch and draw directly on images | annotations.md |
| Redaction | Hide sensitive info with blur/pixelate for privacy compliance | redaction.md |
| Frames | Apply decorative borders (Mat, Bevel, Line, Inset, Hook) | frames.md |
| Crop & Transform | Crop with multiple selection types, rotate, flip, straighten | image-transformations.md |
| Filters & Effects | Apply fine-tuning and predefined filters | adjustments-filters-effects.md |
| Zoom & Pan | Multiple zoom methods and image panning | user-interactions.md |
| Export | Save as PNG, JPEG, SVG, WEBP with quality control | core-operations.md |
| Undo/Redo | Full history of operations | core-operations.md |
| Events | 30+ lifecycle, transformation, shape, and interaction events | events-reference.md |
| Toolbar | Built-in or custom toolbar with events | toolbar-customization.md |
| Accessibility | Keyboard navigation, screen readers, RTL, localization | accessibility-localization.md |
Common Patterns
Pattern 1: Load Image and Enable Annotations
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private string ImageUrl = "YOUR_IMAGE_URL";
private async void OnCreated()
{
await ImageEditor.OpenAsync(ImageUrl);
}
private async Task AddTextAnnotation()
{
ImageDimension dim = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawTextAsync(dim.X.Value, dim.Y.Value, "Important", "Arial", 24);
}
}Pattern 2: Custom Toolbar
<SfImageEditor @ref="ImageEditor" Toolbar="@CustomToolbar" Height="500px">
<ImageEditorEvents Created="OnCreated" ToolbarItemClicked="OnToolbarClick"></ImageEditorEvents>
</SfImageEditor>
@code {
private List<ImageEditorToolbarItemModel> CustomToolbar = new()
{
new ImageEditorToolbarItemModel { Name = "Open" },
new ImageEditorToolbarItemModel { Name = "Crop" },
new ImageEditorToolbarItemModel { Name = "Annotation" },
new ImageEditorToolbarItemModel { Name = "Save" }
};
}Pattern 3: Export Image with Quality Control
private async Task ExportImage()
{
// Export as PNG (lossless, default)
await ImageEditor.ExportAsync("edited-image.png");
// Export as JPEG with quality control (0.0 to 1.0)
await ImageEditor.ExportAsync("photo.jpg", ImageEditorFileType.JPEG, 0.85);
// Export as WEBP (modern format)
await ImageEditor.ExportAsync("image.webp", ImageEditorFileType.WEBP);
// Export as SVG (vector format)
await ImageEditor.ExportAsync("graphic.svg", ImageEditorFileType.SVG);
// Or press Ctrl+S to open export dialog with format selection
}Pattern 4: Privacy Redaction Workflow
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async Task RedactSensitiveInfo()
{
// Draw blur redaction over sensitive areas
await ImageEditor.DrawRedactAsync(
RedactType.Blur,
startX: 100, startY: 100,
width: 200, height: 50,
value: 30 // Blur intensity
);
// Draw pixelate redaction over other areas
await ImageEditor.DrawRedactAsync(
RedactType.Pixelate,
startX: 400, startY: 200,
width: 200, height: 50,
value: 20 // Pixel size
);
// Export redacted image
await ImageEditor.ExportAsync("redacted-document.png");
}
}Pattern 5: Professional Photo Framing
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async Task ApplyPhotoFrame()
{
// Load portrait image
await ImageEditor.OpenAsync("portrait.jpg");
// Apply classic mat frame with gradient
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#FFFFFF",
gradientColor: "#F5F5DC",
size: 50,
inset: 20
);
// Export framed image
await ImageEditor.ExportAsync("framed-portrait.png");
}
}Related Skills
- Implementing Blazor Components - Main library overview
- Implementing Carousels - Image carousel display
- Implementing Rich Text Editor - Text editing capabilities
---
Note: All code examples use Blazor component syntax. Refer to the Getting Started guide for setup instructions specific to your Blazor hosting model (WebAssembly, Web App, Server).
Accessibility and Localization in the Image Editor
Table of Contents
- WCAG Compliance
- Keyboard Navigation
- Screen Reader Support
- Color Contrast
- Localization Setup
- RTL Support
- Best Practices
WCAG Compliance
Accessibility Standards
The Syncfusion Image Editor adheres to WCAG 2.1 Level AA standards:
| Standard | Requirement | Implementation |
|---|---|---|
| 1.4.3 Contrast (AA) | Minimum 4.5:1 text contrast | Applied to all toolbar text |
| 2.1.1 Keyboard | Keyboard accessible | All functions support keyboard |
| 2.4.3 Focus Order | Logical focus order | Follows natural tab order |
| 3.3.1 Error Identification | Clear error messages | User feedback for invalid inputs |
| 4.1.2 Name, Role, Value | ARIA attributes | Proper semantic markup |
Accessibility Features
- Full keyboard navigation support
- Screen reader compatibility
- High contrast mode support
- Focus indicators visible
- Error messages clear and descriptive
Keyboard Navigation
Tab Navigation
Tab through toolbar items and controls:
Tab → Move forward through items
Shift+Tab → Move backward through itemsToolbar Navigation
Navigate toolbar with arrow keys:
Right Arrow → Next toolbar item
Left Arrow → Previous toolbar item
Enter/Space → Activate toolbar item
Escape → Exit toolbar focusAnnotation Navigation
Navigate inserted annotations:
Tab → Select next annotation
Shift+Tab → Select previous annotation
Enter → Edit selected annotation
Delete → Remove selected annotation
Escape → Deselect current annotationZoom and Pan Keyboard
Ctrl + '+' → Zoom in
Ctrl + '−' → Zoom out
Ctrl + '0' → Reset zoom
Arrow Keys → Pan image when zoomedFull Keyboard Workflow
Complete image editing without mouse:
// All keyboard accessible
1. Alt+O → Open image
2. Alt+C → Crop
3. Ctrl+Scroll → Zoom
4. Alt+A → Add annotation
5. Tab → Navigate annotations
6. Alt+S → SaveScreen Reader Support
ARIA Labels
Toolbar items announced with screen readers:
"Open image button"
"Crop button"
"Undo button"
"Zoom in button"
"Save button"Annotation Descriptions
Annotations described when selected:
"Text annotation: 'Important' at position 100, 200"
"Rectangle shape with red stroke"
"Freehand drawing selected"Status Updates
Screen reader announces state changes:
"Image loaded, 800 by 600 pixels"
"Zoom level 150 percent"
"Undo available"
"Redo unavailable"Image Information
Announce image properties when loaded:
private async void AnnounceImageLoaded()
{
ImageDimension dim = await ImageEditor.GetImageDimensionAsync();
// Screen readers announce:
// "Image loaded, dimensions {width} by {height}"
}Color Contrast
Contrast Standards
- Text on backgrounds: 4.5:1 or higher
- UI components: 3:1 or higher
- Focus indicators: Clear and distinct
Theme Compatibility
Themes meet contrast requirements:
- Bootstrap5: Compliant
- Fluent2: Compliant
- Material3: Compliant
- Tailwind3: Compliant
Custom Themes
When creating custom themes, maintain contrast:
/* Good contrast */
.toolbar {
background-color: #FFFFFF;
color: #000000;
/* 21:1 contrast ratio */
}
/* Acceptable contrast */
.toolbar-item {
background-color: #F5F5F5;
color: #333333;
/* 10:1 contrast ratio */
}
/* Poor contrast - AVOID */
.toolbar-item {
background-color: #F5F5F5;
color: #E8E8E8;
/* 1.3:1 contrast - fails WCAG AA */
}Localization Setup
Supported Languages
The Image Editor supports multiple language localizations through Syncfusion localization resources.
Supported Locales
| Locale | Language | Code |
|---|---|---|
| English | English | en |
| Spanish | Español | es |
| French | Français | fr |
| German | Deutsch | de |
| Italian | Italiano | it |
| Portuguese | Português | pt |
| Chinese (Simplified) | 简体中文 | zh |
| Japanese | 日本語 | ja |
| Arabic | العربية | ar |
| Russian | Русский | ru |
Custom Localization
Create custom localization resources:
@using Syncfusion.Blazor.ImageEditor
@using Syncfusion.Globalization
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
// Localization strings
var localeStrings = new Dictionary<string, object>()
{
{ "Open", "Abrir" },
{ "Crop", "Recortar" },
{ "Save", "Guardar" }
};
// Apply custom localization
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}Localized UI Text
All toolbar items automatically localize:
- Buttons translate based on locale
- Tooltips display in selected language
- Contextual menus localized
- Error messages translated
RTL Support
Enable Right-to-Left
Configure for RTL languages:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" EnableRtl="true">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}RTL Languages
- Arabic (ar)
- Hebrew (he)
- Persian (fa)
- Urdu (ur)
RTL Features
- Toolbar items mirror horizontally
- Menu dropdowns align to right
- Controls flip for RTL layout
- Text direction respected
- Annotation positioning adapted
CSS for RTL
[dir="rtl"] .e-toolbar {
direction: rtl;
text-align: right;
}
[dir="rtl"] .e-toolbar-item {
flex-direction: row-reverse;
}Browser Support
Accessibility Testing
Test in modern browsers:
- Chrome with Accessibility Audit
- Firefox with WAVE
- Safari with VoiceOver
- Edge with Narrator
Assistive Technology
Compatible with:
- Screen Readers: NVDA, JAWS, VoiceOver, Narrator
- Voice Control: Windows Speech Recognition, macOS Voice Control
- Switch Access: Single switch devices
- Magnification: ZoomText, built-in magnifiers
Best Practices
Design Considerations
1. Keyboard First
- Design for keyboard navigation
- Provide keyboard shortcuts for common tasks
- Test without mouse
2. Color Independence
- Don't rely on color alone for information
- Use icons and text labels together
- Maintain sufficient contrast
3. Focus Management
- Keep focus indicator visible
- Maintain logical tab order
- Announce focus changes to screen readers
4. Error Handling
- Provide clear error messages
- Suggest correction steps
- Announce errors to screen readers
Localization Best Practices
1. Use Standard Locales
- Stick to IETF language tags
- Test with native speakers
- Provide language selector
2. Handle Longer Text
- RTL languages need more horizontal space
- Asian languages need more vertical space
- Test layout with different languages
3. Date and Time Formats
- Respect locale date formats
- Use locale-aware parsing
- Display time in user's timezone
Accessibility Testing
// Test keyboard navigation
// 1. Open browser DevTools
// 2. Disable mouse (use keyboard only)
// 3. Navigate entire interface
// 4. Verify all functions accessible
// Test screen readers
// 1. Enable screen reader (Narrator, NVDA)
// 2. Navigate application
// 3. Verify all content announced
// 4. Check announcement order
// Test high contrast
// 1. Enable Windows High Contrast
// 2. Verify text readable
// 3. Check focus indicators visible
// 4. Confirm color contrast ratiosAccessibility Checklist
- [ ] All functions accessible via keyboard
- [ ] Tab order logical and visible
- [ ] Focus indicators clear and distinct
- [ ] Screen reader compatible
- [ ] Text contrast meets WCAG AA
- [ ] Images have alt text
- [ ] Error messages clear
- [ ] Labels associated with inputs
- [ ] Localization configured
- [ ] RTL tested
Accessibility and localization ensure the Image Editor is usable by everyone, regardless of ability or location.
Adjustments, Filters & Effects in the Image Editor
Overview
The Image Editor provides fine-tuning adjustments, filters, and frame effects to enhance and modify images. All effects are non-destructive and can be undone.
Fine-Tuning Adjustments
Available Adjustments
Fine-tuning provides slider-based controls for image adjustments:
- Brightness - Increase/decrease overall luminosity
- Contrast - Enhance difference between light and dark areas
- Saturation - Adjust color intensity
- Hue - Shift color tones
- Blur - Apply blur effect
- Shadow - Darken shadow areas
- Exposure - Adjust overall exposure level
Access Fine-Tuning
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Toolbar="@CustomToolbar">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private List<ImageEditorToolbarItemModel> CustomToolbar = new()
{
new ImageEditorToolbarItemModel { Name = "Open" },
new ImageEditorToolbarItemModel { Name = "Finetune" }, // Enable fine-tuning
new ImageEditorToolbarItemModel { Name = "Save" }
};
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}User workflow: 1. Click Fine-tune button in toolbar 2. Select an adjustment from dropdown 3. Use slider to adjust value 4. Preview updates in real-time 5. Click tick icon or canvas to apply
Adjustment Ranges
| Adjustment | Range | Default | Effect |
|---|---|---|---|
| Brightness | -100 to +100 | 0 | Darker to brighter |
| Contrast | -100 to +100 | 0 | Low to high contrast |
| Saturation | -100 to +100 | 0 | Grayscale to vivid |
| Hue | 0 to 360 | 0 | Color rotation |
| Blur | 0 to 100 | 0 | No blur to heavy blur |
| Shadow | -100 to +100 | 0 | Shadow adjustment |
| Exposure | -100 to +100 | 0 | Underexposed to overexposed |
Filters
Available Filters
Predefined filters for quick image enhancement:
- Chrome - Enhance metallic tones
- Cool - Add blue/cool color cast
- Warm - Add orange/warm color cast
- Grayscale - Convert to black and white
- Sepia - Add vintage brownish tone
- Invert - Invert all colors
- High Contrast - Increase overall contrast
- Blur - Apply blur effect
Apply Filters
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Toolbar="@CustomToolbar">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private List<ImageEditorToolbarItemModel> CustomToolbar = new()
{
new ImageEditorToolbarItemModel { Name = "Open" },
new ImageEditorToolbarItemModel { Name = "Filter" }, // Enable filters
new ImageEditorToolbarItemModel { Name = "Save" }
};
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}User workflow: 1. Click Filter button in toolbar 2. Select a filter from available options 3. Filter applies automatically 4. Preview updates immediately 5. Click tick to commit or canvas to cancel
Filter Effects
| Filter | Use Case |
|---|---|
| Chrome | Metal/industrial look |
| Cool | Night/underwater atmosphere |
| Warm | Sunset/golden hour feel |
| Grayscale | Professional/classic look |
| Sepia | Vintage/retro appearance |
| Invert | Negative/artistic effect |
| High Contrast | Enhanced clarity/drama |
| Blur | Background/soft focus |
Frame Effects
Apply Frames
Add decorative borders and frame effects to images:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Toolbar="@CustomToolbar">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private List<ImageEditorToolbarItemModel> CustomToolbar = new()
{
new ImageEditorToolbarItemModel { Name = "Open" },
new ImageEditorToolbarItemModel { Name = "Frame" }, // Enable frames
new ImageEditorToolbarItemModel { Name = "Save" }
};
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}User workflow: 1. Click Frame button in toolbar 2. Select a frame style 3. Frame applies to image 4. Preview shows final result 5. Click tick to apply or canvas to cancel
Frame Options
Common frame styles include:
- Solid color borders (various widths and colors)
- Decorative frames (ornate, minimalist, vintage)
- Mat styles (beveled, shadow effects)
- Professional photo frames
Combining Effects
Sequential Application
Apply multiple effects in sequence:
// Example workflow:
// 1. Adjust brightness
// 2. Apply warm filter
// 3. Add frame
// 4. Export
// User can undo any effect individuallyEach effect is tracked separately in undo/redo history.
Effect Preview
All effects show real-time preview:
- Adjustments update as slider moves
- Filters apply instantly
- Frames display immediately
- No permanent changes until committed
Best Practices
Workflow Tips
1. Adjust before filtering - Fine-tune exposure before color adjustments 2. Use filters sparingly - Too many filters create unnatural results 3. Test combinations - Different filter+adjustment combinations work better 4. Preview before export - Always check final result before saving 5. Use undo liberally - Experiment and undo unwanted effects
Quality Preservation
- Adjustments preserve image data better than filters
- High contrast adjustments can cause clipping
- Blur effects reduce sharpness permanently
- Grayscale conversion is reversible until export
Optimization
- Apply adjustments in order: brightness → contrast → saturation → hue
- Use filters for style, adjustments for correction
- Save high-quality versions before destructive effects
- Test exported results before permanent storage
Effect Combinations Examples
Example 1: Warm Sunset Photo
1. Increase brightness +20
2. Increase saturation +30
3. Increase warm tones (hue adjustment)
4. Apply warm filter
5. Optional: Add vintage frameExample 2: Professional Portrait
1. Slight brightness increase +10
2. Increase contrast +15
3. Apply cool filter subtly
4. Add soft focus (light blur)
5. No frame or minimal borderExample 3: Dramatic Black & White
1. Apply grayscale filter
2. Increase contrast +40
3. Optional: Increase shadows
4. No color adjustments (already grayscale)
5. Add vintage or film frameExample 4: Landscape Enhancement
1. Adjust exposure +15
2. Increase contrast +25
3. Increase saturation +15
4. Apply chrome filter for richness
5. Optional: Add nature-themed frameAll effects are cumulative and reversible until export. Use undo (Ctrl+Z) to revert any changes.
Annotation Styling in the Image Editor
Overview
Customize the appearance of annotations through stroke colors, fill colors, font styling, and event-based customization. All styling changes are tracked in undo/redo history.
Stroke Customization
Stroke Color and Width
Customize the border appearance of shapes and freehand drawings:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated" ShapeChanging="OnShapeChanging"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
private void OnShapeChanging(ShapeChangeEventArgs args)
{
// Customize all shapes
args.CurrentShapeSettings.StrokeColor = "red";
args.CurrentShapeSettings.StrokeWidth = 3;
}
}Color Formats
Supported color formats for stroke:
- Named colors: "red", "blue", "green", "yellow", "black", "white", "orange", "purple", "pink"
- Hex codes: "#FF0000", "#00FF00", "#0000FF"
- RGB: "rgb(255, 0, 0)"
- HSL: "hsl(0, 100%, 50%)"
Stroke Width
Set border thickness in pixels:
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.CurrentShapeSettings.Type == ShapeType.Rectangle)
{
args.CurrentShapeSettings.StrokeWidth = 5; // Thicker border
}
}Fill Colors
Shape Fill
Set the interior color of shapes:
private async void DrawFilledShape()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawRectangleAsync(
x: Dimension.X.Value + 50,
y: Dimension.Y.Value + 50,
width: 150,
height: 100,
strokeWidth: 2,
strokeColor: "black",
fillColor: "lightblue", // Fill interior
degree: 0,
isSelected: false,
borderRadius: 5
);
}Transparent Fill
Use transparent backgrounds:
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.CurrentShapeSettings.Type == ShapeType.Ellipse)
{
args.CurrentShapeSettings.FillColor = "transparent";
}
}Font Styling
Text Font Customization
private async void AddStyledText()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawTextAsync(
x: Dimension.X.Value,
y: Dimension.Y.Value,
text: "Styled Text",
fontFamily: "Georgia", // Font family
fontSize: 36, // Size in pixels
bold: true, // Bold style
italic: true, // Italic style
color: "darkblue" // Text color
);
}Font Family Options
Available font families (default):
- Arial
- Times New Roman
- Courier New
- Georgia
- Verdana
Custom Font Families
Add additional fonts using ImageEditorFontFamily:
<SfImageEditor @ref="ImageEditor" Height="400">
<ImageEditorFontFamily Items="@CustomItems" Default="Arial"></ImageEditorFontFamily>
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private List<ImageEditorDropDownItemModel> CustomItems = new()
{
new ImageEditorDropDownItemModel { Text = "Arial", Value = "arial" },
new ImageEditorDropDownItemModel { Text = "Brush Script MT", Value = "brush script mt" },
new ImageEditorDropDownItemModel { Text = "Papyrus", Value = "papyrus" },
new ImageEditorDropDownItemModel { Text = "Times New Roman", Value = "times new roman" },
new ImageEditorDropDownItemModel { Text = "Courier New", Value = "courier new" }
};
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}Font Size
Set text size in pixels:
// Small text (12px)
await ImageEditor.DrawTextAsync(x, y, "Small", "Arial", 12);
// Medium text (24px)
await ImageEditor.DrawTextAsync(x, y, "Medium", "Arial", 24);
// Large text (48px)
await ImageEditor.DrawTextAsync(x, y, "Large", "Arial", 48);ShapeChanging Event
Event Basics
The ShapeChanging event fires when annotations are created, selected, or modified:
private void OnShapeChanging(ShapeChangeEventArgs args)
{
// args.Action: "insert", "select", "draw"
// args.CurrentShapeSettings: Annotation properties
}Conditional Styling
Apply different styles based on shape type:
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.Action == "insert")
{
if (args.CurrentShapeSettings.Type == ShapeType.Text)
{
args.CurrentShapeSettings.Color = "darkblue";
args.CurrentShapeSettings.FontFamily = "Arial";
args.CurrentShapeSettings.FontSize = 24;
}
else if (args.CurrentShapeSettings.Type == ShapeType.Rectangle)
{
args.CurrentShapeSettings.StrokeColor = "black";
args.CurrentShapeSettings.StrokeWidth = 2;
args.CurrentShapeSettings.FillColor = "lightyellow";
}
else if (args.CurrentShapeSettings.Type == ShapeType.FreehandDraw)
{
args.CurrentShapeSettings.StrokeColor = "red";
args.CurrentShapeSettings.StrokeWidth = 3;
}
}
}Set Default Stroke Colors
Modify defaults while preserving user selections:
private void OnShapeChanging(ShapeChangeEventArgs args)
{
// Only set defaults on insert (new shapes)
if (args.Action == "insert")
{
// Set default for all new rectangles
if (args.CurrentShapeSettings.Type == ShapeType.Rectangle)
{
if (string.IsNullOrEmpty(args.CurrentShapeSettings.StrokeColor))
{
args.CurrentShapeSettings.StrokeColor = "blue";
}
}
}
}ShapeSettings Properties
Available Properties
| Property | Type | Example | Purpose |
|---|---|---|---|
ID | string | "shape_1" | Unique identifier |
Type | ShapeType | ShapeType.Text | Annotation type |
Color | string | "red" | Text/stroke color |
FillColor | string | "lightyellow" | Shape fill |
StrokeColor | string | "black" | Border color |
StrokeWidth | int | 3 | Border thickness |
FontFamily | string | "Arial" | Text font |
FontSize | int | 24 | Text size in px |
Bold | bool | true | Bold text |
Italic | bool | false | Italic text |
FontStyle | string[] | ["bold", "underline"] | Multiple styles |
Update Properties
Modify shapes after creation:
private async void UpdateShapeStyle()
{
ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0)
{
ShapeSettings shape = shapes[0];
shape.StrokeColor = "green";
shape.StrokeWidth = 4;
shape.FillColor = "lightgreen";
await ImageEditor.UpdateShapeAsync(shape);
}
}Practical Examples
Example 1: Watermark with Custom Style
private async void AddStyledWatermark()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawTextAsync(
x: Dimension.X.Value + 100,
y: Dimension.Y.Value + 100,
text: "© 2024 Company",
fontFamily: "Georgia",
fontSize: 40,
bold: true,
italic: false,
color: "white",
isSelected: false,
degree: -45, // Rotated
fillColor: "rgba(0,0,0,0.3)",
strokeColor: "black",
strokeWidth: 1
);
}Example 2: Contextual Shape Styling
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.Action == "insert")
{
// Mark important areas with red
if (args.CurrentShapeSettings.Type == ShapeType.Ellipse)
{
args.CurrentShapeSettings.StrokeColor = "red";
args.CurrentShapeSettings.StrokeWidth = 3;
args.CurrentShapeSettings.FillColor = "transparent";
}
// Label areas with blue text
if (args.CurrentShapeSettings.Type == ShapeType.Text)
{
args.CurrentShapeSettings.Color = "blue";
args.CurrentShapeSettings.FontSize = 20;
}
}
}Example 3: Consistent Brand Colors
private const string BRAND_BLUE = "#0052CC";
private const string BRAND_GRAY = "#F0F0F0";
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.Action == "insert")
{
args.CurrentShapeSettings.StrokeColor = BRAND_BLUE;
args.CurrentShapeSettings.FillColor = BRAND_GRAY;
args.CurrentShapeSettings.StrokeWidth = 2;
}
}All styling changes are immediately visible in the editor and tracked in undo/redo history.
Annotations in the Image Editor
Table of Contents
- Text Annotations
- Multiline Text
- Text Formatting
- Freehand Drawing
- Shape Annotations
- Image Annotations
- Managing Annotations
Text Annotations
Add Text
Insert text annotations at specific coordinates using DrawTextAsync:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
private async void AddSimpleText()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
// DrawTextAsync(x, y, text)
await ImageEditor.DrawTextAsync(Dimension.X.Value, Dimension.Y.Value, "Syncfusion");
}
}Text Customization Options
The DrawTextAsync method supports extensive customization:
private async void AddCustomText()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawTextAsync(
x: Dimension.X.Value + 50,
y: Dimension.Y.Value + 50,
text: "Custom Text",
fontFamily: "Arial", // Font family
fontSize: 40, // Font size in pixels
bold: true, // Bold style
italic: false, // Italic style
color: "red", // Text color
isSelected: false, // Selection state
degree: 0, // Rotation angle
fillColor: "yellow", // Background color
strokeColor: "blue", // Outline/border color
strokeWidth: 2 // Border width in pixels
);
}Text Color and Styling
private async void AddColoredText()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
// Red text with yellow background and blue outline
await ImageEditor.DrawTextAsync(
Dimension.X.Value, Dimension.Y.Value, "Important",
"Times New Roman", 32, false, false,
"red", // Text color
false, 0, "yellow", "blue", 3
);
}Color Format: Supported formats include:
- Named colors: "red", "blue", "green", "yellow", "black", "white", etc.
- Hex codes: "#FF0000", "#00FF00", "#0000FF"
- RGB: "rgb(255, 0, 0)"
Multiline Text
Add Multiline Annotations
Create text annotations spanning multiple lines using newline characters (\n):
private async void AddMultilineText()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
string multilineText = "Line 1\nLine 2\nLine 3";
await ImageEditor.DrawTextAsync(
Dimension.X.Value, Dimension.Y.Value,
multilineText,
"Arial", 24, false, false, "black"
);
}Output: Each line separated by newline character renders on its own line.
Text Formatting
Bold, Italic, Underline, Strikethrough
Apply text formatting styles:
private async void AddFormattedText()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
// Bold text
await ImageEditor.DrawTextAsync(
Dimension.X.Value, Dimension.Y.Value + 10,
"Bold Text",
"Arial", 28, true, false // bold=true, italic=false
);
// Italic text
await ImageEditor.DrawTextAsync(
Dimension.X.Value, Dimension.Y.Value + 50,
"Italic Text",
"Arial", 28, false, true // bold=false, italic=true
);
}Update Formatting After Creation
Modify formatting using ShapeChanging event:
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated" ShapeChanging="OnShapeChanging"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.CurrentShapeSettings.Type == ShapeType.Text)
{
args.CurrentShapeSettings.FontStyle = new[] { "bold", "underline" };
}
}
}Freehand Drawing
Enable Freehand Draw Mode
Activate freehand drawing to sketch directly on the image:
@using Syncfusion.Blazor.ImageEditor
@using Syncfusion.Blazor.Buttons
<div>
<SfButton OnClick="EnableFreehand">Enable Freehand Draw</SfButton>
<SfButton OnClick="DisableFreehand">Disable Freehand Draw</SfButton>
</div>
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
private async void EnableFreehand()
{
await ImageEditor.EnableFreehandDrawAsync();
}
private async void DisableFreehand()
{
await ImageEditor.DisableFreehandDrawAsync();
}
}Customize Freehand Stroke
private void OnShapeChanging(ShapeChangeEventArgs args)
{
if (args.CurrentShapeSettings.Type == ShapeType.FreehandDraw)
{
args.CurrentShapeSettings.StrokeColor = "red";
args.CurrentShapeSettings.StrokeWidth = 3;
}
}Shape Annotations
Rectangle
private async void DrawRectangle()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawRectangleAsync(
x: Dimension.X.Value + 10,
y: Dimension.Y.Value + 60,
width: 150,
height: 70,
strokeWidth: 2,
strokeColor: "black",
fillColor: "transparent",
degree: 0,
isSelected: false,
borderRadius: 5 // Rounded corners
);
}Ellipse
private async void DrawEllipse()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawEllipseAsync(
x: Dimension.X.Value, // Center X
y: Dimension.Y.Value + 200, // Center Y
radiusX: 80, // Horizontal radius
radiusY: 50, // Vertical radius
strokeWidth: 2,
strokeColor: "blue",
fillColor: "lightblue",
degree: 0,
isSelected: false
);
}Line
private async void DrawLine()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawLineAsync(
startX: Dimension.X.Value + 100,
startY: Dimension.Y.Value + 50,
endX: Dimension.X.Value + 300,
endY: Dimension.Y.Value + 50,
strokeWidth: 3,
strokeColor: "green",
isSelected: false
);
}Arrow
private async void DrawArrow()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawArrowAsync(
startX: Dimension.X.Value + 150,
startY: Dimension.Y.Value + 150,
endX: Dimension.X.Value + 300,
endY: Dimension.Y.Value + 150,
strokeWidth: 3,
strokeColor: "red",
arrowStart: ImageEditorArrowHeadType.None, // No arrow at start
arrowEnd: ImageEditorArrowHeadType.SolidArrow, // Arrow at end
isSelected: false
);
}Path
private async Task DrawPath()
{
ImageDimension dimension = await ImageEditor.GetImageDimensionAsync();
ImageEditorPoint[] points = new ImageEditorPoint[]
{
new ImageEditorPoint { X = dimension.X.Value, Y = dimension.Y.Value },
new ImageEditorPoint { X = dimension.X.Value + 50, Y = dimension.Y.Value + 50 },
new ImageEditorPoint { X = dimension.X.Value + 20, Y = dimension.Y.Value + 50 }
};
await ImageEditor.DrawPathAsync(
points: points,
strokeWidth: 3,
strokeColor: "purple",
isSelected: false
);
}Image Annotations
Add Image Overlay
Insert images, logos, or watermarks:
private async void AddImageAnnotation()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
await ImageEditor.DrawImageAsync(
data: "YOUR_IMAGE_URL", // Image URL or data
x: Dimension.X.Value,
y: Dimension.Y.Value,
width: 200,
height: 200,
isAspectRatio: true, // Maintain aspect ratio
degree: 0, // Rotation
opacity: 1.0, // Opacity (0-1)
isSelected: false
);
}Managing Annotations
Delete Annotations
Remove specific annotations by ID:
private async void DeleteAnnotation()
{
// Get all annotations
ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0)
{
// Delete first annotation
await ImageEditor.DeleteShapeAsync(shapes[0].ID);
}
}Each annotation has a unique ID automatically assigned.
Get All Annotations
private async void ListAnnotations()
{
ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
foreach (var shape in shapes)
{
// Access shape properties
var type = shape.Type; // ShapeType (Text, Rectangle, etc.)
var id = shape.ID; // Unique identifier
var color = shape.Color; // Color property
}
}Update Annotations
Modify annotation properties:
private async void UpdateAnnotation()
{
ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0)
{
shapes[0].StrokeColor = "red";
shapes[0].StrokeWidth = 5;
await ImageEditor.UpdateShapeAsync(shapes[0]);
}
}Annotation Events
ShapeChanging Event
Triggered when annotations are modified:
private void OnShapeChanging(ShapeChangeEventArgs args)
{
// args.Action: "insert", "select", "draw"
// args.CurrentShapeSettings: Current annotation properties
if (args.Action == "insert")
{
// New annotation being added
}
}All annotations are tracked in undo/redo history.
Advanced Annotation Methods
DrawTextAsync with Complete Parameters
The full DrawTextAsync method supports additional text formatting:
csharp Task<bool> DrawTextAsync( double x = -1, double y = -1, string text = "", string fontFamily = "", int fontSize = -1, bool bold = false, bool italic = false, string color = "", bool isSelected = false, int degree = -1, string fillColor = "", string strokeColor = "", int strokeWidth = -1, bool underline = false, // NEW bool strikethrough = false // NEW )
Text with Underline and Strikethrough
`csharp private async void AddFormattedText() { ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
// Underlined text await ImageEditor.DrawTextAsync( x: Dimension.X.Value, y: Dimension.Y.Value + 10, text: "Underlined Text", fontFamily: "Arial", fontSize: 24, bold: false, italic: false, color: "black", isSelected: false, degree: 0, fillColor: "", strokeColor: "", strokeWidth: -1, underline: true, // Underline strikethrough: false );
// Strikethrough text await ImageEditor.DrawTextAsync( x: Dimension.X.Value, y: Dimension.Y.Value + 50, text: "Strikethrough Text", fontFamily: "Arial", fontSize: 24, bold: false, italic: false, color: "red", isSelected: false, degree: 0, fillColor: "", strokeColor: "", strokeWidth: -1, underline: false, strikethrough: true // Strikethrough );
// Combined formatting await ImageEditor.DrawTextAsync( x: Dimension.X.Value, y: Dimension.Y.Value + 90, text: "Bold Underlined", fontFamily: "Arial", fontSize: 24, bold: true, italic: false, color: "blue", isSelected: false, degree: 0, fillColor: "", strokeColor: "", strokeWidth: -1, underline: true, strikethrough: false ); } `
Annotation Z-Order Management
Control the stacking order of annotations with z-order methods.
Bring to Front
Move an annotation to the top of all other annotations:
`csharp private async Task BringAnnotationToFront() { ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0) { // Move first shape to front await ImageEditor.BringToFrontAsync(shapes[0].ID); } } `
Send to Back
Move an annotation behind all other annotations:
`csharp private async Task SendAnnotationToBack() { ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0) { // Move first shape to back await ImageEditor.SendToBackAsync(shapes[0].ID); } } `
Bring Forward
Move an annotation one layer forward:
`csharp private async Task MoveAnnotationForward() { ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0) { // Move one layer forward await ImageEditor.BringForwardAsync(shapes[0].ID); } } `
Send Backward
Move an annotation one layer backward:
`csharp private async Task MoveAnnotationBackward() { ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0) { // Move one layer backward await ImageEditor.SendBackwardAsync(shapes[0].ID); } } `
Z-Order Use Cases
Layering text over shapes: `csharp // 1. Draw background rectangle await ImageEditor.DrawRectangleAsync(100, 100, 300, 150, 2, "black", "lightyellow");
// 2. Draw text await ImageEditor.DrawTextAsync(150, 150, "Label", "Arial", 24);
// 3. If text is behind, bring it forward ShapeSettings[] shapes = await ImageEditor.GetShapesAsync(); string textShapeId = shapes.FirstOrDefault(s => s.Type == ShapeType.Text)?.ID; if (textShapeId != null) { await ImageEditor.BringToFrontAsync(textShapeId); } `
Organizing complex annotations: `csharp // Move important annotations to front foreach (var shape in importantShapes) { await ImageEditor.BringToFrontAsync(shape.ID); }
// Send background elements to back foreach (var shape in backgroundShapes) { await ImageEditor.SendToBackAsync(shape.ID); } `
Clone Annotations
Duplicate existing annotations:
`csharp private async Task DuplicateAnnotation() { ShapeSettings[] shapes = await ImageEditor.GetShapesAsync();
if (shapes != null && shapes.Length > 0) { // Clone first annotation bool success = await ImageEditor.CloneShapeAsync(shapes[0].ID);
if (success) { Console.WriteLine("Annotation cloned successfully"); } } } `
Use Cases:
- Duplicate watermarks across image
- Create pattern of similar annotations
- Quick copy of styled elements
Enable/Disable Annotation Modes
Control annotation drawing modes programmatically:
Enable Specific Annotation
`csharp private async Task EnableRectangleDrawing() { // Enable rectangle drawing mode await ImageEditor.EnableActiveAnnotationAsync(ShapeType.Rectangle);
// User can now draw multiple rectangles // Drawing continues until disabled }
private async Task EnableTextAnnotation() { // Enable text annotation mode await ImageEditor.EnableActiveAnnotationAsync(ShapeType.Text); }
private async Task EnableFreehandDrawing() { // Enable freehand drawing await ImageEditor.EnableActiveAnnotationAsync(ShapeType.FreehandDraw); } `
Disable Annotation Mode
`csharp private async Task StopDrawing() { // Disable current annotation mode await ImageEditor.DisableActiveAnnotationAsync();
// User can no longer draw the current annotation type } `
Available ShapeTypes for EnableActiveAnnotationAsync
- ShapeType.Rectangle
- ShapeType.Ellipse
- ShapeType.Line
- ShapeType.Arrow
- ShapeType.Path
- ShapeType.Text
- ShapeType.FreehandDraw
- ShapeType.Image
Annotation Mode Workflow
`csharp // Pattern: Toggle annotation mode private bool isDrawingMode = false;
private async Task ToggleDrawingMode() { if (isDrawingMode) { await ImageEditor.DisableActiveAnnotationAsync(); isDrawingMode = false; Console.WriteLine("Drawing mode disabled"); } else { await ImageEditor.EnableActiveAnnotationAsync(ShapeType.Rectangle); isDrawingMode = true; Console.WriteLine("Rectangle drawing enabled"); } } `
Enable Text Editing
Allow editing of text annotations:
`csharp private async Task EnableTextEdit() { // Enable text editing mode await ImageEditor.EnableTextEditingAsync();
// User can now edit text annotations by clicking them } `
Use Cases:
- Modify existing text annotations
- Correct typos
- Update labels
All advanced annotation methods support undo/redo and are tracked in history.
Core Operations in the Image Editor
Table of Contents
Opening Images
Using the Open Button
Users can open images through the toolbar's Open button:
1. Click the Open icon on the toolbar 2. File explorer displays JPEG, PNG, JPG, WEBP, and BMP files 3. Select an image to load it into the editor
Supported formats: JPEG, PNG, JPG, WEBP, BMP
Programmatic Image Loading
Load images programmatically using the OpenAsync method with full control over image rendering.
Complete Method Signature:
Task OpenAsync(
object data,
bool resetChanges = true,
string fillColor = "",
int width = -1,
int height = -1,
bool isAspectRatio = false
)Parameters:
- data (object): URL string or image data URL to open
- resetChanges (bool): Reset all existing changes when opening (default: true)
- fillColor (string): Background color for transparent images (default: empty/transparent)
- width (int): Target width to render on canvas (default: -1 for original)
- height (int): Target height to render on canvas (default: -1 for original)
- isAspectRatio (bool): Maintain aspect ratio when scaling (default: false)
The component ImageEditorProgrammaticLoading.razor demonstrates 4 loading methods:
1. From URL — Load remote images (web URLs, blob storage URLs with SAS tokens) 2. From File Input — User uploads local files (converted to base64 data URLs) 3. From Azure Blob Storage — Load from Azure with SAS token (requires CORS) 4. From Sample Images — Preloaded demo images
Quick Start: Navigate to /image-editor-loading to try all loading methods interactively.
Load from URL (Basic)
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
// Simple load - resets all changes
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}Load with Advanced Options
private async Task LoadImageWithOptions()
{
// Load with specific dimensions and background
await ImageEditor.OpenAsync(
data: "YOUR_TRANSPARENT_LOGO_URL",
resetChanges: false, // Keep existing edits
fillColor: "#FFFFFF", // White background for transparency
width: 800, // Target width
height: 600, // Target height
isAspectRatio: true // Maintain aspect ratio
);
}
private async Task LoadWithoutReset()
{
// Load new image without clearing undo history
await ImageEditor.OpenAsync(
"YOUR_IMAGE_URL",
resetChanges: false
);
}
private async Task LoadTransparentWithBackground()
{
// Handle transparent PNGs with colored background
await ImageEditor.OpenAsync(
"YOUR_ICON_URL",
resetChanges: true,
fillColor: "#F0F0F0" // Light gray background
);
}Use Cases:
- Remote image URLs (web URLs)
- Azure Blob Storage URLs with SAS tokens
- CDN-hosted images
- Any accessible HTTP(S) URL with proper CORS headers
- Loading transparent images with backgrounds
- Resizing images on load
- Preserving edit history across image loads
Load from File Input
private async Task LoadFromFileAsync(InputFileChangeEventArgs e)
{
try
{
var file = e.File;
using var stream = file.OpenReadStream(maxAllowedSize: 5 * 1024 * 1024);
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
// Convert to base64 data URL
var base64 = Convert.ToBase64String(ms.ToArray());
var dataUrl = $"data:{file.ContentType};base64,{base64}";
await imageEditor.OpenAsync(dataUrl);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
// In markup:
// <input type="file" @onchange="LoadFromFileAsync" accept="image/*" />Key Points:
- Accepts JPEG, PNG, WEBP, BMP files
- Converts file to base64 for in-memory editing
- Max file size: 5 MB (configurable)
- Works offline (no network required)
- File stays in browser memory; not uploaded unless exported
Load from Azure Blob Storage
private async Task LoadFromBlobAsync()
{
try
{
string blobUrl = "https://<account>.blob.core.windows.net/<container>/<blob>?<SAS_token>";
await imageEditor.OpenAsync(blobUrl);
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}Requirements:
- Valid Azure Blob Storage URL
- Include SAS token for authentication
- Enable CORS on blob container:
Allowed origins: https://yourdomain.com
Allowed methods: GET
Max age: 3600- If CORS unavailable, proxy the blob through your backend API
Getting Image Dimensions
Retrieve the current image dimensions and coordinates:
private async void GetImageInfo()
{
ImageDimension Dimension = await ImageEditor.GetImageDimensionAsync();
double x = Dimension.X.Value; // X-coordinate
double y = Dimension.Y.Value; // Y-coordinate
double width = Dimension.Width.Value;
double height = Dimension.Height.Value;
}Use this to position annotations or calculate layout relative to the image.
Saving and Exporting Images
Export using Toolbar Button
Click the Save button on the toolbar to export the modified image:
1. Save button opens the export dialog 2. Choose file format: PNG, JPEG, SVG, or WEBP 3. For JPEG, adjust quality (Good, Great, Highest, or 0-100 slider) 4. Click Download to save
Quick Export with Keyboard Shortcut
Press Ctrl+S to export with minimal dialog interaction:
// Keyboard shortcut handled automatically
// Ctrl+S downloads in the same format as the loaded imageProgrammatic Export with ExportAsync
Export images programmatically using the ExportAsync method with full control over format and quality.
Method Signature:
Task ExportAsync(
string fileName = "",
ImageEditorFileType fileType = ImageEditorFileType.PNG,
double imageQuality = 1
)Parameters:
- fileName (string): Name of the exported file (optional, defaults to original name)
- fileType (ImageEditorFileType): Export format - PNG, JPEG, SVG, or WEBP (default: PNG)
- imageQuality (double): Quality for JPEG exports, 0.0 to 1.0 (default: 1.0)
Basic Export Examples:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
// Export as PNG (lossless, default)
private async Task ExportAsPNG()
{
await ImageEditor.ExportAsync("edited-image.png");
// or
await ImageEditor.ExportAsync("edited-image.png", ImageEditorFileType.PNG);
}
// Export as JPEG with quality control
private async Task ExportAsJPEG()
{
// High quality (100%)
await ImageEditor.ExportAsync("photo.jpg", ImageEditorFileType.JPEG, 1.0);
// Good quality (85%)
await ImageEditor.ExportAsync("photo.jpg", ImageEditorFileType.JPEG, 0.85);
// Medium quality (60%)
await ImageEditor.ExportAsync("photo.jpg", ImageEditorFileType.JPEG, 0.6);
}
// Export as WEBP
private async Task ExportAsWEBP()
{
await ImageEditor.ExportAsync("image.webp", ImageEditorFileType.WEBP);
}
// Export as SVG (vector format)
private async Task ExportAsSVG()
{
await ImageEditor.ExportAsync("graphic.svg", ImageEditorFileType.SVG);
}
// Export with original filename (format only)
private async Task ChangeFormatOnly()
{
// Keeps original filename, changes format
await ImageEditor.ExportAsync("", ImageEditorFileType.JPEG, 0.9);
}
}Use Cases:
- Automated batch processing workflows
- Server-side image processing
- Custom export buttons with specific formats
- Quality optimization for web vs. print
- Format conversion without user interaction
Export Formats
| Format | Quality | Use Case |
|---|---|---|
| PNG | Lossless | Graphics, transparent backgrounds |
| JPEG | Adjustable (0-100) | Photos, compressed images |
| SVG | Vector | Scalable graphics, logos |
| WEBP | Compressed | Web optimization, modern browsers |
JPEG Quality Settings
When exporting as JPEG:
- Good: ~60% quality
- Great: ~80% quality
- Highest: ~95% quality
- Custom Slider: 0-100 range
Higher quality retains more detail but increases file size.
Undo and Redo Operations
Undo Changes
Undo the last operation using the toolbar button or keyboard:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" AllowUndoRedo="true">
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async Task UndoLastAction()
{
// Programmatic undo
await ImageEditor.UndoAsync();
}
private async Task CheckUndoAvailability()
{
bool canUndo = await ImageEditor.CanUndoAsync();
if (canUndo)
{
Console.WriteLine("Undo is available");
}
}
// Keyboard: Ctrl+Z
// Or click Undo button on toolbar
}Keyboard shortcut: Ctrl+Z
Redo Changes
Redo the last undone operation:
private async Task RedoLastAction()
{
// Programmatic redo
await ImageEditor.RedoAsync();
}
private async Task CheckRedoAvailability()
{
bool canRedo = await ImageEditor.CanRedoAsync();
if (canRedo)
{
Console.WriteLine("Redo is available");
}
}
// Keyboard: Ctrl+Y
// Or click Redo button on toolbarKeyboard shortcut: Ctrl+Y
Undo/Redo Behavior
- Undo button becomes enabled after the first operation
- Redo button becomes enabled after an undo action
- All operations are tracked: transformations, annotations, filters, adjustments
- Undo/redo stack persists for the session
- History is limited to 16 actions (oldest actions are removed after 16)
AllowUndoRedo Property
Control undo/redo functionality:
// Enable undo/redo (default)
<SfImageEditor AllowUndoRedo="true" Height="500px"></SfImageEditor>
// Disable undo/redo
<SfImageEditor AllowUndoRedo="false" Height="500px"></SfImageEditor>Note: When AllowUndoRedo is false, undo/redo methods return without action and history is not tracked.
Reset Image
Reset to Original
Revert all modifications and return the image to its original state:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Toolbar="@CustomToolbar">
</SfImageEditor>
@code {
private List<ImageEditorToolbarItemModel> CustomToolbar = new()
{
new ImageEditorToolbarItemModel { Name = "Reset" }
};
}Click the Reset button on the toolbar to discard all changes. This action:
- Reverts all transformations (crop, rotate, flip)
- Removes all annotations
- Clears all filters and adjustments
- Returns the image to loaded state
Note: Reset is permanent for the current session. Changes are not undone step-by-step.
Keyboard Shortcuts
Navigation and Zoom
| Shortcut | Action |
|---|---|
Ctrl + + | Zoom in |
Ctrl + − | Zoom out |
Ctrl + 0 | Fit image to window |
| Arrow Keys | Pan image (when zoomed) |
Editing Operations
| Shortcut | Action |
|---|---|
Ctrl + Z | Undo last operation |
Ctrl + Y | Redo last undone operation |
Ctrl + S | Save/Export image |
Delete | Delete selected annotation |
Annotation
| Shortcut | Action |
|---|---|
Ctrl + Click | Multi-select annotations |
Escape | Deselect current annotation |
Enter | Confirm annotation edit |
Common Workflows
Quick zoom and pan workflow:
Ctrl+Scroll → Zoom
Drag → Pan
Ctrl+Z → Undo zoom
Ctrl+S → SaveAnnotation workflow:
Click annotation tool
Draw annotation
Escape → Deselect
Delete → Remove
Ctrl+Z → Undo drawingAll keyboard shortcuts are non-blocking and work alongside mouse interactions.
Additional Core Methods
Apply and Discard Changes
Control when edits are committed:
`csharp private async Task CommitAnnotations() { // Apply current annotation drawings await ImageEditor.ApplyAsync(); }
private async Task CancelAnnotations() { // Discard current annotation drawings await ImageEditor.DiscardAsync(); } `
Use Cases:
- Commit freehand drawings
- Finalize annotation edits
- Cancel in-progress annotations
Clear Image
Remove the loaded image and reset the editor:
`csharp private async Task ClearEditor() { // Clear loaded image await ImageEditor.ClearImageAsync();
// Editor returns to initial empty state } `
Refresh Component
Force re-render of the Image Editor:
csharp private async Task ForceRefresh() { // Re-render the component await ImageEditor.RefreshAsync(); }
Use Cases:
- Fix rendering issues
- Update after external state changes
- Synchronize after dynamic updates
Get Image Data
Retrieve image data for storage or processing:
`csharp private async Task GetImageForStorage() { // Get as byte array byte[] imageData = await ImageEditor.GetImageDataAsync();
// Save to file system or database await SaveToDatabase(imageData); }
private async Task GetImageDataUrl() { // Get as data URL string string dataUrl = await ImageEditor.GetImageDataUrlAsync();
// Can include or exclude annotations string withAnnotations = await ImageEditor.GetImageDataUrlAsync(includeAnnotations: true); string withoutAnnotations = await ImageEditor.GetImageDataUrlAsync(includeAnnotations: false);
// Save to database or display in <img> tag } `
GetImageDataAsync() Returns:
- Byte array suitable for file I/O
- Use to render in canvas
- Can be passed back to
OpenAsync()
GetImageDataUrlAsync() Returns:
- Base64-encoded data URL string
- Ready for
<img src="">display - Can be saved to database
includeAnnotationsparameter controls whether annotations are included
Events Reference for the Image Editor
Overview
The Image Editor provides comprehensive event support through the ImageEditorEvents component. Events are triggered before and after operations, enabling validation, customization, and tracking of user actions.
Table of Contents
- Event Structure
- Lifecycle Events
- File Operations Events
- Transformation Events
- Shape and Annotation Events
- Adjustment Events
- User Interaction Events
- Toolbar Events
- Event Arguments Reference
Event Structure
ImageEditorEvents Component
All events are configured within the ImageEditorEvents component:
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents
Created="OnCreated"
Destroyed="OnDestroyed"
FileOpened="OnFileOpened"
Saving="OnSaving"
Cropping="OnCropping"
Cropped="OnCropped"
Rotating="OnRotating"
Rotated="OnRotated"
Flipping="OnFlipping"
Flipped="OnFlipped"
ShapeChanging="OnShapeChanging"
ShapeChanged="OnShapeChanged"
ImageFiltering="OnImageFiltering"
ImageFiltered="OnImageFiltered"
FinetuneValueChanging="OnFinetuneValueChanging"
FinetuneValueChanged="OnFinetuneValueChanged"
FrameChanging="OnFrameChanging"
FrameChanged="OnFrameChanged"
ImageResizing="OnImageResizing"
ImageResized="OnImageResized"
Zooming="OnZooming"
Zoomed="OnZoomed"
OnPanStart="OnPanStart"
OnPanEnd="OnPanEnd"
OnShapeResizeStart="OnShapeResizeStart"
OnShapeResizeEnd="OnShapeResizeEnd"
OnShapeDragStart="OnShapeDragStart"
OnShapeDragEnd="OnShapeDragEnd"
OnSelectionResizeStart="OnSelectionResizeStart"
OnSelectionResizeEnd="OnSelectionResizeEnd"
ToolbarUpdating="OnToolbarUpdating"
ToolbarItemClicked="OnToolbarItemClicked"
QuickAccessToolbarOpening="OnQuickAccessToolbarOpening"
HistoryChanged="OnHistoryChanged"
Clicked="OnClicked">
</ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
// Event handler implementations...
}Lifecycle Events
Created Event
Triggered after the Image Editor component is initialized and rendered.
private async void OnCreated()
{
Console.WriteLine("Image Editor initialized");
// Load initial image
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
// Configure settings
// Ready to use all component methods
}Use Cases:
- Load initial images
- Configure component settings
- Initialize application state
- Set default values
Destroyed Event
Triggered before the Image Editor component is destroyed.
private void OnDestroyed()
{
Console.WriteLine("Image Editor destroyed");
// Clean up resources
// Save state if needed
// Remove event listeners
}Use Cases:
- Resource cleanup
- Save user preferences
- Cancel pending operations
- Log component lifecycle
File Operations Events
FileOpened Event
Triggered after an image is successfully opened in the editor.
private void OnFileOpened(FileOpenEventArgs args)
{
Console.WriteLine($"File opened: {args.FileName}");
Console.WriteLine($"File size: {args.FileSize} bytes");
Console.WriteLine($"File type: {args.FileType}");
// Update UI
// Log file information
// Enable/disable features based on file type
}FileOpenEventArgs Properties:
FileName(string): Name of the opened fileFileSize(long): File size in bytesFileType(ImageEditorFileType): File format (PNG, JPEG, etc.)
Saving Event
Triggered before the image is saved/exported.
private void OnSaving(SaveEventArgs args)
{
Console.WriteLine($"Saving as: {args.FileName}");
Console.WriteLine($"Format: {args.FileType}");
Console.WriteLine($"Quality: {args.ImageQuality}");
// Validate file name
// Check disk space
// Show progress indicator
// Cancel save if needed
// args.Cancel = true;
}SaveEventArgs Properties:
FileName(string): Target file nameFileType(ImageEditorFileType): Export formatImageQuality(double): Quality for JPEG (0-1)Cancel(bool): Set to true to cancel operation
Transformation Events
Cropping Event
Triggered before crop operation is applied.
private void OnCropping(CropEventArgs args)
{
Console.WriteLine("Crop operation starting");
Console.WriteLine($"Crop area: {args.StartX}, {args.StartY}");
Console.WriteLine($"Dimensions: {args.Width}x{args.Height}");
// Validate crop dimensions
if (args.Width < 100 || args.Height < 100)
{
Console.WriteLine("Crop area too small");
args.Cancel = true;
}
}CropEventArgs Properties:
StartX(double): X-coordinate of crop regionStartY(double): Y-coordinate of crop regionWidth(double): Crop widthHeight(double): Crop heightCancel(bool): Cancel the operation
Cropped Event
Triggered after crop operation is completed.
private void OnCropped(CroppedEventArgs args)
{
Console.WriteLine("Crop completed");
Console.WriteLine($"New dimensions: {args.Width}x{args.Height}");
// Update UI
// Log action
// Notify user
}CroppedEventArgs Properties:
Width(double): Final image widthHeight(double): Final image height
Rotating Event
Triggered before rotation is applied.
private void OnRotating(RotateEventArgs args)
{
Console.WriteLine($"Rotating by {args.Degree} degrees");
// Validate rotation
// Show loading indicator
// Cancel if needed
// args.Cancel = true;
}RotateEventArgs Properties:
Degree(int): Rotation angleCancel(bool): Cancel the operation
Rotated Event
Triggered after rotation is completed.
private void OnRotated(RotatedEventArgs args)
{
Console.WriteLine($"Rotation completed: {args.Degree} degrees");
// Update UI
// Enable undo button
}RotatedEventArgs Properties:
Degree(int): Applied rotation angle
Flipping Event
Triggered before flip operation.
private void OnFlipping(FlipEventArgs args)
{
Console.WriteLine($"Flipping: {args.Direction}");
// Validate flip
// Show indicator
// Cancel if needed
// args.Cancel = true;
}FlipEventArgs Properties:
Direction(ImageEditorDirection): Horizontal or VerticalCancel(bool): Cancel the operation
Flipped Event
Triggered after flip operation is completed.
private void OnFlipped(FlippedEventArgs args)
{
Console.WriteLine($"Flipped: {args.Direction}");
// Update UI
}FlippedEventArgs Properties:
Direction(ImageEditorDirection): Applied flip direction
Shape and Annotation Events
ShapeChanging Event
Triggered when a shape is being inserted, selected, or modified.
private void OnShapeChanging(ShapeChangeEventArgs args)
{
Console.WriteLine($"Action: {args.Action}");
Console.WriteLine($"Shape Type: {args.CurrentShapeSettings.Type}");
// Customize shape appearance
if (args.Action == "insert")
{
if (args.CurrentShapeSettings.Type == ShapeType.Text)
{
args.CurrentShapeSettings.Color = "blue";
args.CurrentShapeSettings.FontSize = 24;
}
else if (args.CurrentShapeSettings.Type == ShapeType.Rectangle)
{
args.CurrentShapeSettings.StrokeColor = "red";
args.CurrentShapeSettings.StrokeWidth = 3;
}
}
// Cancel if needed
// args.Cancel = true;
}ShapeChangeEventArgs Properties:
Action(string): "insert", "select", "drag", "resize"CurrentShapeSettings(ShapeSettings): Shape propertiesPreviousShapeSettings(ShapeSettings): Previous stateCancel(bool): Cancel the operation
ShapeChanged Event
Triggered after shape modification is completed.
private void OnShapeChanged(ShapeChangedEventArgs args)
{
Console.WriteLine("Shape updated");
Console.WriteLine($"Shape ID: {args.CurrentShapeSettings.ID}");
// Log changes
// Update UI
}ShapeChangedEventArgs Properties:
CurrentShapeSettings(ShapeSettings): Updated shape propertiesPreviousShapeSettings(ShapeSettings): Previous state
OnShapeResizeStart Event
Triggered when shape resizing begins.
private void OnShapeResizeStart(ShapeChangeEventArgs args)
{
Console.WriteLine($"Resizing shape: {args.CurrentShapeSettings.ID}");
// Show resize handles
// Lock aspect ratio if needed
}OnShapeResizeEnd Event
Triggered when shape resizing ends.
private void OnShapeResizeEnd(ShapeChangeEventArgs args)
{
Console.WriteLine($"Resize complete: {args.CurrentShapeSettings.Width}x{args.CurrentShapeSettings.Height}");
// Update UI
// Save changes
}OnShapeDragStart Event
Triggered when shape dragging begins.
private void OnShapeDragStart(ShapeChangeEventArgs args)
{
Console.WriteLine($"Dragging shape: {args.CurrentShapeSettings.ID}");
// Show drag cursor
// Highlight drop zones
}OnShapeDragEnd Event
Triggered when shape dragging ends.
private void OnShapeDragEnd(ShapeChangeEventArgs args)
{
Console.WriteLine($"Drop position: ({args.CurrentShapeSettings.StartX}, {args.CurrentShapeSettings.StartY})");
// Validate position
// Update layout
}Adjustment Events
ImageFiltering Event
Triggered before a filter is applied.
private void OnImageFiltering(ImageFilterEventArgs args)
{
Console.WriteLine($"Applying filter: {args.Filter}");
// Validate filter
// Show preview
// Cancel if needed
// args.Cancel = true;
}ImageFilterEventArgs Properties:
Filter(ImageFilterOption): Filter typeCancel(bool): Cancel the operation
ImageFiltered Event
Triggered after a filter is applied.
private void OnImageFiltered(ImageFilteredEventArgs args)
{
Console.WriteLine($"Filter applied: {args.Filter}");
// Update UI
// Enable undo
}ImageFilteredEventArgs Properties:
Filter(ImageFilterOption): Applied filter
FinetuneValueChanging Event
Triggered when finetune adjustment value is changing.
private void OnFinetuneValueChanging(FinetuneEventArgs args)
{
Console.WriteLine($"Adjusting {args.FinetuneOption}: {args.Value}");
// Show live preview
// Validate range
// Cancel if needed
// args.Cancel = true;
}FinetuneEventArgs Properties:
FinetuneOption(ImageFinetuneOption): Adjustment typeValue(int): Adjustment valueCancel(bool): Cancel the operation
FinetuneValueChanged Event
Triggered after finetune adjustment is applied.
private void OnFinetuneValueChanged(FinetuneValueChangedEventArgs args)
{
Console.WriteLine($"Applied {args.FinetuneOption}: {args.Value}");
// Update UI
// Save state
}FinetuneValueChangedEventArgs Properties:
FinetuneOption(ImageFinetuneOption): Adjustment typeValue(int): Applied value
FrameChanging Event
Triggered before a frame is applied.
private void OnFrameChanging(FrameChangeEventArgs args)
{
Console.WriteLine($"Applying frame: {args.FrameType}");
// Validate frame
// Show preview
// Cancel if needed
// args.Cancel = true;
}FrameChangeEventArgs Properties:
FrameType(FrameType): Frame typeCancel(bool): Cancel the operation
FrameChanged Event
Triggered after a frame is applied.
private void OnFrameChanged(FrameChangedEventArgs args)
{
Console.WriteLine($"Frame applied: {args.FrameType}");
// Update UI
}FrameChangedEventArgs Properties:
FrameType(FrameType): Applied frame type
ImageResizing Event
Triggered before image resize operation.
private void OnImageResizing(ImageResizeEventArgs args)
{
Console.WriteLine($"Resizing to: {args.Width}x{args.Height}");
// Validate dimensions
// Check aspect ratio
// Cancel if needed
// args.Cancel = true;
}ImageResizeEventArgs Properties:
Width(int): Target widthHeight(int): Target heightIsAspectRatio(bool): Maintain aspect ratioCancel(bool): Cancel the operation
ImageResized Event
Triggered after image is resized.
private void OnImageResized(ImageResizedEventArgs args)
{
Console.WriteLine($"Resized to: {args.Width}x{args.Height}");
// Update UI
}ImageResizedEventArgs Properties:
Width(int): New widthHeight(int): New height
User Interaction Events
Zooming Event
Triggered before zoom operation.
private void OnZooming(ZoomEventArgs args)
{
Console.WriteLine($"Zoom level: {args.ZoomFactor}");
Console.WriteLine($"Zoom trigger: {args.ZoomTrigger}");
// Validate zoom level
// Show zoom indicator
// Cancel if needed
// args.Cancel = true;
}ZoomEventArgs Properties:
ZoomFactor(double): Zoom levelZoomTrigger(ZoomTrigger): How zoom was triggered (Toolbar, MouseWheel, Pinch, etc.)Cancel(bool): Cancel the operation
Zoomed Event
Triggered after zoom operation completes.
private void OnZoomed(ZoomedEventArgs args)
{
Console.WriteLine($"Zoomed to: {args.ZoomFactor}");
// Update zoom controls
}ZoomedEventArgs Properties:
ZoomFactor(double): Applied zoom levelZoomTrigger(ZoomTrigger): Zoom method used
OnPanStart Event
Triggered when image panning starts.
private void OnPanStart(PanEventArgs args)
{
Console.WriteLine("Pan started");
// Show pan cursor
// Disable other interactions
}PanEventArgs Properties:
- Position information (varies by implementation)
OnPanEnd Event
Triggered when image panning ends.
private void OnPanEnd(PanEventArgs args)
{
Console.WriteLine("Pan ended");
// Restore cursor
// Re-enable interactions
}OnSelectionResizeStart Event
Triggered when selection resizing starts (crop mode).
private void OnSelectionResizeStart(SelectionChangeEventArgs args)
{
Console.WriteLine("Selection resize started");
// Show resize handles
}SelectionChangeEventArgs Properties:
- Selection position and dimension information
OnSelectionResizeEnd Event
Triggered when selection resizing ends.
private void OnSelectionResizeEnd(SelectionChangeEventArgs args)
{
Console.WriteLine("Selection resize ended");
// Validate selection size
}Clicked Event
Triggered when the image editor canvas is clicked.
private void OnClicked(ImageEditorClickEventArgs args)
{
Console.WriteLine($"Clicked at: ({args.X}, {args.Y})");
// Handle click actions
// Show context menu
// Custom interactions
}ImageEditorClickEventArgs Properties:
X(double): Click X-coordinateY(double): Click Y-coordinate
Toolbar Events
ToolbarUpdating Event
Triggered when contextual toolbar is about to be displayed.
private void OnToolbarUpdating(ToolbarEventArgs args)
{
Console.WriteLine($"Toolbar type: {args.ToolbarType}");
// Customize toolbar items
if (args.ToolbarType == ShapeType.Text)
{
// Show only specific items for text
args.ToolbarItems = new List<ImageEditorToolbarItemModel>()
{
new ImageEditorToolbarItemModel { Name = "FontSize" },
new ImageEditorToolbarItemModel { Name = "Bold" },
new ImageEditorToolbarItemModel { Name = "Color" }
};
}
}ToolbarEventArgs Properties:
ToolbarType(ShapeType): Annotation type triggering toolbarToolbarItems(List<ImageEditorToolbarItemModel>): Toolbar items
ToolbarItemClicked Event
Triggered when a toolbar item is clicked.
private async void OnToolbarItemClicked(ClickEventArgs args)
{
Console.WriteLine($"Toolbar item clicked: {args.Item.Text}");
// Handle custom toolbar items
if (args.Item.Text == "CustomRotate")
{
await ImageEditor.RotateAsync(45);
}
}ClickEventArgs Properties:
Item(ImageEditorToolbarItemModel): Clicked toolbar item
QuickAccessToolbarOpening Event
Triggered when quick access toolbar is opening (when shape is selected).
private void OnQuickAccessToolbarOpening(QuickAccessToolbarEventArgs args)
{
Console.WriteLine("Quick access toolbar opening");
// Customize quick access options
// Hide/show specific options
// Cancel if needed
// args.Cancel = true;
}QuickAccessToolbarEventArgs Properties:
Cancel(bool): Cancel showing the toolbar
History Events
HistoryChanged Event
Triggered when undo/redo history changes.
private void OnHistoryChanged(HistoryChangedEventArgs args)
{
Console.WriteLine($"History action: {args.Action}");
Console.WriteLine($"Entry action: {args.EntryAction}");
Console.WriteLine($"Can undo: {args.CanUndo}");
Console.WriteLine($"Can redo: {args.CanRedo}");
// Update undo/redo buttons
// Show history panel
}HistoryChangedEventArgs Properties:
Action(HistoryChangedAction): Undo or RedoEntryAction(HistoryEntryAction): Type of action in historyCanUndo(bool): Whether undo is availableCanRedo(bool): Whether redo is available
Event Arguments Reference
Complete Event Arguments Classes
// File Operations
public class FileOpenEventArgs
{
public string FileName { get; set; }
public long FileSize { get; set; }
public ImageEditorFileType FileType { get; set; }
}
public class SaveEventArgs
{
public string FileName { get; set; }
public ImageEditorFileType FileType { get; set; }
public double ImageQuality { get; set; }
public bool Cancel { get; set; }
}
// Transformations
public class CropEventArgs
{
public double StartX { get; set; }
public double StartY { get; set; }
public double Width { get; set; }
public double Height { get; set; }
public bool Cancel { get; set; }
}
public class CroppedEventArgs
{
public double Width { get; set; }
public double Height { get; set; }
}
public class RotateEventArgs
{
public int Degree { get; set; }
public bool Cancel { get; set; }
}
public class RotatedEventArgs
{
public int Degree { get; set; }
}
public class FlipEventArgs
{
public ImageEditorDirection Direction { get; set; }
public bool Cancel { get; set; }
}
public class FlippedEventArgs
{
public ImageEditorDirection Direction { get; set; }
}
// Shapes
public class ShapeChangeEventArgs
{
public string Action { get; set; }
public ShapeSettings CurrentShapeSettings { get; set; }
public ShapeSettings PreviousShapeSettings { get; set; }
public bool Cancel { get; set; }
}
public class ShapeChangedEventArgs
{
public ShapeSettings CurrentShapeSettings { get; set; }
public ShapeSettings PreviousShapeSettings { get; set; }
}
// Adjustments
public class ImageFilterEventArgs
{
public ImageFilterOption Filter { get; set; }
public bool Cancel { get; set; }
}
public class ImageFilteredEventArgs
{
public ImageFilterOption Filter { get; set; }
}
public class FinetuneEventArgs
{
public ImageFinetuneOption FinetuneOption { get; set; }
public int Value { get; set; }
public bool Cancel { get; set; }
}
public class FinetuneValueChangedEventArgs
{
public ImageFinetuneOption FinetuneOption { get; set; }
public int Value { get; set; }
}
public class FrameChangeEventArgs
{
public FrameType FrameType { get; set; }
public bool Cancel { get; set; }
}
public class FrameChangedEventArgs
{
public FrameType FrameType { get; set; }
}
public class ImageResizeEventArgs
{
public int Width { get; set; }
public int Height { get; set; }
public bool IsAspectRatio { get; set; }
public bool Cancel { get; set; }
}
public class ImageResizedEventArgs
{
public int Width { get; set; }
public int Height { get; set; }
}
// User Interactions
public class ZoomEventArgs
{
public double ZoomFactor { get; set; }
public ZoomTrigger ZoomTrigger { get; set; }
public bool Cancel { get; set; }
}
public class ZoomedEventArgs
{
public double ZoomFactor { get; set; }
public ZoomTrigger ZoomTrigger { get; set; }
}
public class PanEventArgs
{
// Position and delta information
}
public class SelectionChangeEventArgs
{
// Selection dimensions and position
}
public class ImageEditorClickEventArgs
{
public double X { get; set; }
public double Y { get; set; }
}
// Toolbar
public class ToolbarEventArgs
{
public ShapeType ToolbarType { get; set; }
public List<ImageEditorToolbarItemModel> ToolbarItems { get; set; }
}
public class QuickAccessToolbarEventArgs
{
public bool Cancel { get; set; }
}
// History
public class HistoryChangedEventArgs
{
public HistoryChangedAction Action { get; set; }
public HistoryEntryAction EntryAction { get; set; }
public bool CanUndo { get; set; }
public bool CanRedo { get; set; }
}Best Practices
Event Handling Patterns
// Pattern 1: Validation
private void OnCropping(CropEventArgs args)
{
// Validate before operation
if (args.Width < 100 || args.Height < 100)
{
args.Cancel = true;
ShowMessage("Minimum crop size is 100x100");
}
}
// Pattern 2: UI Updates
private void OnCropped(CroppedEventArgs args)
{
// Update UI after operation
UpdateStatusBar($"Image cropped to {args.Width}x{args.Height}");
}
// Pattern 3: Logging
private void OnHistoryChanged(HistoryChangedEventArgs args)
{
// Log user actions
LogAction($"User performed {args.EntryAction}");
}
// Pattern 4: Customization
private void OnShapeChanging(ShapeChangeEventArgs args)
{
// Apply consistent styling
if (args.Action == "insert")
{
ApplyBrandColors(args.CurrentShapeSettings);
}
}Performance Considerations
// Avoid heavy operations in frequent events
private void OnFinetuneValueChanging(FinetuneEventArgs args)
{
// This fires continuously during slider drag
// Keep processing lightweight
UpdatePreviewLabel(args.Value); // OK
// await SaveToDatabase(args.Value); // AVOID
}
// Use completed events for heavy operations
private async void OnFinetuneValueChanged(FinetuneValueChangedEventArgs args)
{
// This fires once when adjustment is done
// Safe for database operations
await SaveAdjustment(args.FinetuneOption, args.Value);
}All events provide comprehensive control over the Image Editor behavior and enable advanced customization scenarios.
Frames in the Image Editor
Overview
Frames add decorative borders and visual effects around images, enhancing their presentation. The Image Editor provides various frame types with extensive customization options including colors, gradients, sizes, and styles.
Table of Contents
Drawing Frames
DrawFrameAsync Method
The DrawFrameAsync method applies customizable frames to images.
Method Signature:
Task<bool> DrawFrameAsync(
FrameType frameType,
string color = "#fff",
string gradientColor = "",
int size = 20,
int inset = -1,
int offset = -1,
int borderRadius = -1,
FrameLineStyle frameLineStyle = FrameLineStyle.Solid,
int lineCount = -1
)Parameters:
- frameType (FrameType): Type of frame - Mat, Bevel, Line, Inset, or Hook
- color (string): Primary frame color (default: "#fff" white)
- gradientColor (string): Secondary color for gradient effects (default: empty)
- size (int): Frame size as percentage of image dimensions (default: 20)
- inset (int): Inset value for Line, Hook, and Inset frames as percentage (default: 0)
- offset (int): Offset value for Line and Inset frames as percentage (default: 0)
- borderRadius (int): Border radius for Line frames as percentage (default: 0)
- frameLineStyle (FrameLineStyle): Line style for Line frames - Solid, Dashed, or Dotted (default: Solid)
- lineCount (int): Number of lines for Line frame type (default: 0)
Basic Frame Example
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Toolbar="@CustomToolbar">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private List<ImageEditorToolbarItemModel> CustomToolbar = new()
{
new ImageEditorToolbarItemModel { Name = "Open" },
new ImageEditorToolbarItemModel { Name = "Frame" },
new ImageEditorToolbarItemModel { Name = "Save" }
};
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
private async Task AddSimpleFrame()
{
// Apply a simple white mat frame
await ImageEditor.DrawFrameAsync(
frameType: FrameType.Mat,
color: "#FFFFFF",
size: 20
);
}
}Frame Types
FrameType Enum
The FrameType enum defines available frame styles:
public enum FrameType
{
Mat, // Solid border frame (like photo mat)
Bevel, // 3D beveled edge frame
Line, // Single or multiple line frame
Inset, // Recessed/inset frame effect
Hook // Corner hook frame style
}Mat Frame
Creates a solid border around the image, similar to a traditional photo mat:
private async Task ApplyMatFrame()
{
// Simple white mat
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#FFFFFF",
size: 15
);
// Colored mat
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#3498db", // Blue
size: 20
);
// Mat with gradient
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#2c3e50",
gradientColor: "#3498db",
size: 25
);
}Mat Frame Characteristics:
- Solid, uniform border
- Supports solid colors and gradients
- Best for classic photo presentation
- Size parameter controls border width
Bevel Frame
Creates a 3D beveled edge effect around the image:
private async Task ApplyBevelFrame()
{
// Light bevel
await ImageEditor.DrawFrameAsync(
FrameType.Bevel,
color: "#ECF0F1",
size: 15
);
// Dark bevel with gradient
await ImageEditor.DrawFrameAsync(
FrameType.Bevel,
color: "#34495e",
gradientColor: "#2c3e50",
size: 20
);
// Metallic bevel
await ImageEditor.DrawFrameAsync(
FrameType.Bevel,
color: "#95a5a6",
gradientColor: "#7f8c8d",
size: 18
);
}Bevel Frame Characteristics:
- 3D raised edge appearance
- Creates depth and dimension
- Gradient enhances 3D effect
- Best for professional photography
Line Frame
Creates single or multiple line borders around the image:
private async Task ApplyLineFrame()
{
// Single solid line
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#000000",
size: 10,
frameLineStyle: FrameLineStyle.Solid,
lineCount: 1
);
// Double line
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#e74c3c",
size: 15,
frameLineStyle: FrameLineStyle.Solid,
lineCount: 2,
offset: 5
);
// Dashed line with border radius
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#9b59b6",
size: 12,
frameLineStyle: FrameLineStyle.Dashed,
lineCount: 1,
borderRadius: 10
);
// Triple dotted lines
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#16a085",
size: 20,
frameLineStyle: FrameLineStyle.Dotted,
lineCount: 3,
offset: 8
);
}Line Frame Characteristics:
- Minimalist border style
- Supports multiple parallel lines
- Three line styles: Solid, Dashed, Dotted
- Customizable spacing and border radius
Inset Frame
Creates a recessed or inset frame effect:
private async Task ApplyInsetFrame()
{
// Simple inset
await ImageEditor.DrawFrameAsync(
FrameType.Inset,
color: "#34495e",
size: 18,
inset: 5
);
// Deep inset with offset
await ImageEditor.DrawFrameAsync(
FrameType.Inset,
color: "#2c3e50",
size: 25,
inset: 10,
offset: 5
);
// Inset with gradient
await ImageEditor.DrawFrameAsync(
FrameType.Inset,
color: "#8e44ad",
gradientColor: "#9b59b6",
size: 20,
inset: 8,
offset: 3
);
}Inset Frame Characteristics:
- Recessed, sunken appearance
- Creates depth into the image
- Inset parameter controls depth
- Offset adjusts shadow placement
Hook Frame
Creates corner hook-style frame elements:
private async Task ApplyHookFrame()
{
// Corner hooks
await ImageEditor.DrawFrameAsync(
FrameType.Hook,
color: "#c0392b",
size: 15,
inset: 8
);
// Decorative hooks
await ImageEditor.DrawFrameAsync(
FrameType.Hook,
color: "#f39c12",
size: 20,
inset: 12
);
// Gradient hooks
await ImageEditor.DrawFrameAsync(
FrameType.Hook,
color: "#27ae60",
gradientColor: "#2ecc71",
size: 18,
inset: 10
);
}Hook Frame Characteristics:
- Corner-only frame elements
- Vintage photo album aesthetic
- Inset controls hook size
- Minimal visual intrusion
Frame Customization
Color Customization
Frames support various color formats:
// Named colors
await ImageEditor.DrawFrameAsync(FrameType.Mat, "white", "", 20);
await ImageEditor.DrawFrameAsync(FrameType.Mat, "black", "", 20);
// Hex colors
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#3498db", "", 20);
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#e74c3c", "", 20);
// RGB colors
await ImageEditor.DrawFrameAsync(FrameType.Mat, "rgb(52, 152, 219)", "", 20);
// RGBA colors (with transparency)
await ImageEditor.DrawFrameAsync(FrameType.Mat, "rgba(52, 152, 219, 0.8)", "", 20);Gradient Effects
Apply gradient colors for enhanced visual appeal:
private async Task ApplyGradientFrames()
{
// Warm gradient
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#ff6b6b",
gradientColor: "#feca57",
size: 22
);
// Cool gradient
await ImageEditor.DrawFrameAsync(
FrameType.Bevel,
color: "#48dbfb",
gradientColor: "#0abde3",
size: 20
);
// Dark gradient
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#2c2c54",
gradientColor: "#474787",
size: 25
);
}Size Adjustment
Frame size is specified as a percentage of image dimensions:
// Thin frame (10-15%)
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 10);
// Medium frame (15-25%)
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 20);
// Thick frame (25-40%)
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 30);
// Extra thick frame (40%+)
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 45);Size Guidelines:
- 10-15%: Subtle, minimal border
- 15-25%: Standard frame size
- 25-35%: Bold, prominent border
- 35%+: Statement frame (may overwhelm image)
Frame Styles
FrameLineStyle Enum
For Line frame types, specify the line style:
public enum FrameLineStyle
{
Solid, // Continuous line
Dashed, // Dashed line pattern
Dotted // Dotted line pattern
}Line Style Examples
// Solid line frame
await ImageEditor.DrawFrameAsync(
FrameType.Line,
"#000000",
"",
15,
-1, -1, -1,
FrameLineStyle.Solid,
1
);
// Dashed line frame
await ImageEditor.DrawFrameAsync(
FrameType.Line,
"#e74c3c",
"",
15,
-1, -1, -1,
FrameLineStyle.Dashed,
1
);
// Dotted line frame
await ImageEditor.DrawFrameAsync(
FrameType.Line,
"#3498db",
"",
15,
-1, -1, -1,
FrameLineStyle.Dotted,
1
);Practical Examples
Example 1: Classic Photo Mat
private async Task CreateClassicPhotoMat()
{
// White mat with subtle shadow effect
await ImageEditor.DrawFrameAsync(
FrameType.Mat,
color: "#FFFFFF",
gradientColor: "#F5F5F5",
size: 22
);
}Example 2: Modern Minimalist Frame
private async Task CreateModernFrame()
{
// Thin black line with rounded corners
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#000000",
size: 8,
frameLineStyle: FrameLineStyle.Solid,
lineCount: 1,
borderRadius: 5
);
}Example 3: Vintage Photo Album
private async Task CreateVintageFrame()
{
// Sepia-toned hook frame
await ImageEditor.DrawFrameAsync(
FrameType.Hook,
color: "#8B4513",
gradientColor: "#A0522D",
size: 18,
inset: 12
);
}Example 4: Professional Portfolio
private async Task CreateProfessionalFrame()
{
// Elegant bevel with subtle gradient
await ImageEditor.DrawFrameAsync(
FrameType.Bevel,
color: "#2c3e50",
gradientColor: "#34495e",
size: 20
);
}Example 5: Artistic Border
private async Task CreateArtisticFrame()
{
// Multiple dashed lines
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#9b59b6",
size: 25,
offset: 10,
borderRadius: 8,
frameLineStyle: FrameLineStyle.Dashed,
lineCount: 3
);
}Example 6: Certificate Border
private async Task CreateCertificateBorder()
{
// Formal double-line frame
await ImageEditor.DrawFrameAsync(
FrameType.Line,
color: "#C0A062", // Gold color
size: 30,
offset: 12,
frameLineStyle: FrameLineStyle.Solid,
lineCount: 2
);
}ImageFrameSettings Class
The ImageFrameSettings class represents frame configuration:
public class ImageFrameSettings
{
public FrameType Type { get; set; } // Frame type
public string Color { get; set; } // Primary color
public string GradientColor { get; set; } // Gradient color
public int Size { get; set; } // Size percentage
public int Inset { get; set; } // Inset value
public int Offset { get; set; } // Offset value
public int BorderRadius { get; set; } // Border radius
public FrameLineStyle LineStyle { get; set; } // Line style
public int LineCount { get; set; } // Number of lines
}Best Practices
Frame Selection by Image Type
// Portraits: Use mat or bevel frames
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 20);
// Landscapes: Use line or hook frames
await ImageEditor.DrawFrameAsync(FrameType.Line, "#000000", "", 12);
// Product photos: Use clean, minimal frames
await ImageEditor.DrawFrameAsync(FrameType.Line, "#E0E0E0", "", 10);
// Artistic photos: Use creative frames with gradients
await ImageEditor.DrawFrameAsync(FrameType.Bevel, "#3498db", "#9b59b6", 25);Color Harmony
// Neutral frames for any image
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 20);
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#000000", "", 20);
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#808080", "", 20);
// Complementary colors enhance subject
// For warm-toned images, use cool frames
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#3498db", "#2980b9", 22);
// For cool-toned images, use warm frames
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#e74c3c", "#c0392b", 22);Size Proportions
// Square images: Medium frames work well
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 20);
// Landscape images: Thinner frames on sides
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 15);
// Portrait images: Slightly larger frames
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 25);Performance Tips
// Apply frame last in editing workflow
// 1. Load image
await ImageEditor.OpenAsync("photo.jpg");
// 2. Apply edits (crop, filters, annotations)
await ImageEditor.CropAsync();
await ImageEditor.ApplyImageFilterAsync(ImageFilterOption.Sepia);
// 3. Apply frame as final step
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 20);
// 4. Export
await ImageEditor.ExportAsync("final-photo.jpg");Limitations
- Only one frame can be applied at a time
- Applying a new frame replaces the existing frame
- Frame parameters must be within valid ranges:
- Size: 0-100 (percentage)
- Inset: 0-50 (percentage)
- Offset: 0-50 (percentage)
- BorderRadius: 0-50 (percentage)
- LineCount: 1-10 (for Line frames)
Removing Frames
To remove a frame, use the Undo function:
// Apply frame
await ImageEditor.DrawFrameAsync(FrameType.Mat, "#FFFFFF", "", 20);
// Remove frame using undo
await ImageEditor.UndoAsync();
// Or reset entire image
await ImageEditor.ResetAsync();Frames are permanent once exported. Use preview mode to test frame appearance before exporting.
Accessibility Considerations
- Ensure sufficient contrast between frame and image
- Test frames with screen magnification
- Consider color-blind users when choosing frame colors
- Provide alternative text descriptions for framed images
All frame operations support undo/redo and are included in the exported image.
Getting Started with the Blazor Image Editor
Overview
The Syncfusion Blazor Image Editor is a powerful component for image editing and manipulation. This guide covers installation, setup, and basic component rendering in Blazor applications.
Prerequisites
- .NET 6.0 or later
- Visual Studio 2022, Visual Studio Code, or .NET CLI
- Basic knowledge of Blazor component development
Installation
Step 1: Install NuGet Packages
Install the required NuGet packages using NuGet Package Manager or the Package Manager Console:
Install-Package Syncfusion.Blazor.ImageEditor -Version [latest-version]
Install-Package Syncfusion.Blazor.Themes -Version [latest-version]Or using .NET CLI:
dotnet add package Syncfusion.Blazor.ImageEditor
dotnet add package Syncfusion.Blazor.Themes
dotnet restoreThe Syncfusion.Blazor.ImageEditor package provides the component, and Syncfusion.Blazor.Themes provides styling.
Setup in Blazor WebAssembly App
Step 2: Add Imports
Open the _Imports.razor file and add the following namespaces:
@using Syncfusion.Blazor
@using Syncfusion.Blazor.ImageEditorThis makes the ImageEditor component and related types available throughout your application.
Step 3: Register Syncfusion Service
In Program.cs, register the Syncfusion Blazor service:
using Syncfusion.Blazor;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient
{
BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
});
builder.Services.AddSyncfusionBlazor(); // Add this line
await builder.Build().RunAsync();Step 4: Add Stylesheet and Script
In index.html, add the theme stylesheet and script references to the <head> section:
<head>
...
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js"
type="text/javascript"></script>
</head>Available themes: bootstrap5.css, fluent2.css, material3.css, tailwind3.css
Setup in Blazor Web App
Step 2: Add Imports
In the _Imports.razor file (from the client project if using WebAssembly/Auto render modes):
@using Syncfusion.Blazor
@using Syncfusion.Blazor.ImageEditorStep 3: Register Syncfusion Service
Register the service in both the server and client Program.cs files:
Server Program.cs:
using Syncfusion.Blazor;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
builder.Services.AddSyncfusionBlazor(); // Add this line
var app = builder.Build();
...Client Program.cs (if using WebAssembly/Auto):
using Syncfusion.Blazor;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddSyncfusionBlazor();
await builder.Build().RunAsync();Step 4: Add Stylesheet and Script
In App.razor, add references to the theme and script:
<head>
...
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
</head>
<body>
...
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js"
type="text/javascript"></script>
</body>Render the Component
Create a new Blazor page (e.g., Pages/ImageEditor.razor) and add the component:
@page "/image-editor"
<SfImageEditor Height="500px"></SfImageEditor>Run your application with dotnet run or press Ctrl+F5 in Visual Studio. The Image Editor component will render with an empty canvas.
Basic Component with Image Loading
@page "/image-editor"
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px" Width="100%">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
// Load an image when component is initialized
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}The Created event fires after the component is initialized, making it the ideal place to load images or configure initial settings.
Available Themes
Select the appropriate theme stylesheet based on your design requirements:
- Bootstrap5:
bootstrap5.css- Bootstrap-based styling - Fluent2:
fluent2.css- Microsoft Fluent design - Material3:
material3.css- Google Material Design 3 - Tailwind3:
tailwind3.css- Tailwind CSS styling
Next Steps
After setup: 1. Load images using the file explorer or OpenAsync method 2. Add annotations or transformations 3. Export modified images 4. Customize the toolbar as needed
Refer to other reference guides for detailed feature implementation.
Component Properties
Essential Properties
Configure the Image Editor behavior with these important properties:
AllowUndoRedo
Enable or disable undo/redo functionality:
`csharp // Enable undo/redo (default) <SfImageEditor AllowUndoRedo="true" Height="500px"></SfImageEditor>
// Disable undo/redo <SfImageEditor AllowUndoRedo="false" Height="500px"></SfImageEditor> `
Default: rue Type: ool Note: Undo/redo history is limited to 16 actions.
IsReadOnly
Make the Image Editor read-only (view-only mode):
`csharp <SfImageEditor IsReadOnly="true" Height="500px"> <ImageEditorEvents Created="OnCreated"></ImageEditorEvents> </SfImageEditor>
@code { private async void OnCreated() { await ImageEditor.OpenAsync("YOUR_IMAGE_URL"); // User can view but not edit } } `
Default: alse Type: ool Use Cases:
- Display-only mode
- Preview before editing
- Restricted user access
Enabled
Enable or disable user interactions:
`csharp <SfImageEditor Enabled="@isEditorEnabled" Height="500px"></SfImageEditor>
@code { private bool isEditorEnabled = true;
private void ToggleEditor() { isEditorEnabled = !isEditorEnabled; } } `
Default: rue Type: ool Difference from IsReadOnly: When disabled, all interactions are blocked including viewing controls.
ShowQuickAccessToolbar
Control the quick access toolbar visibility (shown when annotations are selected):
`csharp // Show quick access toolbar (default) <SfImageEditor ShowQuickAccessToolbar="true" Height="500px"></SfImageEditor>
// Hide quick access toolbar <SfImageEditor ShowQuickAccessToolbar="false" Height="500px"></SfImageEditor> `
Default: rue Type: ool Quick Access Toolbar Provides: Clone, Delete, Edit text options when annotations are selected.
Theme
Set the visual theme for selection UI elements:
`csharp <SfImageEditor Theme="Theme.Bootstrap5" Height="500px"></SfImageEditor>
<SfImageEditor Theme="Theme.Material3" Height="500px"></SfImageEditor>
<SfImageEditor Theme="Theme.FluentDark" Height="500px"></SfImageEditor> `
Default: Theme.Bootstrap5 Type: Theme enum
Available Themes:
- Theme.Bootstrap5
- Theme.Bootstrap5Dark
- Theme.Tailwind
- Theme.TailwindDark
- Theme.Fluent
- Theme.FluentDark
- Theme.Material
- Theme.MaterialDark
- Theme.Material3
- Theme.Material3Dark
- Theme.HighContrast
- Theme.Bootstrap4
- Theme.Bootstrap
- Theme.BootstrapDark
- Theme.Fabric
- Theme.FabricDark
Note: Theme controls the selection UI, resize handles, and control colors. Main toolbar and canvas styling come from the referenced CSS theme file.
CssClass
Apply custom CSS classes for styling:
`csharp <SfImageEditor CssClass="custom-editor dark-mode" Height="500px"></SfImageEditor>
<style> .custom-editor { border: 2px solid #3498db; border-radius: 8px; }
.dark-mode { background-color: #2c3e50; } </style> `
Default: Empty string Type: string
EnableImageSmoothing
Control image smoothing (anti-aliasing) during rendering:
`csharp // Disable smoothing for crisp pixels (default) <SfImageEditor EnableImageSmoothing="false" Height="500px"></SfImageEditor>
// Enable smoothing for smoother scaled images <SfImageEditor EnableImageSmoothing="true" Height="500px"></SfImageEditor> `
Default: alse Type: ool Use Cases:
- False: Pixel art, text, sharp edges
- True: Photographs, smooth scaling, reduced pixelation
This controls the HTML5 Canvas imageSmoothingEnabled property.
Complete Component Example
`csharp @page "/advanced-editor" @using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="600px" Width="100%" AllowUndoRedo="true" IsReadOnly="false" Enabled="true" ShowQuickAccessToolbar="true" Theme="Theme.Material3" CssClass="professional-editor" EnableImageSmoothing="false" Toolbar="@CustomToolbar"> <ImageEditorEvents Created="OnCreated"></ImageEditorEvents> </SfImageEditor>
<style> .professional-editor { box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); border-radius: 8px; } </style>
@code { SfImageEditor ImageEditor;
private List<ImageEditorToolbarItemModel> CustomToolbar = new() { new ImageEditorToolbarItemModel { Name = "Open" }, new ImageEditorToolbarItemModel { Name = "Crop" }, new ImageEditorToolbarItemModel { Name = "Annotation" }, new ImageEditorToolbarItemModel { Name = "Finetune" }, new ImageEditorToolbarItemModel { Name = "Filter" }, new ImageEditorToolbarItemModel { Name = "Frame" }, new ImageEditorToolbarItemModel { Name = "Save" } };
private async void OnCreated() { await ImageEditor.OpenAsync("YOUR_IMAGE_URL"); } } `
Settings Classes
FinetuneSettings
Configure finetune adjustment ranges (not directly set but defines available ranges):
Finetune adjustments: Brightness, Contrast, Saturation, Hue, Blur, Shadow, Exposure, Opacity
ZoomSettings
Configure zoom behavior (controlled via ImageEditorZoomSettings class):
- Minimum zoom level
- Maximum zoom level
- Zoom factor increments
UploadSettings
Configure image upload behavior (controlled via ImageEditorUploadSettings class):
- Allowed file types
- Maximum file size
- Upload URL
SelectionSettings
Configure selection behavior for cropping (controlled via ImageEditorSelectionSettings class):
- Selection types
- Aspect ratios
- Default selection size
Note: These settings classes are typically configured through component properties or methods rather than directly instantiated.
Image Transformations in the Image Editor
Overview
Image transformations include cropping, rotating, flipping, straightening, and resizing. These operations modify the image structure and are tracked in the undo/redo history.
Cropping Images
Selection Types
The Image Editor supports multiple crop selection types:
1. Custom: Arbitrary rectangular selection 2. Circle: Circular crop area 3. Square: Square crop area 4. Ratio: Fixed aspect ratio selections (16:9, 4:3, 1:1, etc.)
Crop Workflow
@using Syncfusion.Blazor.ImageEditor
<SfImageEditor @ref="ImageEditor" Height="500px">
<ImageEditorEvents Created="OnCreated"></ImageEditorEvents>
</SfImageEditor>
@code {
SfImageEditor ImageEditor;
private async void OnCreated()
{
await ImageEditor.OpenAsync("YOUR_IMAGE_URL");
}
}User interaction: 1. Click Crop button on toolbar 2. Choose selection type from contextual toolbar 3. Draw selection on image (drag to adjust) 4. Pan image to position crop region 5. Click tick icon to apply crop
Crop Selection Positioning
After creating a crop selection:
- Click and drag the selection to reposition
- Drag corners to resize
- Pan the image content within the selection using click-and-drag
- Use straighten slider for alignment
Rotation
Rotate Left and Right
Rotate the image in 90-degree increments:
private async Task RotateImage()
{
// Rotate 90 degrees clockwise
await ImageEditor.RotateAsync(90);
// Rotate 90 degrees counter-clockwise
await ImageEditor.RotateAsync(-90);
// Rotate 180 degrees
await ImageEditor.RotateAsync(180);
}Using Toolbar Buttons
- Rotate Left: Rotate counter-clockwise by 90°
- Rotate Right: Rotate clockwise by 90°
These buttons are available in the toolbar's crop/transform section.
Flipping
Horizontal Flip
Flip the image left-to-right (mirror horizontally):
private async Task FlipHorizontal()
{
await ImageEditor.FlipAsync(ImageEditorDirection.Horizontal);
}Vertical Flip
Flip the image top-to-bottom (mirror vertically):
private async Task FlipVertical()
{
await ImageEditor.FlipAsync(ImageEditorDirection.Vertical);
}Toolbar Buttons
- Horizontal Flip: Mirrors the image left-right
- Vertical Flip: Mirrors the image top-bottom
Both are available in the crop/transform toolbar section.
Straightening
Straighten with Slider
When in crop mode, the straightening slider allows precise angle adjustment:
// Straighten is applied through the crop toolbar
// User interaction:
// 1. Click Crop
// 2. Use straighten slider to adjust angle
// 3. Click tick to applyThe straighten slider:
- Adjusts image rotation in small increments
- Applies to inserted annotations as well
- Preview shows in real-time
- Committed with crop confirmation
Resizing Images
Resize Dimensions
Change the overall image dimensions:
private async Task ResizeImage(int width, int height)
{
// Parameters are in pixels
await ImageEditor.ResizeAsync(width, height);
}
// Example: Resize to 800x600
private async Task ResizeExample()
{
await ImageEditor.ResizeAsync(800, 600);
}Resize Workflow
Using the toolbar: 1. Click Resize button 2. Enter desired width and height 3. Aspect ratio option available 4. Apply changes
Panning
Pan Images
Move the image within the canvas, useful when zoomed in:
// Panning is enabled:
// 1. When a crop selection is active
// 2. When image size exceeds canvas size (zoomed)
// User interaction:
// Click and drag on the image to panPanning conditions:
- Active crop selection for positioning the crop region
- Zoomed image that extends beyond canvas boundaries
- Drag gestures on touch devices
Pan with Mouse
Click and drag the image to move it within the canvas. The cursor changes to indicate panning is available.
Transform Collection
Get Current Transforms
Retrieve all applied transformations:
private async Task GetTransforms()
{
ImageDimension dimension = await ImageEditor.GetImageDimensionAsync();
// dimension includes current position and size after transforms
}Apply Multiple Transforms
Transformations can be combined:
private async Task ComplexTransform()
{
// Crop
// Then rotate
await ImageEditor.RotateAsync(90);
// Then flip
await ImageEditor.FlipAsync(ImageEditorDirection.Horizontal);
// Then straighten (in crop mode)
// All are tracked in undo/redo
}Undo/redo respects the transformation sequence.
Transformation Combinations
Common Workflow Examples
Example 1: Rotate and crop
1. Rotate 90° clockwise
2. Enter crop mode
3. Select custom crop area
4. Apply crop
5. Can undo any stepExample 2: Straighten and resize
1. Enter crop mode
2. Use straighten slider
3. Apply crop
4. Resize image
5. ExportExample 3: Flip and adjust
1. Flip horizontally
2. Enter crop mode
3. Position crop region
4. Apply crop
5. Undo if neededBest Practices
- Use crop for precision: custom selections for exact areas, ratios for maintaining proportions
- Rotate before cropping for better alignment
- Use straighten slider for fine-tuning angles
- Pan to verify crop region before applying
- Test transformations with undo/redo before export
- Resize last to optimize final image dimensions
All transformations support undo/redo and do not permanently modify the source image until exported.
Straightening with Precise Angles
StraightenImageAsync Method
Apply precise straightening angles programmatically (beyond the crop toolbar slider):
csharp Task<bool> StraightenImageAsync(int degree)
Parameters:
- degree (int): Rotation angle between -45 and +45 degrees
- Positive values: Clockwise rotation
- Negative values: Counter-clockwise rotation
Programmatic Straightening
`csharp private async Task StraightenImage(int angle) { // Validate angle range if (angle < -45 || angle > 45) { Console.WriteLine("Angle must be between -45 and +45 degrees"); return; }
// Apply straightening bool success = await ImageEditor.StraightenImageAsync(angle);
if (success) { Console.WriteLine(Straightened by {angle} degrees); } }
// Examples: private async Task StraightenExamples() { // Slight counter-clockwise adjustment await ImageEditor.StraightenImageAsync(-5);
// Moderate clockwise adjustment await ImageEditor.StraightenImageAsync(10);
// Maximum counter-clockwise await ImageEditor.StraightenImageAsync(-45);
// Maximum clockwise await ImageEditor.StraightenImageAsync(45); } `
Use Cases
Straighten scanned documents: csharp private async Task StraightenDocument() { // Common angles for scanned document correction await ImageEditor.StraightenImageAsync(-2); // Slight tilt correction }
Fix horizon in photos: csharp private async Task FixHorizon() { // Correct tilted horizon lines await ImageEditor.StraightenImageAsync(3); }
Precise architectural photo correction: csharp private async Task CorrectArchitecture() { // Fine-tune building alignment await ImageEditor.StraightenImageAsync(-1); }
Difference from RotateAsync
| Method | Angle Range | Use Case |
|---|---|---|
| RotateAsync() | 0, 90, 180, 270, 360 | 90-degree rotations |
| StraightenImageAsync() | -45 to +45 degrees | Fine adjustments and leveling |
Straightening Workflow
`csharp // 1. Load image await ImageEditor.OpenAsync("tilted-photo.jpg");
// 2. Apply straightening await ImageEditor.StraightenImageAsync(-3);
// 3. Crop to remove gaps if needed await ImageEditor.SelectAsync("custom", 0, 0, 800, 600); await ImageEditor.CropAsync();
// 4. Export await ImageEditor.ExportAsync("straightened-photo.jpg"); `
Note: Straightening creates blank areas at corners. Consider cropping after straightening to remove these areas.