Claude Skill

character-reference-sheets

Dress 3D character base renders with AI-generated clothing while preserving the body, pose and framing, so each garment can be cut out and sent to image-to-3D generators. Use when the request involves a Blender base render in A-pose or T-pose, a character visual sheet, a turnarou

LLM Mart · 0 points · 13 views 34 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download guinacio-claude-image-gen-optional-workflows_character-reference-sheets-1df535d.zip · 11 KB
Part of guinacio/claude-image-gen — 2 skills

Install

skills CLI npx skills add https://github.com/guinacio/claude-image-gen/tree/master/optional-workflows/character-reference-sheets
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install guinacio-claude-image-gen@llmmart
Git git clone https://github.com/guinacio/claude-image-gen.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole guinacio/claude-image-gen collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Character reference sheets

Pipeline: a nude body render comes out of Blender, the model dresses that body, each garment is cut out, it goes to an image-to-3D generator, and the mesh comes back into Blender.

The goal of the generation is not a beautiful image. It is the same body as the render, now clothed, with every piece legible and cuttable. Everything below exists to protect that.

Cost rule, before anything else

Never call create_asset without asking first. Every generation spends the user's API credit. Write the full prompt, surface the decisions that change the image, and wait for an explicit go-ahead. This applies to each retry after a bad result too — do not silently fix and re-run.

Workflow

  1. Measure the input renders with scripts/measure.py. If any criterion in section 8 of references/resolutions-and-proportions.md fails, say so and ask for a re-export from Blender. Cheaper than discovering the problem after the image is paid for.
  2. Flatten alpha onto white if the PNG is RGBA. Alpha often becomes black on upload and contaminates the result.
  3. Build the prompt using the architecture in references/prompt-template.md.
  4. Ask for permission to generate.
  5. Generate, one view per call.
  6. Measure the output and compare against the input (thresholds below).
  7. Copy from IMAGE_OUTPUT_DIR into the character project's own output folder, with a descriptive versioned name: character_outfit_front_v2.png.

Measurement dependency

scripts/measure.py requires Python and Pillow. Before first use, ask before installing the dependency, then run:

python -m pip install -r /path/to/character-reference-sheets/requirements.txt

If Pillow is unavailable and cannot be installed, do not generate: report that the mandatory pre-flight measurement could not be completed.

The rule that matters most

Never describe the body in the prompt. Not the build, not shoulder width, not head size, not height. Describing anatomy makes the model draw a new body from the text instead of preserving the one in the image.

Recorded case: a prompt opening with "heavyset bara-build, very broad shoulders, thick muscular arms, wide barrel chest, heavy thighs, small head" collapsed the character's arm span from 88.9% to 74.3% of the frame width — 14.6 points. Same character, same render, same model, rebuilt with the correct architecture and zero body description: 89.2%, a 0.3 point deviation.

The prompt says what to add and what to preserve. Never what the body is.

Parameters

Model gpt-image-2
Aspect ratio 2:3 for a standing character · 1:1 for an isolated garment or prop
Quality Provider default — the current create_asset client does not expose quality
input_fidelity Provider default — the current client does not expose this option. OpenAI documents GPT Image 2 as supporting high-fidelity image inputs, but this workflow does not explicitly request high
References 2 to 4, base image first
Turnarounds never in a single image — one view per call

Verification after generating

Run scripts/measure.py on the input and the output and compare horizontal occupancy (ocup_h):

ocup_h deviation Reading
within ±2 points normal, accept
beyond ±2 points the prompt let the model redraw the body — regenerate

Empirical basis: crocodile character +1.6 / −1.4 across three generations; tiger v2 +0.3; tiger v1 (wrong prompt) −14.6.

Vertical occupancy usually rises 2 to 4 points even when everything is right. On its own it is not a failure signal.

Known residual: limbs get thinner

In every recorded generation so far — three of one character, two of another — arms and thighs came out with less volume than the base render. The PRESERVE block fixes framing and scale; it does not fix muscle mass.

Do not treat this as a new bug on each character. Practical consequences:

  • Leg and foot pieces (pants, boots, sneakers) — safe to cut out, limb volume does not drive the garment's shape.
  • Torso pieces (shirt, vest, jacket) — they were modelled over a narrower torso than the original mesh. The generated 3D tends to come out tight. Warn the user before they send it to an image-to-3D generator.

Where output lands

The server writes to IMAGE_OUTPUT_DIR (an MCP environment variable) and rejects any outputPath outside it. Pass a bare filename and copy the result into the character's folder afterwards.

References

  • references/prompt-template.md — the prompt architecture, with a real example
  • references/resolutions-and-proportions.md — aspect ratios, per-edge margins, Blender export settings, the mandatory pre-flight check, and what to feed an image-to-3D generator
  • scripts/measure.py — bounding box, occupancy and margins
Files (claude-image-gen)
  • references
    • prompt-template.md 6.9 KB
      # The prompt architecture
      
      Seven blocks, in this order. Prompts are always in English and always
      self-contained — generations run in a clean session with no conversation
      context.
      
      ```
      I'm attaching two images.
      
      IMAGE 1 - [what the base render is]. This is the base. Everything in it
      must be preserved.
      
      IMAGE 2 - [what the clothing reference is]. Use it ONLY as a reference for
      which clothing to add. Completely ignore its [style, pose, anatomy, and
      everything present in it that is absent from the render].
      
      TASK: dress the character from IMAGE 1 in that outfit.
      
      Clothing to add:
      - [one line per piece]
      
      Hardware must be crisp and consistent: [the hardware this outfit has].
      Keep every piece of hardware sharp and correctly repeated rather than
      smeared, melted or randomly shaped.
      
      PRESERVE EXACTLY, with no alteration:
      - [preservation list]
      
      Output: a single image, same framing as IMAGE 1.
      ```
      
      ## Block by block
      
      **IMAGE 1** — declare that it is the base and that everything in it is
      preserved. Describe the *kind* of image (3D render, A-pose, orthographic camera,
      white background, flat shading), never the character's anatomy.
      
      **IMAGE 2** — declare that it serves **only** to say which clothing. Then list
      explicitly what to ignore in it. Anything present in the concept art and absent
      from the render must be named, or the model will add it: hair, tail, weapon,
      beard, horns, wings. Also instruct it to ignore painting style, lineart,
      lighting, background, pose and anatomy.
      
      **TASK** — one sentence. It states that the operation is dressing, not drawing.
      
      **Clothing to add** — pieces only. No mention of the body. A detail that
      separates the piece from a generic one (flap pocket, crooked knot, colour panel)
      is worth more than a quality adjective.
      
      **Hardware** — a dedicated paragraph. Hardware is where the model smears most:
      buckles without frames, melted chain links, irregular eyelets. Name the hardware
      this particular outfit actually has.
      
      **PRESERVE EXACTLY** — the block that holds everything together. Fixed base:
      
      ```
      - The same A-pose, in the same position and angle
      - The same orthographic front camera, same framing and same body scale
        within the frame
      - The same arm span: the hands stay exactly where they are, at the same
        distance from the left and right edges
      - The plain white background, no shadow, no scenery, no gradient
      - The same clean 3D render style with flat colors: DO NOT paint it, DO NOT
        add fabric photorealism, DO NOT add grain, DO NOT add dramatic lighting,
        DO NOT add outlines
      - The same character colors and markings, the same proportions, the same
        [head, muzzle, ears, eyes, hands, feet — whatever this character has]
      ```
      
      The arm span line matters most in A-pose and T-pose: with the arms out, width is
      what constrains the frame, and width is where framing breaks.
      
      **Output** — restate that it is a single image, same framing.
      
      ## Reference order
      
      Base **first**, clothing sheet after. The array order is the order the prompt
      calls IMAGE 1 and IMAGE 2.
      
      ## A real example that worked
      
      Anthropomorphic tiger, front A-pose render plus approved concept art. Result:
      `ocup_h` 88.9% → 89.2%, a 0.3 point deviation.
      
      ```
      I'm attaching two images.
      
      IMAGE 1 - a 3D render of my character in A-pose, orthographic front view,
      plain white background, flat matte shading with solid colors. This is the
      base. Everything in it must be preserved.
      
      IMAGE 2 - a concept illustration. Use it ONLY as a reference for which
      clothing to add. Completely ignore its painting style, its lineart, its
      lighting, its pose and its anatomy. Also ignore its head hair, its tail
      and its sword - none of those exist in IMAGE 1 and none must be added.
      
      TASK: dress the character from IMAGE 1 in that outfit.
      
      Clothing to add:
      - Crisp white short-sleeve button-up dress shirt, sleeves ending mid-bicep,
        top three buttons undone showing the cream chest fur, collar open, hem
        untucked and hanging loose over the pants, and a buttoned flap chest
        pocket on the left side
      - A crimson red necktie, knotted but yanked loose: the knot sits low below
        the open collar and is visibly crooked and off-center, the wide end
        trailing down askew, as if just pulled down after work
      - Very baggy loose black cargo pants, deep flap utility pockets on the
        thighs, buckle straps, D-rings and hanging webbing, waistband riding on
        the hips, fabric pooling and stacking over the shoes
      - Crimson red cloth hand wraps fully covering the palms, the backs of the
        hands and the knuckles, then winding up both forearms, with loose ends
        trailing from the wrists. The fingers stay bare from the first knuckle up
      - Bold chunky designer high-top sneakers, white with crimson red panels,
        stitching and laces, thick sculpted white sole, oversized padded tongue,
        small red tiger emblem on the outer side
      - Thin silver chain necklace with a small silver tiger emblem pendant
      
      Hardware must be crisp and consistent: shirt buttons are uniform and evenly
      spaced, buckles have readable frames and prongs, D-rings are cleanly closed,
      chain links are individually defined and of even size, sneaker eyelets are
      regular and the laces cross evenly. Keep every piece of hardware sharp and
      correctly repeated rather than smeared, melted or randomly shaped.
      
      PRESERVE EXACTLY, with no alteration:
      - The same A-pose, in the same position and angle
      - The same orthographic front camera, same framing and same body scale
        within the frame
      - The same arm span: the hands stay exactly where they are, at the same
        distance from the left and right edges
      - The plain white background, no shadow, no scenery, no gradient
      - The same clean 3D render style with flat colors: DO NOT paint it, DO NOT
        add fabric photorealism, DO NOT add grain, DO NOT add dramatic lighting,
        DO NOT add outlines
      - The same character colors and markings, the same proportions, the same
        bald head with no hair, the same muzzle, ears, amber eyes, hand and foot
        shapes, and no tail
      
      Output: a single image, same framing as IMAGE 1.
      ```
      
      ## Counter-example — what not to do
      
      This prompt, on the same render and the same model, collapsed the arm span by
      14.6 points:
      
      ```
      Full body front view of a heavyset bara-build anthropomorphic tiger, adult
      male: tall, very broad shoulders, thick muscular arms, wide barrel chest,
      thick waist, heavy thighs, small head relative to the body. Standing in a
      neutral symmetrical A-pose facing the viewer: legs straight and
      shoulder-width apart, both arms hanging down...
      ```
      
      Three mistakes at once: it describes the anatomy, it describes the pose in text
      instead of instructing the model to preserve the pose in the image, and it never
      declares the reference's role. The model treated the render as inspiration and
      the text as specification — exactly the inverse of what is wanted.
      
      ## Back views
      
      Back views tend to trip the moderation filter when the base render is a nude
      body. When that happens, the recorded workaround is to add the already-dressed
      front view to the references and ask for parity with it, which gives the model a
      clothed target instead of a nude body.
      
    • resolutions-and-proportions.md 9.1 KB
      # Resolutions and proportions for AI-generated references
      
      A general guide — it applies to any character or 3D prop. It complements the
      prompt recipe, which lives in `prompt-template.md`.
      
      ---
      
      ## 1. What each provider actually delivers
      
      **OpenAI (`gpt-image-2`) — only three sizes exist:**
      
      | Aspect ratio | Pixels | Use |
      |---|---|---|
      | `1:1` | 1024 × 1024 | props, isolated pieces, hardware |
      | `3:2` | 1536 × 1024 | lying down / horizontal |
      | `2:3` | 1024 × 1536 | **standing character — the default** |
      
      There is no 4K and no 2K. There is no 16:9. Any other ratio requested is
      substituted with the closest one on the list.
      
      **Gemini** honours the requested ratio natively and (on Pro versions) delivers
      higher resolution. When fine detail matters more than composition, it is the
      stronger side.
      
      ## 2. How the `create_asset` tool maps
      
      The `aspectRatio` parameter accepts 7 values, but on OpenAI only **three are
      exact**. The others are converted and the frame is recomposed — which breaks
      alignment between views.
      
      | You request | OpenAI delivers | Exact? |
      |---|---|---|
      | `1:1` | 1024 × 1024 | yes |
      | `3:2` | 1536 × 1024 | yes |
      | `2:3` | 1024 × 1536 | yes |
      | `4:3` | 1536 × 1024 (3:2) | no, substituted |
      | `16:9` | 1536 × 1024 (3:2) | no, substituted |
      | `3:4` | 1024 × 1536 (2:3) | no, substituted |
      | `9:16` | 1024 × 1536 (2:3) | no, substituted |
      
      **Rule:** on OpenAI use only `1:1`, `3:2` or `2:3`. On Gemini, any of them.
      
      ## 3. Which ratio to use, by subject
      
      | Subject | Ratio | Why |
      |---|---|---|
      | Standing biped (human, anthro) | `2:3` | the silhouette is tall and narrow |
      | Quadruped, or long horizontal tail | `3:2` | the body is wider than it is tall |
      | Isolated garment (vest, shorts, boot) | `2:3` | keeps the proportion of the view it came from |
      | Small prop or hardware (buckle, crucifix, stud, link) | `1:1` | it is compact, a square wastes nothing |
      | Long weapon, vehicle, environment | `3:2` | same as quadruped |
      
      **Never request a full turnaround sheet** (front + side + back in a single
      image). The model splits its pixel budget across the three and each view comes
      out with a third of the detail. One view per call, always.
      
      ## 4. Margin — the subject has to fit **clothed**
      
      This is the easiest mistake to make, because the base render looks perfect.
      
      Clothing **grows outward past the nude silhouette**:
      
      | Piece | Grows toward | How much (1.80 m character) |
      |---|---|---|
      | Shoulder spike | sides and up | 8-10 cm each side |
      | Fur collar | up and around the neck | 5-8 cm |
      | Hanging chain | down | 10-20 cm below the hem |
      | Thick lug sole | down | 4-6 cm |
      | Cargo pocket, thigh strap | sides | 3-5 cm |
      
      Framed tight to the nude body, none of that has anywhere to go: the model either
      crops at the edge or squeezes the piece to fit.
      
      **But margin is not a fixed number — it is per edge, and it depends on the
      outfit.** Reserving 12% at the top is pointless if the character wears no hat:
      it is wasted pixels, and the body shrinks for nothing.
      
      The method: for each edge, ask **what part of that outfit passes the nude
      silhouette in that direction**, and reserve that plus a safety band of ~3%.
      
      | Edge | Question | Typical |
      |---|---|---|
      | Sides | is the widest point the shoulder or the hand? | arms out → the hand rules, and a glove barely grows: **5-6%** |
      | Bottom | thick sole, heel, hanging chain? | combat boot: **10%** · long chain: 15% |
      | Top | hat, hood, horn, crest, collar rising past the head? | none of those: **4%** · with a hat: 15% |
      
      Only reserve 12-15% on an edge when something really grows a lot there.
      Symmetric margin by default is waste; **asymmetric is correct** when only one
      edge needs it (e.g. 4% top, 16% bottom, for combat boots).
      
      If the base render already has the character filling 95% of the height, it is
      *wrong for this purpose*, however well framed it looks.
      
      ### A-pose or T-pose: width is what rules
      
      With the arms out, what limits the framing **is not the height, it is the arm
      span** — and only in the front and back views, because from the side the arms
      disappear behind the body.
      
      Practical consequence: **the front view sets the scale for all the others.**
      Adjust Ortho Scale until the hands fit with 12% of slack in the front view, then
      use exactly that value for the sides and the back, even if a lot of empty space
      is left on the sides of the side view. Empty space is the price of alignment.
      
      With the arms out, the body ends up occupying ~65-70% of the frame height, not
      the 76% of the general rule. That is expected, not an error.
      
      ### On resolution: the gain is modest
      
      A 1.80 m character filling the frame with correct margin:
      
      | Framing | Body height | px per cm | 1 cm stud |
      |---|---|---|---|
      | 1024×1024, body at 96% of height | ~980 px | 5.4 | 5 px |
      | 1024×1536, body at 76% of height | ~1170 px | 6.5 | 6-7 px |
      
      That is ~22% of gain, not a game changer. Input fidelity matters more to fine
      detail than this modest resolution increase. [OpenAI documents GPT Image
      2](https://developers.openai.com/api/docs/models/gpt-image-2) as supporting
      high-fidelity image inputs, but the current `create_asset` client does not
      expose `input_fidelity`, so it uses the provider default. Do not claim that
      `high` is enabled. Use `2:3` for the margin and for the subject's proportion,
      not expecting a sharpness miracle.
      
      ## 5. Exporting from Blender
      
      1. **Output Properties → Resolution X/Y**: set the final size directly —
         `1024 × 1536` for a standing character. Do not export square and crop later.
      2. **Orthographic camera**, not perspective. Perspective distorts the silhouette
         and the views stop matching each other.
      3. **Ortho Scale** adjusted so the body fills ~76% of the height, leaving 12-15%
         of slack top and bottom for the clothing to grow into.
      4. **The same Ortho Scale in all views.** That is what guarantees front, side and
         back stay aligned and superimposable afterwards. To take a tail out of the
         frame in the side view, **move the camera**, do not change the scale.
      5. **Flat white background** (white World) or transparent. No floor, no shadow,
         no HDRI — any gradient reads as "lighting" that the model tries to imitate.
      6. **PNG**, never JPEG. Compression artefacts on a silhouette edge confuse the
         model and it reproduces the artefact.
      
      **On the side view of a character with a long tail:** let the tail run out of
      frame. Framing the whole tail forces a horizontal ratio and pushes the body —
      which is where the clothing is — into a tiny corner.
      
      ## 6. Input images (the references)
      
      - **Maximum 5** per call.
      - Formats: PNG, JPEG, WebP.
      - **They do not need to match the output size**, but they must match the
        **aspect ratio**. A square reference asking for a 2:3 output makes the model
        recompose, and the generated view stops aligning with the others.
      - **Crop reference sheets** down to the relevant half only. A sheet with two
        views side by side and a caption makes the model reproduce a two-view layout
        instead of the object.
      - A reference with a dark background and dramatic lighting (product photography)
        drags its style along. Either crop the background out, or state explicitly in
        the prompt that the image informs the design, not the appearance.
      
      ## 7. What to send to image-to-3D afterwards
      
      The 3D generators (Tripo, Meshy, Rodin, Hunyuan3D, Trellis) want:
      
      - **An isolated object**, no character, no mannequin, no floor
      - **White or removed background**, flat
      - **`1:1` works better** than 2:3 on most of them — reconstruction assumes a
        centred volume
      - **Multi-view**: front and back of the **same** object, same framing, as
        separate images. Never the two glued into one image.
      
      So: generate the clothed view at `2:3` to get detail, isolate the piece, and only
      then reframe to `1:1` before sending it to the 3D generator.
      
      ## 8. Mandatory pre-flight check
      
      **Measure the reference images before any `create_asset` call.** Generating from
      a wrong base burns credit and produces an image that will be discarded.
      
      Criteria, per image:
      
      | Check | Pass | Fail → what to ask for |
      |---|---|---|
      | File aspect ratio | matches the requested `aspectRatio` | re-export at the correct ratio |
      | Top margin | ≥ what the clothing grows there + 3% | see the per-edge table in section 4 |
      | Bottom margin | ≥ what the clothing grows there + 3% | see the per-edge table in section 4 |
      | Side margins | ≥ what the clothing grows there + 3% | see the per-edge table in section 4 |
      | Body vertical occupancy | 75-85% | above 90% is too tight |
      | Long tail or appendage in the side view | out of frame | "move the camera, do not change the scale" |
      | Background | flat white or alpha | remove floor, shadow, gradient |
      | Format | PNG | re-export without JPEG |
      | Consistency between views | same Ortho Scale across all three | re-export the set |
      
      If any item fails: **say so and ask for the fix, do not generate.** Re-exporting
      from Blender is cheaper than discovering the crop after the image is finished.
      
      Use `../scripts/measure.py` — it reports occupancy and margins for each render in
      seconds.
      
      ## 9. One-line summary
      
      Standing character → `2:3`, body at ~76% of the height with 12-15% of margin for
      the clothing to grow into, orthographic, PNG, same Ortho Scale across all views.
      Measure before generating. Isolated piece for 3D → `1:1`.
      
  • scripts
    • measure.py 2.8 KB
      """Measure subject occupancy and margins in base renders and generations.
      
      Usage:
          python measure.py input.png output.png ...
      
      Reads the alpha channel when one exists; otherwise treats anything that is not
      near-white as subject. Prints one line per file with vertical and horizontal
      occupancy plus the four margins, all as a percentage of the frame.
      
      Criteria (see SKILL.md and resolutions-and-proportions.md):
        - input vertical occupancy: 75-85%, or 65-70% in A-pose/T-pose
        - per-edge margin: how far the clothing grows past the nude silhouette
          on that edge, plus roughly 3%
        - ocup_h deviation between input and output: within +-2 points is normal;
          beyond that the prompt let the model redraw the body
      """
      
      import os
      import sys
      
      try:
          from PIL import Image, ImageOps
      except ImportError as error:
          raise SystemExit(
              "Pillow is required. Install it with: "
              "python -m pip install -r /path/to/character-reference-sheets/requirements.txt"
          ) from error
      
      
      def measure(path):
          image = Image.open(path)
          if image.mode in ("RGBA", "LA"):
              bbox = image.split()[-1].getbbox()
          else:
              grey = ImageOps.invert(image.convert("L"))
              bbox = grey.point(lambda v: 255 if v > 12 else 0).getbbox()
      
          if bbox is None:
              return None
      
          width, height = image.size
          left, top, right, bottom = bbox
          return {
              "name": os.path.basename(path),
              "dimensions": f"{width}x{height}",
              "ocup_v": 100 * (bottom - top) / height,
              "ocup_h": 100 * (right - left) / width,
              "top": 100 * top / height,
              "bottom": 100 * (height - bottom) / height,
              "left": 100 * left / width,
              "right": 100 * (width - right) / width,
          }
      
      
      def main(paths):
          if not paths:
              print(__doc__)
              return 1
      
          results = []
          for path in paths:
              result = measure(path)
              if result is None:
                  print(f"{os.path.basename(path)}: empty frame, nothing measured")
                  continue
              results.append(result)
              print(
                  f"{result['name'][:34]:<36}{result['dimensions']:>10}"
                  f"  ocup_v={result['ocup_v']:5.1f}%  ocup_h={result['ocup_h']:5.1f}%"
                  f"  top={result['top']:4.1f}%  bottom={result['bottom']:4.1f}%"
                  f"  left={result['left']:4.1f}%  right={result['right']:4.1f}%"
              )
      
          if len(results) >= 2:
              source, generated = results[0], results[-1]
              drift_h = generated["ocup_h"] - source["ocup_h"]
              drift_v = generated["ocup_v"] - source["ocup_v"]
              verdict = "ok" if abs(drift_h) <= 2 else "REGENERATE - the body was redrawn"
              print(
                  f"\n{source['name'][:24]} -> {generated['name'][:24]}: "
                  f"drift_h={drift_h:+.1f}  drift_v={drift_v:+.1f}  [{verdict}]"
              )
      
          return 0
      
      
      if __name__ == "__main__":
          sys.exit(main(sys.argv[1:]))
      
    • test_measure.py 939 B
      import os
      import tempfile
      import unittest
      
      from PIL import Image, ImageDraw
      
      from measure import measure
      
      
      class MeasureTests(unittest.TestCase):
          def test_measure_reports_subject_occupancy_and_margins(self):
              with tempfile.TemporaryDirectory() as directory:
                  path = os.path.join(directory, "subject.png")
                  image = Image.new("RGB", (10, 10), "white")
                  ImageDraw.Draw(image).rectangle((2, 1, 7, 8), fill="black")
                  image.save(path)
      
                  result = measure(path)
      
              self.assertIsNotNone(result)
              self.assertEqual(result["dimensions"], "10x10")
              self.assertEqual(result["ocup_v"], 80)
              self.assertEqual(result["ocup_h"], 60)
              self.assertEqual(result["top"], 10)
              self.assertEqual(result["bottom"], 10)
              self.assertEqual(result["left"], 20)
              self.assertEqual(result["right"], 20)
      
      
      if __name__ == "__main__":
          unittest.main()
      
  • requirements.txt 15 B
    Pillow>=10.0.0
    
  • SKILL.md 5.4 KB
    ---
    name: character-reference-sheets
    description: Dress 3D character base renders with AI-generated clothing while preserving the body, pose and framing, so each garment can be cut out and sent to image-to-3D generators. Use when the request involves a Blender base render in A-pose or T-pose, a character visual sheet, a turnaround, generating clothing over a nude body mesh, or preparing garment pieces for Tripo, Meshy, Rodin, Hunyuan3D or Trellis. Do not use for website, banner or presentation imagery — the image-generation skill covers that.
    ---
    
    # Character reference sheets
    
    Pipeline: a nude body render comes out of Blender, the model dresses that body,
    each garment is cut out, it goes to an image-to-3D generator, and the mesh comes
    back into Blender.
    
    The goal of the generation is **not a beautiful image**. It is the *same body*
    as the render, now clothed, with every piece legible and cuttable. Everything
    below exists to protect that.
    
    ## Cost rule, before anything else
    
    **Never call `create_asset` without asking first.** Every generation spends the
    user's API credit. Write the full prompt, surface the decisions that change the
    image, and wait for an explicit go-ahead. This applies to each retry after a bad
    result too — do not silently fix and re-run.
    
    ## Workflow
    
    1. **Measure the input renders** with `scripts/measure.py`. If any criterion in
       section 8 of `references/resolutions-and-proportions.md` fails, say so and ask
       for a re-export from Blender. Cheaper than discovering the problem after the
       image is paid for.
    2. **Flatten alpha onto white** if the PNG is RGBA. Alpha often becomes black on
       upload and contaminates the result.
    3. **Build the prompt** using the architecture in `references/prompt-template.md`.
    4. **Ask for permission to generate.**
    5. **Generate**, one view per call.
    6. **Measure the output** and compare against the input (thresholds below).
    7. **Copy** from `IMAGE_OUTPUT_DIR` into the character project's own output
       folder, with a descriptive versioned name: `character_outfit_front_v2.png`.
    
    ## Measurement dependency
    
    `scripts/measure.py` requires Python and Pillow. Before first use, ask before
    installing the dependency, then run:
    
    ```bash
    python -m pip install -r /path/to/character-reference-sheets/requirements.txt
    ```
    
    If Pillow is unavailable and cannot be installed, do not generate: report that
    the mandatory pre-flight measurement could not be completed.
    
    ## The rule that matters most
    
    **Never describe the body in the prompt.** Not the build, not shoulder width,
    not head size, not height. Describing anatomy makes the model *draw a new body
    from the text* instead of preserving the one in the image.
    
    Recorded case: a prompt opening with "heavyset bara-build, very broad shoulders,
    thick muscular arms, wide barrel chest, heavy thighs, small head" collapsed the
    character's arm span from 88.9% to 74.3% of the frame width — **14.6 points**.
    Same character, same render, same model, rebuilt with the correct architecture
    and zero body description: 89.2%, a 0.3 point deviation.
    
    The prompt says **what to add** and **what to preserve**. Never what the body is.
    
    ## Parameters
    
    | | |
    |---|---|
    | Model | `gpt-image-2` |
    | Aspect ratio | `2:3` for a standing character · `1:1` for an isolated garment or prop |
    | Quality | Provider default — the current `create_asset` client does not expose `quality` |
    | `input_fidelity` | Provider default — the current client does not expose this option. [OpenAI documents GPT Image 2](https://developers.openai.com/api/docs/models/gpt-image-2) as supporting high-fidelity image inputs, but this workflow does not explicitly request `high` |
    | References | 2 to 4, base image **first** |
    | Turnarounds | never in a single image — one view per call |
    
    ## Verification after generating
    
    Run `scripts/measure.py` on the input and the output and compare **horizontal
    occupancy** (`ocup_h`):
    
    | `ocup_h` deviation | Reading |
    |---|---|
    | within ±2 points | normal, accept |
    | beyond ±2 points | the prompt let the model redraw the body — regenerate |
    
    Empirical basis: crocodile character +1.6 / −1.4 across three generations; tiger
    v2 +0.3; tiger v1 (wrong prompt) −14.6.
    
    Vertical occupancy usually rises 2 to 4 points even when everything is right. On
    its own it is not a failure signal.
    
    ## Known residual: limbs get thinner
    
    In **every** recorded generation so far — three of one character, two of another
    — arms and thighs came out with less volume than the base render. The `PRESERVE`
    block fixes framing and scale; it does **not** fix muscle mass.
    
    Do not treat this as a new bug on each character. Practical consequences:
    
    - Leg and foot pieces (pants, boots, sneakers) — safe to cut out, limb volume
      does not drive the garment's shape.
    - **Torso pieces** (shirt, vest, jacket) — they were modelled over a narrower
      torso than the original mesh. The generated 3D tends to come out tight. Warn
      the user before they send it to an image-to-3D generator.
    
    ## Where output lands
    
    The server writes to `IMAGE_OUTPUT_DIR` (an MCP environment variable) and
    rejects any `outputPath` outside it. Pass a bare filename and copy the result
    into the character's folder afterwards.
    
    ## References
    
    - `references/prompt-template.md` — the prompt architecture, with a real example
    - `references/resolutions-and-proportions.md` — aspect ratios, per-edge margins,
      Blender export settings, the mandatory pre-flight check, and what to feed an
      image-to-3D generator
    - `scripts/measure.py` — bounding box, occupancy and margins
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related