Search Docs
Loading...
Skip to content

Resize

Change image dimensions by setting exact width and height values, switching size modes, preserving crop state, or resizing grouped blocks together.

A sample photo resized to 400 by 300 pixels and centered on the page canvas.

7 mins
estimated time
GitHub

Image resizing changes a block’s dimensions rather than applying a scale multiplier. Use engine.block.setWidth(_:value:) and engine.block.setHeight(_:value:) for individual dimensions, and choose a SizeMode to control how each value is interpreted.

This guide covers resizing image blocks with absolute or percentage sizing, preserving crop state during resize, resizing groups, and locking resize permissions for templates. To grow or shrink an image proportionally instead, see Scale.

Create an Image Block#

Create a graphic block with an image fill before applying resize operations:

@MainActor
private func createImageBlock(
engine: Engine,
page: DesignBlockID,
baseURL: URL,
) throws -> DesignBlockID {
let imageBlock = try engine.block.create(.graphic)
try engine.block.setShape(imageBlock, shape: engine.block.createShape(.rect))
try engine.block.setWidth(imageBlock, value: 320)
try engine.block.setHeight(imageBlock, value: 240)
try engine.block.setPositionX(imageBlock, value: 120)
try engine.block.setPositionY(imageBlock, value: 120)
let imageFill = try engine.block.createFill(.image)
try engine.block.setURL(
imageFill,
property: "fill/image/imageFileURI",
value: baseURL.appendingPathComponent("ly.img.image/images/sample_1.jpg"),
)
try engine.block.setFill(imageBlock, fill: imageFill)
try engine.block.appendChild(to: page, child: imageBlock)
return imageBlock
}

The resize APIs operate on the block frame. The image fill stays attached to the graphic block and follows the crop and fill mode settings.

Understanding Size Modes#

Size values are interpreted in three modes. SizeMode.absolute uses fixed design units, SizeMode.percent uses parent-relative values from 0.0 to 1.0, and SizeMode.auto lets CE.SDK calculate the size from content where supported.

Use engine.block.getWidth(_:) and engine.block.getHeight(_:) to read the configured values. Use engine.block.getFrameWidth(_:) and engine.block.getFrameHeight(_:) when you need the calculated layout dimensions after CE.SDK resolves the block.

Using the Built-In Resize UI#

When you build an interactive editor with CE.SDK, a selected block displays resize handles on its edges. Control when the non-proportional edge handles appear with the typed resize-handle visibility API:

try engine.editor.setResizeHandlesVisibility(.always)
let resizeHandlesVisibility = try engine.editor.getResizeHandlesVisibility()
print("Resize handles: \(resizeHandlesVisibility.rawValue)")

HandleVisibility accepts .always, .never, and .auto. This setting controls edge-handle visibility only. Programmatic resize APIs and other transform controls still follow the block’s scopes and transform lock state.

Setting Absolute Dimensions#

Set explicit dimensions by switching both axes to SizeMode.absolute, then writing width and height values:

try engine.block.setWidthMode(imageBlock, mode: .absolute)
try engine.block.setHeightMode(imageBlock, mode: .absolute)
try engine.block.setWidth(imageBlock, value: 400)
try engine.block.setHeight(imageBlock, value: 300)
let absoluteWidth = try engine.block.getWidth(imageBlock)
let absoluteHeight = try engine.block.getHeight(imageBlock)
print("Configured size: \(absoluteWidth) x \(absoluteHeight)")

Absolute sizing is the most direct option for fixed layouts, templates, and exports where the target design units are known.

Percentage Sizing#

Use percentage mode for responsive sizing. A value of 1.0 means 100 percent of the parent on that axis:

try engine.block.setWidthMode(imageBlock, mode: .percent)
try engine.block.setHeightMode(imageBlock, mode: .percent)
try engine.block.setWidth(imageBlock, value: 0.5)
try engine.block.setHeight(imageBlock, value: 0.5)
let percentWidth = try engine.block.getWidth(imageBlock)
let widthMode = try engine.block.getWidthMode(imageBlock)
print("Configured width: \(percentWidth) (mode is percent: \(widthMode == .percent))")

Percentage sizing adapts when the parent dimensions change, which makes it useful for reusable templates and generated layouts.

Getting Frame Dimensions#

Configured width and height can differ from the rendered frame in percentage and auto modes. Read the frame dimensions when you need the final layout size:

let frameWidth = try engine.block.getFrameWidth(imageBlock)
let frameHeight = try engine.block.getFrameHeight(imageBlock)
print("Frame size: \(frameWidth) x \(frameHeight)")

Frame dimensions reflect the block’s resolved layout, which CE.SDK calculates after size or mode changes. Read them once the engine has processed the update.

Maintaining Crop During Resize#

When you resize an image block, you change the image frame. The fill and crop state control how the image content stays framed inside that new size.

Pass maintainCrop: true when the current crop should stay visually stable while the frame changes:

try engine.block.setContentFillMode(imageBlock, mode: .crop)
try engine.block.setWidthMode(imageBlock, mode: .absolute)
try engine.block.setHeightMode(imageBlock, mode: .absolute)
try engine.block.setWidth(imageBlock, value: 520, maintainCrop: true)
try engine.block.setHeight(imageBlock, value: 320, maintainCrop: true)
let contentFillMode = try engine.block.getContentFillMode(imageBlock)
print("Content fill mode is crop: \(contentFillMode == .crop)")

Use this for user-adjusted images or layout changes where visual continuity matters. Leave maintainCrop at its default when crop values should stay unadjusted and the visible framing can change according to the current fill and crop state. For reusable code that may receive other block types, call engine.block.supportsContentFillMode(_:) before reading or setting the content fill mode.

Resizing Groups#

Group multiple blocks, then resize the group block to keep the members together:

let group = try engine.block.group([imageBlock, secondImageBlock])
try engine.block.setWidth(group, value: 600)
let groupWidth = try engine.block.getWidth(group)
print("Group width: \(groupWidth)")

When a group is resized, CE.SDK keeps the group aspect ratio and updates both dimensions proportionally.

Content-Aware Resizing#

Use resizeContentAware(_:width:height:) when changing page dimensions for another output format:

try engine.block.resizeContentAware([page], width: 1080, height: 1080)
let pageWidth = try engine.block.getWidth(page)
print("Page width after content-aware resize: \(pageWidth)")

This keeps full-page blocks attached to the page and scales other content proportionally.

Locking Resize Operations#

Resize permissions have two layers: a global scope that sets the scene-wide default, and a block-level scope that overrides it. The block-level setting only takes effect when the global scope is .defer. Under the default Creator role every global scope is .allow, so block-level settings are ignored until you defer the global scope first.

To keep a template block at its configured size, set the global layer/resize scope to .defer, then disable it on the specific block. Read the effective permission with isAllowedByScope(_:key:), which evaluates both layers — isScopeEnabled(_:key:) only reports the block-level flag. For an unconditional lock that also prevents moving and rotating, use setTransformLocked(_:locked:):

try engine.editor.setGlobalScope(key: "layer/resize", value: .defer)
try engine.block.setScopeEnabled(group, key: "layer/resize", enabled: false)
let resizeAllowed = try engine.block.isAllowedByScope(group, key: "layer/resize")
print("Resize allowed: \(resizeAllowed)")
try engine.block.setTransformLocked(group, locked: true)
let locked = try engine.block.isTransformLocked(group)
print("Transform locked: \(locked)")

See Lock Content for the full scope and permission model.

Troubleshooting#

Image Not Resizing#

Check whether the layer/resize scope is disabled or the block is transform-locked. Then verify that the block exists and that the width and height modes match the values you write.

Unexpected Size Values#

Read getWidthMode(_:) and getHeightMode(_:) before interpreting numeric values. In percentage mode, 0.5 means 50 percent of the parent, not 0.5 design units.

Image Appears Cropped#

Resize changes the frame around the image content. Use maintainCrop: true to preserve the existing crop framing, or adjust the crop after resize when you want a different composition.

API Reference#

Methods#

Method Description
engine.block.create(_:) Create a page or graphic block
engine.block.createShape(_:) Create the shape used by a graphic block
engine.block.setShape(_:shape:) Attach a shape to a graphic block
engine.block.createFill(_:) Create an image fill
engine.block.setURL(_:property:value:) Set the image URI on the fill
engine.block.setFill(_:fill:) Attach a fill to a block
engine.block.appendChild(to:child:) Add the image block to the page
engine.block.setPositionX(_:value:) Set a block’s x position
engine.block.setPositionY(_:value:) Set a block’s y position
engine.editor.setResizeHandlesVisibility(_:) Set when editor resize handles are shown
engine.editor.getResizeHandlesVisibility() Read when editor resize handles are shown
engine.block.setWidthMode(_:mode:) Set how CE.SDK interprets the width value
engine.block.setHeightMode(_:mode:) Set how CE.SDK interprets the height value
engine.block.setWidth(_:value:maintainCrop:) Set a block width and optionally preserve crop state
engine.block.setHeight(_:value:maintainCrop:) Set a block height and optionally preserve crop state
engine.block.getWidth(_:) Read the configured width value
engine.block.getHeight(_:) Read the configured height value
engine.block.getWidthMode(_:) Read the width mode
engine.block.getHeightMode(_:) Read the height mode
engine.block.getFrameWidth(_:) Read the resolved frame width after layout
engine.block.getFrameHeight(_:) Read the resolved frame height after layout
engine.block.supportsContentFillMode(_:) Check whether a block exposes content fill mode
engine.block.setContentFillMode(_:mode:) Set how image content fills its frame
engine.block.getContentFillMode(_:) Read how image content fills its frame
engine.block.group(_:) Group blocks before resizing them together
engine.block.resizeContentAware(_:width:height:) Resize blocks while adjusting contained content
engine.editor.setGlobalScope(key:value:) Set the scene-wide default for a scope
engine.block.setScopeEnabled(_:key:enabled:) Enable or disable a scope on a block (applies when the global scope is .defer)
engine.block.isAllowedByScope(_:key:) Read the effective permission after evaluating global and block-level scopes
engine.block.setTransformLocked(_:locked:) Lock or unlock all transforms on a block
engine.block.isTransformLocked(_:) Read the transform lock state

Next Steps#

  • Resize images proportionally with Scale.
  • Control image framing and visible content with Crop.
  • Apply resizing across complete designs with Auto-Resize.