Frame subjects, remove unwanted elements, and prepare images for specific formats using CE.SDK’s comprehensive crop system.
Image cropping selects a region inside an image and discards everything outside that frame. Unlike resizing which changes overall dimensions, cropping lets you focus on specific areas of interest. CE.SDK provides a crop system that works through scale, translation, and rotation to define the visible region of content within a block frame.
This guide covers how to crop images programmatically using the block API, including content fill modes, scaling, positioning, rotation, and aspect ratio locking.
Programmatic Cropping#
Initialize CE.SDK#
For applications that need to crop images programmatically—whether for automation, batch processing, or dynamic user experiences—we start by setting up CE.SDK with the proper configuration.
// Initialize CE.SDK engine in headless modeconst engine = await CreativeEngine.init({ // license: process.env.CESDK_LICENSE, // Optional (trial mode available)});This initializes the CE.SDK engine in headless mode, giving you full API access to the crop system without UI dependencies.
Create a Scene with an Image#
Before cropping, we need a scene with an image block. The example creates a page with specific dimensions and adds an image using the convenience addImage() API.
// Create a design scene with specific page dimensionsconst scene = engine.scene.create();const page = engine.block.create('page');engine.block.setWidth(page, 800);engine.block.setHeight(page, 600);engine.block.appendChild(scene, page);
// Sample image URL for demonstrationsconst imageUri = 'https://img.ly/static/ubq_samples/sample_1.jpg';
// Add an image block using the convenience addImage APIconst imageBlock = await engine.block.addImage(imageUri, { size: { width: 300, height: 200 }});engine.block.appendChild(page, imageBlock);engine.block.setPositionX(imageBlock, 50);engine.block.setPositionY(imageBlock, 50);Check Crop Support#
Before applying crop operations to a block, verify it supports cropping. Not all block types can be cropped—for example, scene blocks do not support crop operations.
// Verify the block supports crop operations before applying themconst supportsCrop = engine.block.supportsCrop(imageBlock);console.log('Block supports crop:', supportsCrop); // trueCrop support is available for:
- Graphic blocks with image fills
- Graphic blocks with video fills
- Shape blocks with fills
Always verify support before applying crop operations to avoid errors.
Content Fill Modes#
CE.SDK provides three content fill modes that control how images fit within their frame. These modes determine whether you have manual control or automatic behavior.
// Content fill modes control how images fit within their frame// Check if the block supports content fill modesconst supportsFillMode = engine.block.supportsContentFillMode(imageBlock);console.log('Supports content fill mode:', supportsFillMode);
// Get the current content fill modeconst currentMode = engine.block.getContentFillMode(imageBlock);console.log('Current fill mode:', currentMode);
// Set content fill mode - options are 'Crop', 'Cover', 'Contain'// 'Cover' automatically scales and positions to fill the entire frameengine.block.setContentFillMode(imageBlock, 'Cover');The available fill modes are:
- Crop - Manual control over the exact crop region using scale and translation
- Cover - Automatically scales and positions content to cover the entire frame (no gaps)
- Contain - Automatically scales and positions content to fit within the frame (may show gaps)
Use Crop mode when you need precise control over which part of the image is visible. Use Cover for automatic framing that fills the entire space.
Scale Content#
When using Crop fill mode, you can scale the content within the crop frame to zoom in or out. Values greater than 1 zoom in, while values less than 1 zoom out.
// Create another image block to demonstrate crop scalingconst scaleBlock = await engine.block.addImage(imageUri, { size: { width: 200, height: 200 }});engine.block.appendChild(page, scaleBlock);engine.block.setPositionX(scaleBlock, 400);engine.block.setPositionY(scaleBlock, 50);
// Set content fill mode to 'Crop' for manual controlengine.block.setContentFillMode(scaleBlock, 'Crop');
// Scale the content within the crop frame// Values > 1 zoom in, values < 1 zoom outengine.block.setCropScaleX(scaleBlock, 1.5);engine.block.setCropScaleY(scaleBlock, 1.5);
// Or use uniform scaling from centerengine.block.setCropScaleRatio(scaleBlock, 1.2);
// Get the current scale valuesconst scaleX = engine.block.getCropScaleX(scaleBlock);const scaleY = engine.block.getCropScaleY(scaleBlock);const scaleRatio = engine.block.getCropScaleRatio(scaleBlock);console.log('Crop scale:', { scaleX, scaleY, scaleRatio });CE.SDK provides two scaling approaches:
- Non-uniform scaling -
setCropScaleX()andsetCropScaleY()for independent horizontal and vertical scaling - Uniform scaling -
setCropScaleRatio()for proportional scaling from the center of the crop frame
Uniform scaling maintains the image’s aspect ratio, while non-uniform scaling can stretch or compress the image.
Position Content#
Pan the content within the crop frame using translation. Translation values represent the offset as a percentage of the crop frame dimensions.
// Pan the content within the crop frame using translation// Values are in percentage of the crop frame dimensionsengine.block.setCropTranslationX(scaleBlock, 0.1); // Move 10% rightengine.block.setCropTranslationY(scaleBlock, -0.1); // Move 10% up
// Get the current translation valuesconst translationX = engine.block.getCropTranslationX(scaleBlock);const translationY = engine.block.getCropTranslationY(scaleBlock);console.log('Crop translation:', { translationX, translationY });Translation values:
- Positive X values move content to the right
- Negative X values move content to the left
- Positive Y values move content down
- Negative Y values move content up
After adjusting scale and translation, use adjustCropToFillFrame() to ensure content covers the entire frame without gaps.
// Ensure content covers the entire frame without gaps// The minScaleRatio parameter sets the minimum scale allowedconst adjustedRatio = engine.block.adjustCropToFillFrame(scaleBlock, 1.0);console.log('Adjusted scale ratio:', adjustedRatio);The minScaleRatio parameter sets the minimum scale allowed—the method returns the actual scale ratio applied.
Rotate Content#
Rotate the content within the crop frame using radians. This rotates the image independently of the block’s overall rotation.
// Create an image block to demonstrate crop rotationconst rotateBlock = await engine.block.addImage(imageUri, { size: { width: 200, height: 200 }});engine.block.appendChild(page, rotateBlock);engine.block.setPositionX(rotateBlock, 50);engine.block.setPositionY(rotateBlock, 300);engine.block.setContentFillMode(rotateBlock, 'Crop');
// Rotate the content within the crop frame (in radians)// Math.PI / 4 = 45 degreesengine.block.setCropRotation(rotateBlock, Math.PI / 4);
// Get the current rotationconst rotation = engine.block.getCropRotation(rotateBlock);console.log('Crop rotation (radians):', rotation);
// Ensure content still fills the frame after rotationengine.block.adjustCropToFillFrame(rotateBlock, 1.0);After rotating content, call adjustCropToFillFrame() to ensure the rotated content still covers the entire frame.
The difference between crop rotation and block rotation:
- Crop rotation - Rotates the content inside the frame while the frame stays fixed
- Block rotation - Rotates the entire block including its frame
Flip Content#
Flip the content horizontally or vertically to create mirror effects.
// Create an image block to demonstrate flippingconst flipBlock = await engine.block.addImage(imageUri, { size: { width: 200, height: 200 }});engine.block.appendChild(page, flipBlock);engine.block.setPositionX(flipBlock, 300);engine.block.setPositionY(flipBlock, 300);engine.block.setContentFillMode(flipBlock, 'Crop');
// Flip the content horizontallyengine.block.flipCropHorizontal(flipBlock);
// Or flip vertically// engine.block.flipCropVertical(flipBlock);Flipping affects only the content within the frame, not the frame itself.
Lock Aspect Ratio#
When building interactive crop interfaces, you can lock the aspect ratio to maintain proportions during resize operations.
// Create an image block to demonstrate aspect ratio lockingconst lockBlock = await engine.block.addImage(imageUri, { size: { width: 200, height: 200 }});engine.block.appendChild(page, lockBlock);engine.block.setPositionX(lockBlock, 550);engine.block.setPositionY(lockBlock, 300);engine.block.setContentFillMode(lockBlock, 'Crop');
// Lock the crop aspect ratio - when locked, crop handles maintain// the current aspect ratio during resize operationsengine.block.setCropAspectRatioLocked(lockBlock, true);
// Check if aspect ratio is lockedconst isLocked = engine.block.isCropAspectRatioLocked(lockBlock);console.log('Aspect ratio locked:', isLocked);When locked, crop handles maintain the current aspect ratio. This is useful for:
- Preparing images for specific formats (social media, print)
- Maintaining consistent proportions across multiple images
- Preventing accidental distortion during editing
Reset Crop#
To restore default crop settings, use resetCrop(). This sets the content fill mode to Cover and adjusts crop values so the content covers the block.
// Reset crop to default state (sets content fill mode to 'Cover')engine.block.resetCrop(lockBlock);Coordinate System#
Crop transforms use normalized values:
| Property | Value Type | Description |
|---|---|---|
| Scale | Float (0.0+) | 1.0 is original size, 2.0 is double, 0.5 is half |
| Translation | Float (-1.0 to 1.0) | Percentage of frame dimensions |
| Rotation | Float (radians) | Math.PI = 180°, Math.PI/2 = 90° |
All crop values are independent of canvas zoom level.
Combining Crop with Other Transforms#
You can combine crop operations with other block transforms like position, rotation, and scale. Crop transforms affect the content within the block, while block transforms affect the block itself on the canvas:
// Crop the content (scales/pans the image within its frame)engine.block.setCropScaleRatio(imageBlock, 1.5);engine.block.setCropRotation(imageBlock, Math.PI / 12);
// Transform the block itself (moves/rotates the entire block on canvas)engine.block.setRotation(imageBlock, Math.PI / 6);engine.block.setWidth(imageBlock, 400);Export Results#
After applying crop transformations, export the processed content to a file.
// Export the result as PNGconst blob = await engine.block.export(page, { mimeType: 'image/png' });const buffer = Buffer.from(await blob.arrayBuffer());writeFileSync('crop-images-output.png', buffer);console.log('Successfully exported crop-images-output.png');Always dispose of the engine instance when processing is complete to free resources.
// Always dispose the engine to free resourcesengine.dispose();Troubleshooting#
| Issue | Cause / Fix |
|---|---|
| Crop functions throw error | Verify block supports crop with supportsCrop() |
| Black bars after scaling | Call adjustCropToFillFrame() or increase scale ratio |
| Content not filling frame | Check content fill mode - use ‘Cover’ for automatic fill |
| Unexpected crop behavior | Ensure content fill mode is set to ‘Crop’ for manual control |
API Reference#
| Method | Description |
|---|---|
block.supportsCrop(id) | Check if a block supports cropping |
block.setCropScaleX(id, scaleX) | Set horizontal crop scale |
block.setCropScaleY(id, scaleY) | Set vertical crop scale |
block.setCropScaleRatio(id, ratio) | Set uniform crop scale from center |
block.setCropRotation(id, rotation) | Set crop rotation in radians |
block.setCropTranslationX(id, x) | Set horizontal crop translation |
block.setCropTranslationY(id, y) | Set vertical crop translation |
block.adjustCropToFillFrame(id, minRatio) | Adjust crop to fill frame |
block.flipCropHorizontal(id) | Flip content horizontally |
block.flipCropVertical(id) | Flip content vertically |
block.isCropAspectRatioLocked(id) | Check if aspect ratio is locked |
block.setCropAspectRatioLocked(id, locked) | Lock/unlock aspect ratio |
block.resetCrop(id) | Reset crop to default state |
block.supportsContentFillMode(id) | Check if block supports fill modes |
block.setContentFillMode(id, mode) | Set content fill mode |
block.getContentFillMode(id) | Get current content fill mode |
block.getCropScaleX(id) | Get horizontal crop scale |
block.getCropScaleY(id) | Get vertical crop scale |
block.getCropScaleRatio(id) | Get uniform crop scale ratio |
block.getCropRotation(id) | Get crop rotation in radians |
block.getCropTranslationX(id) | Get horizontal crop translation |
block.getCropTranslationY(id) | Get vertical crop translation |