Search
Loading...
Skip to content

Insert Images

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 block
val imageBlock = engine.block.create(DesignBlockType.Graphic)
// 2. Create a shape for the image
val shape = engine.block.createShape(ShapeType.Rect)
engine.block.setShape(imageBlock, shape = shape)
// 3. Create an image fill
val 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 clarity
engine.block.setKind(imageBlock, kind = "image")
// 5. Add image to the scene
val 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.Uri
import 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 image
val imageBlock = engine.asset.defaultApplyAsset(newAsset)
// Applies the image to a block that already exists
engine.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 scale
engine.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.0
val 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 siblings
engine.block.sendToBack(imageBlock) // Move below siblings
engine.block.bringForward(imageBlock) // One step forward
engine.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 setRotation or 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.