You can insert images into a scene using CE.SDK, either through the prebuilt UI for Android or programmatically via Kotlin. This gives you the flexibility to build interactive design workflows, enable user-generated content, or automate image placement based on logic or data.
What You’ll Learn#
- Two ways to insert images:
- Programmatically by creating a graphic block, applying an image fill, and setting its position/size/rotation/z-index.
- With Editor UI using the controls and asset libraries of a prebuilt editor such as the Design Editor or Photo Editor.
- Supported image sources such as app assets, file URIs, and remote URLs.
- Practical transforms after insertion such as move, scale, rotate and order.
When to Use It#
- You’re building custom UI or automation flow to add images to compositions.
- You want a ready-made editing experience on Android with an image picker and panels.
Inserting Images Using the UI#
CE.SDK’s UI includes a built-in image tool that lets users add images from device sources directly onto the canvas. Once inserted, users can move, resize, crop, rotate, or stack images visually.
Supported image sources:
- Gallery (Photos app)
- Storage (Files app)
- Camera (device camera)
- Image (project asset library)
In the Asset Library, a user can add images from the Gallery, the camera or the Files app.
You can customize how the image tool appears in the user interface.
Inserting Images Programmatically#
For apps with automation, batch workflows, or logic-driven design experiences, you can insert images into a scene using the block API and the graphics engine.
Here’s how to do it:
// 1. Create a graphic blockval imageBlock = engine.block.create(DesignBlockType.Graphic)
// 2. Create a shape for the imageval shape = engine.block.createShape(ShapeType.Rect)engine.block.setShape(imageBlock, shape = shape)
// 3. Create an image fillval imageFill = engine.block.createFill(FillType.Image)engine.block.setString( block = imageFill, property = "fill/image/imageFileURI", value = "https://img.ly/static/ubq_samples/sample_4.jpg")engine.block.setFill(imageBlock, fill = imageFill)
// 4. (Optional) Set semantic kind to "image" for clarityengine.block.setKind(imageBlock, kind = "image")
// 5. Add image to the sceneval page = engine.block.findByType(DesignBlockType.Page).first()engine.block.appendChild(page, child = imageBlock)The shape can be any of the supported shapes like ShapeType.Rect, ShapeType.Star, etc and masks the inserted image. The asset URI in step 3 can either be a remote URL or a local asset URI.
For assets from app resources, use a URI:
import android.net.Uri
val uri = Uri.parse("file:///android_asset/images/poster.jpg")For file assets, use standard Android file handling:
import android.net.Uriimport java.io.File
val file = File(context.filesDir, "uploads/avatar.png")val uri = Uri.fromFile(file)When working with the asset catalog, you can apply an image that’s an AssetResult either to:
- The scene directly
- A block
val assetList = engine.asset.findAssets(sourceId, queryData)val newAsset = assetList.assets.first()
// Creates a new block that contains the imageval imageBlock = engine.asset.defaultApplyAsset(newAsset)
// Applies the image to a block that already existsengine.asset.defaultApplyAssetToBlock(newAsset, someBlock)Image Properties#
After inserting the image, you can change the block’s layout properties using standard methods in the engine.block API.
Positioning#
Refer to the guide in the Transform Section for Move for more details and other options.
// Set X/Y position on the canvas (in absolute units)engine.block.setPositionX(imageBlock, value = 100f)engine.block.setPositionY(imageBlock, value = 200f)Scaling#
Refer to the guide in the Transform Section for Scale for more details and other options.
// Uniform scaleengine.block.setFloat(imageBlock, property = "transform/scale/x", value = 1.5f)engine.block.setFloat(imageBlock, property = "transform/scale/y", value = 1.5f)
// Non-uniform (stretching)engine.block.setFloat(imageBlock, property = "transform/scale/x", value = 2.0f)engine.block.setFloat(imageBlock, property = "transform/scale/y", value = 1.0f)Rotation#
Refer to the guide in the Transform Section for Rotate for more details and other options.
// Rotate 45 degrees (in radians)import kotlin.math.PI
val degrees = 45.0val radians = (degrees * PI / 180).toFloat()engine.block.setFloat(imageBlock, property = "transform/rotation", value = radians)Layering#
Control stack order using the helper methods to move blocks forward (towards the user) or backwards. You can also pin a block to the front or back of the stack.
engine.block.bringToFront(imageBlock) // Move above siblingsengine.block.sendToBack(imageBlock) // Move below siblingsengine.block.bringForward(imageBlock) // One step forwardengine.block.sendBackward(imageBlock) // One step backward
engine.block.setAlwaysOnTop(imageBlock, enabled = true)Insert Into an Existing Block#
If your template exposes a placeholder block or you are creating an automated workflow, you can replace an image fill instead of creating a new block. Locate the block using its name property or by its known id.
When you know the id of the target:
val fill = engine.block.createFill(FillType.Image)engine.block.setString(fill, property = "fill/image/imageFileURI", value = imageURI)engine.block.setFill(targetBlock, fill = fill)When you’re using the name property to find the block, you need to search manually:
val allBlocks = engine.block.findByType(DesignBlockType.Graphic)val targetBlock = allBlocks.find { block -> engine.block.getString(block, property = "name") == "HeroTile"} ?: return
val fill = engine.block.createFill(FillType.Image)engine.block.setString(fill, property = "fill/image/imageFileURI", value = imageURI)engine.block.setFill(targetBlock, fill = fill)Troubleshooting#
❌ Nothing appears after insert:
- Verify that the block is attached to the page.
- Verify the URI string is correct.
- Check the scene’s current zoom and camera framing.
❌ Remote images fail:
- Confirm HTTPS and CORS settings.
- Verify network permissions in AndroidManifest.xml.
- Test the URL in a browser.
❌ Pixelated result:
- Change the block size or use a higher-resolution source image.
❌ Unexpected orientation of image:
- Some formats carry EXIF orientation information. Apply
setRotationor normalize the asset during import.
Next Steps#
Now that you’ve learned about inserting images into your compositions, here are some topics to explore to deepen your understanding.
- Apply more transformations such as crop, or scale.
- Create templates for automating content creation and formatting.
- Export compositions in a variety of formats.