Skip to main content

layerize

Use when rebuilding a flat raster image — an ad, banner, social post, poster or other creative (PNG / JPEG / WebP) — as an editable, layered CoDesign design or `.imgly` file; when asked to layerize, decompose, de-flatten or "make editable" an image; or when splitting an image into separate layers with live, editable text.

Quellinformationen

Repository
imgly/codesign
Letzte Quellaktivität
20. Oktober 2026 um 21:27
Erkannte Sprache von SKILL.md
Englisch
Sterne
43
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
layerize
description
Use when rebuilding a flat raster image — an ad, banner, social post, poster or other creative (PNG / JPEG / WebP) — as an editable, layered CoDesign design or `.imgly` file; when asked to layerize, decompose, de-flatten or "make editable" an image; or when splitting an image into separate layers with live, editable text.
requires
asset_generate, asset_search
argument-hint
<image> [output.imgly]
# layerize Rebuild a source image as an editable CoDesign design: pixel layers from Seedream's layer decomposition, text rebuilt as real, editable text. ## Inputs - **Source image** — the file the user points at. - **Output path** — where the `.imgly` deliverable goes. If the user named none, use the source's path with the extension replaced by `.imgly`. Keep intermediate files (layer metadata, comparison renders, cut-outs) out of the output location. ## Stage 1 — Layers (Seedream) Call `asset_generate` — **one successful call per image**: - `model`: `bytedance/seedream-5-pro-layerize` - `image_uris`: `[uri]` — the source image, added to the workspace with `asset_add({ source: { path } })` - An image under 512 × 512 pixels is refused: upscale it first (`../models/upscalers.md`), one more paid generation, and pass the upscaled result's `id`. - `prompt`: exactly what the `models` skill prescribes for this model. Read `../models/bytedance-seedream.md` before the call — it also explains the result (which asset is the background, why cut-outs come back rescaled, how bounding boxes are written). **Never retry a call that may have generated.** If it times out, find its output with `asset_search({ sourceId: 'ly.img.workspace.images' })` (newest first): the images created together with the source's dimensions or smaller, the full-size one being the background. If it returns an error instead, check the same way first; only when none of its output is in the workspace did it not run — fix the cause the error names and call it again. After the third failure, stop: build nothing, report the errors with their `gw_…` request ids, and ask the user how to proceed. Seedream is not optional: no other model and no local cut-outs replace it. Save the returned `metadata` (layer names, z order, bounding boxes) as soon as you have it. Place the layers with this `edit` code first — the page at the background's size, the background, then every cut-out at its bounding box. Paste the whole `asset_generate` result as `RESULT`: ```js const result = RESULT; const layers = result.metadata.find((m) => m.type === 'layers').data.layers; const [bg, ...cutouts] = result.assets; const width = Number(bg.meta.width); const height = Number(bg.meta.height); const [existing] = await engine.design.findByType('page'); const [scene] = await engine.design.findByType('scene'); const page = existing ?? (await engine.design.create( { type: 'page', props: { width, height } }, { parent: scene } )); await engine.design.setProps(page, { width, height }); const image = (name, uri, [x0, y0, x1, y1]) => engine.design.create( { type: 'graphic', name, props: { position: { x: x0, y: y0 }, width: x1 - x0, height: y1 - y0, shape: { type: 'rect' }, fill: { type: 'image', uri }, contentFill: { mode: 'Contain' } } }, { parent: page } ); await image('background', bg.id, [0, 0, width, height]); for (const [i, asset] of cutouts.entries()) { const layer = layers[i + 1]; const box = layer?.bounding_box?.absolute; if (box) await image(layer.name || `layer-${i + 1}`, asset.id, box); } return { type: 'text', text: JSON.stringify({ page, layers: layers.map((l) => l.name) }) }; ``` Then handle Seedream's layers as follows (its output is not trustworthy as-is): - Every layer sits at its bounding box; cut-outs come back rescaled, and `contentFill: Contain` fits each one into its box. If the bounding boxes are missing, find each layer's scale and position by matching it against the original. - Drop Seedream's text layers; text is rebuilt in stage 2. Check that the background no longer shows the text. If it still does, inpaint it. - Inventory: every visible element must be in exactly one layer. - Drop duplicate layers. - Cut any element Seedream missed straight from the original (take the alpha from the difference between the original and the composite). - A part that sits in front of another object (e.g. a hand holding a product) may be its own layer, grouped with the object it belongs to. - Background: keep the original pixels wherever no element covers them, and color-match the filled-in areas to the original. ## Stage 2 — Text (you do the vision pass yourself) For each visible text block, record: - exact string with line breaks - role (headline / sub / body / cta / legal / price) - pixel bounding box and alignment - cap height and line pitch in px - font characteristics (serif/sans/script, width, weight, italic, caps) - fill, stroke and shadow colors as hex - whether it sits on a shape Rules: - Ignore text printed on products, packaging, labels, barcodes or logos. - Keep a visually coherent block as ONE entry: a three-line headline is one block, not three. - Transcribe literally; write "unknown" instead of guessing. Set each block as real, editable text: - closest Google Font (name a fallback too) - uppercase through the text case property (`text.case: 'Uppercase'`), not typed capitals - font size derived from the measured cap height - letter spacing (`text.letterSpacing`, a factor) and line height (`text.lineHeight: { visual }`) fitted to the measured line widths and line pitch - shadow (`dropShadow`) or stroke tuned to match the original - a button or chip keeps its shape as a separate layer under the text **Matching the original beats CoDesign's typography lint:** keep the original's tracking and leading even when the lint warns about them. ## Build - One page at the source's pixel size. - Layers from back to front: background, scene groups, logo, text. - Give every layer a descriptive name (`background`, `left-figure`, `product-can`, `logo-…`, `headline-…`). - Group each scene's layers together, and group the text blocks. ## Acceptance Compare against the original: place the source image once more as the top layer, at the page's size, with `blend: { mode: 'Difference' }`, and `preview` it. Where the rebuild matches, the preview is black; every bright shape is a difference — a missing or doubled element, text off its baseline, a wrong color. Then destroy that layer. Check with a PNG export (`export({ format: 'png' })`) compared against the original. Fix and re-export until every point holds: - text baselines within ±2 px, line widths within ±2 % - text shadow visually matches the original - average absolute pixel difference below 10/255 - no element missing, no element appearing twice - named layers, grouped per scene Then run the judge loop against the source (`../judge/SKILL.md`), export with `export({ format: 'imgly', outPath: '<output path>' })`, and report: - the layer list - what Seedream got wrong and how it was fixed - where the intermediate files are
Auf GitHub ansehen