MODEL IDprunaai:p-image@ideogram
live

P-Image-Ideogram

Pruna AI
by Pruna AI

P-Image-Ideogram is a Pruna AI text-to-image model built in collaboration with Ideogram for fast, high-quality visual generation across product, people, and brand-oriented creative work. It offers four generation modes, from Very Low to High, so teams can choose the right balance of speed, cost, and image quality for each workflow while retaining strong prompt following and unusually capable text rendering. The model supports both natural-language prompting and more structured JSON-style prompting for tighter control over layout, color palettes, bounding boxes, and typography-heavy compositions.

P-Image-Ideogram

Prompting P-Image-Ideogram

How to prompt P-Image-Ideogram in both modes: natural language for quick exploration and structured JSON for explicit control over layout, colour, and typography.

P-Image-Ideogram is a Pruna AI text-to-image model built with Ideogram, aimed at brand and design work where the text has to be right and the layout has to land. It takes prompts two ways: plain natural language for quick exploration, and a structured JSON prompt that places each element and pins its colour.

That hero is a single structured prompt, with the campaign headline and every line of the bottle's label pinned as its own text element. That is the control a structured prompt buys you. The rest of this guide covers both ways in: natural language for quick exploration, and the structured JSON prompt for exactly that.

Request shape

A generation needs a positivePrompt, which is either a plain sentence or a structured JSON object (both modes are covered below). width and height default to 1024, seed is optional, and settings holds the two controls that shape a run: enhancePrompt, which rewrites your prompt before generation, and thinkingLevel, which sets how hard the model works.

import { createClient } from '@runware/sdk'

const client = await createClient({ apiKey: process.env.RUNWARE_API_KEY })
await client.connect()

const [result] = await client.run({
  model: 'prunaai:p-image@ideogram',
  positivePrompt: 'A minimalist skincare brand poster: a frosted serum bottle on a pale stone against a soft sage backdrop, with a bold headline that reads "PURE HYDRATION". Photoreal editorial photography, generous negative space, no other text.',
  width: 1600,
  height: 2400,
  settings: {
    enhancePrompt: false,
    thinkingLevel: 'high'
  }
})
import asyncio
import os

from runware import Runware


async def main():
    async with Runware(api_key=os.environ["RUNWARE_API_KEY"]) as client:
        results = await client.run({
            "model": "prunaai:p-image@ideogram",
            "positivePrompt": "A minimalist skincare brand poster: a frosted serum bottle on a pale stone against a soft sage backdrop, with a bold headline that reads \"PURE HYDRATION\". Photoreal editorial photography, generous negative space, no other text.",
            "width": 1600,
            "height": 2400,
            "settings": {
                "enhancePrompt": False,
                "thinkingLevel": "high"
            }
        })


asyncio.run(main())
curl https://api.runware.ai/v1 \
  -H "Authorization: Bearer $RUNWARE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "taskType": "imageInference",
      "taskUUID": "c3d4e5f6-7a8b-4c90-9d1e-2f3a4b5c6d70",
      "model": "prunaai:p-image@ideogram",
      "positivePrompt": "A minimalist skincare brand poster: a frosted serum bottle on a pale stone against a soft sage backdrop, with a bold headline that reads \"PURE HYDRATION\". Photoreal editorial photography, generous negative space, no other text.",
      "width": 1600,
      "height": 2400,
      "settings": {
        "enhancePrompt": false,
        "thinkingLevel": "high"
      }
    }
  ]'
runware run prunaai:p-image@ideogram \
  positivePrompt="A minimalist skincare brand poster: a frosted serum bottle on a pale stone against a soft sage backdrop, with a bold headline that reads \"PURE HYDRATION\". Photoreal editorial photography, generous negative space, no other text." \
  width=1600 \
  height=2400 \
  settings.enhancePrompt=false \
  settings.thinkingLevel=high
{
  "taskType": "imageInference",
  "taskUUID": "c3d4e5f6-7a8b-4c90-9d1e-2f3a4b5c6d70",
  "model": "prunaai:p-image@ideogram",
  "positivePrompt": "A minimalist skincare brand poster: a frosted serum bottle on a pale stone against a soft sage backdrop, with a bold headline that reads \"PURE HYDRATION\". Photoreal editorial photography, generous negative space, no other text.",
  "width": 1600,
  "height": 2400,
  "settings": {
    "enhancePrompt": false,
    "thinkingLevel": "high"
  }
}
Response
[
  {
    "taskType": "imageInference",
    "taskUUID": "c3d4e5f6-7a8b-4c90-9d1e-2f3a4b5c6d70",
    "imageUUID": "8e1f2a3b-4c5d-4e60-a7b8-9c0d1e2f3a4b",
    "imageURL": "https://im.runware.ai/image/os/a14d18/ws/2/ii/8e1f2a3b-4c5d-4e60-a7b8-9c0d1e2f3a4b.jpg"
  }
]

width and height run from 64 to 2560 in steps of 16, bounded by a 4,194,304 pixel budget (2048 × 2048 square, or any other pair whose area fits). thinkingLevel defaults to high, which is the right setting for finished work. Drop to low or very low only for cheap, fast drafts. The examples here set enhancePrompt to false so the prompt you read is the prompt the model rendered.

thinkingLevel is a compute dial more than an interpretation switch. On a fully specified prompt the four levels hold the same composition, so a higher level refines detail rather than reading your words differently. Where it shows is on a sparse prompt: the higher the level, the more the model fills in on its own, which is why a specific prompt keeps high refining what you asked for instead of inventing around it.

Writing a natural-language prompt

A natural-language prompt is built in layers, each answering a different question about the image:

A wide outdoor billboard mockup for a running shoe brand, A single low-top running shoe in bright coral and white floats slightly left of centre against a deep charcoal background, lit from the right so the sole catches a hard highlight, To the right of the shoe, a bold white headline reads "RUN LIGHTER", with a thin coral underline beneath it, Photoreal product photography, dramatic studio lighting, high contrast, wide horizontal composition, no other text
SubjectComposition and framingLightingTextStyle

Lead with the subject, then place it, light it, add any copy, and close on the treatment. Quoting the exact text ("RUN LIGHTER") is what gets it rendered as written rather than paraphrased. Natural language is the right mode for exploration, where you want a strong result fast and you are still deciding what the piece even is.

Structured prompts

For exact layout and multi-line copy, pass the prompt as a JSON object instead of a sentence. A structured prompt gives you a slot for every element, each with its own text, position, and colour, which is what you want for posters, packaging, and any design where the copy has to land in the right place. The structured prompt is an object with three top-level keys: a high_level_description, a style_description carrying the overall treatment and palette, and a compositional_deconstruction that lists the background and an array of elements.

{
  "high_level_description": "A vertical launch poster for a specialty coffee brand",
  "style_description": {
    "art_style": "flat editorial brand design, crisp legible type",
    "color_palette": ["#c1502e", "#f4e9d8", "#3a2417"]
  },
  "compositional_deconstruction": {
    "background": "solid warm terracotta",
    "elements": [
      { "type": "text", "color_palette": ["#f4e9d8"], "text": "NEW SEASON ROAST", "desc": "large cream headline near the top" },
      { "type": "obj", "desc": "a clean flat illustration of a coffee bag in cream and brown" }
    ]
  }
}

Each element is either a text or an obj, and the type is a hard dispatch. A text element renders its text field literally, so a brand name comes back spelled exactly as you wrote it. An obj element paints its desc as natural language. The desc field is freeform inside both, so the structure is rigid scaffolding around plain-language content slots. Reach for structured prompts when the frame carries more than one line of text, when you are building a template where the layout stays fixed and only the copy changes, or when a natural-language prompt keeps drifting off the arrangement you asked for.

Colour palettes

Colours described in words are interpretation. A color_palette array of hex values is direction, a channel the model reads as colours to favour rather than words to read. Both graphics below ask for the same muted scheme, one in prose and one as hex:

The palette works at two scopes. At the image level, style_description.color_palette takes up to 16 hex values and anchors the whole composition. On a single element, color_palette takes up to 5 and scopes a colour to that element, which is how a brand colour holds on one word without tinting the rest of the frame. Pass the colours that must be exact as hex, and leave the rest to the prose.

Bounding boxes

When an element has to sit in a specific region, add a bbox to it. It is four integers in 0 to 1000 normalised coordinates, ordered [y_min, x_min, y_max, x_max], row first, and it coexists with desc so the box sets the rectangle while the description still carries the treatment:

Each label landed in the rectangle its bbox declared. Most layouts do not need boxes, since positional language in desc ("centred along the top", "lower-right corner") carries them. Reach for bbox when descriptive placement keeps drifting and an element has to hold a precise spot.

Structured prompts use snake_case keys only: color_palette, compositional_deconstruction, high_level_description. Camel case or hyphens are not read. The model page schema lists every field and its order.

Prompt enhancement

enhancePrompt rewrites your prompt before generation, and it defaults to on. On a terse prompt it fills in detail the model then renders:

Off, the bare prompt renders as-is, rough and literal. On, it is expanded into a fuller, finished can design. Enhancement is useful for fleshing out a sparse prompt and a liability for control: the rewrite runs before generation and is not itself seeded, so the same seed and prompt produce a different image on every call while enhancement is on. Turn it off once the composition matters, and a fixed seed then returns the same image every time, which is how you keep a result while you tune the wording around it.

Typography in practice

Text rendering is the reason to reach for this model, and a structured prompt is how you get it reliably. Give each line its own text element and the model holds copy that most image models turn to mush. The wrapper below is one structured prompt with five text elements:

Every line came back as written, at the weight and place its element assigned. The rule underneath is the same one the whole model runs on: quote the copy, never describe it. A string inside a text element is rendered literally, so "COCOA & SALT" is pinned, while "a brand name in gold" would hand the wording to the model. A single headline survives that in plain natural language, but the moment a design carries several strings, put each in its own element.

Tips

  1. Start in natural language. It is faster for finding a direction, and you can rebuild the winner as a structured prompt once you know what you want.

  2. Switch to structured for templates and exact layouts. Fixed scaffolding with swappable copy is what structured prompts are for.

  3. Quote every string that matters. Text inside quotation marks, or inside a text element, renders literally. Anything you describe is reinterpreted.

  4. Pass exact colours as hex. A color_palette is direction the model follows. Colour words in prose are only a suggestion.

  5. Reach for bbox only when placement drifts. Positional language handles most layouts, and boxes are the heavier tool for when it does not.

  6. Turn off enhancePrompt before you commit. It helps exploration and breaks reproducibility, so disable it once you need the same prompt to land the same image.