Image Generation

An image is generated from a prompt, in an art style, at the shape of your canvas. This page covers describing an image, generating it, changing it afterwards, and placing it.

Describing an image

from imaginaryarts import ImageAssetBuilder

hero = ImageAssetBuilder(
    prompt="An old Greek philosopher on a rocky shore at dawn, holding a cup of seawater up to the light",
    name="thales-shore",
)
ParameterMeaning
promptWhat the picture shows. Required.
art_styleOverrides the builder-wide style for this one image. A preset, or a plain string used as a custom style description.
filesReference images to show the model alongside the prompt. See below.
nameA label for the saved files. Optional, and free to change.
takeBump to 2, 3, ... to generate the same prompt again and get a different result.

ImageAssetBuilder.from_scene(scene) builds one from an authored scene, taking its prompt and its name.

Generating

AssetsBuilder takes the builders and generates them together:

from imaginaryarts import AssetsBuilder, ImageModel, ImageDirection, ImageDirectionStyle

images = AssetsBuilder(
    project=project,
    model=ImageModel(name="nanobanana2", size=(1080, 1920)),
    direction=ImageDirection(art_style=ImageDirectionStyle.DarkAcademia()),
    assets=[hero, ImageAssetBuilder(prompt="...")],
).build()

images[0].path      # the PNG on disk
images[0].prompt    # the full prompt that was sent, style included

The result indexes and iterates like a list, in the order you gave. .add(builder) appends one more before build().

ImageModel names the model and the shape. size sets the aspect ratio rather than exact pixels, so (1080, 1920) means "vertical, 9 by 16"; "1080x1920" is accepted too. Nano Banana 2 is the only image model today.

Writing prompts that work

The model is good, but it draws what it is told. A few habits produce reliable results:

  • Lead with the subject and the setting, then lighting, then mood. "A lighthouse keeper on the gallery of the tower, storm at sea, lantern light on the rain" beats "dramatic lighthouse scene".
  • One moment, one focal point. A prompt that lists five things gets a collage.
  • Frame for the canvas. Vertical video favours a single figure or a tall composition; say "full-length" or "close-up" when it matters.
  • Don't ask for text. Lettering in generated images is unreliable; add words with add_static_text instead.
  • Leave the style to the style. The art style is prepended automatically; repeating "watercolor" in every prompt only fights it.

Editing an image

Sometimes an image is nearly right. Rather than re-rolling and hoping, edit it: the model is given the existing picture and an instruction, and changes only what the instruction asks for.

hero = ImageAssetBuilder(prompt="...") \
    .edit("give the philosopher a closed, thoughtful expression") \
    .edit("make the sky stormier")

Each .edit() returns a new builder with one more step; the original is untouched. Each step is cached on the one before it, so adding a third edit costs one generation, and removing the last one costs nothing because the earlier result is still on disk. take= on an edit re-rolls just that step:

.edit("make the sky stormier", take=2)

An edit instruction can mention references with @name, just like a prompt.

Reference images

To have a real person, product or place in a generated image, or to keep a generated character consistent across images, give the model reference pictures. The full mechanism, named references you can mention with @, is described in Using reference characters, props, and environments.

For a one-off, files= attaches images directly to a single prompt:

ImageAssetBuilder(
    prompt="Return a photo of Elon Musk (see reference image) laughing on a heap of dollar bills",
    files=[ImageFile(ROOT / "assets/references/elon.jpg")],
)

Placing an image

An image has no duration, so it is placed for an interval, usually one that comes from the voice:

placed = voiceover.tile()
for i, scene in enumerate(placed.scenes):
    video.add_image(images[i], interval=[scene.start, scene.end]) \
         .add_effect(Effects.FadeIn(250)).add_effect(Effects.FadeOut(250))
    video.add_motion(CameraMotion.KenBurns(), interval=[scene.start, scene.end])

A slow camera motion is what makes a still feel like footage; see Camera Motion.

What is cached

An image's identity is its full prompt (so the art style is part of it), the model, the size, the references it mentions, and its take. Change any of those and it regenerates; change anything else, including its position in the list or its name, and it does not. See Re-generating and iterating.