
Syncfusion Angular Image Editor
- 210 installs
- Updated August 4, 2026
- syncfusion/angular-ui-components-skills
Use syncfusion-angular-image-editor for development tasks
About
syncfusion-angular-image-editor: A skill for development. This provides functionality for development workflows.
- syncfusion-angular-image-editor
Syncfusion Angular Image Editor by the numbers
- 210 all-time installs (skills.sh)
- +12 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,932 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/angular-ui-components-skills --skill syncfusion-angular-image-editorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 210 |
|---|---|
| Last updated | August 4, 2026 |
| Repository | syncfusion/angular-ui-components-skills ↗ |
What it does
Use syncfusion-angular-image-editor for development tasks
Files
Implementing Syncfusion Angular Image Editor
The Syncfusion Angular Image Editor component provides a comprehensive, feature-rich solution for image editing and annotation. It allows developers to integrate professional image editing capabilities directly into Angular applications, supporting a wide range of editing operations including annotations, transformations, filtering, and more.
Component Overview
The Image Editor is a powerful, standalone component that provides:
- Complete image editing suite with 20+ built-in tools
- Flexible annotation system supporting text, shapes, and freehand drawing
- Advanced transformations including rotate, flip, straighten, zoom, and pan
- Professional image filters (cold, warm, chrome, sepia, invert, grayscale, etc.)
- Fine-tuning controls for brightness, contrast, saturation, hue, exposure, blur, and opacity
- Frame application with multiple frame types and customization options
- Redaction tools for privacy protection (blur and pixelate)
- Multiple input/output options including local files, base64, blob, file uploader, and file manager
- Rich undo/redo history (16 steps maximum)
- Fully customizable toolbars with contextual and quick-access options
- Z-order management for annotation layering
- Mobile-friendly with touch gestures (pinch zoom)
- Full accessibility support including WCAG 2.2, keyboard navigation, and screen reader compatibility
- Multi-language support with 150+ localization keywords
Documentation and Navigation Guide
Getting Started & Installation
📄 Read: references/getting-started.md
- Installation and package setup
- Dependencies and module imports
- Basic component implementation
- CSS imports and theme configuration
- First render and initialization
Annotations & Drawing
📄 Read: references/annotations.md
- Text annotations with formatting (bold, italic, underline, strikethrough)
- Multiline text support
- Font family and text color customization
- Freehand drawing with stroke adjustment
- Shape annotations (rectangles, ellipses, lines, arrows, paths)
- Image annotations and watermarking
- Deleting and managing annotations
- Shape styling and default customization
Selection & Cropping
📄 Read: references/selection-and-cropping.md
- Custom selection shapes
- Square and circle selections
- Aspect ratio selections (2:3, 3:2, 4:3, 16:9, etc.)
- Cropping selected regions
- Selection event handling
- Locking selection areas
- Custom ratio selection during cropping
Image Transformations
📄 Read: references/transform.md
- Rotating images (clockwise/counterclockwise)
- Flipping horizontally and vertically
- Straightening images with fine adjustments
- Zooming in/out with min/max zoom levels
- Panning functionality and events
- Transform event handlers
- Keyboard shortcuts for transformations
Filtering & Fine-tuning
📄 Read: references/filter-and-finetune.md
- Applying image filters (Cold, Warm, Chrome, Sepia, Invert, Grayscale, Black & White)
- Fine-tuning brightness and contrast
- Adjusting saturation levels
- Hue adjustments
- Exposure control
- Blur effects
- Opacity adjustments
- Filter and finetune event handling
Frame Application
📄 Read: references/frames.md
- Frame types (Mat, Bevel, Line, Hook, Inset)
- Frame color customization
- Gradient color support
- Frame size and offset configuration
- Border radius for line-type frames
- Frame line styles (solid, dashed, dotted)
- Frame changing events
Redaction & Privacy
📄 Read: references/redaction.md
- Drawing redactions (blur and pixelate types)
- Customizing redaction properties
- Selecting specific redactions
- Updating redaction settings
- Deleting redactions
- Retrieving redaction details
Open & Save Operations
📄 Read: references/open-and-save.md
- Opening images from multiple sources (local, base64, blob, uploader, file manager, treeview)
- Saving with format selection (PNG, JPEG, SVG, WEBP, BMP)
- Image quality control for JPEG format
- Exporting as different formats
- Converting to base64, byte arrays, and blob
- Watermark application during open/save
- Custom save dialogs and server uploads
- Image settings for custom dimensions
Undo & Redo Operations
📄 Read: references/undo-redo.md
- Implementing undo functionality
- Implementing redo functionality
- Understanding history limitations (16 steps)
- Keyboard shortcuts (Ctrl+Z, Ctrl+Y)
Toolbar Customization
📄 Read: references/toolbar.md
- Built-in toolbar items and their functions
- Adding custom toolbar items
- Showing/hiding toolbar
- Enabling/disabling specific items
- Contextual toolbar customization
- Toolbar templates for complete customization
- Toolbar events (toolbarCreated, toolbarItemClicked, toolbarUpdating)
Quick Access Toolbar
📄 Read: references/quick-access-toolbar.md
- Quick access toolbar visibility control
- Adding custom items to quick access toolbar
- Customizing annotation-specific actions
- Event handling for toolbar operations
Z-Order & Layering
📄 Read: references/z-order.md
- Bringing annotations forward
- Sending annotations backward
- Bringing annotations to front
- Sending annotations to back
- Managing multiple annotation layers
Accessibility & Compliance
📄 Read: references/accessibility.md
- WCAG 2.2 compliance standards
- Keyboard shortcuts and navigation
- Screen reader support
- Color contrast standards
- Mobile accessibility support
- RTL (Right-to-Left) support
API Reference
📄 Read: references/api.md
- Complete properties reference with types and defaults
- All methods with parameters and return types
- All events with descriptions
- Event arguments reference
- Filter, finetune, shape, and frame types
- Selection shapes and export formats
- Usage examples for properties and events
Localization
📄 Read: references/localization.md
- Setting locale configuration
- Customizing UI text in multiple languages
- Translation keywords and values
- Supporting international audiences
Image Restrictions & Validation
📄 Read: references/image-restrictions.md
- Specifying allowed file extensions
- Setting minimum file size limits
- Setting maximum file size limits
- Validation error messages
- Upload settings configuration
Image Resizing
📄 Read: references/resize.md
- Resizing image dimensions
- Aspect ratio preservation
- Resize event handling
- Custom dimension specifications
End-User Capabilities
📄 Read: references/end-user-capabilities.md
- User-facing features and workflows
- Opening images through UI
- Zoom operations via toolbar, pinch, mouse wheel, keyboard
- Panning functionality
- Toolbar-based transformations
- Annotation creation and editing
- Filter and fine-tune application
- Save and export workflows
How-To Guides
📄 Read: references/clear-image.md - Clearing editor state for dialog reuse
📄 Read: references/fit-to-width-height.md - Dynamic zoom fitting
📄 Read: references/render-in-dialog.md - Modal dialog integration
📄 Read: references/reset-image.md - Reverting to original state
Quick Start Example
import { Component } from '@angular/core';
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
@Component({
imports: [ImageEditorModule],
standalone: true,
selector: 'app-root',
template: `
<div style="width: 550px; height: 350px;">
<ejs-imageeditor
#imageEditor
[toolbar]="['Open', 'Undo', 'Redo', 'Crop', 'Annotate', 'Finetune', 'Filter', 'Resize', 'Save', 'Reset']"
></ejs-imageeditor>
</div>
<button (click)="openImage()">Open Image</button>
`
})
export class AppComponent {
@ViewChild('imageEditor') imageEditor: any;
openImage() {
this.imageEditor.open('path-to-image.png');
}
addAnnotation() {
this.imageEditor.drawText(50, 50, 'Sample Text', 'Arial', 12, false, false, '#000000');
}
rotateImage() {
this.imageEditor.rotate(90);
}
saveImage() {
this.imageEditor.export('edited-image', 'png');
}
}Common Patterns
Pattern 1: Open Image & Add Annotations
// Open image from file
this.imageEditor.open('image.png');
// Add text annotation
this.imageEditor.drawText(100, 100, 'Important', 'Arial', 16, true, false, '#FF0000');
// Add rectangle
this.imageEditor.drawRectangle(50, 50, 200, 150, 2, '#0000FF', '#FFFFFF');
// Add freehand drawing
this.imageEditor.freehandDraw();Pattern 2: Apply Filters & Fine-tuning
// Apply filter
this.imageEditor.applyImageFilter('Sepia');
// Fine-tune brightness
this.imageEditor.finetuneImage('Brightness', 50);
// Fine-tune contrast
this.imageEditor.finetuneImage('Contrast', -30);
// Fine-tune saturation
this.imageEditor.finetuneImage('Saturation', 40);Pattern 3: Crop & Transform
// Select region for cropping
this.imageEditor.select('Custom', 50, 50, 300, 200);
// Crop the selected region
this.imageEditor.crop();
// Rotate after cropping
this.imageEditor.rotate(90);
// Flip horizontally
this.imageEditor.flip('Horizontal');Pattern 4: Customized Toolbar
toolbar: [
'Open',
'Undo',
'Redo',
'Crop',
'RotateLeft',
'RotateRight',
'HorizontalFlip',
'VerticalFlip',
'Annotate',
'Finetune',
'Filter',
'Frame',
'Redact',
'Resize',
'Save',
'Reset'
];Pattern 5: Save with Different Formats
// Save as PNG (default)
this.imageEditor.export('myImage', 'png');
// Save as JPEG with quality
this.imageEditor.export('myImage', 'jpeg', 90);
// Get base64 data
const base64Data = this.imageEditor.getImageData();
// Save as blob
this.imageEditor.getImageData().then(data => {
const blob = this.dataURLtoBlob(data);
// Send to server
});Key Props & Configuration
| Property | Type | Description | When to Use |
|---|---|---|---|
toolbar | array | List of toolbar items to display | Customize visible tools |
toolbarTemplate | template | Custom template for entire toolbar | Complete toolbar redesign |
uploadSettings | object | File validation rules (extensions, size) | Restrict upload formats/sizes |
zoomSettings | object | Min/max zoom factor configuration | Control zoom boundaries |
fontFamily | array | Additional font families for text | Add custom fonts |
locale | string | Language for UI text | Multi-language support |
height | string/number | Component height | Layout sizing |
width | string/number | Component width | Layout sizing |
showQuickAccessToolbar | boolean | Show quick access toolbar | Control quick toolbar visibility |
Common Use Cases
1. Photo Editing App - Full-featured image editor with all tools 2. Document Annotation - Highlight, mark, and comment on documents 3. Social Media Content - Apply filters, frames, and text to images 4. Privacy Protection - Redact sensitive information before sharing 5. Profile Picture Editor - Crop, rotate, and apply filters to avatars 6. Real Estate Listings - Rotate, frame, and annotate property photos 7. Feedback & Collaboration - Annotate screenshots for team communication 8. Template Design - Layer annotations with z-order for custom layouts 9. Form Image Capture - Crop, rotate, and optimize mobile camera captures 10. Watermark Application - Add text and image watermarks for branding
Reference Files
All detailed documentation is organized by feature in the references/ folder. Each reference file is self-contained and covers specific functionality in depth.
See individual reference files for code examples, event handling, and advanced configurations.
Accessibility in Angular Image Editor
The Image Editor is fully accessible and compliant with WCAG 2.2, Section 508, and ADA standards.
Accessibility Standards
The Image Editor supports:
- ✓ WCAG 2.2 Level AA compliance
- ✓ Section 508 compliance
- ✓ Screen reader support
- ✓ Keyboard navigation
- ✓ Color contrast standards
- ✓ Right-to-left (RTL) support
- ✓ Mobile accessibility
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Ctrl + Z | Undo |
Ctrl + Y | Redo |
Ctrl + S | Save |
Ctrl + O | Open |
Ctrl + + | Zoom In |
Ctrl + - | Zoom Out |
Delete | Delete selected annotation |
Enter | Apply crop/resize |
Escape | Discard operation |
Screen Reader Support
import { Component } from '@angular/core';
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-accessible-editor',
template: `
<h1>Image Editor</h1>
<p>Use toolbar buttons or keyboard shortcuts to edit image</p>
<ejs-imageeditor
#imageEditor
role="region"
aria-label="Image Editor"
></ejs-imageeditor>
`,
imports: [ImageEditorModule],
standalone: true
})
export class AccessibleEditorComponent { }Color Contrast
All UI elements meet WCAG AA contrast requirements:
- Text: minimum 4.5:1 ratio
- UI components: minimum 3:1 ratio
Right-to-Left (RTL) Support
The Image Editor supports RTL languages. RTL mode can be enabled globally or per component:
// Set RTL globally
document.documentElement.dir = 'rtl';
@Component({
template: `
<ejs-imageeditor></ejs-imageeditor>
`
})
export class RTLEditorComponent { }Mobile Accessibility
The Image Editor is fully mobile-accessible:
- Touch gestures for all operations
- Large touch targets for buttons
- Adaptive toolbar layout
- Keyboard support on mobile
Touch Gestures
- Pinch: Zoom in/out
- Tap: Select/activate
- Drag: Pan image or move annotations
- Double-tap: Zoom to fit
Keyboard Navigation
Users can navigate all toolbar items and controls using:
Tab- Move forward through controlsShift + Tab- Move backward through controlsEnter- Activate buttonSpace- Toggle checkbox/button
ARIA Labels
@Component({
template: `
<ejs-imageeditor
aria-label="Image Editor - Use Ctrl+Z for undo, Ctrl+S to save"
></ejs-imageeditor>
`
})
export class AriaLabelComponent { }Complete Accessible Setup
@Component({
selector: 'app-fully-accessible',
template: `
<div role="main">
<h1>Image Editing Tool</h1>
<p>Instructions: Use toolbar or keyboard shortcuts (Ctrl+Z: undo, Ctrl+S: save)</p>
<ejs-imageeditor
#imageEditor
aria-label="Image Editor with full keyboard support"
role="region"
></ejs-imageeditor>
<p>
<strong>Keyboard Help:</strong>
Ctrl+O: Open, Ctrl+S: Save, Ctrl+Z: Undo,
Ctrl+Y: Redo, Delete: Remove selected annotation
</p>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class FullyAccessibleComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
ngOnInit() {
// Detect and set RTL language
if (document.documentElement.dir === 'rtl') {
// RTL is automatically applied based on HTML dir attribute
}
}
}Testing Accessibility
Test with accessibility tools:
- Axe DevTools
- Accessibility Checker
- NVDA screen reader
- JAWS screen reader
WAI-ARIA Roles
The Image Editor uses appropriate ARIA roles:
region- Main editor areabutton- Toolbar buttonstoolbar- Toolbar containerimg- Image preview
Best Practices
1. Provide keyboard alternatives for all mouse actions 2. Use semantic HTML in custom templates 3. Test with screen readers regularly 4. Maintain color contrast in custom themes 5. Support RTL for international users
Validation
The Image Editor passes:
- Axe-core automated checks
- Accessibility Checker validation
- Manual WCAG 2.2 assessment
Edge Cases
Issue: Screen reader not reading toolbar
- Solution: Ensure toolbar items have aria-labels; use semantically correct HTML
Issue: Keyboard shortcuts not working
- Solution: Focus must be on Image Editor; verify keyboard layout matches
Annotations in Angular Image Editor
Table of Contents
---
Text Annotations
Text annotations allow you to add customizable text labels and captions directly onto images.
Add Basic Text
Use the drawText() method to insert text:
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-text-annotation',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="addTextAnnotation()">Add Text</button>
`
})
export class TextAnnotationComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
addTextAnnotation() {
this.imageEditor?.drawText(
100, // x-coordinate
50, // y-coordinate
'Hello World', // text content
'Arial', // font family
20, // font size
false, // bold
false, // italic
'#000000' // text color
);
}
}Text Parameters
| Parameter | Type | Description |
|---|---|---|
x | number | X-coordinate of text position |
y | number | Y-coordinate of text position |
text | string | Text content to display |
fontFamily | string | Font family (Arial, Times New Roman, etc.) |
fontSize | number | Font size in pixels |
bold | boolean | Apply bold style |
italic | boolean | Apply italic style |
color | string | Text color in hex format |
isSelected | boolean | Show text in selected state |
degree | number | Rotation angle in degrees |
fillColor | string | Background fill color |
strokeColor | string | Text outline color |
strokeWidth | number | Outline thickness |
underline | boolean | Apply underline |
strikethrough | boolean | Apply strikethrough |
Multiline Text
Text containing newline characters automatically splits into multiple lines:
addMultilineText() {
this.imageEditor?.drawText(
100,
50,
'Line 1\nLine 2\nLine 3', // Newline characters
'Arial',
16,
false,
false,
'#000000'
);
}Text Formatting
Apply advanced text formatting with all style options:
addFormattedText() {
this.imageEditor?.drawText(
100,
50,
'Important Notice',
'Arial',
20,
true, // bold
true, // italic
'#FFFFFF', // white text
true, // selected
0, // no rotation
'#FF0000', // red background
'#000000', // black outline
3, // 3px stroke
true, // underline
false // no strikethrough
);
}Customize Font Family
Add additional font families beyond defaults:
@Component({
imports: [ImageEditorModule],
standalone: true,
template: `<ejs-imageeditor [fontFamily]="customFonts"></ejs-imageeditor>`
})
export class FontCustomizationComponent {
customFonts = [
{ id: 'Arial', text: 'Arial' },
{ id: 'Georgia', text: 'Georgia' },
{ id: 'Courier New', text: 'Courier New' },
{ id: 'Comic Sans MS', text: 'Comic Sans MS' }
];
}Handle Shape Events
Handle shape modifications through the shapeChange or shapeChanging events:
@Component({
template: `
<ejs-imageeditor
[shapeChanging]="onShapeChanging"
></ejs-imageeditor>
`
})
export class TextCustomizationComponent {
onShapeChanging(args: any) {
if (args.currentShapeSettings) {
// Validate or modify shape properties
console.log('Shape changing:', args.currentShapeSettings);
}
}
}---
Freehand Drawing
Enable users to draw and sketch directly on the image.
Enable Freehand Drawing
export class FreehandComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
enableFreehandDraw() {
this.imageEditor?.freehandDraw();
}
}Customize Stroke Properties
You can customize stroke properties on shapes:
@Component({
template: `
<ejs-imageeditor
#imageEditor
></ejs-imageeditor>
<button (click)="enableFreehand()">Freehand Draw</button>
`
})
export class FreehandCustomComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
enableFreehand() {
this.imageEditor?.freehandDraw(true);
}
}Delete Freehand Drawing
deleteFreehandAnnotation(shapeId: string) {
this.imageEditor?.deleteShape(shapeId);
}---
Shape Annotations
Add geometric shapes like rectangles, ellipses, lines, and arrows.
Rectangle Shape
addRectangle() {
this.imageEditor?.drawRectangle(
50, // x-coordinate (top-left)
50, // y-coordinate (top-left)
200, // width
150, // height
2, // stroke width
'#0000FF', // stroke color
'#FFFFFF', // fill color
0, // rotation degree
true, // isSelected
10 // border radius
);
}Ellipse Shape
addEllipse() {
this.imageEditor?.drawEllipse(
300, // x-coordinate (center)
200, // y-coordinate (center)
100, // radiusX
75, // radiusY
2, // stroke width
'#00FF00', // stroke color
'#FFFF00', // fill color
0, // rotation degree
true // isSelected
);
}Line Shape
addLine() {
this.imageEditor?.drawLine(
50, // startX
50, // startY
300, // endX
300, // endY
3, // stroke width
'#FF0000', // stroke color
true // isSelected
);
}Arrow Shape
addArrow() {
this.imageEditor?.drawArrow(
100, // startX
100, // startY
400, // endX
100, // endY
3, // stroke width
'#FF6600', // stroke color
'Start', // arrowStart type (None, Start, End)
'End', // arrowEnd type
true // isSelected
);
}Path Shape
addPath() {
const points = [
{ x: 50, y: 50 },
{ x: 100, y: 100 },
{ x: 150, y: 50 },
{ x: 200, y: 150 }
];
this.imageEditor?.drawPath(
points, // array of ImageEditorPoint
3, // stroke width
'#FF00FF', // stroke color
true // isSelected
);
}Customize Shape Defaults
You can customize individual shapes after creating them:
@Component({
template: `
<ejs-imageeditor
#imageEditor
></ejs-imageeditor>
<button (click)="addCustomRectangle()">Add Custom Rectangle</button>
`
})
export class ShapeDefaultsComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
addCustomRectangle() {
// Draw rectangle with custom properties
this.imageEditor?.drawRectangle(
50, 50, // x, y
200, 150, // width, height
3, // strokeWidth
'#0066FF', // strokeColor
'#CCCCCC' // fillColor
);
}
}Delete Shapes
deleteShape(shapeId: string) {
this.imageEditor?.deleteShape(shapeId);
}
// Retrieve shape IDs
getAllShapes() {
const shapes = this.imageEditor?.getShapeSetting();
console.log(shapes); // Array of ShapeSettings
}---
Image Annotations
Add images or icons as annotations on top of the image.
Add Image Annotation
addImageAnnotation() {
this.imageEditor?.drawImage(
'watermark.png', // image data or URL
100, // x-coordinate
100, // y-coordinate
200, // width
100, // height
true, // maintain aspect ratio
0, // rotation degree
0.8, // opacity (0-1)
true // isSelected
);
}Using Base64 Image Data
addBase64Image() {
const base64String = 'data:image/png;base64,iVBORw0KGgoAAAANS...';
this.imageEditor?.drawImage(
base64String,
150,
150,
200,
150,
true,
0,
1.0,
false
);
}Watermarking Images
Add watermarks when opening or saving images:
@Component({
template: `
<ejs-imageeditor
[fileOpened]="onFileOpened"
></ejs-imageeditor>
<button (click)="openImage()">Open Image</button>
`
})
export class WatermarkComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
openImage() {
this.imageEditor?.open('image.png');
}
onFileOpened() {
// Add watermark text
this.imageEditor?.drawText(
50, 50,
'© My Company',
'Arial',
24,
false,
false,
'#FFFFFF'
);
// Or add watermark image
this.imageEditor?.drawImage(
'logo.png',
10, 10,
100, 50,
true, 0, 0.5, false
);
}
}---
Managing Annotations
Retrieve All Annotations
getAnnotations() {
const annotations = this.imageEditor?.getShapeSetting();
annotations?.forEach(annotation => {
console.log('Shape ID:', annotation.id);
console.log('Type:', annotation.type); // 'text', 'shape', 'image', etc.
console.log('Position:', { x: annotation.x, y: annotation.y });
});
}Delete Annotations
deleteAnnotationById(shapeId: string) {
this.imageEditor?.deleteShape(shapeId);
}
deleteAllAnnotations() {
const annotations = this.imageEditor?.getShapeSetting();
annotations?.forEach(annotation => {
this.imageEditor?.deleteShape(annotation.id);
});
}Manage Annotations with Events
@Component({
template: `
<ejs-imageeditor
[shapeChange]="onShapeChange"
></ejs-imageeditor>
`
})
export class ShapeEventComponent {
onShapeChange(args: any) {
console.log('Shape changed:', args);
}
}---
Edge Cases & Troubleshooting
Issue: Text appears blurry when rotated
- Solution: Limit rotation to multiples of 90 degrees for text
Issue: Shape not visible after drawing
- Solution: Check if stroke color matches background; ensure stroke width > 0
Issue: Annotations disappear after transformations
- Solution: Annotations are transformed along with the image; this is expected behavior
Issue: Cannot edit text after creation
- Solution: Select the text annotation first, then modifications appear in toolbar
ImageEditor Component API Reference
This comprehensive API reference covers all properties, methods, and events available in the Syncfusion Angular ImageEditor component.
Properties
allowUndoRedo
- Type:
boolean - Default:
true - Description: Specifies whether undo/redo operations are enabled in the image editor.
cssClass
- Type:
string - Default:
'' - Description: Defines one or more CSS classes that can be used to customize the appearance of the Image Editor component.
disabled
- Type:
boolean - Default:
false - Description: Defines whether an Image Editor component is enabled or disabled.
finetuneSettings
- Type:
FinetuneSettingsModel - Default:
null - Description: Specifies the finetune settings option which can be used to perform color adjustments in the image editor control.
- Available Options:
brightness: { min, max, defaultValue }contrast: { min, max, defaultValue }saturation: { min, max, defaultValue }hue: { min, max, defaultValue }exposure: { min, max, defaultValue }blur: { min, max, defaultValue }opacity: { min, max, defaultValue }
fontFamily
- Type:
FontFamilyModel - Description: Predefine the font families that populate in font family dropdown list from the toolbar.
height
- Type:
string - Default:
'100%' - Description: Specifies the height of the Image Editor.
imageSmoothingEnabled
- Type:
boolean - Default:
false - Description: Determines whether high-quality images should be smoothed when rendered.
locale
- Type:
string - Default:
'' - Description: Overrides the global culture and localization value for this component. Default global culture is 'en-US'.
quickAccessToolbarTemplate
- Type:
string | Function - Default:
null - Description: Specifies a template for the quick access toolbar. Use this property to customize the quick access toolbar.
selectionSettings
- Type:
SelectionSettingsModel - Default:
null - Description: Specifies the selection settings to customize selection behavior and appearance.
showQuickAccessToolbar
- Type:
boolean - Default:
true - Description: Specifies whether to show/hide the quick access toolbar.
theme
- Type:
string | Theme - Default:
Theme.Bootstrap5 - Description: Specifies the theme of the Image Editor. The appearance of the shape selection in Image Editor is determined by this property.
toolbar
- Type:
string[] | ItemModel[] - Default:
null - Description: Specifies the toolbar items to perform UI interactions.
- Available Toolbar Items:
- Crop - helps to crop an image as ellipse, square, various ratio aspects, custom selection with resize, drag and drop.
- Straightening - helps to rotate an image by a specified angle.
- Annotate - help to insert a shape on image that supports rectangle, ellipse, line, arrow, path, text, image and freehand drawing.
- Transform - helps to rotate and flip an image.
- Finetunes - helps to perform adjustments on an image.
- Filters - helps to perform predefined color filters.
- Frame - helps to add decorative borders or frames around images.
- Resize - helps to modify the dimensions of an image.
- ZoomIn - performs zoom-in an image.
- ZoomOut - performs zoom-out an image.
- Save - save the modified image.
- Open - open an image to perform editing.
- Undo - helps to revert the last action.
- Redo - helps to redo the last action.
- Reset - reset the modification and restore the original image.
toolbarTemplate
- Type:
any - Default:
null - Description: Specifies a custom template for the toolbar of an image editor control. If this property is defined, the 'toolbar' property will not have any effect.
uploadSettings
- Type:
UploadSettingsModel - Description: Represents the settings for configuring image uploads.
- Available Options:
allowedExtensions: Specifies the allowed file extensions for uploaded images.minFileSize: Specifies the minimum size (in bytes) for the uploaded image.maxFileSize: Specifies the maximum size (in bytes) for the uploaded image.
width
- Type:
string - Default:
'100%' - Description: Specifies the width of an Image Editor.
zoomSettings
- Type:
ZoomSettingsModel - Default:
null - Description: Specifies the zoom settings to perform zooming action.
- Available Options:
minZoomFactor: Minimum zoom factor.maxZoomFactor: Maximum zoom factor.zoomFactor: Initial zoom factor.zoomTrigger: Specifies zoom triggers (MouseWheel, Pinch, Toolbar, Commands).zoomPoint: Point to zoom in/out on.
---
Methods
apply()
- Returns:
void - Description: Applies the operations performed in the Image Editor, such as annotation drawings.
applyImageFilter(filterOption)
- Parameters:
filterOption:ImageFilterOption- Specifies the filter options to the image.- Returns:
void - Description: Filtering an image with the given type of filters.
bringForward(shapeId)
- Parameters:
shapeId:string- Specifies the shape id to move the shape on an image.- Returns:
void - Description: Moves a shape to ahead of one shape based on the given shape id.
bringToFront(shapeId)
- Parameters:
shapeId:string- Specifies the shape id to move the shape on an image.- Returns:
void - Description: Moves a shape to the front of all other shapes based on the given shape id.
canRedo()
- Returns:
boolean - Description: Specifies if it's possible to redo the last recent action made in an Image Editor.
canUndo()
- Returns:
boolean - Description: Specifies if it's possible to undo the last recent action made in an Image Editor.
clearImage()
- Returns:
void - Description: Clears the loaded image in the Image Editor.
clearSelection(resetCrop?)
- Parameters:
resetCrop(optional):boolean- Specifies to reset last cropped image.- Returns:
void - Description: Clears the current selection performed in the image editor.
cloneShape(shapeId)
- Parameters:
shapeId:string- Specifies the shape id to clone a shape on an image.- Returns:
boolean - Description: Duplicates a shape based on the given shape ID in the ImageEditor.
crop()
- Returns:
boolean - Description: Crops an image based on the selection done in the image editor.
deleteRedact(id)
- Parameters:
id:string- Specifies the redaction id to delete the redaction on an image.- Returns:
void - Description: Deletes a redaction based on the given shape id.
deleteShape(id)
- Parameters:
id:string- Specifies the shape id to delete the shape on an image.- Returns:
void - Description: Deletes a shape based on the given shape id.
discard()
- Returns:
void - Description: Discards the operations performed in the Image Editor, such as annotation drawings.
drawArrow(startX?, startY?, endX?, endY?, strokeWidth?, strokeColor?, arrowStart?, arrowEnd?, isSelected?)
- Parameters:
startX(optional):number- Specifies start point x-coordinate of arrow.startY(optional):number- Specifies start point y-coordinate of arrow.endX(optional):number- Specifies end point x-coordinates of arrow.endY(optional):number- Specifies end point y-coordinates of the arrow.strokeWidth(optional):number- Specifies the stroke width of arrow.strokeColor(optional):string- Specifies the stroke color of arrow.arrowStart(optional):ArrowheadType- Specifies the type of arrowhead for start position (default: 'None').arrowEnd(optional):ArrowheadType- Specifies the type of arrowhead for end position (default: 'SolidArrow').isSelected(optional):boolean- Specifies to show the arrow in the selected state.- Returns:
boolean - Description: Draw arrow on an image.
drawEllipse(x?, y?, radiusX?, radiusY?, strokeWidth?, strokeColor?, fillColor?, degree?, isSelected?)
- Parameters:
x(optional):number- Specifies x-coordinate of ellipse.y(optional):number- Specifies y-coordinate of ellipse.radiusX(optional):number- Specifies the radius x point for the ellipse.radiusY(optional):number- Specifies the radius y point for the ellipse.strokeWidth(optional):number- Specifies the stroke width of ellipse.strokeColor(optional):string- Specifies the stroke color of ellipse.fillColor(optional):string- Specifies the fill color of the ellipse.degree(optional):number- Specifies the degree to rotate the ellipse.isSelected(optional):boolean- Specifies to show the ellipse in the selected state.- Returns:
boolean - Description: Draw ellipse on an image.
drawFrame(frameType, color?, gradientColor?, size?, inset?, offset?, borderRadius?, frameLineStyle?, lineCount?)
- Parameters:
frameType:FrameType- Specifies the frame option to be drawn on an image.color(optional):string- Specifies the color of a frame on an image (default: '#fff').gradientColor(optional):string- Specifies the gradient color of a frame on an image (default: '').size(optional):number- Specifies the size of the frame as a percentage (default: 20).inset(optional):number- Specifies the inset value for line, hook, and inset type frames as a percentage (default: 0).offset(optional):number- Specifies the offset value for line and inset type frames as a percentage (default: 0).borderRadius(optional):number- Specifies the border radius for line-type frames as a percentage (default: 0).frameLineStyle(optional):FrameLineStyle- Specifies the type of line to be drawn for line-type frames (default: Solid).lineCount(optional):number- Specifies the number of lines for line-type frames (default: 0).- Returns:
boolean - Description: Draw a frame on an image.
drawImage(data, x?, y?, width?, height?, isAspectRatio?, degree?, opacity?, isSelected?)
- Parameters:
data:string | ImageData- Specifies url of the image or image data.x(optional):number- Specifies x-coordinate of a starting point for an image.y(optional):number- Specifies y-coordinate of a starting point for an image.width(optional):number- Specifies the width of the image.height(optional):number- Specifies the height of the image.isAspectRatio(optional):boolean- Specifies whether to maintain aspect ratio or not.degree(optional):number- Specifies the degree to rotate the image.opacity(optional):number- Specifies the value for the image.isSelected(optional):boolean- Specifies to show the image in the selected state.- Returns:
boolean - Description: Draw an image as annotation on an image.
drawLine(startX?, startY?, endX?, endY?, strokeWidth?, strokeColor?, isSelected?)
- Parameters:
startX(optional):number- Specifies start point x-coordinate of line.startY(optional):number- Specifies start point y-coordinate of line.endX(optional):number- Specifies end point x-coordinates of line.endY(optional):number- Specifies end point y-coordinates of the line.strokeWidth(optional):number- Specifies the stroke width of line.strokeColor(optional):string- Specifies the stroke color of line.isSelected(optional):boolean- Specifies to show the line in the selected state.- Returns:
boolean - Description: Draw line on an image.
drawPath(pointColl, strokeWidth?, strokeColor?, isSelected?)
- Parameters:
pointColl:Point[]- Specifies collection of start and end x, y-coordinates of path.strokeWidth(optional):number- Specifies the stroke width of path.strokeColor(optional):string- Specifies the stroke color of path.isSelected(optional):boolean- Specifies to show the path in the selected state.- Returns:
boolean - Description: Draw path on an image.
drawRectangle(x?, y?, width?, height?, strokeWidth?, strokeColor?, fillColor?, degree?, isSelected?, borderRadius?)
- Parameters:
x(optional):number- Specifies x-coordinate of rectangle.y(optional):number- Specifies y-coordinate of rectangle.width(optional):number- Specifies the width of the rectangle.height(optional):number- Specifies the height of the rectangle.strokeWidth(optional):number- Specifies the stroke width of rectangle.strokeColor(optional):string- Specifies the stroke color of rectangle.fillColor(optional):string- Specifies the fill color of the rectangle.degree(optional):number- Specifies the degree to rotate the rectangle.isSelected(optional):boolean- Specifies to show the rectangle in the selected state.borderRadius(optional):number- Specifies the radius to apply border radius to rectangle.- Returns:
boolean - Description: Draw a rectangle on an image.
drawRedact(type?, x?, y?, width?, height?, value?)
- Parameters:
type(optional):RedactType- Specifies the type of redaction to be drawn on the image (blur or pixelate).x(optional):number- Specifies x-coordinate of redaction.y(optional):number- Specifies y-coordinate of redaction.width(optional):number- Specifies the width of the redaction (default: 100).height(optional):number- Specifies the height of the redaction (default: 50).value(optional):number- Specifies the blur value for blur-type redaction or the pixel size for pixelate-type redaction (default: 20).- Returns:
boolean - Description: Draw a redaction on an image.
drawText(x?, y?, text?, fontFamily?, fontSize?, bold?, italic?, color?, isSelected?, degree?, fillColor?, strokeColor?, strokeWidth?, transformCollection?, underline?, strikethrough?)
- Parameters:
x(optional):number- Specifies x-coordinate of text.y(optional):number- Specifies y-coordinate of text.text(optional):string- Specifies the text to add on an image.fontFamily(optional):string- Specifies the font family of the text.fontSize(optional):number- Specifies the font size of the text.bold(optional):boolean- Specifies whether the text is bold or not.italic(optional):boolean- Specifies whether the text is italic or not.color(optional):string- Specifies font color of the text.isSelected(optional):boolean- Specifies to show the text in the selected state.degree(optional):number- Specifies the degree to rotate the text.fillColor(optional):string- Specifies the background Color of the text.strokeColor(optional):string- Specifies the outline color of the text annotation.strokeWidth(optional):number- Specifies the outline stroke width of the text annotation.transformCollection(optional):TransformationCollection[]- Specifies the transform collection of the text annotation.underline(optional):boolean- Specifies whether the text should be underlined.strikethrough(optional):boolean- Specifies whether the text should have a strikethrough.- Returns:
boolean - Description: Draw a text on an image.
enableShapeDrawing(shapeType, isEnabled?)
- Parameters:
shapeType:ShapeType- Specifies the type of shape to be enabled or disabled for drawing.isEnabled(optional):boolean- Specifies a value to indicate whether to enable or disable shape drawing (default: true).- Returns:
void - Description: Enable or disable a shape drawing option in an Image Editor.
enableTextEditing()
- Returns:
void - Description: Enable text area editing in the ImageEditor.
export(type?, fileName?, imageQuality?)
- Parameters:
type(optional):string- Specifies a format of image to be saved.fileName(optional):string- Specifies a file name to be saved.imageQuality(optional):number- Specifies the quality of an image to be saved (default: 1).- Returns:
void - Description: Export an image using the specified file name and the extension.
finetuneImage(finetuneOption, value)
- Parameters:
finetuneOption:ImageFinetuneOption- Specifies the finetune options to be performed in the image.value:number- Specifies the value for finetuning the image.- Returns:
void - Description: Finetuning an image with the given type of finetune and its value in the image editor.
flip(direction)
- Parameters:
direction:Direction- Specifies the direction to flip the image (Horizontal or Vertical).- Returns:
void - Description: Flips an image by horizontally or vertically in the image editor.
freehandDraw(value)
- Parameters:
value:boolean- Specifies a value whether to enable or disable freehand drawing.- Returns:
void - Description: Enable or disable a freehand drawing in an Image Editor.
getImageData()
- Returns:
ImageData - Description: Returns an image as ImageData to load it in to a canvas.
getImageDimension()
- Returns:
Dimension - Description: Get the dimension of an image in the image editor such as x, y, width, and height. The method helps to get dimension after cropped an image.
getImageFilter(filterOption)
- Parameters:
filterOption:ImageFilterOption- Specifies the filter options to the image.- Returns:
string - Description: Update filter to the canvas in the ImageEditor.
getRedacts()
- Returns:
RedactSettings[] - Description: Get all the shapes details which is drawn on an image editor.
getShapeSetting(id)
- Parameters:
id:string- Specifies the shape id on an image.- Returns:
ShapeSettings - Description: Get particular shapes details based on id of the shape which is drawn on an image editor.
getShapeSettings()
- Returns:
ShapeSettings[] - Description: Get all the shapes details which is drawn on an image editor.
open(url)
- Parameters:
url:string | ImageData- Specifies the URL or image data to open.- Returns:
void - Description: Opens an image as URL or ImageData for editing in an image editor.
pan(value, x?, y?)
- Parameters:
value:boolean- Specifies a value whether enable or disable panning.x(optional):number- Specifies a value to pan the image horizontally.y(optional):number- Specifies a value to pan the image vertically.- Returns:
void - Description: Enable or disable a panning on the Image Editor.
redo()
- Returns:
void - Description: Redo the last user action that was undone by the user or
undomethod.
reset()
- Returns:
void - Description: Reset all the changes done in an image editor and revert to original image.
resize(width, height, isAspectRatio?)
- Parameters:
width:number- Specifies the width of an image.height:number- Specifies the height of an image.isAspectRatio(optional):boolean- Specifies whether the scaling option is enabled or not.- Returns:
boolean - Description: Resize an image by changing its width and height.
rotate(degree)
- Parameters:
degree:number- Specifies a degree to rotate an image (positive for clockwise, negative for anti-clockwise).- Returns:
boolean - Description: Rotate an image to clockwise and anti-clockwise.
select(type, startX?, startY?, width?, height?)
- Parameters:
type:string- Specifies the shape (circle, square, custom selection, or pre-defined ratios).startX(optional):number- Specifies the start x-coordinate point of the selection.startY(optional):number- Specifies the start y-coordinate point of the selection.width(optional):number- Specifies the width of the selection area.height(optional):number- Specifies the height of the selection area.- Returns:
void - Description: Perform selection in an image editor. The selection helps to crop an image.
selectRedact(id)
- Parameters:
id:string- Specifies the shape id to select a redact on an image.- Returns:
boolean - Description: Select a redaction based on the given redaction id.
selectShape(id)
- Parameters:
id:string- Specifies the shape id to select a shape on an image.- Returns:
boolean - Description: Select a shape based on the given shape id.
sendBackward(shapeId)
- Parameters:
shapeId:string- Specifies the shape id to move the shape on an image.- Returns:
void - Description: Moves a shape to behind one shape based on the given shape id.
sendToBack(shapeId)
- Parameters:
shapeId:string- Specifies the shape id to move the shape on an image.- Returns:
void - Description: Moves a shape to behind all other shapes based on the given shape id.
straightenImage(degree)
- Parameters:
degree:number- The degree value specifying the amount of rotation for straightening the image (positive for clockwise, negative for counterclockwise).- Returns:
boolean - Description: Straightens an image by rotating it clockwise or counterclockwise.
undo()
- Returns:
void - Description: Reverse the last action which performed by the user in the Image Editor.
update()
- Returns:
void - Description: To refresh the Canvas Wrapper.
updateRedact(setting, isSelected?)
- Parameters:
setting:RedactSettings- Specifies the redact settings to be updated for the shape on an image.isSelected(optional):boolean- Specifies to show the redacts in the selected state.- Returns:
boolean - Description: This method is used to update the existing redacts by changing its height, width, blur, and pixel size in the component.
updateShape(setting, isSelected?)
- Parameters:
setting:ShapeSettings- Specifies the shape settings to be updated for the shape on an image.isSelected(optional):boolean- Specifies to show the shape in the selected state.- Returns:
boolean - Description: This method is used to update the existing shapes by changing its height, width, color, and font styles in the component.
zoom(zoomFactor, zoomPoint?)
- Parameters:
zoomFactor:number- The percentage-based zoom factor to use (e.g., 20 for 2x zoom).zoomPoint(optional):Point- The point in the image editor to zoom in/out on.- Returns:
void - Description: Zoom in or out on a point in the image editor.
---
Events
beforeSave
- Type:
EmitType<BeforeSaveEventArgs> - Description: Event callback that is raised before an image is saved.
click
- Type:
EmitType<ImageEditorClickEventArgs> - Description: Event callback that is raised while clicking on an image in the Image Editor.
created
- Type:
EmitType<Event> - Description: Event callback that is raised after rendering the Image Editor component.
cropping
- Type:
EmitType<CropEventArgs> - Description: Event callback that is raised while cropping an image.
destroyed
- Type:
EmitType<Event> - Description: Event callback that is raised once the component is destroyed with its elements and bound events.
editComplete
- Type:
EmitType<EditCompleteEventArgs> - Description: Event callback that is triggered after the completion of an editing action in the image editor. This event occurs after the image editor canvas has been updated through actions such as cropping, drawing annotations, applying filters, fine-tuning, or other customizations.
fileOpened
- Type:
EmitType<OpenEventArgs> - Description: Event callback that is raised once an image is opened in an Image Editor.
finetuneValueChanging
- Type:
EmitType<FinetuneEventArgs> - Description: Event callback that is raised when applying fine tune to an image.
flipping
- Type:
EmitType<FlipEventArgs> - Description: Event callback that is raised while flipping an image.
frameChange
- Type:
EmitType<FrameChangeEventArgs> - Description: Event callback that is raised while applying frames on an image.
imageFiltering
- Type:
EmitType<ImageFilterEventArgs> - Description: Event callback that is raised when applying filter to an image.
panning
- Type:
EmitType<PanEventArgs> - Description: Event callback that is raised while panning an image.
quickAccessToolbarItemClick
- Type:
EmitType<ClickEventArgs> - Description: Event callback that is raised once the quick access toolbar item is clicked.
quickAccessToolbarOpen
- Type:
EmitType<QuickAccessToolbarEventArgs> - Description: Event callback that is raised when opening the quick access toolbar.
resizing
- Type:
EmitType<ResizeEventArgs> - Description: Event callback that is raised while resizing an image.
rotating
- Type:
EmitType<RotateEventArgs> - Description: Event callback that is raised while rotating an image.
saved
- Type:
EmitType<SaveEventArgs> - Description: Event callback that is raised once an image is saved.
selectionChanging
- Type:
EmitType<SelectionChangeEventArgs> - Description: Event callback that is raised while changing selection in an Image Editor.
shapeChange
- Type:
EmitType<ShapeChangeEventArgs> - Description: Event callback that is raised after shape changing action is performed in an image editor.
shapeChanging
- Type:
EmitType<ShapeChangeEventArgs> - Description: Event callback that is raised while changing shapes in an Image Editor.
toolbarCreated
- Type:
EmitType<ToolbarEventArgs> - Description: Event callback that is raised once the toolbar is created.
toolbarItemClicked
- Type:
EmitType<ClickEventArgs> - Description: Event callback that is raised once the toolbar item is clicked.
toolbarUpdating
- Type:
EmitType<ToolbarEventArgs> - Description: Event callback that is raised while updating/refreshing the toolbar.
---
Event Arguments Reference
BeforeSaveEventArgs
Properties available when the beforeSave event is triggered.
ImageEditorClickEventArgs
Properties available when the click event is triggered.
CropEventArgs
Properties available when the cropping event is triggered.
EditCompleteEventArgs
Properties available when the editComplete event is triggered.
OpenEventArgs
Properties available when the fileOpened event is triggered.
FinetuneEventArgs
Properties available when the finetuneValueChanging event is triggered.
FlipEventArgs
Properties available when the flipping event is triggered.
FrameChangeEventArgs
Properties available when the frameChange event is triggered.
ImageFilterEventArgs
Properties available when the imageFiltering event is triggered.
PanEventArgs
Properties available when the panning event is triggered.
QuickAccessToolbarEventArgs
Properties available when the quickAccessToolbarOpen event is triggered.
ResizeEventArgs
Properties available when the resizing event is triggered.
RotateEventArgs
Properties available when the rotating event is triggered.
SaveEventArgs
Properties available when the saved event is triggered.
SelectionChangeEventArgs
Properties available when the selectionChanging event is triggered.
ShapeChangeEventArgs
Properties available when the shapeChange or shapeChanging event is triggered.
ToolbarEventArgs
Properties available when the toolbarCreated or toolbarUpdating event is triggered.
ClickEventArgs
Properties available when the toolbarItemClicked or quickAccessToolbarItemClick event is triggered.
---
Filter Types
Available Image Filters
- Cold - Applies a cool blue tone
- Warm - Applies a warm orange tone
- Chrome - Applies a chrome effect
- Sepia - Applies a sepia tone
- Invert - Inverts the image colors
- Grayscale - Converts to grayscale
- Black & White - High contrast black and white
---
Finetune Types
Available Fine-tune Options
- Brightness - Adjust image brightness (-100 to 100)
- Contrast - Adjust image contrast (-100 to 100)
- Saturation - Adjust color saturation (-100 to 100)
- Hue - Adjust color hue (-180 to 180)
- Exposure - Adjust image exposure (-100 to 100)
- Blur - Apply blur effect (0 to higher values)
- Opacity - Adjust transparency (0 to 100)
---
Shape Types
Available Shape Types
- Rectangle - Draw rectangular shapes
- Ellipse - Draw elliptical/circular shapes
- Line - Draw straight lines
- Arrow - Draw arrows with customizable heads
- Path - Draw freehand paths
- Text - Add text annotations
- Image - Add image annotations
- FreehandDraw - Freehand drawing mode
---
Frame Types
Available Frame Types
- Mat - Traditional mat frame
- Bevel - Beveled edge frame
- Line - Simple line frame
- Hook - Hook style frame
- Inset - Inset style frame
---
Direction Types
Available Direction Values for Flip
- Horizontal - Flip horizontally
- Vertical - Flip vertically
---
Selection Shapes
Available Selection Types
- Circle - Circular selection
- Square - Square selection
- Custom - Custom rectangular selection
- 2:3 - Aspect ratio 2:3
- 3:2 - Aspect ratio 3:2
- 4:3 - Aspect ratio 4:3
- 16:9 - Aspect ratio 16:9
- 1:1 - Square aspect ratio
- And other common aspect ratios
---
Export Format Types
Supported Export Formats
- png - Portable Network Graphics
- jpeg - Joint Photographic Experts Group (with quality control)
- svg - Scalable Vector Graphics
- webp - Web Picture format
- bmp - Bitmap format
---
Usage Examples
Example 1: Using Events
<ejs-imageeditor
#imageEditor
(created)="onCreated()"
(saved)="onSaved($event)"
(editComplete)="onEditComplete($event)"
>
</ejs-imageeditor>
export class AppComponent {
onCreated() {
console.log('ImageEditor created');
}
onSaved(args: SaveEventArgs) {
console.log('Image saved', args);
}
onEditComplete(args: EditCompleteEventArgs) {
console.log('Edit complete', args);
}
}Example 2: Setting Properties
zoomSettings = {
minZoomFactor: 1,
maxZoomFactor: 100,
zoomFactor: 1,
zoomTrigger: ZoomTrigger.MouseWheel | ZoomTrigger.Pinch,
zoomPoint: new Point { x: 500, y: 500 }
};
finetuneSettings = {
brightness: { min: -100, max: 100, defaultValue: 0 },
contrast: { min: -100, max: 100, defaultValue: 0 },
saturation: { min: -100, max: 100, defaultValue: 0 }
};
uploadSettings = {
allowedExtensions: ['.jpg', '.png', '.gif'],
minFileSize: 5000,
maxFileSize: 5000000
};
toolbar = [
'Open', 'Undo', 'Redo', 'Crop', 'Annotate',
'Finetune', 'Filter', 'Frame', 'Redact', 'Resize',
'Save', 'Reset'
];---
Related References
For more information on specific features, refer to:
- Getting Started - Installation and setup
- Annotations - Drawing annotations
- Selection and Cropping - Selection tools
- Transformations - Rotate, flip, zoom
- Filters and Fine-tuning - Color adjustments
- Toolbar Customization - Customize toolbar
- Accessibility - WCAG compliance
Clearing the Image Editor
Reset editor state for reusing the component in dialogs or multi-image workflows.
Clear Image Method
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-clear',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="clearEditor()">Clear Editor</button>
`
})
export class ClearComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
clearEditor() {
this.imageEditor?.clearImage();
}
}What Clear Image Does
The clearImage() method:
- Removes current image from canvas
- Clears all annotations
- Resets zoom to 100%
- Clears undo/redo history
- Returns canvas to empty state
Dialog Integration Pattern
@Component({
selector: 'app-image-editor-dialog',
template: `
<button (click)="openDialog()">Edit Image</button>
<ng-template #dialogContent>
<ejs-imageeditor
#imageEditor
style="height: 500px;"
></ejs-imageeditor>
<div style="margin-top: 10px; text-align: right;">
<button (click)="saveImage()">Save</button>
<button (click)="closeDialog()">Cancel</button>
</div>
</ng-template>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class ImageEditorDialogComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
dialogRef?: DialogRef;
openDialog() {
// Clear editor before opening dialog
this.imageEditor?.clearImage();
// Open dialog
this.dialogRef = this.dialog.open(this.dialogContent, {
width: '800px',
height: '600px'
});
}
closeDialog() {
// Clear when closing to free resources
this.imageEditor?.clearImage();
this.dialogRef?.close();
}
saveImage() {
// Save image before clearing
const imageData = this.imageEditor?.export();
// Handle save...
this.closeDialog();
}
}Multi-Image Editor
@Component({
selector: 'app-multi-image-editor',
template: `
<div style="display: flex; gap: 20px;">
<div>
<h3>Image List</h3>
<ul>
<li *ngFor="let image of images; let i = index"
(click)="editImage(i)"
[style.fontWeight]="currentIndex === i ? 'bold' : 'normal'">
{{ image.name }}
</li>
</ul>
</div>
<div>
<h3>Editor</h3>
<ejs-imageeditor
#imageEditor
style="width: 500px; height: 400px;"
></ejs-imageeditor>
<div style="margin-top: 10px;">
<button (click)="saveCurrentImage()">Save</button>
<button (click)="nextImage()">Next</button>
<button (click)="previousImage()">Previous</button>
</div>
</div>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class MultiImageEditorComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
images: Array<{name: string, data: string}> = [];
currentIndex = 0;
editImage(index: number) {
// Clear previous image
this.imageEditor?.clearImage();
// Load new image
this.currentIndex = index;
const image = this.images[index];
this.imageEditor?.open(image.data);
}
saveCurrentImage() {
const image = this.images[this.currentIndex];
image.data = this.imageEditor?.export() || image.data;
}
nextImage() {
this.saveCurrentImage();
if (this.currentIndex < this.images.length - 1) {
this.editImage(this.currentIndex + 1);
}
}
previousImage() {
this.saveCurrentImage();
if (this.currentIndex > 0) {
this.editImage(this.currentIndex - 1);
}
}
}Best Practices
1. Clear before dialog: Reset editor state before opening dialog 2. Clear after close: Free resources when closing dialog 3. Save before clear: Always save image data before clearing 4. Batch operations: Use clearImage() between processing multiple images
Use Cases
Dialog-based editor: Clear when opening/closing dialog Batch processing: Clear between images in image processing workflow Resource cleanup: Clear when component is destroyed Fresh start: Allow users to start over without reloading component
Performance Note
Clearing the editor immediately:
- Frees canvas resources
- Clears undo/redo history
- Resets internal state
- Prepares for next image
End-User Capabilities Guide
Learn what users can do with the Angular Image Editor interface.
Table of Contents
- Opening Images
- Viewing and Navigation
- Image Manipulation
- Annotations
- Effects and Filters
- Image Operations
- Exporting Results
Opening Images
Users can add images to the editor by:
- File Upload: Click "Open" toolbar button to browse and select images
- Drag and Drop: Drag image files directly onto the editor canvas
- URL: Paste image URLs in the open dialog
- Recent Images: Access previously edited images from history
Supported Formats
- JPEG (.jpg, .jpeg) - Best for photos
- PNG (.png) - Supports transparency
- SVG (.svg) - Vector graphics
- WebP (.webp) - Modern web format
- BMP (.bmp) - Legacy format
File Size Limits:
- Minimum: 100 × 100 pixels
- Maximum: 5000 × 5000 pixels (configurable)
- File size: Up to 50MB (configurable)
Viewing and Navigation
Zoom Controls
Users can zoom images using:
- Toolbar buttons: "+" and "-" buttons
- Preset zoom levels: 25%, 50%, 100%, 150%, 200%
- Fit to Width: Auto-fit horizontal dimension
- Fit to Height: Auto-fit vertical dimension
- Fit to Window: Show entire image
- Mouse wheel: Scroll to zoom in/out
- Keyboard: Ctrl+Plus (zoom in), Ctrl+Minus (zoom out)
Panning
When zoomed beyond canvas size:
- Click and drag on the image to pan
- Arrow keys to move viewport
- Hand cursor indicates pannable area
Reset View
- Reset Zoom: Returns to 100% zoom
- Fit to Canvas: Auto-scales to fit available space
Image Manipulation
Rotation and Flipping
Rotate:
- Rotate Left (90° counter-clockwise)
- Rotate Right (90° clockwise)
- Rotate 180°
Flip:
- Flip Horizontal (mirror left-right)
- Flip Vertical (mirror top-bottom)
- Flip Both (180° rotation alternative)
Straighten:
- Fine-tune angle from -45° to +45°
- Remove camera tilt from photos
Cropping
Users can crop images:
1. Select Crop Tool from toolbar 2. Draw crop area on image (freeform or preset ratio) 3. Adjust corners to refine selection 4. Apply Crop when satisfied
Preset Ratios:
- Custom (free form)
- Square (1:1)
- 3×2 (landscape photos)
- 2×3 (portrait)
- 16×9 (widescreen)
- 4×3 (standard)
- 9×16 (mobile)
Straightening
Drag straighten slider to align tilted images:
- Range: -45° to +45°
- Live preview shows result
- Apply to commit changes
Annotations
Text Annotations
Users can add text to images: 1. Click "Text" annotation tool 2. Click on image to place text 3. Type message 4. Customize:
- Font family, size, and weight
- Color and opacity
- Alignment (left, center, right)
- Underline and strikethrough
Drawing Annotations
Freehand Drawing:
- Sketch freely on image
- Adjust brush size and color
- Draw multiple strokes
Shape Annotations:
- Rectangle, Ellipse, Line, Arrow
- Path drawing (connected lines)
- Customize stroke color and width
Image Annotations
Overlay images on current image:
- Add watermarks
- Combine multiple images
- Position and scale overlay
Annotation Management
- Select existing annotations (click on them)
- Move annotations (drag)
- Resize annotations (corner handles)
- Delete annotations (select + Delete key)
- Undo/Redo annotation changes (Ctrl+Z, Ctrl+Y)
Effects and Filters
Preset Filters
Apply one-click effects:
- Warm: Adds warm tones to image
- Cold: Adds cool/blue tones
- Sepia: Vintage brown tone
- Chrome: Bright metallic effect
- Invert: Inverts all colors
- Grayscale: Black and white
- BlackAndWhite: High-contrast B&W
Fine-Tuning Adjustments
Adjust image properties with sliders:
| Parameter | Range | Use Case |
|---|---|---|
| Brightness | 0-100 | Lighten/darken image |
| Contrast | 0-100 | Increase/decrease tonal range |
| Saturation | 0-100 | Boost or reduce color intensity |
| Hue | 0-360° | Shift color tone |
| Exposure | 0-100 | Brighten shadows/reduce highlights |
| Blur | 1-100 | Add blur effect |
| Opacity | 0-100 | Image transparency |
Custom Presets
Save and reuse adjustment combinations: 1. Adjust filters and fine-tuning 2. Save current settings as preset 3. Apply preset to other images
Image Operations
Frames
Add decorative borders:
- Mat Frame: Solid color border
- Bevel Frame: 3D beveled edge
- Line Frame: Simple line border
- Hook Frame: Vintage corner hooks
- Inset Frame: Inset depth effect
Customize frame:
- Color and gradient options
- Border size and width
- Corner styles
- Shadow and offset
Redaction (Privacy Protection)
Hide sensitive information:
Blur Redaction:
- Pixelate area to obscure details
- Useful for faces, license plates, text
Solid Redaction:
- Cover with solid color bar
- Ideal for names, addresses, amounts
Strikethrough Redaction:
- Cross out sensitive text
- Shows removal intent
Z-Order (Layering)
Manage annotation stacking:
- Bring Forward: Move up one layer
- Send Backward: Move down one layer
- Bring to Front: Move to top
- Send to Back: Move to bottom
Exporting Results
Export Options
Users can save edited images as:
Image Formats:
- JPEG (adjustable quality)
- PNG (preserves transparency)
- SVG (vector-based)
- WebP (modern format)
- BMP (legacy format)
Output Methods:
- Download: Save to computer
- Copy: Copy to clipboard
- Share: Generate shareable link
- Print: Direct print
Export Settings
JPEG/WebP Quality:
- Range: 0-100%
- Higher quality = larger file size
- Recommended: 85-95% for best balance
PNG Options:
- Preserves transparency
- No quality loss
- Larger file sizes
Watermarking:
- Add watermark during export
- Text or image watermark
- Adjustable opacity and position
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Ctrl+Z | Undo |
| Ctrl+Y | Redo |
| Ctrl++ | Zoom in |
| Ctrl+- | Zoom out |
| Ctrl+0 | Reset zoom |
| Delete | Delete selected annotation |
| Arrow Keys | Pan when zoomed |
| Escape | Deselect tool |
Best Practices for Users
1. Start with basics: Crop and straighten before advanced edits 2. Use presets: Filters and presets save time 3. Zoom appropriately: 100% zoom for precise work 4. Undo liberally: Use undo/redo to experiment 5. Save versions: Export multiple formats for different uses 6. Test on target: Verify output on intended platform (web, print, etc.)
Common User Tasks
Task: Prepare photo for website 1. Open original photo 2. Crop to 16:9 ratio 3. Apply warm filter 4. Increase saturation by 20% 5. Export as WebP at 85% quality
Task: Create social media thumbnail 1. Open image 2. Crop to 1:1 (square) 3. Add text annotation with caption 4. Apply chrome filter 5. Export as PNG
Task: Remove sensitive information 1. Open image 2. Select redaction tool (blur) 3. Draw over sensitive areas 4. Apply to all areas 5. Export as JPEG
Task: Create collage 1. Open base image 2. Add multiple image annotations 3. Position and scale each 4. Add text labels 5. Export final composition
Filtering and Fine-tuning in Angular Image Editor
Table of Contents
---
Image Filters
Apply preset visual effects to instantly change image appearance.
Available Filters
// Filter options available:
// 'Default' - Remove all filters
// 'Cold' - Cool blue tone
// 'Warm' - Warm orange tone
// 'Chrome' - Chrome effect
// 'Sepia' - Vintage brown tone
// 'Invert' - Inverted colors
// 'Grayscale' - Black and white
// 'BlackAndWhite' - High contrast black and whiteApply Filter
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-filters',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="applyCold()">Cold</button>
<button (click)="applyWarm()">Warm</button>
<button (click)="applySepia()">Sepia</button>
<button (click)="applyInvert()">Invert</button>
<button (click)="applyGrayscale()">Grayscale</button>
<button (click)="removeFilter()">Default</button>
`
})
export class FiltersComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
applyCold() {
this.imageEditor?.applyImageFilter('Cold');
}
applyWarm() {
this.imageEditor?.applyImageFilter('Warm');
}
applySepia() {
this.imageEditor?.applyImageFilter('Sepia');
}
applyInvert() {
this.imageEditor?.applyImageFilter('Invert');
}
applyGrayscale() {
this.imageEditor?.applyImageFilter('Grayscale');
}
removeFilter() {
this.imageEditor?.applyImageFilter('Default');
}
}Filter Effects Summary
| Filter | Effect | Use Case |
|---|---|---|
Cold | Blue cast, cool tones | Winter photos, cooling warmth |
Warm | Orange cast, warm tones | Sunset photos, adding warmth |
Chrome | Metallic chrome effect | Modern, stylized look |
Sepia | Brown vintage tone | Vintage, nostalgic feel |
Invert | Inverted colors | Creative effect, negative |
Grayscale | Black and white | Classic, timeless look |
BlackAndWhite | High contrast B&W | Dramatic, artistic |
Toolbar Filter Selection
Users can select filters through toolbar:
@Component({
template: `
<ejs-imageeditor
[toolbar]="['Filter', 'Finetune', 'Save']"
></ejs-imageeditor>
`
})
export class FilterToolbarComponent { }---
Fine-tuning Operations
Make precise adjustments to image properties.
Brightness Adjustment
increaseBrightness() {
// Value range: typically -100 to 100
this.imageEditor?.finetuneImage('Brightness', 30);
}
decreaseBrightness() {
this.imageEditor?.finetuneImage('Brightness', -30);
}Contrast Adjustment
increaseContrast() {
this.imageEditor?.finetuneImage('Contrast', 40);
}
decreaseContrast() {
this.imageEditor?.finetuneImage('Contrast', -40);
}Saturation Adjustment
increaseSaturation() {
this.imageEditor?.finetuneImage('Saturation', 50);
}
decreaseSaturation() {
this.imageEditor?.finetuneImage('Saturation', -50);
}Hue Adjustment
shiftHue() {
this.imageEditor?.finetuneImage('Hue', 45);
}
resetHue() {
this.imageEditor?.finetuneImage('Hue', 0);
}Exposure Adjustment
increaseExposure() {
this.imageEditor?.finetuneImage('Exposure', 25);
}
decreaseExposure() {
this.imageEditor?.finetuneImage('Exposure', -25);
}Blur Effect
applyBlur() {
this.imageEditor?.finetuneImage('Blur', 10);
}
removeBlur() {
this.imageEditor?.finetuneImage('Blur', 0);
}Opacity Adjustment
makeTransparent() {
this.imageEditor?.finetuneImage('Opacity', 0.5); // 50% opacity
}
makeOpaque() {
this.imageEditor?.finetuneImage('Opacity', 1.0); // 100% opacity
}Combining Adjustments
enhancePhoto() {
// Increase brightness
this.imageEditor?.finetuneImage('Brightness', 15);
// Increase contrast
this.imageEditor?.finetuneImage('Contrast', 20);
// Increase saturation
this.imageEditor?.finetuneImage('Saturation', 30);
}---
Event Handling
Image Filtering Event
@Component({
template: `
<ejs-imageeditor
[imageFiltering]="onImageFiltering"
></ejs-imageeditor>
`
})
export class ImageFilteringEventComponent {
onImageFiltering(args: any) {
console.log('Filter Type:', args.filter);
// Can prevent filter application
if (args.filter === 'Sepia') {
args.cancel = true; // Prevent sepia filter
}
}
}Fine-tune Value Changing Event
@Component({
template: `
<ejs-imageeditor
[finetuneValueChanging]="onFinetuneChanging"
></ejs-imageeditor>
`
})
export class FinetuneEventComponent {
onFinetuneChanging(args: any) {
console.log('Finetune Type:', args.finetune); // 'Brightness', 'Contrast', etc.
console.log('Value:', args.value);
// Limit brightness adjustment
if (args.finetune === 'Brightness' && args.value > 50) {
args.value = 50;
}
// Prevent specific adjustments
if (args.finetune === 'Blur') {
args.cancel = true;
}
}
}---
Complete Examples
Professional Photo Enhancement
@Component({
selector: 'app-photo-enhancer',
template: `
<div style="padding: 20px;">
<h3>Photo Enhancer</h3>
<div style="margin-bottom: 10px;">
<button (click)="enhanceAuto()">Auto Enhance</button>
<button (click)="increaseBrightness()">Brighter</button>
<button (click)="decreaseBrightness()">Darker</button>
<button (click)="vibrancy()">Vibrant</button>
<button (click)="vintage()">Vintage</button>
</div>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor
#imageEditor
[toolbar]="['Open', 'Finetune', 'Filter', 'Undo', 'Redo', 'Save']"
></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule],
standalone: true
})
export class PhotoEnhancerComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
enhanceAuto() {
this.imageEditor?.finetuneImage('Brightness', 10);
this.imageEditor?.finetuneImage('Contrast', 15);
this.imageEditor?.finetuneImage('Saturation', 20);
}
increaseBrightness() {
this.imageEditor?.finetuneImage('Brightness', 20);
}
decreaseBrightness() {
this.imageEditor?.finetuneImage('Brightness', -20);
}
vibrancy() {
this.imageEditor?.applyImageFilter('Warm');
this.imageEditor?.finetuneImage('Saturation', 30);
}
vintage() {
this.imageEditor?.applyImageFilter('Sepia');
this.imageEditor?.finetuneImage('Contrast', -10);
}
}Slider-Based Adjustment
@Component({
selector: 'app-slider-adjustment',
template: `
<div style="padding: 20px;">
<div style="margin-bottom: 20px;">
<label>Brightness:</label>
<input
type="range"
min="-100"
max="100"
value="0"
(change)="onBrightnessChange($event)"
>
<span>{{ brightnessValue }}</span>
</div>
<div style="margin-bottom: 20px;">
<label>Contrast:</label>
<input
type="range"
min="-100"
max="100"
value="0"
(change)="onContrastChange($event)"
>
<span>{{ contrastValue }}</span>
</div>
<div style="margin-bottom: 20px;">
<label>Saturation:</label>
<input
type="range"
min="-100"
max="100"
value="0"
(change)="onSaturationChange($event)"
>
<span>{{ saturationValue }}</span>
</div>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor #imageEditor></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class SliderAdjustmentComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
brightnessValue = 0;
contrastValue = 0;
saturationValue = 0;
onBrightnessChange(event: any) {
this.brightnessValue = event.target.value;
this.imageEditor?.finetuneImage('Brightness', this.brightnessValue);
}
onContrastChange(event: any) {
this.contrastValue = event.target.value;
this.imageEditor?.finetuneImage('Contrast', this.contrastValue);
}
onSaturationChange(event: any) {
this.saturationValue = event.target.value;
this.imageEditor?.finetuneImage('Saturation', this.saturationValue);
}
}Creative Effects Suite
@Component({
selector: 'app-effects-suite',
template: `
<div style="padding: 20px;">
<div style="margin-bottom: 10px;">
<button (click)="duotone()">Duotone</button>
<button (click)="dramaticlighting()">Dramatic</button>
<button (click)="softfocus()">Soft Focus</button>
<button (click)="noir()">Film Noir</button>
<button (click)="reset()">Reset</button>
</div>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor #imageEditor></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule],
standalone: true
})
export class EffectsSuiteComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
duotone() {
this.imageEditor?.applyImageFilter('Cold');
this.imageEditor?.finetuneImage('Saturation', -50);
this.imageEditor?.finetuneImage('Contrast', 30);
}
dramaticlighting() {
this.imageEditor?.finetuneImage('Contrast', 50);
this.imageEditor?.finetuneImage('Brightness', -10);
this.imageEditor?.finetuneImage('Saturation', 20);
}
softfocus() {
this.imageEditor?.finetuneImage('Blur', 15);
this.imageEditor?.finetuneImage('Brightness', 10);
}
noir() {
this.imageEditor?.applyImageFilter('BlackAndWhite');
this.imageEditor?.finetuneImage('Contrast', 40);
this.imageEditor?.finetuneImage('Brightness', -5);
}
reset() {
this.imageEditor?.applyImageFilter('Default');
this.imageEditor?.finetuneImage('Brightness', 0);
this.imageEditor?.finetuneImage('Contrast', 0);
this.imageEditor?.finetuneImage('Saturation', 0);
}
}---
Best Practices
1. Combine filters and fine-tuning for complex effects 2. Use undo/redo to experiment without losing original 3. Save after adjustments to preserve edits 4. Monitor event handlers for performance with extreme values 5. Provide presets for common adjustments 6. Use sliders for user-controlled fine-tuning
---
Edge Cases & Troubleshooting
Issue: Changes not visible immediately
- Solution: Wait for event to complete; some effects render asynchronously
Issue: Over-adjusting creates poor quality
- Solution: Use moderate values (±50 range); extreme values may distort image
Issue: Cannot undo filter application
- Solution: Ensure undo is enabled and history hasn't reached 16-step limit
Issue: Filter + fine-tune combination looks different than expected
- Solution: Apply in consistent order; different sequences may yield different visual results
Fit to Width and Height
Automatically zoom and position images to fit within canvas boundaries.
Fit to Width
Scale image to match canvas width while maintaining aspect ratio:
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-fit-width',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="fitToWidth()">Fit to Width</button>
`
})
export class FitWidthComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
fitToWidth() {
const zoomPercent = this.calculateWidthFitPercent();
this.imageEditor?.zoom(zoomPercent);
}
calculateWidthFitPercent() {
// Calculate zoom percentage for width fit
// Returns appropriate zoom level as percentage (e.g., 50 for 50%)
return 100; // Simplified example
}
}Fit to Height
Scale image to match canvas height while maintaining aspect ratio:
fitToHeight() {
const zoomPercent = this.calculateHeightFitPercent();
this.imageEditor?.zoom(zoomPercent);
}
calculateHeightFitPercent() {
// Calculate zoom percentage for height fit
// Returns appropriate zoom level as percentage
return 100;
}Fit to Canvas (Both Width and Height)
Scale image to fit entire canvas:
fitToCanvas() {
const zoomPercent = this.calculateCanvasFitPercent();
this.imageEditor?.zoom(zoomPercent);
}
calculateCanvasFitPercent() {
// Calculate zoom percentage to fit entire canvas
// Usually the smaller of width/height fit percentages
return 100;
}Practical Example
@Component({
selector: 'app-fit-to-view',
template: `
<div style="padding: 20px;">
<div style="margin-bottom: 10px; gap: 5px; display: flex;">
<button (click)="fitToWidth()">Fit Width</button>
<button (click)="fitToHeight()">Fit Height</button>
<button (click)="fitToCanvas()">Fit All</button>
<button (click)="zoom100()">100%</button>
</div>
<div>Current Zoom: {{ currentZoom }}%</div>
<div style="width: 600px; height: 400px; border: 1px solid #ccc;">
<ejs-imageeditor
#imageEditor
></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class FitToViewComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
currentZoom = 100;
fitToWidth() {
// Fit image to canvas width
const zoomPercent = 75; // Adjust based on your needs
this.imageEditor?.zoom(zoomPercent);
this.currentZoom = zoomPercent;
}
fitToHeight() {
// Fit image to canvas height
const zoomPercent = 75;
this.imageEditor?.zoom(zoomPercent);
this.currentZoom = zoomPercent;
}
fitToCanvas() {
// Fit entire image to canvas
const zoomPercent = 60;
this.imageEditor?.zoom(zoomPercent);
this.currentZoom = zoomPercent;
}
zoom100() {
this.imageEditor?.zoom(100);
this.currentZoom = 100;
}
}Responsive Layout
@Component({
selector: 'app-responsive-editor',
template: `
<div [style.width.%]="100"
[style.height.%]="100"
#container>
<ejs-imageeditor
#imageEditor
[style.width.%]="100"
[style.height.%]="100"
></ejs-imageeditor>
</div>
`,
imports: [ImageEditorModule],
standalone: true
})
export class ResponsiveEditorComponent implements OnInit {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
@ViewChild('container') container?: ElementRef;
ngOnInit() {
// Auto-fit when container resizes
window.addEventListener('resize', () => {
this.fitToCanvas();
});
}
fitToCanvas() {
// Adjust zoom to fit canvas on resize
const zoomPercent = 80; // Default zoom percentage
this.imageEditor?.zoom(zoomPercent);
}
}Common Zoom Levels
// Apply common zoom percentages
zoom25() {
this.imageEditor?.zoom(25);
}
zoom50() {
this.imageEditor?.zoom(50);
}
zoom75() {
this.imageEditor?.zoom(75);
}
zoom100() {
this.imageEditor?.zoom(100);
}
zoom150() {
this.imageEditor?.zoom(150);
}
zoom200() {
this.imageEditor?.zoom(200);
}Best Practices
1. Fit on load: Auto-fit image when first opened 2. Preserve aspect ratio: Always maintain aspect ratio when fitting 3. Responsive: Refit when window resizes 4. User control: Provide both auto-fit and manual zoom options 5. Bounds: Don't exceed 100% unless zooming for detail
Frame Application in Angular Image Editor
Supported Frame Types
The Image Editor provides 5 decorative frame types:
- Mat - Simple border frame
- Bevel - 3D beveled border
- Line - Simple line border with styling
- Hook - Ornamental hook-style border
- Inset - Inset border effect
Apply Frame to Image
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-frames',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="applyMatFrame()">Mat Frame</button>
<button (click)="applyBevelFrame()">Bevel Frame</button>
<button (click)="applyLineFrame()">Line Frame</button>
`
})
export class FramesComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
applyMatFrame() {
this.imageEditor?.drawFrame(
'Mat', // frameType
'#FF6B6B', // color
undefined, // gradientColor (optional)
30 // size
);
}
applyBevelFrame() {
this.imageEditor?.drawFrame(
'Bevel',
'#4ECDC4',
undefined,
25
);
}
applyLineFrame() {
this.imageEditor?.drawFrame(
'Line',
'#FFD93D',
undefined,
20
);
}
}Frame Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
frameType | string | Frame type (Mat, Bevel, Line, Hook, Inset) | Yes |
color | string | Primary color (hex format) | Yes |
gradientColor | string | Secondary color for gradient | No |
size | number | Frame thickness/size | Yes |
inset | number | Inset value (Line, Hook, Inset types) | No |
offset | number | Offset value (Line, Inset types) | No |
borderRadius | number | Border radius (Line type) | No |
frameLineStyle | string | Line style: Solid, Dashed, Dotted (Line type) | No |
lineCount | number | Number of lines (Line type) | No |
Frame Type Examples
Mat Frame
applyMatFrame() {
this.imageEditor?.drawFrame(
'Mat',
'#CC5555', // Reddish color
'#FF9999', // Light red gradient
40 // Large frame
);
}Bevel Frame
applyBevelFrame() {
this.imageEditor?.drawFrame(
'Bevel',
'#4169E1', // Royal blue
'#87CEEB', // Sky blue gradient
35
);
}Line Frame with Styling
applyLineFrame() {
this.imageEditor?.drawFrame(
'Line',
'#2ECC71', // Green
undefined, // No gradient
25, // size
undefined, // inset
undefined, // offset
10, // borderRadius
'Dashed' // frameLineStyle
);
}Hook Frame
applyHookFrame() {
this.imageEditor?.drawFrame(
'Hook',
'#9B59B6', // Purple
'#E8DAEF', // Light purple
30
);
}Inset Frame
applyInsetFrame() {
this.imageEditor?.drawFrame(
'Inset',
'#E67E22', // Orange
undefined,
28,
15, // inset
5 // offset
);
}Line Frame Styles
// Solid line (default)
this.imageEditor?.drawFrame('Line', '#333', undefined, 20, 0, 0, 0, 'Solid');
// Dashed line
this.imageEditor?.drawFrame('Line', '#333', undefined, 20, 0, 0, 0, 'Dashed');
// Dotted line
this.imageEditor?.drawFrame('Line', '#333', undefined, 20, 0, 0, 0, 'Dotted');Gradient Color Support
Apply gradient colors for visual depth:
applyGradientFrame() {
this.imageEditor?.drawFrame(
'Mat',
'#FF1744', // Primary color (red)
'#D50000', // Gradient color (darker red)
35
);
}Frame Changing Event
@Component({
template: `
<ejs-imageeditor
[frameChanging]="onFrameChanging"
></ejs-imageeditor>
`
})
export class FrameEventComponent {
onFrameChanging(args: any) {
console.log('Previous Frame:', args.previousFrameSetting);
console.log('Current Frame:', args.currentFrameSetting);
// Can validate and modify frame
if (args.currentFrameSetting.size > 50) {
args.currentFrameSetting.size = 50; // Limit size
}
// Prevent frame application
if (args.currentFrameSetting.frameType === 'Hook') {
args.cancel = true;
}
}
}Toolbar Frame Selection
Allow users to select frames through toolbar:
@Component({
template: `
<ejs-imageeditor
[toolbar]="['Open', 'Frame', 'Save']"
></ejs-imageeditor>
`
})
export class FrameToolbarComponent { }Complete Frame Example
@Component({
selector: 'app-frame-gallery',
template: `
<div style="padding: 20px;">
<h3>Frame Gallery</h3>
<div style="margin-bottom: 15px;">
<button (click)="applyMat()">Mat</button>
<button (click)="applyBevel()">Bevel</button>
<button (click)="applyLine()">Line (Dashed)</button>
<button (click)="applyHook()">Hook</button>
<button (click)="applyInset()">Inset</button>
<button (click)="removeFrame()">Remove</button>
</div>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor
#imageEditor
[frameChanging]="onFrameChanging"
></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule],
standalone: true
})
export class FrameGalleryComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
applyMat() {
this.imageEditor?.drawFrame('Mat', '#D4AF37', '#FFD700', 40);
}
applyBevel() {
this.imageEditor?.drawFrame('Bevel', '#696969', '#A9A9A9', 35);
}
applyLine() {
this.imageEditor?.drawFrame('Line', '#000000', undefined, 20, 0, 0, 5, 'Dashed', 2);
}
applyHook() {
this.imageEditor?.drawFrame('Hook', '#8B4513', '#D2B48C', 30);
}
applyInset() {
this.imageEditor?.drawFrame('Inset', '#C0C0C0', '#808080', 25, 10, 5);
}
removeFrame() {
// Apply transparent or original frame to remove
this.imageEditor?.drawFrame('Mat', '#FFFFFF', '#FFFFFF', 0);
}
onFrameChanging(args: any) {
console.log('Frame applied:', args.currentFrameSetting.frameType);
}
}Best Practices
1. Test frame sizes with your image dimensions 2. Use contrasting colors for frame visibility 3. Consider gradient colors for professional appearance 4. Match frame style to image content 5. Save after frame application to preserve edits
Edge Cases & Troubleshooting
Issue: Frame not visible after application
- Solution: Ensure frame color contrasts with image; check size parameter
Issue: Gradient color not applying
- Solution: Ensure gradientColor is provided; not all frame types support gradient
Issue: Cannot remove applied frame
- Solution: Apply new frame over existing or reload image without frame
Getting Started with Angular Image Editor
Installation and Setup
Prerequisites
Ensure your development environment meets the system requirements for Syncfusion Angular UI Components.
Install Angular CLI
npm install -g @angular/cliCreate a New Application
ng new syncfusion-image-editor-app
cd syncfusion-image-editor-appYou can choose your preferred stylesheet format (CSS, SCSS, Less).
Install Syncfusion Image Editor Package
Use Angular CLI's add command to install the package:
ng add @syncfusion/ej2-angular-image-editorThis command automatically:
- Adds
@syncfusion/ej2-angular-image-editorand peer dependencies topackage.json - Imports the Image Editor component in your application
- Registers the default Syncfusion Material theme in
angular.json
Install for Legacy Projects (Angular 15 and Below)
For ngcc compatibility:
npm add @syncfusion/ej2-angular-image-editor@32.1.19-ngccModule Import
In your component file, import the Image Editor module:
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
import { Component } from '@angular/core';
@Component({
imports: [ImageEditorModule],
standalone: true,
selector: 'app-root',
template: `<ejs-imageeditor></ejs-imageeditor>`
})
export class AppComponent { }CSS Configuration
Using Material3 Theme (Recommended)
The Material theme is automatically added when you run ng add. If you need to add it manually:
/* In styles.css or styles.scss */
@import "../node_modules/@syncfusion/ej2-base/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-buttons/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-lists/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-popups/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-splitbuttons/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-navigations/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-dropdowns/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-inputs/styles/material3.css";
@import "../node_modules/@syncfusion/ej2-image-editor/styles/material3.css";Important: Import CSS files in the order shown to ensure proper dependency resolution.
Other Theme Options
material.css- Standard Material themebootstrap.css- Bootstrap themebootstrap5.css- Bootstrap 5 themefabric.css- Fabric themefluent.css- Fluent themehighcontrast.css- High Contrast theme
Basic Component Implementation
Minimal Example
import { Component } from '@angular/core';
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
@Component({
imports: [ImageEditorModule],
standalone: true,
selector: 'app-root',
template: `
<div style="width: 550px; height: 350px;">
<ejs-imageeditor></ejs-imageeditor>
</div>
`
})
export class AppComponent { }With Initial Image
import { Component, ViewChild } from '@angular/core';
import { ImageEditorModule, ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
imports: [ImageEditorModule],
standalone: true,
selector: 'app-root',
template: `
<div style="width: 550px; height: 350px;">
<ejs-imageeditor
#imageEditor
[created]="onCreated"
></ejs-imageeditor>
</div>
`
})
export class AppComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
onCreated() {
this.imageEditor?.open('image.png');
}
}Running the Application
ng serveNavigate to http://localhost:4200/ in your browser.
Dependencies
The Image Editor component has the following dependencies:
@syncfusion/ej2-angular-image-editor
├── @syncfusion/ej2-angular-base
└── @syncfusion/ej2-image-editor
├── @syncfusion/ej2-base
├── @syncfusion/ej2-data
├── @syncfusion/ej2-buttons
├── @syncfusion/ej2-lists
├── @syncfusion/ej2-dropdowns
├── @syncfusion/ej2-inputs
├── @syncfusion/ej2-navigations
├── @syncfusion/ej2-popups
└── @syncfusion/ej2-splitbuttonsThese dependencies are automatically installed with ng add.
Supported Angular Versions
- Angular 21 and above (recommended)
- Angular 19, 20
- Angular 12-18 with compatibility considerations
First Render
After installation, the Image Editor renders in the template with:
- Empty canvas ready for image loading
- Toolbar with default editing tools
- Ready to handle user interactions
Use the open() method to load an image after the component is initialized using the created event or @ViewChild reference.
Troubleshooting
Issue: Module not found error
- Solution: Run
npm installto ensure all dependencies are installed
Issue: Styles not applied
- Solution: Verify CSS imports are in the correct order and point to the correct theme folder
Issue: Image Editor not rendering
- Solution: Ensure the container has specified
widthandheightstyles
Image Restrictions in Angular Image Editor
Validate uploaded images by file type and size.
Allowed File Extensions
import { Component } from '@angular/core';
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-restrictions',
template: `
<ejs-imageeditor
[uploadSettings]="uploadSettings"
></ejs-imageeditor>
`,
imports: [ImageEditorModule],
standalone: true
})
export class RestrictionsComponent {
uploadSettings = {
allowedExtensions: '.jpg,.png,.svg,.webp,.bmp'
};
}File Size Restrictions
uploadSettings = {
minFileSize: 1024, // 1 KB minimum
maxFileSize: 5242880 // 5 MB maximum
};Combined Restrictions
uploadSettings = {
allowedExtensions: '.jpg,.png,.svg',
minFileSize: 512, // 512 bytes
maxFileSize: 2097152 // 2 MB
};Validation Error Handling
@Component({
template: `
<input type="file" #fileInput (change)="onFileSelected($event)">
<p *ngIf="validationError" style="color: red;">{{ validationError }}</p>
<ejs-imageeditor [uploadSettings]="uploadSettings"></ejs-imageeditor>
`
})
export class ValidationComponent {
validationError = '';
uploadSettings = {
allowedExtensions: '.jpg,.png',
maxFileSize: 1048576 // 1 MB
};
onFileSelected(event: any) {
const file = event.target.files[0];
// Check extension
const ext = '.' + file.name.split('.').pop().toLowerCase();
if (!this.uploadSettings.allowedExtensions.includes(ext)) {
this.validationError = `File type not allowed. Use: ${this.uploadSettings.allowedExtensions}`;
return;
}
// Check size
if (file.size > this.uploadSettings.maxFileSize) {
this.validationError = `File too large. Max: 1 MB`;
return;
}
this.validationError = '';
}
}Default Restrictions
If not specified, defaults allow:
- Extensions:
.jpg, .png, .svg, .webp, .bmp - Size: Unlimited
Complete Example
@Component({
selector: 'app-image-validator',
template: `
<div style="padding: 20px;">
<input
type="file"
#fileInput
(change)="onFileSelected($event)"
accept=".jpg,.jpeg,.png,.svg,.webp,.bmp"
>
<p *ngIf="validationError" style="color: red; font-weight: bold;">
❌ {{ validationError }}
</p>
<p *ngIf="validationSuccess" style="color: green;">
✓ File validated and ready
</p>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor
#imageEditor
[uploadSettings]="uploadSettings"
></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class ImageValidatorComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
validationError = '';
validationSuccess = false;
uploadSettings = {
allowedExtensions: '.jpg,.jpeg,.png,.svg,.webp,.bmp',
minFileSize: 1024, // 1 KB
maxFileSize: 10485760 // 10 MB
};
onFileSelected(event: any) {
const file = event.target.files[0];
if (!file) return;
this.validationError = '';
this.validationSuccess = false;
// Check extension
const ext = '.' + file.name.split('.').pop().toLowerCase();
if (!this.uploadSettings.allowedExtensions.includes(ext)) {
this.validationError = `Invalid file type. Allowed: JPG, PNG, SVG, WEBP, BMP`;
return;
}
// Check size
if (file.size < this.uploadSettings.minFileSize) {
this.validationError = `File too small. Minimum: 1 KB`;
return;
}
if (file.size > this.uploadSettings.maxFileSize) {
this.validationError = `File too large. Maximum: 10 MB`;
return;
}
// Load validated image
const reader = new FileReader();
reader.onload = (e: any) => {
this.imageEditor?.open(e.target.result);
this.validationSuccess = true;
};
reader.readAsDataURL(file);
}
}Best Practices
1. Set realistic limits - 5-20 MB typical for web 2. Warn users clearly - Display supported formats 3. Allow common formats - JPG, PNG minimum 4. Compress before save - Use WEBP format 5. Test with edge cases - Very small/large files
Edge Cases
Issue: Base64 images bypass extension check
- Solution: Validate file size still applies; check MIME type in base64 string
Issue: SVG files rejected despite allowance
- Solution: Ensure .svg extension allowed; check content-type header
Localization in Angular Image Editor
Support multiple languages for international users.
Set Locale
import { Component } from '@angular/core';
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-localization',
template: `<ejs-imageeditor [locale]="'es'"></ejs-imageeditor>`,
imports: [ImageEditorModule],
standalone: true
})
export class LocalizationComponent { }Supported Locales
- 'en' - English (default)
- 'de' - German
- 'fr' - French
- 'es' - Spanish
- 'ar' - Arabic
- 'ja' - Japanese
- 'zh' - Chinese
- 'ru' - Russian
- And 50+ more
Custom Translations
@Component({
template: `<ejs-imageeditor [locale]="'de'"></ejs-imageeditor>`
})
export class GermanEditorComponent { }Define Custom Locale
import { register } from '@syncfusion/ej2-base';
const customLocale = {
'my-custom': {
ImageEditor: {
'Crop': 'Custom Crop',
'ZoomIn': 'Aumentar',
'Save': 'Guardar',
'Undo': 'Deshacer'
}
}
};
register('customLocale', customLocale);
@Component({
template: `<ejs-imageeditor [locale]="'my-custom'"></ejs-imageeditor>`
})
export class CustomLocaleComponent { }Common Localization Keys
Key UI elements that are localized:
- Toolbar labels (Crop, Save, Undo, Redo, etc.)
- Dialog titles and buttons
- Tooltips
- Filter names
- Shape names
- Error messages
Multi-language Application
@Component({
selector: 'app-multi-lang',
template: `
<select (change)="onLanguageChange($event)">
<option value="en">English</option>
<option value="es">Spanish</option>
<option value="fr">French</option>
<option value="de">German</option>
</select>
<ejs-imageeditor [locale]="selectedLocale"></ejs-imageeditor>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class MultiLanguageComponent {
selectedLocale = 'en';
onLanguageChange(event: any) {
this.selectedLocale = event.target.value;
}
}RTL Support
For Arabic, Hebrew, and other RTL languages, set the HTML dir attribute:
// In HTML template or globally
// <html dir="rtl">
@Component({
template: `
<ejs-imageeditor
[locale]="'ar'"
></ejs-imageeditor>
`
})
export class RTLComponent { }Edge Cases
Issue: Some text not translating
- Solution: Custom components need individual translations
Issue: RTL not applying correctly
- Solution: Ensure enableRtl matches locale direction
Open and Save in Angular Image Editor
Table of Contents
---
Supported Formats
The Image Editor supports: PNG, JPEG, SVG, WEBP, BMP
- Default save format: PNG
- Recommended web formats: PNG, WEBP (best compression)
- Photo format: JPEG (with quality control)
---
Opening Images
From Local File Path
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-open-save',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="openLocalImage()">Open Image</button>
`
})
export class OpenSaveComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
openLocalImage() {
this.imageEditor?.open('path/to/image.png');
}
}From Base64 String
openBase64Image() {
const base64String = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...';
this.imageEditor?.open(base64String);
}From File Uploader
@Component({
template: `
<input type="file" #fileInput (change)="onFileSelected($event)">
<ejs-imageeditor #imageEditor></ejs-imageeditor>
`
})
export class FileUploaderComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
onFileSelected(event: any) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = (e: any) => {
this.imageEditor?.open(e.target.result);
};
reader.readAsDataURL(file);
}
}From Blob Storage
openFromBlob(blob: Blob) {
const blobUrl = URL.createObjectURL(blob);
this.imageEditor?.open(blobUrl);
}Opening Images from Different Sources
The open() method accepts:
- URL path:
'path/to/image.png' - Base64 string:
'data:image/png;base64,...' - ImageData object: ImageData from canvas
---
Saving Images
Export to File
exportImage() {
this.imageEditor?.export('edited-image', 'png');
}
exportAsJpeg() {
this.imageEditor?.export('photo', 'jpeg', 90); // 90% quality
}
exportAsWebp() {
this.imageEditor?.export('optimized', 'webp');
}Save as Base64
saveAsBase64() {
this.imageEditor?.getImageData()
.then((data: any) => {
console.log('Base64 String:', data);
// Send to server or store
});
}Save as Blob
saveAsBlob() {
this.imageEditor?.getImageData()
.then((dataUrl: any) => {
// Convert data URL to blob
fetch(dataUrl)
.then(response => response.blob())
.then(blob => {
// Upload to server or save
this.uploadToServer(blob);
});
});
}
uploadToServer(blob: Blob) {
const formData = new FormData();
formData.append('image', blob, 'edited-image.png');
// POST to server
fetch('/api/upload', { method: 'POST', body: formData });
}Save as Byte Array
saveAsByteArray() {
this.imageEditor?.getImageData()
.then((dataUrl: any) => {
// Convert to byte array
const bytes = new Uint8Array(/* ... */);
// Send to server for storage
});
}Keyboard Shortcut
Ctrl + S → Download in original format---
Open/Save Events
File Opened Event
@Component({
template: `
<ejs-imageeditor
[fileOpened]="onFileOpened"
></ejs-imageeditor>
`
})
export class FileOpenedEventComponent {
onFileOpened(args: any) {
console.log('File Name:', args.fileName);
console.log('File Type:', args.fileType);
// Add watermark automatically
// this.addWatermark();
}
}Before Save Event
The beforeSave event is triggered before saving the image:
@Component({
template: `
<ejs-imageeditor
[beforeSave]="onBeforeSave"
></ejs-imageeditor>
`
})
export class BeforeSaveComponent {
onBeforeSave(args: any) {
console.log('Before saving image');
// Validate before save
if (!this.validateImage()) {
args.cancel = true;
}
}
validateImage() {
// Your validation logic
return true;
}
}Saved Event
@Component({
template: `
<ejs-imageeditor
[saved]="onSaved"
></ejs-imageeditor>
`
})
export class SavedEventComponent {
onSaved(args: any) {
console.log('Image saved successfully');
}
}Created Event
@Component({
template: `
<ejs-imageeditor
[created]="onCreated"
></ejs-imageeditor>
`
})
export class CreatedEventComponent {
onCreated() {
console.log('Image Editor ready');
// Load default image or initialize
}
}Destroyed Event
@Component({
template: `
<ejs-imageeditor
[destroyed]="onDestroyed"
></ejs-imageeditor>
`
})
export class DestroyedEventComponent {
onDestroyed() {
console.log('Image Editor destroyed');
// Cleanup resources
}
}---
Advanced Options
Add Watermark While Opening
@Component({
template: `
<ejs-imageeditor
[fileOpened]="addWatermark"
></ejs-imageeditor>
<button (click)="loadImage()">Load</button>
`
})
export class WatermarkComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
loadImage() {
this.imageEditor?.open('image.png');
}
addWatermark() {
// Text watermark
this.imageEditor?.drawText(
50, 50,
'© 2024 My Company',
'Arial', 20, false, false, '#FFFFFF'
);
}
}Custom Save Workflow
@Component({
template: `
<ejs-imageeditor
#imageEditor
[toolbar]="['Open', 'Save']"
[beforeSave]="onBeforeSave"
></ejs-imageeditor>
`
})
export class CustomSaveComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
onBeforeSave(args: any) {
args.cancel = true; // Prevent default download
this.imageEditor?.getImageData()
.then((data: any) => {
// Custom save logic - upload to server
const filename = prompt('Enter filename:', 'image');
if (filename) {
this.uploadImage(data, filename);
}
});
}
uploadImage(imageData: any, filename: string) {
// Send to server
console.log('Uploading:', filename);
}
}Multiple Format Export
@Component({
template: `
<button (click)="exportPNG()">PNG</button>
<button (click)="exportJPEG()">JPEG</button>
<button (click)="exportSVG()">SVG</button>
<ejs-imageeditor #imageEditor></ejs-imageeditor>
`
})
export class MultiFormatComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
exportPNG() {
this.imageEditor?.export('image', 'png');
}
exportJPEG() {
this.imageEditor?.export('photo', 'jpeg', 85);
}
exportSVG() {
this.imageEditor?.export('vector', 'svg');
}
}Quality Control for JPEG
saveJpegWithQuality(quality: number) {
// Quality: 0-100
// 100 = highest quality (larger file)
// 50 = medium quality (balanced)
// 10 = low quality (smallest file)
this.imageEditor?.export('photo', 'jpeg', quality);
}
// Examples:
exportHighQuality() {
this.saveJpegWithQuality(95); // Professional
}
exportBalanced() {
this.saveJpegWithQuality(75); // Web standard
}
exportCompressed() {
this.saveJpegWithQuality(50); // Email/mobile
}Batch Operations
@Component({
selector: 'app-batch-processor',
template: `
<button (click)="processMultiple()">Process Images</button>
`
})
export class BatchProcessorComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
images = ['img1.jpg', 'img2.jpg', 'img3.jpg'];
async processMultiple() {
for (const img of this.images) {
await this.processImage(img);
}
}
processImage(imagePath: string): Promise<void> {
return new Promise((resolve) => {
this.imageEditor?.open(imagePath);
setTimeout(() => {
// Apply edits
this.imageEditor?.rotate(90);
this.imageEditor?.applyImageFilter('Warm');
// Save
this.imageEditor?.export(`edited-${imagePath}`, 'png');
resolve();
}, 500);
});
}
}---
Complete Example: Full Workflow
@Component({
selector: 'app-image-editor-full',
template: `
<div style="padding: 20px;">
<input type="file" #fileInput (change)="onFileSelected($event)">
<button (click)="saveToPng()">Save PNG</button>
<button (click)="saveToJpeg()">Save JPEG</button>
<button (click)="saveBase64()">Copy Base64</button>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor
#imageEditor
[fileOpened]="onFileOpened"
></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule],
standalone: true
})
export class FullWorkflowComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
onFileSelected(event: any) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = (e: any) => {
this.imageEditor?.open(e.target.result);
};
reader.readAsDataURL(file);
}
onFileOpened(args: any) {
console.log('Loaded:', args.fileName);
}
saveToPng() {
this.imageEditor?.export('edited-image', 'png');
}
saveToJpeg() {
this.imageEditor?.export('photo', 'jpeg', 90);
}
saveBase64() {
this.imageEditor?.getImageData()
.then((data: any) => {
// Copy to clipboard
navigator.clipboard.writeText(data);
alert('Base64 copied to clipboard');
});
}
}---
Edge Cases & Troubleshooting
Issue: Image won't open
- Solution: Verify file format is supported; check CORS for remote URLs
Issue: Save dialog doesn't appear
- Solution: Ensure browser allows downloads; check popup/save permissions
Issue: Base64 string is huge
- Solution: Use WEBP format for better compression; reduce image dimensions
Issue: Quality loss in JPEG export
- Solution: Increase quality parameter (closer to 100); consider PNG for lossless
Quick Access Toolbar in Angular Image Editor
The quick access toolbar provides annotation-specific actions when shapes or annotations are selected.
Enable/Disable Quick Access Toolbar
import { Component } from '@angular/core';
import { ImageEditorModule } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-quick-toolbar',
template: `
<ejs-imageeditor
[showQuickAccessToolbar]="true"
></ejs-imageeditor>
`,
imports: [ImageEditorModule],
standalone: true
})
export class QuickToolbarComponent { }Customize Quick Access Toolbar
@Component({
template: `
<ejs-imageeditor
[quickAccessToolbarOpen]="onQuickAccessOpen"
></ejs-imageeditor>
`
})
export class CustomQuickToolbarComponent {
onQuickAccessOpen(args: any) {
// Handle quick access toolbar opening
console.log('Quick access toolbar opened:', args);
}
}Quick Access Toolbar Items
Available items for different annotation types:
- For Rectangles/Ellipses/Lines/Arrows:
- Stroke Color
- Stroke Width
- Fill Color
- Remove
- Duplicate
- For Text:
- Font Family
- Font Size
- Font Color
- Bold, Italic, Underline
- Edit Text
- Remove
- Duplicate
- For Freehand Drawing:
- Stroke Color
- Stroke Width
- Remove
Add Custom Item to Quick Access Toolbar
@Component({
template: `
<ejs-imageeditor
[quickAccessToolbarOpen]="addCustomItem"
></ejs-imageeditor>
`
})
export class CustomItemComponent {
addCustomItem(args: any) {
// Add new custom button
args.toolbarItems.push({
text: 'Duplicate Annotation',
id: 'duplicateAnn',
icon: '➕'
});
}
}Handle Quick Access Toolbar Actions
@Component({
template: `
<ejs-imageeditor
[toolbarItemClicked]="onToolbarItemClicked"
></ejs-imageeditor>
`
})
export class ToolbarActionComponent {
onToolbarItemClicked(args: any) {
if (args.id === 'duplicateAnn') {
console.log('Custom action triggered');
}
}
}Complete Example
@Component({
selector: 'app-quick-toolbar-demo',
template: `
<div>
<p>Select an annotation to see quick access toolbar</p>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor
#imageEditor
[showQuickAccessToolbar]="true"
[quickAccessToolbarOpen]="onToolbarOpen"
></ejs-imageeditor>
</div>
<button (click)="addText()">Add Text</button>
<button (click)="addRectangle()">Add Rectangle</button>
</div>
`,
imports: [ImageEditorModule],
standalone: true
})
export class QuickToolbarDemoComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
onToolbarOpen(args: any) {
console.log('Quick toolbar opened');
}
addText() {
this.imageEditor?.drawText(100, 100, 'Sample', 'Arial', 16, false, false, '#000000');
}
addRectangle() {
this.imageEditor?.drawRectangle(50, 50, 200, 150, 2, '#0000FF', '#FFFFFF');
}
}Best Practices
1. Add frequently used actions to quick access toolbar 2. Keep custom items minimal (2-3 max) 3. Use clear, descriptive text labels 4. Test with different annotation types
Edge Cases
Issue: Quick access toolbar not appearing
- Solution: Ensure showQuickAccessToolbar is true; select annotation first
Issue: Custom items not showing
- Solution: Add items in quickAccessToolbarOpen event; verify unique IDs
Redaction in Angular Image Editor
Redaction protects sensitive information by obscuring areas using blur or pixelate effects.
Redaction Types
- Blur - Gaussian blur effect (default)
- Pixelate - Pixel mosaic effect
Draw Redaction
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-redaction',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="addBlurRedact()">Blur Redact</button>
<button (click)="addPixelateRedact()">Pixelate Redact</button>
`
})
export class RedactionComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
addBlurRedact() {
this.imageEditor?.drawRedact(
'Blur', // type: 'Blur' or 'Pixelate'
100, // x-coordinate
100, // y-coordinate
200, // width
100, // height
20 // blur value (default 20)
);
}
addPixelateRedact() {
this.imageEditor?.drawRedact(
'Pixelate', // type
300, // x
50, // y
150, // width
100, // height
10 // pixel size
);
}
}Redaction Parameters
| Parameter | Type | Description |
|---|---|---|
type | string | 'Blur' or 'Pixelate' |
x | number | X-coordinate (top-left) |
y | number | Y-coordinate (top-left) |
width | number | Redaction width (default: 100) |
height | number | Redaction height (default: 50) |
value | number | Blur value (0-100) or pixel size |
Get Redaction IDs
getAllRedacts() {
const redacts = this.imageEditor?.getRedacts();
redacts?.forEach(redact => {
console.log('ID:', redact.id);
console.log('Type:', redact.type);
console.log('Position:', { x: redact.x, y: redact.y });
});
return redacts;
}Select Redaction
selectRedact(redactId: string) {
this.imageEditor?.selectRedact(redactId);
}
selectFirstRedact() {
const redacts = this.imageEditor?.getRedacts();
if (redacts && redacts.length > 0) {
this.imageEditor?.selectRedact(redacts[0].id);
}
}Update Redaction
updateRedact(redactId: string) {
const newSettings = {
id: redactId,
type: 'Blur',
x: 100,
y: 100,
width: 250, // Updated width
height: 150, // Updated height
value: 30 // Updated blur value
};
this.imageEditor?.updateRedact(newSettings, true); // true = show as selected
}Delete Redaction
deleteRedact(redactId: string) {
this.imageEditor?.deleteRedact(redactId);
}
deleteAllRedacts() {
const redacts = this.imageEditor?.getRedacts();
redacts?.forEach(redact => {
this.imageEditor?.deleteRedact(redact.id);
});
}Complete Redaction Example
@Component({
selector: 'app-redaction-manager',
template: `
<div style="padding: 20px;">
<div style="margin-bottom: 10px;">
<button (click)="addBlurRedact()">Add Blur</button>
<button (click)="addPixelateRedact()">Add Pixelate</button>
<button (click)="increaseBlur()">Increase Blur</button>
<button (click)="deleteSelected()">Delete</button>
<button (click)="removeAll()">Remove All</button>
</div>
<div>Redacts: {{ redactCount }}</div>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor #imageEditor></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class RedactionManagerComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
redactCount = 0;
selectedRedactId: string | null = null;
addBlurRedact() {
this.imageEditor?.drawRedact('Blur', 100, 100, 200, 100, 20);
this.updateRedactCount();
}
addPixelateRedact() {
this.imageEditor?.drawRedact('Pixelate', 300, 50, 150, 100, 10);
this.updateRedactCount();
}
increaseBlur() {
const redacts = this.imageEditor?.getRedacts();
if (redacts && redacts[0]) {
this.selectedRedactId = redacts[0].id;
redacts[0].value = Math.min(100, (redacts[0].value || 0) + 10);
this.imageEditor?.updateRedact(redacts[0]);
}
}
deleteSelected() {
if (this.selectedRedactId) {
this.imageEditor?.deleteRedact(this.selectedRedactId);
this.updateRedactCount();
}
}
removeAll() {
this.imageEditor?.getRedacts()?.forEach(redact => {
this.imageEditor?.deleteRedact(redact.id);
});
this.updateRedactCount();
}
updateRedactCount() {
this.redactCount = this.imageEditor?.getRedacts()?.length || 0;
}
}Use Cases
1. PII Protection - Hide personal information (names, addresses, SSN) 2. Confidential Documents - Redact sensitive text/numbers 3. Photo Privacy - Hide faces or identifiable features 4. Legal Documents - Redact privileged information 5. Medical Records - Hide patient identification
Best Practices
1. Use blur for text - More natural looking 2. Use pixelate for faces - Effective anonymization 3. Verify coverage - Ensure sensitive areas fully covered 4. Save redacted image - Export after redaction complete 5. Test on different backgrounds - Some redactions show through lighter
Edge Cases & Troubleshooting
Issue: Redaction partially visible or transparent
- Solution: Increase blur value or ensure 100% pixel coverage
Issue: Cannot delete specific redaction
- Solution: Verify redact ID; use
getRedacts()to retrieve correct ID
Issue: Pixelate shows original image through
- Solution: Increase pixel size or use blur instead
Undo and Redo in Angular Image Editor
The Image Editor maintains a history of up to 16 actions, allowing users to undo and redo their edits.
Undo Operation
Revert the most recent action:
import { ViewChild } from '@angular/core';
import { ImageEditorComponent } from '@syncfusion/ej2-angular-image-editor';
@Component({
selector: 'app-undo-redo',
template: `
<ejs-imageeditor #imageEditor></ejs-imageeditor>
<button (click)="undoAction()">Undo (Ctrl+Z)</button>
<button (click)="redoAction()">Redo (Ctrl+Y)</button>
`
})
export class UndoRedoComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
undoAction() {
this.imageEditor?.undo();
}
redoAction() {
this.imageEditor?.redo();
}
}Redo Operation
Reapply an action that was undone:
redoLastAction() {
this.imageEditor?.redo();
}Keyboard Shortcuts
| Shortcut | Action |
|---|---|
Ctrl + Z | Undo |
Ctrl + Y | Redo |
History Limitations
- Maximum history depth: 16 actions
- When limit reached: Oldest action is removed as new actions are added
- Example: After 16 edits, performing another action removes the 1st action
Complete Example
@Component({
selector: 'app-undo-redo-manager',
template: `
<div style="padding: 20px;">
<button (click)="undo()" [disabled]="!canUndo">↶ Undo</button>
<button (click)="redo()" [disabled]="!canRedo">↷ Redo</button>
<span>{{ actionCount }}/16 actions</span>
<div style="width: 600px; height: 400px;">
<ejs-imageeditor #imageEditor></ejs-imageeditor>
</div>
</div>
`,
imports: [ImageEditorModule, CommonModule],
standalone: true
})
export class UndoRedoManagerComponent {
@ViewChild('imageEditor') imageEditor?: ImageEditorComponent;
canUndo = false;
canRedo = false;
actionCount = 0;
undo() {
this.imageEditor?.undo();
this.updateState();
}
redo() {
this.imageEditor?.redo();
this.updateState();
}
updateState() {
// Update button states based on history
this.actionCount = Math.min(this.actionCount + 1, 16);
}
}Edge Cases
Issue: Undo not working after save
- Solution: Undo/redo history is preserved after save; continue editing to undo
Issue: Cannot undo past 16 actions
- Solution: This is by design; oldest actions are automatically removed
Issue: Redo becomes unavailable
- Solution: After performing new action following undo, redo history is cleared